From d1be0b5dce72a3bc355e915916955b1a9a267c47 Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Mon, 25 May 2020 21:13:07 +0200 Subject: toplevel window: make it a dialog when you're reimplementing parts of the dialog manager, might as well just use the real thing --- alf/alfwindow.cpp | 289 +++++++++++++++++------------------------------------- 1 file changed, 88 insertions(+), 201 deletions(-) (limited to 'alf/alfwindow.cpp') diff --git a/alf/alfwindow.cpp b/alf/alfwindow.cpp index c33a2b4..8e765ea 100644 --- a/alf/alfwindow.cpp +++ b/alf/alfwindow.cpp @@ -5,19 +5,28 @@ typedef struct { void *closure; int modalResult; ALFLayout layout; - WORD defid; HWND hwndFocus; HFONT hMessageFont; + WORD defid; } ALFWindowPriv; +struct ALFWindow_CreateParams{ + ALFWindowVTable *vtbl; + void *closure; +}; + +TCHAR _alf_windowClass[28] = {0}; + static void -ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv, void *closure) +ALF_InitializeWindowPriv(HWND hwnd, ALFWindowPriv *priv, struct ALFWindow_CreateParams *params) { - priv->vtbl = (ALFWindowVTable*)GetClassLongPtr(hwnd, 0); - priv->closure = closure; - priv->defid = (WORD)-1; + (void)hwnd; + + priv->vtbl = params->vtbl; + priv->closure = params->closure; ALF_Layout_Init(&priv->layout); priv->layout.bgcolor = ALF_COLOR_SYS(COLOR_BTNFACE); + priv->defid = IDOK; } static void @@ -68,86 +77,8 @@ ALF_UpdateFontsPriv(HWND win, ALFWindowPriv *priv) SendMessage(win, WM_SETFONT, (WPARAM)priv->hMessageFont, (LPARAM)1); } -static BOOL CALLBACK -ALF_Window_RemoveDefButton_EnumChildProc(HWND hwnd, LPARAM lParam) -{ - HWND keeper = (HWND)lParam; - if (hwnd != keeper && (SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) { - SendMessage(hwnd, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); - } - - return TRUE; -} - -static void -ALF_Window_RemoveDefButton(HWND hwnd, ALFWindowPriv *priv, HWND keeper) -{ - (void)priv; - - EnumChildWindows(hwnd, ALF_Window_RemoveDefButton_EnumChildProc, (LPARAM)keeper); -} - -static void -ALF_Window_FixDefButton(HWND hwnd, ALFWindowPriv *priv, HWND prevFocus, HWND currFocus, BOOL force) -{ - LRESULT prevCode = prevFocus ? SendMessage(prevFocus, WM_GETDLGCODE, 0, 0) : 0; - LRESULT currCode = currFocus ? SendMessage(currFocus, WM_GETDLGCODE, 0, 0) : 0; - - // speed hack: only do something if the focus moves from or to a defaultable button - if (!force && !(prevFocus && (prevCode & (DLGC_DEFPUSHBUTTON|DLGC_UNDEFPUSHBUTTON))) - && !(currFocus && (currCode & (DLGC_DEFPUSHBUTTON|DLGC_UNDEFPUSHBUTTON)))) - return; - - // find the target for the new default button - HWND newDefBtn = NULL; - LRESULT newDefCode = 0; - if (currFocus && (currCode & (DLGC_DEFPUSHBUTTON|DLGC_UNDEFPUSHBUTTON))) { - newDefBtn = currFocus; - newDefCode = currCode; - } else { - WORD defid = priv->defid != (WORD)-1 ? priv->defid : IDOK; - HWND defhwnd = ALF_WidgetHwndById(hwnd, defid); - if (defhwnd) { - newDefCode = SendMessage(defhwnd, WM_GETDLGCODE, 0, 0); - if (newDefCode & (DLGC_DEFPUSHBUTTON|DLGC_UNDEFPUSHBUTTON)) - newDefBtn = defhwnd; - } - } - - // speed hack: stop here if the target button is already default - // there is supposed to be exactly one default button - if (!force && newDefBtn && (newDefCode & DLGC_DEFPUSHBUTTON)) - return; - // remove default button style from all other buttons - ALF_Window_RemoveDefButton(hwnd, priv, newDefBtn); - - // apply default button style to the new def btn - if (newDefBtn && (newDefCode & DLGC_UNDEFPUSHBUTTON)) { - SendMessage(newDefBtn, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); - } -} - -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); - - ALF_Window_FixDefButton(hwnd, priv, oldFocus, priv->hwndFocus, FALSE); - } - } else { - priv->hwndFocus = GetNextDlgTabItem(hwnd, NULL, FALSE); - if (priv->hwndFocus) - ALF_ApplyFocus(hwnd, priv, FALSE); - } -} - -static BOOL +/*static BOOL ALF_PreTranslateMessagePriv(HWND win, ALFWindowPriv *priv, MSG *message) { BOOL ret = FALSE; @@ -159,21 +90,48 @@ ALF_PreTranslateMessagePriv(HWND win, ALFWindowPriv *priv, MSG *message) ret = IsDialogMessage(win, message); return ret; +}*/ + +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_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)); + if (msg == WM_INITDIALOG) { + struct ALFWindow_CreateParams *params = (struct ALFWindow_CreateParams *)lparam; + + ALFWindowPriv *priv = ALF_New(ALFWindowPriv, 1); + SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, (LONG_PTR)priv); + ALF_InitializeWindowPriv(hwnd, priv, params); + + int dpi = (int)ALF_Compat_GetDpiForWindow(hwnd); + SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts + + if (priv->vtbl && priv->vtbl->create) { + priv->vtbl->create(priv->closure, hwnd); } + + // FIXME! still necessary? + /*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); } - ALFWindowPriv *priv = (ALFWindowPriv*)(void*)GetWindowLongPtr(hwnd, 0); + ALFWindowPriv *priv = (ALFWindowPriv*)(void*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); if (priv != NULL) { if (priv->vtbl->message) { return priv->vtbl->message(priv->closure, hwnd, msg, wparam, lparam); @@ -181,7 +139,7 @@ ALF_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return ALF_DefWindowProc(hwnd, msg, wparam, lparam); } } else { - return DefWindowProc(hwnd, msg, wparam, lparam); + return DefDlgProc(hwnd, msg, wparam, lparam); } } @@ -198,7 +156,7 @@ ALF_Window_Paint(ALFWindowPriv *priv, HWND hwnd, HDC dc, RECT *r) LRESULT ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, 0); + ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(hwnd, DLGWINDOWEXTRA); if (msg == ALF_WM_GETMODALRESULT) { return (LRESULT)priv->modalResult; @@ -212,12 +170,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return (LRESULT)priv->layout.dpi; } - 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; @@ -246,10 +198,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return 0; } - 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); @@ -312,19 +260,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } } - if (msg == WM_ACTIVATE) { - if (!HIWORD(wparam)) { // if !minimized - if (LOWORD(wparam)) { - ALF_ApplyFocus(hwnd, priv, TRUE); - } else { - priv->hwndFocus = GetFocus(); - - ALF_Window_RemoveDefButton(hwnd, priv, NULL); - } - } - return 0; - } - if (msg == WM_SIZE) { ALF_Layout_Apply(&priv->layout, hwnd); } @@ -358,21 +293,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } } - if (msg == WM_CREATE) { - int dpi = (int)ALF_Compat_GetDpiForWindow(hwnd); - SendMessage(hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)dpi); // will also update fonts - - 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); } @@ -386,7 +306,7 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == WM_NCDESTROY) { - SetWindowLongPtr(hwnd, 0, 0); + SetWindowLongPtr(hwnd, DLGWINDOWEXTRA, 0); ALF_DestroyWindowPriv(priv); } @@ -405,24 +325,6 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) InvalidateRect(hwnd, NULL, TRUE); } - if (msg == DM_GETDEFID) { - if (priv->defid == (WORD)-1) { - return 0; - } else { - return MAKELONG(priv->defid, DC_HASDEFID); - } - } - if (msg == DM_SETDEFID) { - WORD newdefid = (WORD)wparam; - if (newdefid != priv->defid) { - priv->defid = newdefid; - - if (GetForegroundWindow() == hwnd) - ALF_Window_FixDefButton(hwnd, priv, NULL, GetFocus(), TRUE); - } - return TRUE; - } - if (msg == WM_WINDOWPOSCHANGED) { if (priv->vtbl->windowposchanged) { priv->vtbl->windowposchanged(priv->closure, hwnd, (WINDOWPOS *)lparam); @@ -447,74 +349,59 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return ret; } - return DefWindowProc(hwnd, msg, wparam, lparam); + return DefDlgProc(hwnd, msg, wparam, lparam); } -LPTSTR -ALF_RegisterWindowClass(HINSTANCE hInstance, const ALFWindowClassParams *params) +void +ALF_RegisterWindowClass(void) { WNDCLASS cls; ZeroMemory(&cls, sizeof(cls)); - ALFWindowVTable *pvtbl = ALF_New(ALFWindowVTable, 1); - *pvtbl = params->vtbl; + ALF_BuildUniqueName(_alf_windowClass, TEXT("ALFWindow."), (ULONG_PTR)&_alf_windowClass); - 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.style = 0; + cls.hInstance = ALF_HINSTANCE; cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); cls.hbrBackground = NULL; - cls.lpszClassName = classNamePtr; - cls.cbWndExtra = sizeof(void*); - cls.cbClsExtra = sizeof(void*); + cls.lpszClassName = _alf_windowClass; + cls.cbWndExtra = DLGWINDOWEXTRA + sizeof(void*); + cls.cbClsExtra = 0; cls.lpfnWndProc = ALF_WindowProc; ATOM classatom = RegisterClass(&cls); if (!classatom) { - ALF_Free(pvtbl); - return NULL; + MessageBox(NULL, TEXT("FATAL: Couldn't register toplevel window class"), TEXT("DEBUG"), MB_ICONHAND|MB_OK); } - - // 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) +HWND +ALF_CreateToplevelWindow(HWND hwndParent, ALFWindowVTable *vtbl, void *closure) { - return CreateWindowEx(0, - className, - TEXT("Window"), - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, - 300, 100, //FIXME - hwndParent, - NULL, - hinstance, - &closure); +#pragma pack(push, 1) + struct { + DLGTEMPLATE t; + WCHAR s[32]; + } t; +#pragma pack(pop) + ZeroMemory(&t, sizeof(t)); + t.t.style = WS_OVERLAPPEDWINDOW | DS_CENTER; + t.t.dwExtendedStyle = 0; + t.t.x = 0; + t.t.y = 0; + t.t.cx = 200; + t.t.cy = 80; + 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); } -- cgit v1.2.3