diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-18 09:07:40 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-04-18 09:07:40 +0200 |
| commit | 4054b17c661d2e709895e8235e9dce6edaa61e4f (patch) | |
| tree | d58838d16d8547dc56eb7ff4fa0d2854d3e39c2d /alf | |
| parent | 13416486e03f9a7b52083cf6e291482a90f8e813 (diff) | |
extract toplevel window stuff into alfwindow.cpp
Diffstat (limited to 'alf')
| -rw-r--r-- | alf/alf.cpp | 427 | ||||
| -rw-r--r-- | alf/alfpriv.h | 20 | ||||
| -rw-r--r-- | alf/alfwindow.cpp | 439 |
3 files changed, 439 insertions, 447 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index fc441bf..d40522f 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -5,37 +5,6 @@ static LONG _alf_initLock = 0; static LONG _alf_initCounter = 0; -/* ALF App and Window */ - -static void -ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv, void *closure) -{ - priv->vtbl = (ALFWindowVTable*)GetClassLongPtr(hwnd, 0); - priv->closure = closure; - priv->defid = (WORD)-1; - ALF_Layout_Init(&priv->layout); -} - -static void -ALF_DestroyWindowPriv(ALFWindowPriv *priv) -{ - if (priv->vtbl->postdestroy) - priv->vtbl->postdestroy(priv->closure); - - ALF_Layout_Clear(&priv->layout); - - if (priv->fonts.hMessageFont) - DeleteObject(priv->fonts.hMessageFont); - - ALF_Free(priv); -} - -int -ALF_CentipointsToPxPriv(ALFWindowPriv *priv, int cptValue) -{ - return MulDiv(cptValue, (int)priv->fonts.dpi, 7200); -} - void ALF_UpdateFonts(HWND win) { @@ -43,302 +12,11 @@ ALF_UpdateFonts(HWND win) } void -ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv) -{ - priv->fonts.dpi = ALF_Compat_GetDpiForWindow(win); - - // XXX: SystemParametersInfoForDpi is Unicode-only and needs Vista+ NONCLIENTMETRICS, - ALF_NONCLIENTMETRICSW_VISTA ncm; - ZeroMemory(&ncm, sizeof(ncm)); - ncm.cbSize = sizeof(ncm); - - if (ALF_Compat_SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, priv->fonts.dpi)) { -#ifdef UNICODE - priv->fonts.lfMessageFont = ncm.lfMessageFont; -#else - ALF_Compat_LogFontWtoA(&ncm.lfMessageFont, &priv->fonts.lfMessageFont); -#endif - } else { - // FIXME! fallback to default font, 8pt MS Shell Dlg - ZeroMemory(&priv->fonts.lfMessageFont, sizeof(priv->fonts.lfMessageFont)); - - priv->fonts.lfMessageFont.lfHeight = -MulDiv(8, (int)priv->fonts.dpi, 72); - lstrcpy(priv->fonts.lfMessageFont.lfFaceName, TEXT("MS Shell Dlg")); - } - - if (priv->fonts.hMessageFont) { - DeleteObject(priv->fonts.hMessageFont); - } - priv->fonts.hMessageFont = CreateFontIndirect(&priv->fonts.lfMessageFont); - - SendMessage(win, WM_SETFONT, (WPARAM)priv->fonts.hMessageFont, (LPARAM)1); -} - -void ALF_InvalidateLayout(HWND hwnd) { SendMessage(hwnd, ALF_WM_INVALIDATELAYOUT, 0, 0); } -static void -ALF_ApplyFocus(HWND hwnd, ALFWindowPriv *priv, BOOL restoringFocus) -{ - if (priv->hwndFocus) { - if (!restoringFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL) - SendMessage(priv->hwndFocus, EM_SETSEL, 0, -1); - - if (GetForegroundWindow() == hwnd) { - HWND oldFocus = SetFocus(priv->hwndFocus); - - // FIXME! restore default button state - if (oldFocus && SendMessage(oldFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { - SendMessage(oldFocus, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - - if (priv->defid != (WORD)-1) { - HWND hwndOld = ALF_WidgetHwndById(hwnd, priv->defid); - if (hwndOld && SendMessage(hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { - SendMessage(hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - } - - if (priv->hwndFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { - SendMessage(priv->hwndFocus, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); - } else { - HWND hwndDef = ALF_WidgetHwndById(hwnd, priv->defid); - if (hwndDef && SendMessage(hwndDef, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { - SendMessage(hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); - } - } - } - } else { - priv->hwndFocus = GetNextDlgTabItem(hwnd, NULL, FALSE); - if (priv->hwndFocus) - ALF_ApplyFocus(hwnd, priv, FALSE); - } -} - -LRESULT -ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, 0); - - if (msg == ALF_WM_GETMODALRESULT) { - return (LRESULT)priv->modalResult; - } - if (msg == ALF_WM_SETMODALRESULT) { - priv->modalResult = (int)wparam; - return 0; - } - - if (msg == ALF_WM_CENTIPOINTTOPX) { - return (LRESULT)ALF_CentipointsToPxPriv(priv, (int)wparam); - } - - if (msg == ALF_WM_SETFOCUS) { - priv->hwndFocus = (HWND)lparam; - ALF_ApplyFocus(hwnd, priv, FALSE); - return 0; - } - - if (msg == ALF_WM_UPDATEFONTS) { - ALF_UpdateFontsPriv(hwnd, priv); - return 0; - } - - if (msg == WM_SETFONT) { - priv->font = (HFONT)wparam; - if (LOWORD(lparam) != 0) - InvalidateRect(hwnd, NULL, TRUE); - - // fallthrough to layout, will propagate font to children - } - - if (msg == WM_GETFONT) { - return (LRESULT)priv->font; - } - - if (msg == ALF_WM_PRETRANSLATEMSG) { - return (LRESULT)ALF_PreTranslateMessagePriv(hwnd, priv, (MSG *)lparam); - } - - 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->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->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_ACTIVATE) { - if (!HIWORD(wparam)) { // if !minimized - if (LOWORD(wparam)) { - ALF_ApplyFocus(hwnd, priv, TRUE); - } else { - priv->hwndFocus = GetFocus(); - - // FIXME! remove default button state - // there has to be a better way to do this - if (priv->defid != (WORD)-1) { - HWND hwndDefBtn = ALF_WidgetHwndById(hwnd, priv->defid); - if (hwndDefBtn && SendMessage(hwndDefBtn, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { - SendMessage(hwndDefBtn, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - } - - if (priv->hwndFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { - SendMessage(priv->hwndFocus, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - } - } - return 0; - } - - 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), - priv->fonts.dpi)) { - MINMAXINFO *i = (MINMAXINFO *)lparam; - i->ptMinTrackSize.x = tmp.right - tmp.left; - i->ptMinTrackSize.y = tmp.bottom - tmp.top; - return 0; - } - } - - if (msg == WM_CREATE) { - ALF_UpdateFontsPriv(hwnd, priv); - if (priv->vtbl->create) { - priv->vtbl->create(priv->closure, hwnd); - } - BOOL alwaysUnderline = FALSE; - SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &alwaysUnderline, 0); - if (!alwaysUnderline) { - SendMessage(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); - } - ALF_Layout_Apply(&priv->layout, hwnd); - } - - if (msg == WM_DESTROY && priv->vtbl->destroy) { - priv->vtbl->destroy(priv->closure, hwnd); - } - - if (msg == WM_CLOSE) { - if (!priv->vtbl->close || !priv->vtbl->close(priv->closure, hwnd)) { - priv->modalResult = 2; - ShowWindow(hwnd, FALSE); - } - return TRUE; - } - - if (msg == WM_NCDESTROY) { - SetWindowLongPtr(hwnd, 0, 0); - ALF_DestroyWindowPriv(priv); - } - - if (msg == WM_DPICHANGED) { - ALF_UpdateFontsPriv(hwnd, priv); - ALF_Layout_Invalidate(&priv->layout, hwnd); - 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); - } - - if (msg == DM_GETDEFID) { - if (priv->defid == (WORD)-1) { - return 0; - } else { - return MAKELONG(priv->defid, DC_HASDEFID); - } - } - if (msg == DM_SETDEFID) { - if (priv->defid != (WORD)-1) { - HWND hwndOld = ALF_WidgetHwndById(hwnd, priv->defid); - if (hwndOld && SendMessage(hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { - SendMessage(hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - } - - priv->defid = (WORD)wparam; - HWND hwndNew = ALF_WidgetHwndById(hwnd, priv->defid); - if (hwndNew && SendMessage(hwndNew, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { - SendMessage(hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); - } - return TRUE; - } - - 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 - // windows will call WM_GETMINMAXINFO and fix it - if (msg == ALF_WM_VALIDATELAYOUT) { - RECT r; - if (GetWindowRect(hwnd, &r)) { - SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); - } - } - - return ret; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - void ALF_AddWidget(HWND win, int x, int y, HWND widget, int minWidth, int minHeight, DWORD flags) { @@ -353,30 +31,6 @@ ALF_AddWidget(HWND win, int x, int y, HWND widget, int minWidth, int minHeight, SendMessage(win, ALF_WM_ADDWIDGET, 0, (LPARAM)¶ms); } -static LRESULT CALLBACK -ALF_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - if (msg == WM_NCCREATE) { - CREATESTRUCT *cs = (CREATESTRUCT*)(void*)lparam; - if (cs->lpCreateParams) { - ALFWindowPriv *priv = ALF_New(ALFWindowPriv, 1); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv); - ALF_InitializeWindowPriv(hwnd, priv, *((void**)cs->lpCreateParams)); - } - } - - ALFWindowPriv *priv = (ALFWindowPriv*)(void*)GetWindowLongPtr(hwnd, 0); - if (priv != NULL) { - if (priv->vtbl->message) { - return priv->vtbl->message(priv->closure, hwnd, msg, wparam, lparam); - } else { - return ALF_DefWindowProc(hwnd, msg, wparam, lparam); - } - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - void ALF_Initialize(void) { @@ -467,73 +121,6 @@ ALF_BuildUniqueName(TCHAR *buf, const TCHAR *prefix, ULONG_PTR uniquifier) buf[prefixlen + numlen] = 0; } -LPTSTR -ALF_RegisterWindowClass(HINSTANCE hInstance, const ALFWindowClassParams *params) -{ - WNDCLASS cls; - ZeroMemory(&cls, sizeof(cls)); - - ALFWindowVTable *pvtbl = ALF_New(ALFWindowVTable, 1); - *pvtbl = params->vtbl; - - const TCHAR *classNamePtr = params->className; - TCHAR classNameBuf[256]; - if (!classNamePtr) { - ZeroMemory(classNameBuf, sizeof(classNameBuf)); - classNamePtr = classNameBuf; - - ALF_BuildUniqueName(classNameBuf, TEXT("ALFWindow."), (ULONG_PTR)pvtbl); - } - - cls.style = params->classStyle; - cls.hInstance = hInstance; - cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); - cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); - cls.lpszClassName = classNamePtr; - cls.cbWndExtra = sizeof(void*); - cls.cbClsExtra = sizeof(void*); - cls.lpfnWndProc = ALF_WindowProc; - - ATOM classatom = RegisterClass(&cls); - if (!classatom) { - ALF_Free(pvtbl); - return NULL; - } - - // XXX: This could have been a HWND_MESSAGE window, but Win95 doesn't support these - HWND tmp = CreateWindowEx(0, MAKEINTATOM(classatom), TEXT("dummy"), 0, 0, 0, 0, 0, NULL, 0, hInstance, 0); - SetClassLongPtr(tmp, 0, (LONG_PTR)pvtbl); - DestroyWindow(tmp); - - return MAKEINTATOM(classatom); -} - -void -ALF_UnregisterWindowClass(HINSTANCE hinstance, LPCTSTR className) -{ - HWND tmp = CreateWindowEx(0, className, TEXT("dummy"), 0, 0, 0, 0, 0, NULL, 0, hinstance, 0); - ALFWindowVTable *pvtbl = (ALFWindowVTable*)GetClassLongPtr(tmp, 0); - DestroyWindow(tmp); - - ALF_Free(pvtbl); - - UnregisterClass(className, hinstance); -} - -HWND ALF_InstantiateWindow(HINSTANCE hinstance, LPCTSTR className, HWND hwndParent, void *closure) -{ - return CreateWindowEx(0, - className, - TEXT("Window"), - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, - 300, 100, //FIXME - hwndParent, - NULL, - hinstance, - &closure); -} - void ALF_DestroyWindow(HWND win) { @@ -546,20 +133,6 @@ ALF_PreTranslateMessage(HWND hwnd, MSG *message) return (BOOL)SendMessage(hwnd, ALF_WM_PRETRANSLATEMSG, 0, (LPARAM)message); } -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; -} - int ALF_ShowModal(HWND win) { diff --git a/alf/alfpriv.h b/alf/alfpriv.h index a145f8f..d539baf 100644 --- a/alf/alfpriv.h +++ b/alf/alfpriv.h @@ -17,31 +17,11 @@ #include "alfcompat.h" #include "alflayout.h" -typedef struct { - ALFWindowVTable *vtbl; - void *closure; - ALFWindowFonts fonts; - int modalResult; - ALFLayout layout; - WORD defid; - HWND hwndFocus; - HFONT font; -} ALFWindowPriv; - extern TCHAR *_alf_comboClass; extern TCHAR *_alf_panelClass; extern TCHAR *_alf_labelClass; extern TCHAR *_alf_notebookClass; -int -ALF_CentipointsToPxPriv(ALFWindowPriv *priv, int cptValue); - -void -ALF_UpdateFontsPriv(HWND hwnd, ALFWindowPriv *priv); - -BOOL -ALF_PreTranslateMessagePriv(HWND win, ALFWindowPriv *priv, MSG *message); - void ALF_RegisterComboClass(void); diff --git a/alf/alfwindow.cpp b/alf/alfwindow.cpp new file mode 100644 index 0000000..0b395b6 --- /dev/null +++ b/alf/alfwindow.cpp @@ -0,0 +1,439 @@ +#include "alfpriv.h" + +typedef struct { + ALFWindowVTable *vtbl; + void *closure; + ALFWindowFonts fonts; + int modalResult; + ALFLayout layout; + WORD defid; + HWND hwndFocus; + HFONT font; +} ALFWindowPriv; + +static void +ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv, void *closure) +{ + priv->vtbl = (ALFWindowVTable*)GetClassLongPtr(hwnd, 0); + priv->closure = closure; + priv->defid = (WORD)-1; + ALF_Layout_Init(&priv->layout); +} + +static void +ALF_DestroyWindowPriv(ALFWindowPriv *priv) +{ + if (priv->vtbl->postdestroy) + priv->vtbl->postdestroy(priv->closure); + + ALF_Layout_Clear(&priv->layout); + + if (priv->fonts.hMessageFont) + DeleteObject(priv->fonts.hMessageFont); + + ALF_Free(priv); +} + +static void +ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv) +{ + priv->fonts.dpi = ALF_Compat_GetDpiForWindow(win); + + // XXX: SystemParametersInfoForDpi is Unicode-only and needs Vista+ NONCLIENTMETRICS, + ALF_NONCLIENTMETRICSW_VISTA ncm; + ZeroMemory(&ncm, sizeof(ncm)); + ncm.cbSize = sizeof(ncm); + + if (ALF_Compat_SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, priv->fonts.dpi)) { +#ifdef UNICODE + priv->fonts.lfMessageFont = ncm.lfMessageFont; +#else + ALF_Compat_LogFontWtoA(&ncm.lfMessageFont, &priv->fonts.lfMessageFont); +#endif + } else { + // FIXME! fallback to default font, 8pt MS Shell Dlg + ZeroMemory(&priv->fonts.lfMessageFont, sizeof(priv->fonts.lfMessageFont)); + + priv->fonts.lfMessageFont.lfHeight = -MulDiv(8, (int)priv->fonts.dpi, 72); + lstrcpy(priv->fonts.lfMessageFont.lfFaceName, TEXT("MS Shell Dlg")); + } + + if (priv->fonts.hMessageFont) { + DeleteObject(priv->fonts.hMessageFont); + } + priv->fonts.hMessageFont = CreateFontIndirect(&priv->fonts.lfMessageFont); + + SendMessage(win, WM_SETFONT, (WPARAM)priv->fonts.hMessageFont, (LPARAM)1); +} + +static int +ALF_CentipointsToPxPriv(ALFWindowPriv *priv, int cptValue) +{ + return MulDiv(cptValue, (int)priv->fonts.dpi, 7200); +} + +static void +ALF_ApplyFocus(HWND hwnd, ALFWindowPriv *priv, BOOL restoringFocus) +{ + if (priv->hwndFocus) { + if (!restoringFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_HASSETSEL) + SendMessage(priv->hwndFocus, EM_SETSEL, 0, -1); + + if (GetForegroundWindow() == hwnd) { + HWND oldFocus = SetFocus(priv->hwndFocus); + + // FIXME! restore default button state + if (oldFocus && SendMessage(oldFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { + SendMessage(oldFocus, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + + if (priv->defid != (WORD)-1) { + HWND hwndOld = ALF_WidgetHwndById(hwnd, priv->defid); + if (hwndOld && SendMessage(hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { + SendMessage(hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + } + + if (priv->hwndFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { + SendMessage(priv->hwndFocus, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + } else { + HWND hwndDef = ALF_WidgetHwndById(hwnd, priv->defid); + if (hwndDef && SendMessage(hwndDef, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { + SendMessage(hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + } + } + } + } else { + priv->hwndFocus = GetNextDlgTabItem(hwnd, NULL, FALSE); + if (priv->hwndFocus) + ALF_ApplyFocus(hwnd, priv, FALSE); + } +} + +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; +} + +static LRESULT CALLBACK +ALF_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + if (msg == WM_NCCREATE) { + CREATESTRUCT *cs = (CREATESTRUCT*)(void*)lparam; + if (cs->lpCreateParams) { + ALFWindowPriv *priv = ALF_New(ALFWindowPriv, 1); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv); + ALF_InitializeWindowPriv(hwnd, priv, *((void**)cs->lpCreateParams)); + } + } + + ALFWindowPriv *priv = (ALFWindowPriv*)(void*)GetWindowLongPtr(hwnd, 0); + if (priv != NULL) { + if (priv->vtbl->message) { + return priv->vtbl->message(priv->closure, hwnd, msg, wparam, lparam); + } else { + return ALF_DefWindowProc(hwnd, msg, wparam, lparam); + } + } else { + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +LRESULT +ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, 0); + + if (msg == ALF_WM_GETMODALRESULT) { + return (LRESULT)priv->modalResult; + } + if (msg == ALF_WM_SETMODALRESULT) { + priv->modalResult = (int)wparam; + return 0; + } + + if (msg == ALF_WM_CENTIPOINTTOPX) { + return (LRESULT)ALF_CentipointsToPxPriv(priv, (int)wparam); + } + + if (msg == ALF_WM_SETFOCUS) { + priv->hwndFocus = (HWND)lparam; + ALF_ApplyFocus(hwnd, priv, FALSE); + return 0; + } + + if (msg == ALF_WM_UPDATEFONTS) { + ALF_UpdateFontsPriv(hwnd, priv); + return 0; + } + + if (msg == WM_SETFONT) { + priv->font = (HFONT)wparam; + if (LOWORD(lparam) != 0) + InvalidateRect(hwnd, NULL, TRUE); + + // fallthrough to layout, will propagate font to children + } + + if (msg == WM_GETFONT) { + return (LRESULT)priv->font; + } + + if (msg == ALF_WM_PRETRANSLATEMSG) { + return (LRESULT)ALF_PreTranslateMessagePriv(hwnd, priv, (MSG *)lparam); + } + + 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->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->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_ACTIVATE) { + if (!HIWORD(wparam)) { // if !minimized + if (LOWORD(wparam)) { + ALF_ApplyFocus(hwnd, priv, TRUE); + } else { + priv->hwndFocus = GetFocus(); + + // FIXME! remove default button state + // there has to be a better way to do this + if (priv->defid != (WORD)-1) { + HWND hwndDefBtn = ALF_WidgetHwndById(hwnd, priv->defid); + if (hwndDefBtn && SendMessage(hwndDefBtn, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { + SendMessage(hwndDefBtn, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + } + + if (priv->hwndFocus && SendMessage(priv->hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { + SendMessage(priv->hwndFocus, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + } + } + return 0; + } + + 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), + priv->fonts.dpi)) { + MINMAXINFO *i = (MINMAXINFO *)lparam; + i->ptMinTrackSize.x = tmp.right - tmp.left; + i->ptMinTrackSize.y = tmp.bottom - tmp.top; + return 0; + } + } + + if (msg == WM_CREATE) { + ALF_UpdateFontsPriv(hwnd, priv); + if (priv->vtbl->create) { + priv->vtbl->create(priv->closure, hwnd); + } + BOOL alwaysUnderline = FALSE; + SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &alwaysUnderline, 0); + if (!alwaysUnderline) { + SendMessage(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); + } + ALF_Layout_Apply(&priv->layout, hwnd); + } + + if (msg == WM_DESTROY && priv->vtbl->destroy) { + priv->vtbl->destroy(priv->closure, hwnd); + } + + if (msg == WM_CLOSE) { + if (!priv->vtbl->close || !priv->vtbl->close(priv->closure, hwnd)) { + priv->modalResult = 2; + ShowWindow(hwnd, FALSE); + } + return TRUE; + } + + if (msg == WM_NCDESTROY) { + SetWindowLongPtr(hwnd, 0, 0); + ALF_DestroyWindowPriv(priv); + } + + if (msg == WM_DPICHANGED) { + ALF_UpdateFontsPriv(hwnd, priv); + ALF_Layout_Invalidate(&priv->layout, hwnd); + 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); + } + + if (msg == DM_GETDEFID) { + if (priv->defid == (WORD)-1) { + return 0; + } else { + return MAKELONG(priv->defid, DC_HASDEFID); + } + } + if (msg == DM_SETDEFID) { + if (priv->defid != (WORD)-1) { + HWND hwndOld = ALF_WidgetHwndById(hwnd, priv->defid); + if (hwndOld && SendMessage(hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) { + SendMessage(hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + } + + priv->defid = (WORD)wparam; + HWND hwndNew = ALF_WidgetHwndById(hwnd, priv->defid); + if (hwndNew && SendMessage(hwndNew, WM_GETDLGCODE, 0, 0) & DLGC_UNDEFPUSHBUTTON) { + SendMessage(hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + } + return TRUE; + } + + 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 + // windows will call WM_GETMINMAXINFO and fix it + if (msg == ALF_WM_VALIDATELAYOUT) { + RECT r; + if (GetWindowRect(hwnd, &r)) { + SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + } + } + + return ret; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +LPTSTR +ALF_RegisterWindowClass(HINSTANCE hInstance, const ALFWindowClassParams *params) +{ + WNDCLASS cls; + ZeroMemory(&cls, sizeof(cls)); + + ALFWindowVTable *pvtbl = ALF_New(ALFWindowVTable, 1); + *pvtbl = params->vtbl; + + const TCHAR *classNamePtr = params->className; + TCHAR classNameBuf[256]; + if (!classNamePtr) { + ZeroMemory(classNameBuf, sizeof(classNameBuf)); + classNamePtr = classNameBuf; + + ALF_BuildUniqueName(classNameBuf, TEXT("ALFWindow."), (ULONG_PTR)pvtbl); + } + + cls.style = params->classStyle; + cls.hInstance = hInstance; + cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); + cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); + cls.lpszClassName = classNamePtr; + cls.cbWndExtra = sizeof(void*); + cls.cbClsExtra = sizeof(void*); + cls.lpfnWndProc = ALF_WindowProc; + + ATOM classatom = RegisterClass(&cls); + if (!classatom) { + ALF_Free(pvtbl); + return NULL; + } + + // XXX: This could have been a HWND_MESSAGE window, but Win95 doesn't support these + HWND tmp = CreateWindowEx(0, MAKEINTATOM(classatom), TEXT("dummy"), 0, 0, 0, 0, 0, NULL, 0, hInstance, 0); + SetClassLongPtr(tmp, 0, (LONG_PTR)pvtbl); + DestroyWindow(tmp); + + return MAKEINTATOM(classatom); +} + +void +ALF_UnregisterWindowClass(HINSTANCE hinstance, LPCTSTR className) +{ + HWND tmp = CreateWindowEx(0, className, TEXT("dummy"), 0, 0, 0, 0, 0, NULL, 0, hinstance, 0); + ALFWindowVTable *pvtbl = (ALFWindowVTable*)GetClassLongPtr(tmp, 0); + DestroyWindow(tmp); + + ALF_Free(pvtbl); + + UnregisterClass(className, hinstance); +} + +HWND ALF_InstantiateWindow(HINSTANCE hinstance, LPCTSTR className, HWND hwndParent, void *closure) +{ + return CreateWindowEx(0, + className, + TEXT("Window"), + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + CW_USEDEFAULT, CW_USEDEFAULT, + 300, 100, //FIXME + hwndParent, + NULL, + hinstance, + &closure); +} + + |
