user32: Windows doesn't send the initialization messages to a dialog if a passed in dlgProc is NULL

Dmitry Timoshkov dmitry at codeweavers.com
Tue May 8 03:47:41 CDT 2007


Hello,

as reported in the bug 8314 Windows doesn't always send WM_INITDIALOG from
inside of CreateDialogParam. An investigation shows that Windows doesn't
send the initialization messages to a dialog if a passed in dlgProc is NULL,
and the app depends on that.

Changelog:
    user32: Windows doesn't send the initialization messages to a dialog
    if a passed in dlgProc is NULL.

---
 dlls/user32/dialog.c          |   17 ++++---
 dlls/user32/tests/msg.c       |  104 ++++++++++++++++++++++++++++++++++++++++-
 dlls/user32/tests/resource.rc |    8 +++
 3 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c
index 3acd37a..ad729d0 100644
--- a/dlls/user32/dialog.c
+++ b/dlls/user32/dialog.c
@@ -651,7 +651,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
     if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
     else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
 
-    if (dlgInfo->hUserFont)
+    if (dlgProc && dlgInfo->hUserFont)
         SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
 
     /* Create controls */
@@ -660,13 +660,16 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
     {
         /* Send initialisation messages and set focus */
 
-        if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ) &&
-            ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
+        if (dlgProc)
         {
-            /* By returning TRUE, app has requested a default focus assignment */
-            dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
-            if( dlgInfo->hwndFocus )
-                SetFocus( dlgInfo->hwndFocus );
+            if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ) &&
+                ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
+            {
+                /* By returning TRUE, app has requested a default focus assignment */
+                dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
+                if( dlgInfo->hwndFocus )
+                    SetFocus( dlgInfo->hwndFocus );
+            }
         }
 
         if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index a6daf82..b40f678 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -207,7 +207,7 @@ static const struct message WmSWP_ResizeNoZOrder[] = {
     { WM_NCCALCSIZE, sent|wparam, 1 },
     { WM_NCPAINT, sent },
     { WM_GETTEXT, sent|defwinproc|optional },
-    { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
+    { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */
     { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE },
     { WM_SIZE, sent|defwinproc|wparam, 0 },
     { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
@@ -6321,6 +6321,7 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
 	    !lstrcmpiA(buf, "my_button_class") ||
 	    !lstrcmpiA(buf, "my_edit_class") ||
 	    !lstrcmpiA(buf, "static") ||
+	    !lstrcmpiA(buf, "MyDialogClass") ||
 	    !lstrcmpiA(buf, "#32770"))
 	{
 	    struct message msg;
@@ -6367,6 +6368,7 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
 	    !lstrcmpiA(buf, "my_button_class") ||
 	    !lstrcmpiA(buf, "my_edit_class") ||
 	    !lstrcmpiA(buf, "static") ||
+	    !lstrcmpiA(buf, "MyDialogClass") ||
 	    !lstrcmpiA(buf, "#32770"))
 	{
 	    struct message msg;
@@ -8874,6 +8876,56 @@ static void test_ShowWindow(void)
     DestroyWindow(hwnd);
 }
 
+static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    struct message msg;
+
+    trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    switch (message)
+    {
+    case WM_WINDOWPOSCHANGING:
+    case WM_WINDOWPOSCHANGED:
+    {
+        WINDOWPOS *winpos = (WINDOWPOS *)lParam;
+
+        trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
+        trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+              winpos->hwnd, winpos->hwndInsertAfter,
+              winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+        dump_winpos_flags(winpos->flags);
+
+        /* Log only documented flags, win2k uses 0x1000 and 0x2000
+         * in the high word for internal purposes
+         */
+        wParam = winpos->flags & 0xffff;
+        /* We are not interested in the flags that don't match under XP and Win9x */
+        wParam &= ~(SWP_NOZORDER);
+        break;
+    }
+
+    /* explicitly ignore WM_GETICON message */
+    case WM_GETICON:
+        return 0;
+    }
+
+    msg.message = message;
+    msg.flags = sent|wparam|lparam;
+    msg.wParam = wParam;
+    msg.lParam = lParam;
+    add_message(&msg);
+
+    /* calling DefDlgProc leads to a recursion under XP */
+
+    switch (message)
+    {
+    case WM_INITDIALOG:
+    case WM_GETDLGCODE:
+        return 0;
+    }
+    return 1;
+}
+
 static const struct message WmDefDlgSetFocus_1[] = {
     { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 },
     { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */
@@ -8898,11 +8950,39 @@ static const struct message WmDefDlgSetFocus_2[] = {
     { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */
     { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */
     { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */
+    { WM_CTLCOLOREDIT, sent|optional }, /* XP */
+    { 0 }
+};
+/* Creation of a dialog */
+static const struct message WmCreateDialogParamSeq_1[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_SIZE, sent|wparam, SIZE_RESTORED },
+    { WM_MOVE, sent },
+    { WM_SETFONT, sent },
+    { WM_INITDIALOG, sent },
+    { WM_CHANGEUISTATE, sent|optional },
+    { 0 }
+};
+/* Creation of a dialog */
+static const struct message WmCreateDialogParamSeq_2[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_SIZE, sent|wparam, SIZE_RESTORED },
+    { WM_MOVE, sent },
+    { WM_CHANGEUISTATE, sent|optional },
     { 0 }
 };
 
 static void test_dialog_messages(void)
 {
+    WNDCLASS cls;
     HWND hdlg, hedit1, hedit2, hfocus;
     LRESULT ret;
 
@@ -8973,9 +9053,31 @@ static void test_dialog_messages(void)
     check_selection(hedit2, 0, 3);
 
     EndDialog(hdlg, 0);
+    flush_sequence();
 
 #undef set_selection
 #undef check_selection
+
+    ok(GetClassInfo(0, "#32770", &cls), "GetClassInfo failed\n");
+    cls.lpszClassName = "MyDialogClass";
+    cls.hInstance = GetModuleHandle(0);
+    /* need a cast since a dlgproc is used as a wndproc */
+    cls.lpfnWndProc = (WNDPROC)test_dlg_proc;
+    if (!RegisterClass(&cls)) assert(0);
+
+    hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0);
+    ok(IsWindow(hdlg), "CreateDialogParam failed\n");
+    ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE);
+    EndDialog(hdlg, 0);
+    flush_sequence();
+
+    hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0);
+    ok(IsWindow(hdlg), "CreateDialogParam failed\n");
+    ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE);
+    EndDialog(hdlg, 0);
+    flush_sequence();
+
+    UnregisterClass(cls.lpszClassName, cls.hInstance);
 }
 
 static void test_nullCallback(void)
diff --git a/dlls/user32/tests/resource.rc b/dlls/user32/tests/resource.rc
index 8434f61..47328fc 100644
--- a/dlls/user32/tests/resource.rc
+++ b/dlls/user32/tests/resource.rc
@@ -72,6 +72,14 @@ FONT 8, "MS Shell Dlg"
 {
 }
 
+CLASS_TEST_DIALOG_2 DIALOG DISCARDABLE  0, 0, 100, 100
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "CreateDialogParams Test"
+CLASS "MyDialogClass"
+FONT 8, "MS Shell Dlg"
+{
+}
+
 FOCUS_TEST_DIALOG DIALOG DISCARDABLE 0, 0, 60, 30
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CONTROL
 CAPTION "Test dialog"
-- 
1.5.1.3






More information about the wine-patches mailing list