Started implementing menus on Windows.
This commit is contained in:
parent
b7e2905c72
commit
f303f066e2
1
test.c
1
test.c
|
@ -17,6 +17,7 @@ static uiMenuItem editMenu[] = {
|
|||
{ "Undo", uiMenuItemTypeCommand },
|
||||
{ uiMenuItemSeparator, uiMenuItemTypeSeparator },
|
||||
{ "Check Me", uiMenuItemTypeCheckbox },
|
||||
{ "A&ccelerator T_est", uiMenuItemTypeCommand },
|
||||
{ uiMenuItemPreferences, uiMenuItemTypeCommand },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ OSCFILES = \
|
|||
init.c \
|
||||
label.c \
|
||||
main.c \
|
||||
menu.c \
|
||||
newcontrol.c \
|
||||
parent.c \
|
||||
tab.c \
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
// 20 april 2015
|
||||
#include "uipriv_windows.h"
|
||||
|
||||
static void appendSeparator(HMENU menu)
|
||||
{
|
||||
if (AppendMenuW(menu, MF_SEPARATOR, 0, NULL) == 0)
|
||||
logLastError("error appending separator in appendSeparator()");
|
||||
}
|
||||
|
||||
static void appendTextItem(HMENU menu, const char *text)
|
||||
{
|
||||
WCHAR *wtext;
|
||||
|
||||
wtext = toUTF16(text);
|
||||
if (AppendMenuW(menu, MF_STRING, 0, wtext) == 0)
|
||||
logLastError("error appending menu item in appendTextItem()");
|
||||
uiFree(wtext);
|
||||
}
|
||||
|
||||
static void appendMenuItem(HMENU menu, const uiMenuItem *item)
|
||||
{
|
||||
// TODO see if there are stock items for these three
|
||||
if (item->Name == uiMenuItemQuit) {
|
||||
// TODO verify type
|
||||
appendSeparator(menu);
|
||||
appendTextItem(menu, "Quit");
|
||||
return;
|
||||
}
|
||||
if (item->Name == uiMenuItemPreferences) {
|
||||
// TODO verify type
|
||||
appendSeparator(menu);
|
||||
appendTextItem(menu, "Preferences");
|
||||
return;
|
||||
}
|
||||
if (item->Name == uiMenuItemAbout) {
|
||||
// TODO verify type
|
||||
appendSeparator(menu);
|
||||
appendTextItem(menu, "About");
|
||||
return;
|
||||
}
|
||||
if (item->Name == uiMenuItemSeparator) {
|
||||
// TODO verify type
|
||||
appendSeparator(menu);
|
||||
return;
|
||||
}
|
||||
switch (item->Type) {
|
||||
case uiMenuItemTypeCommand:
|
||||
case uiMenuItemTypeCheckbox:
|
||||
appendTextItem(menu, item->Name);
|
||||
return;
|
||||
}
|
||||
// TODO complain
|
||||
}
|
||||
|
||||
|
||||
static HMENU makeMenu(uiMenuItem *items)
|
||||
{
|
||||
HMENU menu;
|
||||
const uiMenuItem *i;
|
||||
|
||||
menu = CreatePopupMenu();
|
||||
if (menu == NULL)
|
||||
logLastError("error creating menu in makeMenu()");
|
||||
for (i = items; i->Name != NULL; i++)
|
||||
appendMenuItem(menu, i);
|
||||
return menu;
|
||||
}
|
||||
|
||||
HMENU makeMenubar(void)
|
||||
{
|
||||
HMENU menubar;
|
||||
const uiMenu *m;
|
||||
WCHAR *wname;
|
||||
HMENU menu;
|
||||
|
||||
if (options.Menu == NULL)
|
||||
complain("asked to give uiWindow a menubar but didn't specify a menu in uiInitOptions");
|
||||
|
||||
menubar = CreateMenu();
|
||||
if (menubar == NULL)
|
||||
logLastError("error creating menubar in makeMenubar()");
|
||||
|
||||
for (m = options.Menu; m->Name != NULL; m++) {
|
||||
wname = toUTF16(m->Name);
|
||||
menu = makeMenu(m->Items);
|
||||
if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, wname) == 0)
|
||||
logLastError("error appending menu to menubar in makeMenubar()");
|
||||
uiFree(wname);
|
||||
}
|
||||
|
||||
return menubar;
|
||||
}
|
|
@ -40,34 +40,37 @@ enum {
|
|||
#define HWND(c) ((HWND) uiControlHandle(uiControl(c)))
|
||||
#define uiParentHWND(p) ((HWND) uiParentHandle(p))
|
||||
|
||||
// debug_windows.c
|
||||
// debug.c
|
||||
extern HRESULT logLastError(const char *);
|
||||
extern HRESULT logHRESULT(const char *, HRESULT);
|
||||
extern HRESULT logMemoryExhausted(const char *);
|
||||
|
||||
// init_windows.c
|
||||
// init.c
|
||||
extern HINSTANCE hInstance;
|
||||
extern int nCmdShow;
|
||||
extern HFONT hMessageFont;
|
||||
extern HBRUSH hollowBrush;
|
||||
|
||||
// util_windows.c
|
||||
// util.c
|
||||
extern int windowClassOf(HWND, ...);
|
||||
|
||||
// text_windows.c
|
||||
// text.c
|
||||
extern WCHAR *toUTF16(const char *);
|
||||
extern char *toUTF8(const WCHAR *);
|
||||
extern WCHAR *windowText(HWND);
|
||||
|
||||
// comctl32_windows.c
|
||||
// comctl32.c
|
||||
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
||||
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
||||
extern const char *initCommonControls(void);
|
||||
|
||||
// window_windows.c
|
||||
// window.c
|
||||
extern ATOM registerWindowClass(HICON, HCURSOR);
|
||||
|
||||
// parent_windows.c
|
||||
// parent.c
|
||||
extern HWND initialParent;
|
||||
extern const char *initParent(HICON, HCURSOR);
|
||||
|
||||
// menu.c
|
||||
extern HMENU makeMenubar(void);
|
||||
|
|
|
@ -87,6 +87,7 @@ static void windowDestroy(uiWindow *ww)
|
|||
// and finally destroy
|
||||
// TODO check for errors
|
||||
DestroyWindow(w->hwnd);
|
||||
// no need to explicitly destroy the menubar, if any; that's done automatically during window destruction
|
||||
}
|
||||
|
||||
static uintptr_t windowHandle(uiWindow *ww)
|
||||
|
@ -180,20 +181,27 @@ static void windowSetMargined(uiWindow *ww, int margined)
|
|||
uiParentUpdate(w->content);
|
||||
}
|
||||
|
||||
uiWindow *uiNewWindow(const char *title, int width, int height)
|
||||
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
||||
{
|
||||
struct window *w;
|
||||
RECT adjust;
|
||||
WCHAR *wtitle;
|
||||
BOOL hasMenubarBOOL;
|
||||
HMENU hmenu;
|
||||
|
||||
w = uiNew(struct window);
|
||||
w->onClosing = defaultOnClosing;
|
||||
|
||||
hasMenubarBOOL = FALSE;
|
||||
if (hasMenubar)
|
||||
hasMenubarBOOL = TRUE;
|
||||
|
||||
adjust.left = 0;
|
||||
adjust.top = 0;
|
||||
adjust.right = width;
|
||||
adjust.bottom = height;
|
||||
if (AdjustWindowRectEx(&adjust, style, FALSE, exstyle) == 0)
|
||||
// TODO does not handle menu wrapping; see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx
|
||||
if (AdjustWindowRectEx(&adjust, style, hasMenubarBOOL, exstyle) == 0)
|
||||
logLastError("error getting real window coordinates in uiWindow()");
|
||||
|
||||
wtitle = toUTF16(title);
|
||||
|
@ -209,6 +217,12 @@ uiWindow *uiNewWindow(const char *title, int width, int height)
|
|||
|
||||
w->content = uiNewParent((uintptr_t) (w->hwnd));
|
||||
|
||||
if (hasMenubar) {
|
||||
hmenu = makeMenubar();
|
||||
if (SetMenu(w->hwnd, hmenu) == 0)
|
||||
logLastError("error giving menu to window in uiNewWindow()");
|
||||
}
|
||||
|
||||
uiWindow(w)->Destroy = windowDestroy;
|
||||
uiWindow(w)->Handle = windowHandle;
|
||||
uiWindow(w)->Title = windowTitle;
|
||||
|
|
Loading…
Reference in New Issue