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 },
|
{ "Undo", uiMenuItemTypeCommand },
|
||||||
{ uiMenuItemSeparator, uiMenuItemTypeSeparator },
|
{ uiMenuItemSeparator, uiMenuItemTypeSeparator },
|
||||||
{ "Check Me", uiMenuItemTypeCheckbox },
|
{ "Check Me", uiMenuItemTypeCheckbox },
|
||||||
|
{ "A&ccelerator T_est", uiMenuItemTypeCommand },
|
||||||
{ uiMenuItemPreferences, uiMenuItemTypeCommand },
|
{ uiMenuItemPreferences, uiMenuItemTypeCommand },
|
||||||
{ NULL, 0 },
|
{ NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ OSCFILES = \
|
||||||
init.c \
|
init.c \
|
||||||
label.c \
|
label.c \
|
||||||
main.c \
|
main.c \
|
||||||
|
menu.c \
|
||||||
newcontrol.c \
|
newcontrol.c \
|
||||||
parent.c \
|
parent.c \
|
||||||
tab.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 HWND(c) ((HWND) uiControlHandle(uiControl(c)))
|
||||||
#define uiParentHWND(p) ((HWND) uiParentHandle(p))
|
#define uiParentHWND(p) ((HWND) uiParentHandle(p))
|
||||||
|
|
||||||
// debug_windows.c
|
// debug.c
|
||||||
extern HRESULT logLastError(const char *);
|
extern HRESULT logLastError(const char *);
|
||||||
extern HRESULT logHRESULT(const char *, HRESULT);
|
extern HRESULT logHRESULT(const char *, HRESULT);
|
||||||
extern HRESULT logMemoryExhausted(const char *);
|
extern HRESULT logMemoryExhausted(const char *);
|
||||||
|
|
||||||
// init_windows.c
|
// init.c
|
||||||
extern HINSTANCE hInstance;
|
extern HINSTANCE hInstance;
|
||||||
extern int nCmdShow;
|
extern int nCmdShow;
|
||||||
extern HFONT hMessageFont;
|
extern HFONT hMessageFont;
|
||||||
extern HBRUSH hollowBrush;
|
extern HBRUSH hollowBrush;
|
||||||
|
|
||||||
// util_windows.c
|
// util.c
|
||||||
extern int windowClassOf(HWND, ...);
|
extern int windowClassOf(HWND, ...);
|
||||||
|
|
||||||
// text_windows.c
|
// text.c
|
||||||
extern WCHAR *toUTF16(const char *);
|
extern WCHAR *toUTF16(const char *);
|
||||||
extern char *toUTF8(const WCHAR *);
|
extern char *toUTF8(const WCHAR *);
|
||||||
extern WCHAR *windowText(HWND);
|
extern WCHAR *windowText(HWND);
|
||||||
|
|
||||||
// comctl32_windows.c
|
// comctl32.c
|
||||||
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||||
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
||||||
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
||||||
extern const char *initCommonControls(void);
|
extern const char *initCommonControls(void);
|
||||||
|
|
||||||
// window_windows.c
|
// window.c
|
||||||
extern ATOM registerWindowClass(HICON, HCURSOR);
|
extern ATOM registerWindowClass(HICON, HCURSOR);
|
||||||
|
|
||||||
// parent_windows.c
|
// parent.c
|
||||||
extern HWND initialParent;
|
extern HWND initialParent;
|
||||||
extern const char *initParent(HICON, HCURSOR);
|
extern const char *initParent(HICON, HCURSOR);
|
||||||
|
|
||||||
|
// menu.c
|
||||||
|
extern HMENU makeMenubar(void);
|
||||||
|
|
|
@ -87,6 +87,7 @@ static void windowDestroy(uiWindow *ww)
|
||||||
// and finally destroy
|
// and finally destroy
|
||||||
// TODO check for errors
|
// TODO check for errors
|
||||||
DestroyWindow(w->hwnd);
|
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)
|
static uintptr_t windowHandle(uiWindow *ww)
|
||||||
|
@ -180,20 +181,27 @@ static void windowSetMargined(uiWindow *ww, int margined)
|
||||||
uiParentUpdate(w->content);
|
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;
|
struct window *w;
|
||||||
RECT adjust;
|
RECT adjust;
|
||||||
WCHAR *wtitle;
|
WCHAR *wtitle;
|
||||||
|
BOOL hasMenubarBOOL;
|
||||||
|
HMENU hmenu;
|
||||||
|
|
||||||
w = uiNew(struct window);
|
w = uiNew(struct window);
|
||||||
w->onClosing = defaultOnClosing;
|
w->onClosing = defaultOnClosing;
|
||||||
|
|
||||||
|
hasMenubarBOOL = FALSE;
|
||||||
|
if (hasMenubar)
|
||||||
|
hasMenubarBOOL = TRUE;
|
||||||
|
|
||||||
adjust.left = 0;
|
adjust.left = 0;
|
||||||
adjust.top = 0;
|
adjust.top = 0;
|
||||||
adjust.right = width;
|
adjust.right = width;
|
||||||
adjust.bottom = height;
|
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()");
|
logLastError("error getting real window coordinates in uiWindow()");
|
||||||
|
|
||||||
wtitle = toUTF16(title);
|
wtitle = toUTF16(title);
|
||||||
|
@ -209,6 +217,12 @@ uiWindow *uiNewWindow(const char *title, int width, int height)
|
||||||
|
|
||||||
w->content = uiNewParent((uintptr_t) (w->hwnd));
|
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)->Destroy = windowDestroy;
|
||||||
uiWindow(w)->Handle = windowHandle;
|
uiWindow(w)->Handle = windowHandle;
|
||||||
uiWindow(w)->Title = windowTitle;
|
uiWindow(w)->Title = windowTitle;
|
||||||
|
|
Loading…
Reference in New Issue