From 379e9fd3a72fbf5f136443284bc6a2d81bb828fa Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Sat, 30 May 2020 16:16:50 +0200 Subject: toplevel: rename and reorganize functions --- Makefile.mingw | 6 +- Makefile.mingw-amd64 | 6 +- Makefile.vc6 | 6 +- Makefile.vc6-ansi | 6 +- alf/alf.cpp | 82 +-------- alf/alf.h | 148 ++++++++------- alf/alfbutton.cpp | 6 - alf/alfpriv.h | 6 +- alf/alftoplevel.cpp | 505 +++++++++++++++++++++++++++++++++++++++++++++++++++ alf/alfwindow.cpp | 424 ------------------------------------------ widgetfactory.cpp | 10 +- 11 files changed, 610 insertions(+), 595 deletions(-) create mode 100644 alf/alftoplevel.cpp delete mode 100644 alf/alfwindow.cpp diff --git a/Makefile.mingw b/Makefile.mingw index 8c29c5d..cf2ba63 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory.exe out/alf/alf.c out/widgetfactory-c.exe -out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alflabel.o out/alflayout.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alfwindow.o +out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alflabel.o out/alflayout.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alftoplevel.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -50,13 +50,13 @@ out/alfnotebook.o: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayout. out/alfpanel.o: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alfwindow.o: alf/alfwindow.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h +out/alftoplevel.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< out/widgetfactory.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfwindow.cpp +out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.mingw-amd64 b/Makefile.mingw-amd64 index 17e7aea..b723180 100644 --- a/Makefile.mingw-amd64 +++ b/Makefile.mingw-amd64 @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory64.exe out/alf/alf64.c out/widgetfactory64-c.exe -out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alfwindow.amd64.o +out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alftoplevel.amd64.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.amd64.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -50,13 +50,13 @@ out/alfnotebook.amd64.o: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alfl out/alfpanel.amd64.o: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alfwindow.amd64.o: alf/alfwindow.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h +out/alftoplevel.amd64.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< out/widgetfactory.amd64.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfwindow.cpp +out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.vc6 b/Makefile.vc6 index c850e7d..95a6681 100644 --- a/Makefile.vc6 +++ b/Makefile.vc6 @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link unicows.lib kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -46,8 +46,8 @@ out/alfnotebook.obj: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayou out/alfpanel.obj: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfpanel.cpp -out/alfwindow.obj: alf/alfwindow.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h - $(CXX) $(CFLAGS) -c -Fo$@ alf/alfwindow.cpp +out/alftoplevel.obj: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alftoplevel.cpp out/widgetfactory.obj: widgetfactory.cpp alf/alf.h $(CXX) $(CFLAGS) -c -Fo$@ widgetfactory.cpp diff --git a/Makefile.vc6-ansi b/Makefile.vc6-ansi index 8a6cb3f..adf38bf 100644 --- a/Makefile.vc6-ansi +++ b/Makefile.vc6-ansi @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link /entry:_entry /opt:nowin98 /fixed:no kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -46,8 +46,8 @@ out/alfnotebook.obj: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayou out/alfpanel.obj: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfpanel.cpp -out/alfwindow.obj: alf/alfwindow.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h - $(CXX) $(CFLAGS) -c -Fo$@ alf/alfwindow.cpp +out/alftoplevel.obj: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alftoplevel.cpp out/widgetfactory.obj: widgetfactory.cpp alf/alf.h $(CXX) $(CFLAGS) -c -Fo$@ widgetfactory.cpp diff --git a/alf/alf.cpp b/alf/alf.cpp index de23784..84ba71d 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -45,7 +45,7 @@ ALF_Initialize(void) ALF_LoadCompatFunctions(); - ALF_RegisterWindowClass(); + ALF_RegisterToplevelClass(); ALF_RegisterControlClass(); ALF_Compat_BufferedPaintInit(); @@ -67,7 +67,8 @@ ALF_UnInitialize(void) if (!--_alf_initCounter) { ALF_Compat_BufferedPaintUnInit(); - UnregisterClass(_alf_windowClass, ALF_HINSTANCE); + ALF_UnregisterToplevelClass(); + UnregisterClass(_alf_controlClass, ALF_HINSTANCE); ALF_UnloadCompatFunctions(); @@ -104,52 +105,6 @@ ALF_Free(const void *p) HeapFree(GetProcessHeap(), 0, (void*)p); } -void -ALF_DestroyWindow(HWND win) -{ - DestroyWindow(win); -} - -int -ALF_ShowModal(HWND win) -{ - MSG msg; - - ALF_SetModalResult(win, 0); - - // TODO: disable parent window - ShowWindow(win, SW_SHOW); - - while (GetMessage(&msg, NULL, 0, 0) > 0) { - // TODO: call application message hooks - // TODO: call preprocess message hook - - if (!IsDialogMessage(win, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - int mr = ALF_GetModalResult(win); - if (mr) - return mr; - } - - return 0; -} - - -void -ALF_SetModalResult(HWND win, int result) -{ - SendMessage(win, ALF_WM_SETMODALRESULT, (WPARAM)result, 0); -} - -int -ALF_GetModalResult(HWND win) -{ - return (int)SendMessage(win, ALF_WM_GETMODALRESULT, 0, 0); -} - int ALF_CentipointsToPixels(int cptValue, int dpi) { @@ -162,37 +117,6 @@ ALF_GetDpi(HWND window) return (int)SendMessage(window, ALF_WM_GETDPI, 0, 0); } -void -ALF_ResizeWindow(HWND win, int cptWidth, int cptHeight) -{ - int dpi = ALF_GetDpi(win); - - int pxwidth = ALF_CentipointsToPixels(cptWidth, dpi); - int pxheight = ALF_CentipointsToPixels(cptHeight, dpi); - - ALF_ResizeWindowPx(win, pxwidth, pxheight); -} - -void -ALF_ResizeWindowPx(HWND win, int pxwidth, int pxheight) -{ - MINMAXINFO tmp = { - { 0, 0 }, - { pxwidth, pxheight }, - { 0, 0 }, - { pxwidth, pxheight }, - { pxwidth, pxheight } - }; - SendMessage(win, WM_GETMINMAXINFO, 0, (LPARAM)&tmp); - - if (tmp.ptMinTrackSize.x > pxwidth) - pxwidth = tmp.ptMinTrackSize.x; - if (tmp.ptMinTrackSize.y > pxheight) - pxheight = tmp.ptMinTrackSize.y; - - SetWindowPos(win, NULL, 0, 0, pxwidth, pxheight, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER); -} - struct ALF_WidgetHwndById_Closure { HWND result; WORD needle; diff --git a/alf/alf.h b/alf/alf.h index aab0f00..cb2e48e 100644 --- a/alf/alf.h +++ b/alf/alf.h @@ -18,7 +18,7 @@ typedef struct { BOOL (*pretranslatemessage)(void * /*closure*/, HWND /*window*/, MSG * /*message*/); void (*paint)(void * /*closure*/, HWND, HDC, RECT *); void (*windowposchanged)(void * /*closure*/, HWND, WINDOWPOS *); -} ALFWindowVTable; +} ALFToplevelVTable; typedef struct { void (*attachvtbl)(void * /*closure*/, HWND /*panel*/); @@ -159,62 +159,12 @@ ALF_Free(const void *p); COLORREF ALF_ColorToGdi(ALFColor color); -HWND -ALF_CreateToplevelWindow(HWND hwndParent, ALFWindowVTable *vtbl, void *closure); - -void -ALF_DestroyWindow(HWND win); - int ALF_CentipointsToPixels(int cptValue, int dpi); int ALF_GetDpi(HWND hwnd); -LRESULT -ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - -void -ALF_EnsureWindowBigEnough(HWND toplevel); - -HWND -ALF_AddLabel(HWND win, WORD id, int x, int y, const TCHAR *text); - -DWORD -ALF_LabelStyle(HWND hwndLabel); - -void -ALF_LabelSetStyle(HWND hwndLabel, DWORD style); - -HWND -ALF_AddEdit(HWND win, WORD id, int x, int y, const TCHAR *text); - -HWND -ALF_AddButton(HWND win, WORD id, int x, int y, const TCHAR *text); - -// NOTE about default buttons: -// -// - If no default button is specified, the default button will be the button -// with the id IDOK. A WM_COMMAND message on pressing the return key will be -// sent even if no widget with the default id can be found. -// - In NT 3.51, the default button must be a direct child of the window. Otherwise -// the default button effect will not work. -// - In Win32s on Win3.1, the default button should be a direct child of the window. -// Otherwise the default button effect will be buggy when setting the focus -// via WM_NEXTDLGCTL or ALF_SetFocus(), but it will work correctly when using -// the TAB key. -// - Changing the default button will only fully take effect after a focus change. -// It might temporarily lead to artifacts such as having two or no default buttons. -// -// Recommendation: Set the default button during window initialization, and then -// immediately set the focus via ALF_SetFocus(). If you want to support NT 3.51 -// or Win32s, ensure that the default button is a direct child of the toplevel window. -void -ALF_SetDefaultButton(HWND win, WORD id); - -void -ALF_DestroyWidget(HWND win, WORD id); - void ALF_AddWidget(HWND win, int x, int y, HWND widget, int width, int height, DWORD flags); @@ -255,21 +205,6 @@ ALF_TextColor(HWND win); void ALF_SetTextColor(HWND win, ALFColor color); -void -ALF_ResizeWindow(HWND win, int cptWidth, int cptHeight); - -void -ALF_ResizeWindowPx(HWND win, int pxWidth, int pxHeight); - -int -ALF_ShowModal(HWND win); - -void -ALF_SetModalResult(HWND win, int result); - -int -ALF_GetModalResult(HWND win); - void ALF_SetFocus(HWND target); @@ -360,10 +295,89 @@ ALF_LayoutColumnExpandNumerator(HWND parent, int colno); BOOL ALF_LayoutSetColumnExpandNumerator(HWND parent, int colno, int expand); - void ALF_FillRect(HDC dc, const RECT *rc, ALFColor color); +void +ALF_DestroyWidget(HWND win, WORD id); + +// toplevel window + +HWND +ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure); + +void +ALF_Toplevel_Resize(HWND win, int cptWidth, int cptHeight); + +void +ALF_Toplevel_ResizePx(HWND win, int pxWidth, int pxHeight); + + +// To add to your message loop like IsDialogMessage +// NOT TREAD SAFE: Only call from the thread owning the window +// (accesses internal data structures directly for performance) +BOOL +ALF_Toplevel_PreTranslateMessage(HWND toplevel, MSG *msg); + +// Shows the window as a modal window (i.e. disabling the owner window) +// returns once the modal window has been ended via ALF_Toplevel_SetModalResult +// NOT THREAD SAFE: Only call from the thread owning the window +// (accesses internal data structures directly for performance) +LPARAM +ALF_Toplevel_ShowModal(HWND toplevel); + +void +ALF_Toplevel_SetModalResult(HWND win, LRESULT result); + +LRESULT +ALF_Toplevel_GetModalResult(HWND win); + +LRESULT +ALF_Toplevel_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + +void +ALF_Toplevel_EnsureBigEnough(HWND toplevel); + +// NOTE about default buttons: +// +// - If no default button is specified, the default button will be the button +// with the id IDOK. A WM_COMMAND message on pressing the return key will be +// sent even if no widget with the default id can be found. +// - In NT 3.51, the default button must be a direct child of the window. Otherwise +// the default button effect will not work. +// - In Win32s on Win3.1, the default button should be a direct child of the window. +// Otherwise the default button effect will be buggy when setting the focus +// via WM_NEXTDLGCTL or ALF_SetFocus(), but it will work correctly when using +// the TAB key. +// - Changing the default button will only fully take effect after a focus change. +// It might temporarily lead to artifacts such as having two or no default buttons. +// +// Recommendation: Set the default button during window initialization, and then +// immediately set the focus via ALF_SetFocus(). If you want to support NT 3.51 +// or Win32s, ensure that the default button is a direct child of the toplevel window. +void +ALF_Toplevel_SetDefaultButton(HWND win, WORD id); + +// label + +HWND +ALF_AddLabel(HWND win, WORD id, int x, int y, const TCHAR *text); + +DWORD +ALF_LabelStyle(HWND hwndLabel); + +void +ALF_LabelSetStyle(HWND hwndLabel, DWORD style); + +// edit + +HWND +ALF_AddEdit(HWND win, WORD id, int x, int y, const TCHAR *text); + +// button + +HWND +ALF_AddButton(HWND win, WORD id, int x, int y, const TCHAR *text); // combo box diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp index 6d7d319..00bd3fb 100644 --- a/alf/alfbutton.cpp +++ b/alf/alfbutton.cpp @@ -1415,9 +1415,3 @@ ALF_AddRadioButton(HWND parent, WORD id, int x, int y, const TCHAR *text) } } -void -ALF_SetDefaultButton(HWND win, WORD id) -{ - SendMessage(win, DM_SETDEFID, (WPARAM)id, 0); -} - diff --git a/alf/alfpriv.h b/alf/alfpriv.h index 0c5cc25..586bbba 100644 --- a/alf/alfpriv.h +++ b/alf/alfpriv.h @@ -17,11 +17,13 @@ #include "alfcompat.h" #include "alflayout.h" -extern TCHAR _alf_windowClass[]; extern TCHAR _alf_controlClass[]; void -ALF_RegisterWindowClass(void); +ALF_RegisterToplevelClass(void); + +void +ALF_UnregisterToplevelClass(void); void ALF_RegisterControlClass(void); diff --git a/alf/alftoplevel.cpp b/alf/alftoplevel.cpp new file mode 100644 index 0000000..99f78e5 --- /dev/null +++ b/alf/alftoplevel.cpp @@ -0,0 +1,505 @@ +#include "alfpriv.h" + +typedef struct { + ALFToplevelVTable *vtbl; + void *closure; + LPARAM modalResult; + ALFLayout layout; + HWND hwndFocus; + HFONT hMessageFont; +} ALFToplevelPriv; + +struct ALFToplevel_CreateParams{ + ALFToplevelVTable *vtbl; + void *closure; +}; + +static TCHAR _alf_toplevelClass[28] = {0}; + +static void +ALF_InitializeToplevelPriv(HWND hwnd, ALFToplevelPriv *priv) +{ + (void)hwnd; + + ALF_Layout_Init(&priv->layout); + priv->layout.bgcolor = ALF_COLOR_SYS(COLOR_BTNFACE); +} + +static void +ALF_DestroyToplevelPriv(ALFToplevelPriv *priv) +{ + if (priv->vtbl && priv->vtbl->postdestroy) + priv->vtbl->postdestroy(priv->closure); + + ALF_Layout_Clear(&priv->layout); + + if (priv->hMessageFont) + DeleteObject(priv->hMessageFont); + + ALF_Free(priv); +} + +static void +ALF_UpdateFontsPriv(HWND win, ALFToplevelPriv *priv) +{ + // XXX: SystemParametersInfoForDpi is Unicode-only and needs Vista+ NONCLIENTMETRICS, + ALF_NONCLIENTMETRICSW_VISTA ncm; + ZeroMemory(&ncm, sizeof(ncm)); + ncm.cbSize = sizeof(ncm); + + LOGFONT lfMessageFont; + ZeroMemory(&lfMessageFont, sizeof(lfMessageFont)); + + if (ALF_Compat_SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, (UINT)priv->layout.dpi)) { +#ifdef UNICODE + lfMessageFont = ncm.lfMessageFont; +#else + ALF_Compat_LogFontWtoA(&ncm.lfMessageFont, &lfMessageFont); +#endif + } else { + // FIXME! fallback to default font, 8pt MS Shell Dlg + ZeroMemory(&lfMessageFont, sizeof(lfMessageFont)); + + lfMessageFont.lfHeight = -MulDiv(8, priv->layout.dpi, 72); + lstrcpy(lfMessageFont.lfFaceName, TEXT("MS Shell Dlg")); + } + + if (priv->hMessageFont) { + DeleteObject(priv->hMessageFont); + } + + priv->hMessageFont = CreateFontIndirect(&lfMessageFont); + + SendMessage(win, WM_SETFONT, (WPARAM)priv->hMessageFont, (LPARAM)1); +} + + +/*static BOOL +ALF_PreTranslateMessagePriv(HWND win, ALFToplevelPriv *priv, MSG *message) +{ + BOOL ret = FALSE; + + if (priv->vtbl->pretranslatemessage) + ret = priv->vtbl->pretranslatemessage(priv->closure, win, message); + + if (!ret) + ret = IsDialogMessage(win, message); + + return ret; +}*/ + +void +ALF_Toplevel_EnsureBigEnough(HWND toplevel) +{ + MINMAXINFO i; + ZeroMemory(&i, sizeof(i)); + SendMessage(toplevel, WM_GETMINMAXINFO, 0, (LPARAM)&i); + + WINDOWPLACEMENT wp; + ZeroMemory(&wp, sizeof(wp)); + wp.length = sizeof(wp); + + GetWindowPlacement(toplevel, &wp); + + if (wp.rcNormalPosition.right - wp.rcNormalPosition.left < i.ptMinTrackSize.x || + wp.rcNormalPosition.bottom - wp.rcNormalPosition.top < i.ptMinTrackSize.y) { + if (wp.rcNormalPosition.right - wp.rcNormalPosition.left < i.ptMinTrackSize.x) + wp.rcNormalPosition.right = wp.rcNormalPosition.left + i.ptMinTrackSize.x; + if (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top < i.ptMinTrackSize.y) + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + i.ptMinTrackSize.y; + + SetWindowPlacement(toplevel, &wp); + } +} + +static INT_PTR CALLBACK +ALF_Toplevel_DlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + (void)hwnd; + (void)msg; + (void)wparam; + (void)lparam; + + return FALSE; +} + + +static LRESULT CALLBACK +ALF_Toplevel_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + if (msg == WM_CREATE) { + ALFToplevelPriv *priv = ALF_New(ALFToplevelPriv, 1); + SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, (LONG_PTR)priv); + ALF_InitializeToplevelPriv(hwnd, priv); + + int dpi = (int)ALF_Compat_GetDpiForWindow(hwnd); + SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts + } + + ALFToplevelPriv *priv = (ALFToplevelPriv*)(void*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); + if (priv != NULL) { + if (priv->vtbl && priv->vtbl->message) { + return priv->vtbl->message(priv->closure, hwnd, msg, wparam, lparam); + } else { + return ALF_Toplevel_DefWindowProc(hwnd, msg, wparam, lparam); + } + } else { + return DefDlgProc(hwnd, msg, wparam, lparam); + } +} + +static void +ALF_Toplevel_Paint(ALFToplevelPriv *priv, HWND hwnd, HDC dc, RECT *r) +{ + if (priv->vtbl && priv->vtbl->paint) { + priv->vtbl->paint(priv->closure, hwnd, dc, r); + } else { + ALF_FillRect(dc, r, priv->layout.bgcolor); + } +} + +LRESULT +ALF_Toplevel_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + ALFToplevelPriv *priv = (ALFToplevelPriv*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); + + if (msg == WM_INITDIALOG) { + struct ALFToplevel_CreateParams *params = (struct ALFToplevel_CreateParams *)lparam; + + priv->vtbl = params->vtbl; + priv->closure = params->closure; + + BOOL retval = TRUE; + if (priv->vtbl && priv->vtbl->initialize) { + retval = priv->vtbl->initialize(priv->closure, hwnd); + } + + ALF_Toplevel_EnsureBigEnough(hwnd); + + return retval; + } + + if (msg == ALF_WM_GETMODALRESULT) { + return (LRESULT)priv->modalResult; + } + if (msg == ALF_WM_SETMODALRESULT) { + priv->modalResult = lparam; + return 0; + } + + if (msg == ALF_WM_GETDPI) { + return (LRESULT)priv->layout.dpi; + } + + if (msg == ALF_WM_UPDATEFONTS) { + ALF_UpdateFontsPriv(hwnd, priv); + return 0; + } + + if (msg == WM_ERASEBKGND) { + return TRUE; // handled in WM_PAINT + } + + if (msg == WM_PRINTCLIENT) { + RECT r = { 0, 0, 0, 0 }; + GetClientRect(hwnd, &r); + + ALF_Toplevel_Paint(priv, hwnd, (HDC)wparam, &r); + return TRUE; + } + + if (msg == WM_PAINT) { + PAINTSTRUCT ps; + HDC dc = BeginPaint(hwnd, &ps); + + ALF_Toplevel_Paint(priv, hwnd, dc, &ps.rcPaint); + + EndPaint(hwnd, &ps); + + return 0; + } + + if (msg == WM_COMMAND) { + HWND source = (HWND)lparam; + WORD code = HIWORD(wparam); + WORD id = LOWORD(wparam); + LRESULT ret = 0; + if (source != 0) + ret = SendMessage(source, 0x2000 + WM_COMMAND, wparam, lparam); + + if (ret == 0 && priv->vtbl && priv->vtbl->command) + ret = priv->vtbl->command(priv->closure, hwnd, code, id, source); + + return ret; + } + + if (msg == WM_NOTIFY) { + NMHDR *nmhdr = (NMHDR *)lparam; + LRESULT ret = 0; + + if (nmhdr->hwndFrom) + ret = SendMessage(nmhdr->hwndFrom, 0x2000 + WM_NOTIFY, wparam, lparam); + + if (ret == 0 && priv->vtbl && priv->vtbl->notify) + ret = priv->vtbl->notify(priv->closure, hwnd, wparam, nmhdr); + + return ret; + } + + if (msg == WM_DRAWITEM) { + LPDRAWITEMSTRUCT dis = (DRAWITEMSTRUCT *)lparam; + LRESULT ret = 0; + if (wparam && dis->hwndItem) { + ret = SendMessage(dis->hwndItem, 0x2000 + WM_DRAWITEM, wparam, lparam); + } + + if (ret) + return ret; + } + + if (msg == WM_CTLCOLORSTATIC) { + LRESULT ret = SendMessage((HWND)lparam, 0x2000 + WM_CTLCOLORSTATIC, wparam, lparam); + + if (ret) { + return ret; + } else { + SetBkColor((HDC)wparam, GetSysColor(COLOR_BTNFACE)); + SetTextColor((HDC)wparam, GetSysColor(COLOR_BTNTEXT)); + return (LRESULT)GetSysColorBrush(COLOR_BTNFACE); + } + } + + if (msg == WM_CTLCOLORBTN) { + LRESULT ret = SendMessage((HWND)lparam, 0x2000 + WM_CTLCOLORBTN, wparam, lparam); + + if (ret) { + return ret; + } else { + SetBkColor((HDC)wparam, GetSysColor(COLOR_BTNFACE)); + SetTextColor((HDC)wparam, GetSysColor(COLOR_BTNTEXT)); + return (LRESULT)GetSysColorBrush(COLOR_BTNFACE); + } + } + + if (msg == WM_SIZE) { + ALF_Layout_Apply(&priv->layout, hwnd); + } + + if (msg == WM_SHOWWINDOW) { + if (wparam) + ALF_Layout_Validate(&priv->layout, hwnd); + } + + if (msg == WM_GETMINMAXINFO) { + RECT tmp; + ZeroMemory(&tmp, sizeof(tmp)); + + SIZE s; + ZeroMemory(&s, sizeof(s)); + ALF_Layout_GetMinSize(&priv->layout, hwnd, &s); + + tmp.right = s.cx; + tmp.bottom = s.cy; + + if (ALF_Compat_AdjustWindowRectExForDpi( + &tmp, + (DWORD)GetWindowLong(hwnd, GWL_STYLE), + GetMenu(hwnd) != NULL, + (DWORD)GetWindowLong(hwnd, GWL_EXSTYLE), + (UINT)priv->layout.dpi)) { + MINMAXINFO *i = (MINMAXINFO *)lparam; + i->ptMinTrackSize.x = tmp.right - tmp.left; + i->ptMinTrackSize.y = tmp.bottom - tmp.top; + return 0; + } + } + + if (msg == WM_DESTROY && priv->vtbl && priv->vtbl->destroy) { + priv->vtbl->destroy(priv->closure, hwnd); + } + + if (msg == WM_CLOSE) { + if (!priv->vtbl || !priv->vtbl->close || !priv->vtbl->close(priv->closure, hwnd)) { + priv->modalResult = 2; + ShowWindow(hwnd, FALSE); + } + return TRUE; + } + + if (msg == WM_NCDESTROY) { + SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, 0); + ALF_DestroyToplevelPriv(priv); + } + + if (msg == WM_DPICHANGED) { + int dpi = LOWORD(wparam); + SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts and invalidate layout + + RECT *r = (RECT*)lparam; + SetWindowPos(hwnd, NULL, r->left, r->top, r->right-r->left, r->bottom-r->top, SWP_NOACTIVATE|SWP_NOZORDER); + } + + if (msg == WM_THEMECHANGED || msg == WM_SETTINGCHANGE) { + ALF_UpdateFontsPriv(hwnd, priv); + ALF_Layout_Invalidate(&priv->layout, hwnd); + ALF_InvalidateBackground(hwnd); + InvalidateRect(hwnd, NULL, TRUE); + } + + if (msg == WM_WINDOWPOSCHANGED) { + if (priv->vtbl && priv->vtbl->windowposchanged) { + priv->vtbl->windowposchanged(priv->closure, hwnd, (WINDOWPOS *)lparam); + } + } + + LRESULT ret = 0; + if (ALF_Layout_HandleMessage(&priv->layout, hwnd, msg, wparam, lparam, &ret)) { + // if the layout was changed, our current size might be too small + if (msg == ALF_WM_VALIDATELAYOUT) { + ALF_Toplevel_EnsureBigEnough(hwnd); + } + + if (msg == ALF_WM_DPICHANGE) { + ALF_UpdateFontsPriv(hwnd, priv); + } + + return ret; + } + + return DefDlgProc(hwnd, msg, wparam, lparam); +} + +void +ALF_RegisterToplevelClass(void) +{ + WNDCLASS cls; + ZeroMemory(&cls, sizeof(cls)); + + wsprintf(_alf_toplevelClass, TEXT("ALFWindow.%p"), (ULONG_PTR)&_alf_toplevelClass[0]); + + cls.style = 0; + cls.hInstance = ALF_HINSTANCE; + cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); + cls.hbrBackground = NULL; + cls.lpszClassName = _alf_toplevelClass; + cls.cbWndExtra = DLGWINDOWEXTRA + sizeof(void*); + cls.cbClsExtra = 0; + cls.lpfnWndProc = ALF_Toplevel_WindowProc; + + ATOM classatom = RegisterClass(&cls); + if (!classatom) { + MessageBox(NULL, TEXT("FATAL: Couldn't register toplevel window class"), TEXT("DEBUG"), MB_ICONHAND|MB_OK); + } +} + +void +ALF_UnregisterToplevelClass(void) +{ + UnregisterClass(_alf_toplevelClass, ALF_HINSTANCE); +} + +HWND +ALF_CreateToplevelWindow(HWND hwndParent, ALFToplevelVTable *vtbl, void *closure) +{ +#pragma pack(push, 1) + struct { + DLGTEMPLATE t; + WCHAR s[32]; + } t; +#pragma pack(pop) + ZeroMemory(&t, sizeof(t)); + t.t.style = WS_OVERLAPPEDWINDOW; + t.t.dwExtendedStyle = 0; + t.t.x = 0; + t.t.y = 0; + t.t.cx = 10; + t.t.cy = 10; + t.t.cdit = 0; + + // NOTE: this only works because we know the window class name is all ascii + for (int i = 0; _alf_toplevelClass[i]; ++i) { + t.s[i+1] = _alf_toplevelClass[i]; + } + + struct ALFToplevel_CreateParams params; + params.vtbl = vtbl; + params.closure = closure; + return CreateDialogIndirectParam(ALF_HINSTANCE, &t.t, hwndParent, ALF_Toplevel_DlgProc, (LPARAM)¶ms); +} + +void +ALF_Toplevel_SetDefaultButton(HWND win, WORD id) +{ + SendMessage(win, DM_SETDEFID, (WPARAM)id, 0); +} + +LPARAM +ALF_Toplevel_ShowModal(HWND win) +{ + MSG msg; + + ALF_Toplevel_SetModalResult(win, 0); + + // TODO: disable parent window + ShowWindow(win, SW_SHOW); + + while (GetMessage(&msg, NULL, 0, 0) > 0) { + // TODO: call application message hooks + // TODO: call preprocess message hook + + if (!IsDialogMessage(win, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + int mr = ALF_Toplevel_GetModalResult(win); + if (mr) + return mr; + } + + return 0; +} + + +void +ALF_Toplevel_SetModalResult(HWND win, LPARAM result) +{ + SendMessage(win, ALF_WM_SETMODALRESULT, 0, result); +} + +LPARAM +ALF_Toplevel_GetModalResult(HWND win) +{ + return (LPARAM)SendMessage(win, ALF_WM_GETMODALRESULT, 0, 0); +} + +void +ALF_Toplevel_Resize(HWND win, int cptWidth, int cptHeight) +{ + int dpi = ALF_GetDpi(win); + + int pxwidth = ALF_CentipointsToPixels(cptWidth, dpi); + int pxheight = ALF_CentipointsToPixels(cptHeight, dpi); + + ALF_Toplevel_ResizePx(win, pxwidth, pxheight); +} + +void +ALF_Toplevel_ResizePx(HWND win, int pxwidth, int pxheight) +{ + MINMAXINFO tmp = { + { 0, 0 }, + { pxwidth, pxheight }, + { 0, 0 }, + { pxwidth, pxheight }, + { pxwidth, pxheight } + }; + SendMessage(win, WM_GETMINMAXINFO, 0, (LPARAM)&tmp); + + if (tmp.ptMinTrackSize.x > pxwidth) + pxwidth = tmp.ptMinTrackSize.x; + if (tmp.ptMinTrackSize.y > pxheight) + pxheight = tmp.ptMinTrackSize.y; + + SetWindowPos(win, NULL, 0, 0, pxwidth, pxheight, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER); +} diff --git a/alf/alfwindow.cpp b/alf/alfwindow.cpp deleted file mode 100644 index f59e784..0000000 --- a/alf/alfwindow.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#include "alfpriv.h" - -typedef struct { - ALFWindowVTable *vtbl; - void *closure; - int modalResult; - ALFLayout layout; - HWND hwndFocus; - HFONT hMessageFont; -} ALFWindowPriv; - -struct ALFWindow_CreateParams{ - ALFWindowVTable *vtbl; - void *closure; -}; - -TCHAR _alf_windowClass[28] = {0}; - -static void -ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv) -{ - (void)hwnd; - - ALF_Layout_Init(&priv->layout); - priv->layout.bgcolor = ALF_COLOR_SYS(COLOR_BTNFACE); -} - -static void -ALF_DestroyWindowPriv(ALFWindowPriv *priv) -{ - if (priv->vtbl && priv->vtbl->postdestroy) - priv->vtbl->postdestroy(priv->closure); - - ALF_Layout_Clear(&priv->layout); - - if (priv->hMessageFont) - DeleteObject(priv->hMessageFont); - - ALF_Free(priv); -} - -static void -ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv) -{ - // XXX: SystemParametersInfoForDpi is Unicode-only and needs Vista+ NONCLIENTMETRICS, - ALF_NONCLIENTMETRICSW_VISTA ncm; - ZeroMemory(&ncm, sizeof(ncm)); - ncm.cbSize = sizeof(ncm); - - LOGFONT lfMessageFont; - ZeroMemory(&lfMessageFont, sizeof(lfMessageFont)); - - if (ALF_Compat_SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, (UINT)priv->layout.dpi)) { -#ifdef UNICODE - lfMessageFont = ncm.lfMessageFont; -#else - ALF_Compat_LogFontWtoA(&ncm.lfMessageFont, &lfMessageFont); -#endif - } else { - // FIXME! fallback to default font, 8pt MS Shell Dlg - ZeroMemory(&lfMessageFont, sizeof(lfMessageFont)); - - lfMessageFont.lfHeight = -MulDiv(8, priv->layout.dpi, 72); - lstrcpy(lfMessageFont.lfFaceName, TEXT("MS Shell Dlg")); - } - - if (priv->hMessageFont) { - DeleteObject(priv->hMessageFont); - } - - priv->hMessageFont = CreateFontIndirect(&lfMessageFont); - - SendMessage(win, WM_SETFONT, (WPARAM)priv->hMessageFont, (LPARAM)1); -} - - -/*static BOOL -ALF_PreTranslateMessagePriv(HWND win, ALFWindowPriv *priv, MSG *message) -{ - BOOL ret = FALSE; - - if (priv->vtbl->pretranslatemessage) - ret = priv->vtbl->pretranslatemessage(priv->closure, win, message); - - if (!ret) - ret = IsDialogMessage(win, message); - - return ret; -}*/ - -void -ALF_EnsureWindowBigEnough(HWND toplevel) -{ - MINMAXINFO i; - ZeroMemory(&i, sizeof(i)); - SendMessage(toplevel, WM_GETMINMAXINFO, 0, (LPARAM)&i); - - WINDOWPLACEMENT wp; - ZeroMemory(&wp, sizeof(wp)); - wp.length = sizeof(wp); - - GetWindowPlacement(toplevel, &wp); - - if (wp.rcNormalPosition.right - wp.rcNormalPosition.left < i.ptMinTrackSize.x || - wp.rcNormalPosition.bottom - wp.rcNormalPosition.top < i.ptMinTrackSize.y) { - if (wp.rcNormalPosition.right - wp.rcNormalPosition.left < i.ptMinTrackSize.x) - wp.rcNormalPosition.right = wp.rcNormalPosition.left + i.ptMinTrackSize.x; - if (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top < i.ptMinTrackSize.y) - wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + i.ptMinTrackSize.y; - - SetWindowPlacement(toplevel, &wp); - } -} - -static INT_PTR CALLBACK -ALF_Window_DlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - (void)hwnd; - (void)msg; - (void)wparam; - (void)lparam; - - return FALSE; -} - - -static LRESULT CALLBACK -ALF_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - if (msg == WM_CREATE) { - ALFWindowPriv *priv = ALF_New(ALFWindowPriv, 1); - SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, (LONG_PTR)priv); - ALF_InitializeWindowPriv(hwnd, priv); - - int dpi = (int)ALF_Compat_GetDpiForWindow(hwnd); - SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts - } - - ALFWindowPriv *priv = (ALFWindowPriv*)(void*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); - if (priv != NULL) { - if (priv->vtbl && priv->vtbl->message) { - return priv->vtbl->message(priv->closure, hwnd, msg, wparam, lparam); - } else { - return ALF_DefWindowProc(hwnd, msg, wparam, lparam); - } - } else { - return DefDlgProc(hwnd, msg, wparam, lparam); - } -} - -static void -ALF_Window_Paint(ALFWindowPriv *priv, HWND hwnd, HDC dc, RECT *r) -{ - if (priv->vtbl && priv->vtbl->paint) { - priv->vtbl->paint(priv->closure, hwnd, dc, r); - } else { - ALF_FillRect(dc, r, priv->layout.bgcolor); - } -} - -LRESULT -ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); - - if (msg == WM_INITDIALOG) { - struct ALFWindow_CreateParams *params = (struct ALFWindow_CreateParams *)lparam; - - priv->vtbl = params->vtbl; - priv->closure = params->closure; - - BOOL retval = TRUE; - if (priv->vtbl && priv->vtbl->initialize) { - retval = priv->vtbl->initialize(priv->closure, hwnd); - } - - ALF_EnsureWindowBigEnough(hwnd); - - return retval; - } - - if (msg == ALF_WM_GETMODALRESULT) { - return (LRESULT)priv->modalResult; - } - if (msg == ALF_WM_SETMODALRESULT) { - priv->modalResult = (int)wparam; - return 0; - } - - if (msg == ALF_WM_GETDPI) { - return (LRESULT)priv->layout.dpi; - } - - if (msg == ALF_WM_UPDATEFONTS) { - ALF_UpdateFontsPriv(hwnd, priv); - return 0; - } - - if (msg == WM_ERASEBKGND) { - return TRUE; // handled in WM_PAINT - } - - if (msg == WM_PRINTCLIENT) { - RECT r = { 0, 0, 0, 0 }; - GetClientRect(hwnd, &r); - - ALF_Window_Paint(priv, hwnd, (HDC)wparam, &r); - return TRUE; - } - - if (msg == WM_PAINT) { - PAINTSTRUCT ps; - HDC dc = BeginPaint(hwnd, &ps); - - ALF_Window_Paint(priv, hwnd, dc, &ps.rcPaint); - - EndPaint(hwnd, &ps); - - return 0; - } - - if (msg == WM_COMMAND) { - HWND source = (HWND)lparam; - WORD code = HIWORD(wparam); - WORD id = LOWORD(wparam); - LRESULT ret = 0; - if (source != 0) - ret = SendMessage(source, 0x2000 + WM_COMMAND, wparam, lparam); - - if (ret == 0 && priv->vtbl && priv->vtbl->command) - ret = priv->vtbl->command(priv->closure, hwnd, code, id, source); - - return ret; - } - - if (msg == WM_NOTIFY) { - NMHDR *nmhdr = (NMHDR *)lparam; - LRESULT ret = 0; - - if (nmhdr->hwndFrom) - ret = SendMessage(nmhdr->hwndFrom, 0x2000 + WM_NOTIFY, wparam, lparam); - - if (ret == 0 && priv->vtbl && priv->vtbl->notify) - ret = priv->vtbl->notify(priv->closure, hwnd, wparam, nmhdr); - - return ret; - } - - if (msg == WM_DRAWITEM) { - LPDRAWITEMSTRUCT dis = (DRAWITEMSTRUCT *)lparam; - LRESULT ret = 0; - if (wparam && dis->hwndItem) { - ret = SendMessage(dis->hwndItem, 0x2000 + WM_DRAWITEM, wparam, lparam); - } - - if (ret) - return ret; - } - - if (msg == WM_CTLCOLORSTATIC) { - LRESULT ret = SendMessage((HWND)lparam, 0x2000 + WM_CTLCOLORSTATIC, wparam, lparam); - - if (ret) { - return ret; - } else { - SetBkColor((HDC)wparam, GetSysColor(COLOR_BTNFACE)); - SetTextColor((HDC)wparam, GetSysColor(COLOR_BTNTEXT)); - return (LRESULT)GetSysColorBrush(COLOR_BTNFACE); - } - } - - if (msg == WM_CTLCOLORBTN) { - LRESULT ret = SendMessage((HWND)lparam, 0x2000 + WM_CTLCOLORBTN, wparam, lparam); - - if (ret) { - return ret; - } else { - SetBkColor((HDC)wparam, GetSysColor(COLOR_BTNFACE)); - SetTextColor((HDC)wparam, GetSysColor(COLOR_BTNTEXT)); - return (LRESULT)GetSysColorBrush(COLOR_BTNFACE); - } - } - - if (msg == WM_SIZE) { - ALF_Layout_Apply(&priv->layout, hwnd); - } - - if (msg == WM_SHOWWINDOW) { - if (wparam) - ALF_Layout_Validate(&priv->layout, hwnd); - } - - if (msg == WM_GETMINMAXINFO) { - RECT tmp; - ZeroMemory(&tmp, sizeof(tmp)); - - SIZE s; - ZeroMemory(&s, sizeof(s)); - ALF_Layout_GetMinSize(&priv->layout, hwnd, &s); - - tmp.right = s.cx; - tmp.bottom = s.cy; - - if (ALF_Compat_AdjustWindowRectExForDpi( - &tmp, - (DWORD)GetWindowLong(hwnd, GWL_STYLE), - GetMenu(hwnd) != NULL, - (DWORD)GetWindowLong(hwnd, GWL_EXSTYLE), - (UINT)priv->layout.dpi)) { - MINMAXINFO *i = (MINMAXINFO *)lparam; - i->ptMinTrackSize.x = tmp.right - tmp.left; - i->ptMinTrackSize.y = tmp.bottom - tmp.top; - return 0; - } - } - - if (msg == WM_DESTROY && priv->vtbl && priv->vtbl->destroy) { - priv->vtbl->destroy(priv->closure, hwnd); - } - - if (msg == WM_CLOSE) { - if (!priv->vtbl || !priv->vtbl->close || !priv->vtbl->close(priv->closure, hwnd)) { - priv->modalResult = 2; - ShowWindow(hwnd, FALSE); - } - return TRUE; - } - - if (msg == WM_NCDESTROY) { - SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, 0); - ALF_DestroyWindowPriv(priv); - } - - if (msg == WM_DPICHANGED) { - int dpi = LOWORD(wparam); - SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts and invalidate layout - - RECT *r = (RECT*)lparam; - SetWindowPos(hwnd, NULL, r->left, r->top, r->right-r->left, r->bottom-r->top, SWP_NOACTIVATE|SWP_NOZORDER); - } - - if (msg == WM_THEMECHANGED || msg == WM_SETTINGCHANGE) { - ALF_UpdateFontsPriv(hwnd, priv); - ALF_Layout_Invalidate(&priv->layout, hwnd); - ALF_InvalidateBackground(hwnd); - InvalidateRect(hwnd, NULL, TRUE); - } - - if (msg == WM_WINDOWPOSCHANGED) { - if (priv->vtbl->windowposchanged) { - priv->vtbl->windowposchanged(priv->closure, hwnd, (WINDOWPOS *)lparam); - } - } - - LRESULT ret = 0; - if (ALF_Layout_HandleMessage(&priv->layout, hwnd, msg, wparam, lparam, &ret)) { - // if the layout was changed, our current size might be too small - if (msg == ALF_WM_VALIDATELAYOUT) { - ALF_EnsureWindowBigEnough(hwnd); - } - - if (msg == ALF_WM_DPICHANGE) { - ALF_UpdateFontsPriv(hwnd, priv); - } - - return ret; - } - - return DefDlgProc(hwnd, msg, wparam, lparam); -} - -void -ALF_RegisterWindowClass(void) -{ - WNDCLASS cls; - ZeroMemory(&cls, sizeof(cls)); - - wsprintf(_alf_windowClass, TEXT("ALFWindow.%p"), (ULONG_PTR)&_alf_windowClass[0]); - - cls.style = 0; - cls.hInstance = ALF_HINSTANCE; - cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); - cls.hbrBackground = NULL; - cls.lpszClassName = _alf_windowClass; - cls.cbWndExtra = DLGWINDOWEXTRA + sizeof(void*); - cls.cbClsExtra = 0; - cls.lpfnWndProc = ALF_WindowProc; - - ATOM classatom = RegisterClass(&cls); - if (!classatom) { - MessageBox(NULL, TEXT("FATAL: Couldn't register toplevel window class"), TEXT("DEBUG"), MB_ICONHAND|MB_OK); - } -} - -HWND -ALF_CreateToplevelWindow(HWND hwndParent, ALFWindowVTable *vtbl, void *closure) -{ -#pragma pack(push, 1) - struct { - DLGTEMPLATE t; - WCHAR s[32]; - } t; -#pragma pack(pop) - ZeroMemory(&t, sizeof(t)); - t.t.style = WS_OVERLAPPEDWINDOW; - t.t.dwExtendedStyle = 0; - t.t.x = 0; - t.t.y = 0; - t.t.cx = 10; - t.t.cy = 10; - t.t.cdit = 0; - - // NOTE: this only works because we know the window class name is all ascii - for (int i = 0; _alf_windowClass[i]; ++i) { - t.s[i+1] = _alf_windowClass[i]; - } - - struct ALFWindow_CreateParams params; - params.vtbl = vtbl; - params.closure = closure; - return CreateDialogIndirectParam(ALF_HINSTANCE, &t.t, hwndParent, ALF_Window_DlgProc, (LPARAM)¶ms); -} - - diff --git a/widgetfactory.cpp b/widgetfactory.cpp index 69d0c48..c7f5f8d 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -827,7 +827,7 @@ WinMain } } - ALFWindowVTable vtbl; + ALFToplevelVTable vtbl; ZeroMemory(&vtbl, sizeof(vtbl)); vtbl.command = handleCommand; @@ -864,7 +864,7 @@ WinMain ALF_LayoutSetRowExpandNumerator(win, 1, 1); ALF_LayoutSetColumnExpandNumerator(win, 4, 1); - ALF_SetDefaultButton(win, ID_HELLO); + ALF_Toplevel_SetDefaultButton(win, ID_HELLO); ALF_SetFocus(GetNextDlgTabItem(win, win, FALSE)); HMENU mainmenu = CreateMenu(); @@ -896,10 +896,10 @@ WinMain SetMenu(win, mainmenu); - ALF_EnsureWindowBigEnough(win); - ALF_ShowModal(win); + ALF_Toplevel_EnsureBigEnough(win); + ALF_Toplevel_ShowModal(win); - ALF_DestroyWindow(win); + DestroyWindow(win); ALF_UnInitialize(); return 0; -- cgit v1.2.3