1 /* Unit test suite for the dialog functions. 2 * 3 * Copyright 2004 Bill Medland 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 * 19 * 20 * 21 * This test suite currently works by building a quite complex hierarchy of 22 * objects in a variety of styles and then performs a limited number of tests 23 * for the previous and next dialog group or tab items. 24 * 25 * The test specifically does not test all possibilities at this time since 26 * there are several cases where the Windows behaviour is rather strange and 27 * significant work would be required to get the Wine code to duplicate the 28 * strangeness, especially since most are in situations that would not 29 * normally be met. 30 */ 31 32 #ifndef __REACTOS__ 33 #define WINVER 0x0600 /* For NONCLIENTMETRICS with padding */ 34 #endif 35 36 #include <assert.h> 37 #include <stdio.h> 38 #include <stdarg.h> 39 40 #include "wine/test.h" 41 #include "windef.h" 42 #include "winbase.h" 43 #include "wingdi.h" 44 #include "winuser.h" 45 #include "winnls.h" 46 47 #define MAXHWNDS 1024 48 static HWND hwnd [MAXHWNDS]; 49 static unsigned int numwnds=1; /* 0 is reserved for null */ 50 51 /* Global handles */ 52 static HINSTANCE g_hinst; /* This application's HINSTANCE */ 53 static HWND g_hwndMain, g_hwndButton1, g_hwndButton2, g_hwndButtonCancel; 54 static HWND g_hwndTestDlg, g_hwndTestDlgBut1, g_hwndTestDlgBut2, g_hwndTestDlgEdit; 55 static HWND g_hwndInitialFocusT1, g_hwndInitialFocusT2, g_hwndInitialFocusGroupBox; 56 57 static LONG g_styleInitialFocusT1, g_styleInitialFocusT2; 58 static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand; 59 60 static BOOL g_terminated; 61 static BOOL g_button1Clicked; 62 63 typedef struct { 64 INT_PTR id; 65 int parent; 66 DWORD style; 67 DWORD exstyle; 68 } h_entry; 69 70 static const h_entry hierarchy [] = { 71 /* 0 is reserved for the null window */ 72 { 1, 0, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE}, 73 { 20, 1, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 74 { 2, 1, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT}, 75 { 60, 2, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 76 /* What happens with groups when the parent is disabled */ 77 { 8, 2, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, WS_EX_CONTROLPARENT}, 78 { 85, 8, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUP, 0}, 79 { 9, 8, WS_CHILD, WS_EX_CONTROLPARENT}, 80 { 86, 9, WS_CHILD | WS_VISIBLE, 0}, 81 { 87, 9, WS_CHILD | WS_VISIBLE, 0}, 82 { 31, 8, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 83 { 10, 2, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT}, 84 { 88, 10, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 85 { 11, 10, WS_CHILD, WS_EX_CONTROLPARENT}, 86 { 89, 11, WS_CHILD | WS_VISIBLE, 0}, 87 { 32, 11, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 88 { 90, 11, WS_CHILD | WS_VISIBLE, 0}, 89 { 33, 10, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 90 { 21, 2, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 91 { 61, 2, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 92 { 3, 1, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0}, 93 { 22, 3, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 94 { 62, 3, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 95 { 7, 3, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT}, 96 { 4, 7, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0}, 97 { 83, 4, WS_CHILD | WS_VISIBLE, 0}, 98 { 5, 4, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0}, 99 /* A couple of controls around the main dialog */ 100 { 29, 5, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 101 { 81, 5, WS_CHILD | WS_VISIBLE, 0}, 102 /* The main dialog with lots of controls */ 103 { 6, 5, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT}, 104 /* At the start of a dialog */ 105 /* Disabled controls are skipped */ 106 { 63, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0}, 107 /* Invisible controls are skipped */ 108 { 64, 6, WS_CHILD | WS_TABSTOP, 0}, 109 /* Invisible disabled controls are skipped */ 110 { 65, 6, WS_CHILD | WS_DISABLED | WS_TABSTOP, 0}, 111 /* Non-tabstop controls are skipped for tabs but not for groups */ 112 { 66, 6, WS_CHILD | WS_VISIBLE, 0}, 113 /* End of first group, with no tabstops in it */ 114 { 23, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 115 /* At last a tabstop */ 116 { 67, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 117 /* A group that is totally disabled or invisible */ 118 { 24, 6, WS_CHILD | WS_DISABLED | WS_GROUP, 0}, 119 { 68, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0}, 120 { 69, 6, WS_CHILD | WS_TABSTOP, 0}, 121 /* A valid group in the middle of the dialog (not the first nor last group*/ 122 { 25, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 123 /* A non-tabstop item will be skipped for tabs */ 124 { 70, 6, WS_CHILD | WS_VISIBLE, 0}, 125 /* A disabled item will be skipped for tabs and groups */ 126 { 71, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0}, 127 /* A valid item will be found for tabs and groups */ 128 { 72, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 129 /* A disabled item to skip when looking for the next group item */ 130 { 73, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0}, 131 /* The next group begins with an enabled visible label */ 132 { 26, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 133 { 74, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 134 { 75, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 135 /* That group is terminated by a disabled label */ 136 { 27, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_GROUP, 0}, 137 { 76, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 138 { 77, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 139 /* That group is terminated by an invisible label */ 140 { 28, 6, WS_CHILD | WS_GROUP, 0}, 141 /* The end of the dialog with item for loop and recursion testing */ 142 { 78, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 143 /* No tabstop so skipped for prev tab, but found for prev group */ 144 { 79, 6, WS_CHILD | WS_VISIBLE, 0}, 145 { 80, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0}, 146 /* A couple of controls after the main dialog */ 147 { 82, 5, WS_CHILD | WS_VISIBLE, 0}, 148 { 30, 5, WS_CHILD | WS_VISIBLE | WS_GROUP, 0}, 149 /* And around them */ 150 { 84, 4, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0}, 151 {0, 0, 0, 0} 152 }; 153 154 static DWORD get_button_style(HWND button) 155 { 156 return GetWindowLongW(button, GWL_STYLE) & BS_TYPEMASK; 157 } 158 159 static BOOL CreateWindows (HINSTANCE hinst) 160 { 161 const h_entry *p = hierarchy; 162 163 while (p->id != 0) 164 { 165 DWORD style, exstyle; 166 char ctrlname[16]; 167 168 /* Basically assert that the hierarchy is valid and track the 169 * maximum control number 170 */ 171 if (p->id >= numwnds) 172 { 173 if (p->id >= ARRAY_SIZE(hwnd)) 174 { 175 trace ("Control %ld is out of range\n", p->id); 176 return FALSE; 177 } 178 else 179 numwnds = p->id+1; 180 } 181 if (p->id <= 0) 182 { 183 trace ("Control %ld is out of range\n", p->id); 184 return FALSE; 185 } 186 if (hwnd[p->id] != 0) 187 { 188 trace ("Control %ld is used more than once\n", p->id); 189 return FALSE; 190 } 191 192 /* Create the control */ 193 sprintf (ctrlname, "ctrl%4.4ld", p->id); 194 hwnd[p->id] = CreateWindowExA(p->exstyle, p->parent ? "static" : "GetNextDlgItemWindowClass", ctrlname, p->style, 10, 10, 10, 10, hwnd[p->parent], p->parent ? (HMENU) (2000 + p->id) : 0, hinst, 0); 195 if (!hwnd[p->id]) 196 { 197 trace ("Failed to create control %ld\n", p->id); 198 return FALSE; 199 } 200 201 /* Check that the styles are as we specified (except the main one 202 * which is quite frequently messed up). If this keeps breaking then 203 * we could mask out the bits that don't concern us. 204 */ 205 if (p->parent) 206 { 207 style = GetWindowLongA(hwnd[p->id], GWL_STYLE); 208 exstyle = GetWindowLongA(hwnd[p->id], GWL_EXSTYLE); 209 if (style != p->style || exstyle != p->exstyle) 210 { 211 trace ("Style mismatch at %ld: %8.8x %8.8x cf %8.8x %8.8x\n", p->id, style, exstyle, p->style, p->exstyle); 212 } 213 } 214 p++; 215 } 216 217 return TRUE; 218 } 219 220 /* Form the lParam of a WM_KEYDOWN message */ 221 static DWORD KeyDownData (int repeat, int scancode, int extended, int wasdown) 222 { 223 return ((repeat & 0x0000FFFF) | ((scancode & 0x00FF) << 16) | 224 (extended ? 0x01000000 : 0) | (wasdown ? 0x40000000 : 0)); 225 } 226 227 /* Form a WM_KEYDOWN VK_TAB message to the specified window */ 228 static void FormTabMsg (MSG *pMsg, HWND hwnd) 229 { 230 pMsg->hwnd = hwnd; 231 pMsg->message = WM_KEYDOWN; 232 pMsg->wParam = VK_TAB; 233 pMsg->lParam = KeyDownData (1, 0x0F, 0, 0); 234 /* pMsg->time is not set. It shouldn't be needed */ 235 /* pMsg->pt is ignored */ 236 } 237 238 /* Form a WM_KEYDOWN VK_RETURN message to the specified window */ 239 static void FormEnterMsg (MSG *pMsg, HWND hwnd) 240 { 241 pMsg->hwnd = hwnd; 242 pMsg->message = WM_KEYDOWN; 243 pMsg->wParam = VK_RETURN; 244 pMsg->lParam = KeyDownData (1, 0x1C, 0, 0); 245 /* pMsg->time is not set. It shouldn't be needed */ 246 /* pMsg->pt is ignored */ 247 } 248 249 /*********************************************************************** 250 * 251 * The actual tests 252 */ 253 254 typedef struct 255 { 256 int isok; /* or is it todo */ 257 int test; 258 int dlg; 259 int ctl; 260 int tab; 261 int prev; 262 int res; 263 } test_record; 264 265 static int id (HWND h) 266 { 267 unsigned int i; 268 for (i = 0; i < numwnds; i++) 269 if (hwnd[i] == h) 270 return i; 271 return -1; 272 } 273 274 /* Tests 275 * 276 * Tests 1-8 test the hCtl argument of null or the dialog itself. 277 * 278 * 1. Prev Group of null is null 279 * 2. Prev Tab of null is null 280 * 3. Prev Group of hDlg in hDlg is null 281 * 4. Prev Tab of hDlg in hDlg is null 282 * 5. Next Group of null is first visible enabled child 283 * Check it skips invisible, disabled and both. 284 * 6. Next Tab of null is first visible enabled tabstop 285 * Check it skips invisible, disabled, nontabstop, and in combination. 286 * 7. Next Group of hDlg in hDlg is as of null 287 * 8. Next Tab of hDlg in hDlg is as of null 288 * 289 * Tests 9-14 test descent 290 * 291 * 9. DS_CONTROL does not result in descending the hierarchy for Tab Next 292 * 10. DS_CONTROL does not result in descending the hierarchy for Group Next 293 * 11. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Next 294 * 12. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Next 295 * 13. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Prev 296 * 14. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Prev 297 * 298 * Tests 15-24 are the basic Prev/Next Group tests 299 * 300 * 15. Next Group of a visible enabled non-group control is the next visible 301 * enabled non-group control, if there is one before the next group 302 * 16. Next Group of a visible enabled non-group control wraps around to the 303 * beginning of the group on finding a control that starts another group. 304 * Note that the group is in the middle of the dialog. 305 * 17. As 16 except note that the next group is started with a disabled 306 * visible control. 307 * 18. As 16 except note that the next group is started with an invisible 308 * enabled control. 309 * 19. Next Group wraps around the controls of the dialog 310 * 20. Next Group is the same even if the initial control is disabled. 311 * 21. Next Group is the same even if the initial control is invisible. 312 * 22. Next Group is the same even if the initial control has the group style 313 * 23. Next Group returns the initial control if there is no visible enabled 314 * control in the group. (Initial control disabled and not group style). 315 * 24. Prev version of test 16. 316 * Prev Group of a visible enabled non-group control wraps around to the 317 * beginning of the group on finding a control that starts the group. 318 * Note that the group is in the middle of the dialog. 319 * 320 * In tests 25 to 28 the control is sitting under dialogs which do not have 321 * the WS_EX_CONTROLPARENT style and so cannot be reached from the top of 322 * the dialog. 323 * 324 * 25. Next Group of an inaccessible control is as if it were accessible 325 * 26. Prev Group of an inaccessible control begins searching at the highest 326 * level ancestor that did not permit recursion down the hierarchy 327 * 27. Next Tab of an inaccessible control is as if it were accessible 328 * 28. Prev Tab of an inaccessible control begins searching at the highest 329 * level ancestor that did not permit recursion down the hierarchy. 330 * 331 * Tests 29- are the basic Tab tests 332 * 333 * 29. Next Tab of a control is the next visible enabled control with the 334 * Tabstop style (N.B. skips disabled, invisible and non-tabstop) 335 * 30. Prev Tab of a control is the previous visible enabled control with the 336 * Tabstop style (N.B. skips disabled, invisible and non-tabstop) 337 * 31. Next Tab test with at least two layers of descent and finding the 338 * result not at the first control. 339 * 32. Next Tab test with at least two layers of descent with the descent and 340 * control at the start of each level. 341 * 33. Prev Tab test with at least two layers of descent and finding the 342 * result not at the last control. 343 * 34. Prev Tab test with at least two layers of descent with the descent and 344 * control at the end of each level. 345 * 346 * 35. Passing NULL may result in the first child being the one returned. 347 * (group test) 348 * 36. Passing NULL may result in the first child being the one returned. 349 * (tab test) 350 */ 351 352 static void test_GetNextDlgItem(void) 353 { 354 static test_record test [] = 355 { 356 /* isok test dlg ctl tab prev res */ 357 358 { 1, 1, 6, 0, 0, 1, 0}, 359 { 1, 2, 6, 0, 1, 1, 0}, 360 { 1, 3, 6, 6, 0, 1, 0}, 361 { 1, 4, 6, 6, 1, 1, 0}, 362 { 1, 5, 6, 0, 0, 0, 66}, 363 { 1, 6, 6, 0, 1, 0, 67}, 364 { 1, 7, 6, 6, 0, 0, 66}, 365 { 1, 8, 6, 6, 1, 0, 67}, 366 367 { 1, 9, 4, 83, 1, 0, 84}, 368 { 1, 10, 4, 83, 0, 0, 5}, 369 { 1, 11, 5, 81, 1, 0, 67}, 370 { 1, 12, 5, 81, 0, 0, 66}, 371 { 1, 13, 5, 82, 1, 1, 78}, 372 373 { 1, 14, 5, 82, 0, 1, 79}, 374 { 1, 15, 6, 70, 0, 0, 72}, 375 { 1, 16, 6, 72, 0, 0, 25}, 376 { 1, 17, 6, 75, 0, 0, 26}, 377 { 1, 18, 6, 77, 0, 0, 76}, 378 { 1, 19, 6, 79, 0, 0, 66}, 379 { 1, 20, 6, 71, 0, 0, 72}, 380 { 1, 21, 6, 64, 0, 0, 66}, 381 382 { 1, 22, 6, 25, 0, 0, 70}, 383 { 1, 23, 6, 68, 0, 0, 68}, 384 { 1, 24, 6, 25, 0, 1, 72}, 385 { 1, 25, 1, 70, 0, 0, 72}, 386 /*{ 0, 26, 1, 70, 0, 1, 3}, Crashes Win95*/ 387 { 1, 27, 1, 70, 1, 0, 72}, 388 /*{ 0, 28, 1, 70, 1, 1, 61}, Crashes Win95*/ 389 390 { 1, 29, 6, 67, 1, 0, 72}, 391 { 1, 30, 6, 72, 1, 1, 67}, 392 393 { 1, 35, 2, 0, 0, 0, 60}, 394 { 1, 36, 2, 0, 1, 0, 60}, 395 396 { 0, 0, 0, 0, 0, 0, 0} /* End of test */ 397 }; 398 const test_record *p = test; 399 400 ok (CreateWindows (g_hinst), "Could not create test windows\n"); 401 402 while (p->dlg) 403 { 404 HWND a; 405 a = (p->tab ? GetNextDlgTabItem : GetNextDlgGroupItem) (hwnd[p->dlg], hwnd[p->ctl], p->prev); 406 todo_wine_if (!p->isok) 407 ok (a == hwnd[p->res], "Test %d: %s %s item of %d in %d was %d instead of %d\n", p->test, p->prev ? "Prev" : "Next", p->tab ? "Tab" : "Group", p->ctl, p->dlg, id(a), p->res); 408 p++; 409 } 410 } 411 412 /* 413 * OnMainWindowCreate 414 */ 415 static BOOL OnMainWindowCreate(HWND hwnd, LPCREATESTRUCTA lpcs) 416 { 417 g_hwndButton1 = CreateWindowA("button", "Button &1", 418 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON | BS_TEXT, 419 10, 10, 80, 80, hwnd, (HMENU)100, g_hinst, 0); 420 if (!g_hwndButton1) return FALSE; 421 422 g_hwndButton2 = CreateWindowA("button", "Button &2", 423 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT, 424 110, 10, 80, 80, hwnd, (HMENU)200, g_hinst, 0); 425 if (!g_hwndButton2) return FALSE; 426 427 g_hwndButtonCancel = CreateWindowA("button", "Cancel", 428 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT, 429 210, 10, 80, 80, hwnd, (HMENU)IDCANCEL, g_hinst, 0); 430 if (!g_hwndButtonCancel) return FALSE; 431 432 return TRUE; 433 } 434 435 436 /* 437 * OnTestDlgCreate 438 */ 439 440 static BOOL OnTestDlgCreate (HWND hwnd, LPCREATESTRUCTA lpcs) 441 { 442 g_hwndTestDlgEdit = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | 443 WS_EX_RIGHTSCROLLBAR | WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE, 444 "Edit", "Edit", 445 WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL, 446 16,33,184,24, hwnd, (HMENU)101, g_hinst, 0); 447 if (!g_hwndTestDlgEdit) return FALSE; 448 449 g_hwndTestDlgBut1 = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR 450 | WS_EX_NOPARENTNOTIFY, 451 "button", "Button &1", 452 WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT, 453 204,33,30,24, hwnd, (HMENU)201, g_hinst, 0); 454 if (!g_hwndTestDlgBut1) return FALSE; 455 456 g_hwndTestDlgBut2 = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR 457 | WS_EX_NOPARENTNOTIFY, "button", 458 "Button &2", 459 WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT, 460 90,102,80,24, hwnd, (HMENU)IDCANCEL, g_hinst, 0); 461 if (!g_hwndTestDlgBut2) return FALSE; 462 463 return TRUE; 464 } 465 466 static LRESULT CALLBACK main_window_procA (HWND hwnd, UINT uiMsg, WPARAM wParam, 467 LPARAM lParam) 468 { 469 switch (uiMsg) 470 { 471 /* Add blank case statements for these to ensure we don't use them 472 * by mistake. 473 */ 474 case DM_GETDEFID: break; 475 case DM_SETDEFID: break; 476 477 case WM_CREATE: 478 return (OnMainWindowCreate (hwnd, 479 (LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1); 480 case WM_COMMAND: 481 if (wParam == IDCANCEL) 482 { 483 g_terminated = TRUE; 484 return 0; 485 } 486 else if ((wParam == 100 || wParam == 0xFFFF) && lParam) 487 { 488 g_button1Clicked = TRUE; 489 } 490 break; 491 } 492 493 return DefWindowProcA (hwnd, uiMsg, wParam, lParam); 494 } 495 496 static LRESULT CALLBACK disabled_test_proc (HWND hwnd, UINT uiMsg, 497 WPARAM wParam, LPARAM lParam) 498 { 499 switch (uiMsg) 500 { 501 case WM_INITDIALOG: 502 { 503 DWORD dw; 504 HWND hwndOk; 505 506 dw = SendMessageA(hwnd, DM_GETDEFID, 0, 0); 507 assert(DC_HASDEFID == HIWORD(dw)); 508 hwndOk = GetDlgItem(hwnd, LOWORD(dw)); 509 assert(hwndOk); 510 EnableWindow(hwndOk, FALSE); 511 512 PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0); 513 PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0); 514 break; 515 } 516 case WM_COMMAND: 517 if (wParam == IDOK) 518 { 519 g_terminated = TRUE; 520 EndDialog(hwnd, 0); 521 return 0; 522 } 523 else if (wParam == IDCANCEL) 524 { 525 EndDialog(hwnd, 0); 526 return 0; 527 } 528 break; 529 } 530 531 return DefWindowProcA (hwnd, uiMsg, wParam, lParam); 532 } 533 534 static LRESULT CALLBACK testDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam, 535 LPARAM lParam) 536 { 537 switch (uiMsg) 538 { 539 /* Add blank case statements for these to ensure we don't use them 540 * by mistake. 541 */ 542 case DM_GETDEFID: break; 543 case DM_SETDEFID: break; 544 545 case WM_CREATE: 546 return (OnTestDlgCreate (hwnd, 547 (LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1); 548 case WM_COMMAND: 549 if(LOWORD(wParam) == 300) g_bReceivedCommand = TRUE; 550 } 551 552 return DefDlgProcA (hwnd, uiMsg, wParam, lParam); 553 } 554 555 static LRESULT CALLBACK test_control_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 556 { 557 switch(msg) 558 { 559 case WM_CREATE: 560 { 561 static const short sample[] = { 10,1,2,3,4,5 }; 562 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; 563 short *data = cs->lpCreateParams; 564 ok(!memcmp(data, sample, sizeof(sample)), "data mismatch: %d,%d,%d,%d,%d\n", data[0], data[1], data[2], data[3], data[4]); 565 } 566 return 0; 567 568 default: 569 break; 570 } 571 572 return DefWindowProcA(hwnd, msg, wparam, lparam); 573 } 574 575 static BOOL RegisterWindowClasses (void) 576 { 577 WNDCLASSA cls; 578 579 cls.style = 0; 580 cls.lpfnWndProc = DefWindowProcA; 581 cls.cbClsExtra = 0; 582 cls.cbWndExtra = 0; 583 cls.hInstance = g_hinst; 584 cls.hIcon = NULL; 585 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW); 586 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 587 cls.lpszMenuName = NULL; 588 cls.lpszClassName = "GetNextDlgItemWindowClass"; 589 590 if (!RegisterClassA (&cls)) return FALSE; 591 592 cls.lpfnWndProc = main_window_procA; 593 cls.lpszClassName = "IsDialogMessageWindowClass"; 594 if (!RegisterClassA (&cls)) return FALSE; 595 596 cls.lpfnWndProc = test_control_procA; 597 cls.lpszClassName = "TESTCONTROL"; 598 if (!RegisterClassA (&cls)) return FALSE; 599 600 GetClassInfoA(0, "#32770", &cls); 601 cls.lpfnWndProc = testDlgWinProc; 602 cls.lpszClassName = "WM_NEXTDLGCTLWndClass"; 603 if (!RegisterClassA (&cls)) return FALSE; 604 605 return TRUE; 606 } 607 608 static void test_WM_NEXTDLGCTL(void) 609 { 610 HWND child1, child2, child3; 611 MSG msg; 612 DWORD dwVal; 613 614 g_hwndTestDlg = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR 615 | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW, 616 "WM_NEXTDLGCTLWndClass", 617 "WM_NEXTDLGCTL Message test window", 618 WS_POPUPWINDOW | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_OVERLAPPED | 619 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK | DS_SETFONT | DS_MODALFRAME, 620 0, 0, 235, 135, 621 NULL, NULL, g_hinst, 0); 622 623 assert (g_hwndTestDlg); 624 assert (g_hwndTestDlgBut1); 625 assert (g_hwndTestDlgBut2); 626 assert (g_hwndTestDlgEdit); 627 628 /* 629 * Test message DM_SETDEFID 630 */ 631 632 DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, IDCANCEL, 0 ); 633 DefDlgProcA( g_hwndTestDlgBut1, BM_SETSTYLE, BS_DEFPUSHBUTTON, FALSE ); 634 dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0); 635 636 ok ( IDCANCEL == (LOWORD(dwVal)), "Did not set default ID\n" ); 637 638 /* 639 * Check whether message WM_NEXTDLGCTL is changing the focus to next control and if 640 * the destination control is a button, style of the button should be changed to 641 * BS_DEFPUSHBUTTON with out making it default. 642 */ 643 644 /* Keep the focus on Edit control. */ 645 SetFocus(g_hwndTestDlgEdit); 646 ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n"); 647 648 /* Test message WM_NEXTDLGCTL */ 649 DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0); 650 ok((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n"); 651 652 /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */ 653 dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0); 654 ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n"); 655 656 /* 657 * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and 658 * the style of default button changed to BS_PUSHBUTTON. 659 */ 660 ok(get_button_style(g_hwndTestDlgBut1) == BS_DEFPUSHBUTTON, "Button1's style not set to BS_DEFPUSHBUTTON"); 661 ok(get_button_style(g_hwndTestDlgBut2) == BS_PUSHBUTTON, "Button2's style not set to BS_PUSHBUTTON"); 662 663 /* Move focus to Button2 using "WM_NEXTDLGCTL" */ 664 DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0); 665 ok((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n"); 666 667 /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */ 668 dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0); 669 ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n"); 670 671 /* 672 * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and 673 * the style of button which lost the focus changed to BS_PUSHBUTTON. 674 */ 675 ok(get_button_style(g_hwndTestDlgBut1) == BS_PUSHBUTTON, "Button1's style not set to BS_PUSHBUTTON"); 676 ok(get_button_style(g_hwndTestDlgBut2) == BS_DEFPUSHBUTTON, "Button2's style not set to BS_DEFPUSHBUTTON"); 677 678 /* Move focus to Edit control using "WM_NEXTDLGCTL" */ 679 DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0); 680 ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n"); 681 682 /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */ 683 dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0); 684 ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n"); 685 686 /* test nested default buttons */ 687 688 child1 = CreateWindowA("button", "child1", WS_VISIBLE|WS_CHILD, 0, 0, 50, 50, 689 g_hwndTestDlg, (HMENU)100, g_hinst, NULL); 690 ok(child1 != NULL, "failed to create first child\n"); 691 child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 60, 60, 30, 30, 692 g_hwndTestDlg, (HMENU)200, g_hinst, NULL); 693 ok(child2 != NULL, "failed to create second child\n"); 694 /* create nested child */ 695 child3 = CreateWindowA("button", "child3", WS_VISIBLE|WS_CHILD, 10, 10, 10, 10, 696 child1, (HMENU)300, g_hinst, NULL); 697 ok(child3 != NULL, "failed to create subchild\n"); 698 699 DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 200, 0); 700 dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0); 701 ok(LOWORD(dwVal) == 200, "expected 200, got %x\n", dwVal); 702 703 DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 300, 0); 704 dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0); 705 ok(LOWORD(dwVal) == 300, "expected 300, got %x\n", dwVal); 706 ok(SendMessageW( child3, WM_GETDLGCODE, 0, 0) != DLGC_DEFPUSHBUTTON, 707 "expected child3 not to be marked as DLGC_DEFPUSHBUTTON\n"); 708 709 g_bReceivedCommand = FALSE; 710 FormEnterMsg (&msg, child3); 711 ok(IsDialogMessageA(g_hwndTestDlg, &msg), "Did not handle the ENTER\n"); 712 ok(g_bReceivedCommand, "Did not trigger the default Button action\n"); 713 714 DestroyWindow(child3); 715 DestroyWindow(child2); 716 DestroyWindow(child1); 717 DestroyWindow(g_hwndTestDlg); 718 } 719 720 static LRESULT CALLBACK hook_proc(INT code, WPARAM wParam, LPARAM lParam) 721 { 722 ok(0, "unexpected hook called, code %d\n", code); 723 return CallNextHookEx(NULL, code, wParam, lParam); 724 } 725 726 static BOOL g_MSGF_DIALOGBOX; 727 static LRESULT CALLBACK hook_proc2(INT code, WPARAM wParam, LPARAM lParam) 728 { 729 ok(code == MSGF_DIALOGBOX, "unexpected hook called, code %d\n", code); 730 g_MSGF_DIALOGBOX = code == MSGF_DIALOGBOX; 731 return CallNextHookEx(NULL, code, wParam, lParam); 732 } 733 734 static void test_IsDialogMessage(void) 735 { 736 HHOOK hook; 737 MSG msg; 738 739 g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass", 740 WS_OVERLAPPEDWINDOW, 741 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 742 NULL, NULL, g_hinst, 0); 743 744 assert (g_hwndMain); 745 assert (g_hwndButton1); 746 assert (g_hwndButtonCancel); 747 748 if (0) 749 { 750 /* crashes on Windows */ 751 IsDialogMessageA(NULL, NULL); 752 IsDialogMessageA(g_hwndMain, NULL); 753 } 754 755 /* The focus should initially be nowhere. The first TAB should take it 756 * to the first button. The second TAB should take it to the Cancel 757 * button. 758 */ 759 760 /* valid window, invalid message window */ 761 hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc2, NULL, GetCurrentThreadId()); 762 FormTabMsg (&msg, (HWND)0xbeefbeef); 763 ok (!IsDialogMessageA(g_hwndMain, &msg), "expected failure\n"); 764 ok(g_MSGF_DIALOGBOX, "hook wasn't called\n"); 765 g_MSGF_DIALOGBOX = FALSE; 766 UnhookWindowsHookEx(hook); 767 768 hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId()); 769 FormTabMsg (&msg, g_hwndMain); 770 771 ok (!IsDialogMessageA(NULL, &msg), "expected failure\n"); 772 ok (!IsDialogMessageA((HWND)0xbeefbeef, &msg), "expected failure\n"); 773 774 UnhookWindowsHookEx(hook); 775 776 ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle first TAB\n"); 777 ok ((GetFocus() == g_hwndButton1), "Focus did not move to first button\n"); 778 FormTabMsg (&msg, g_hwndButton1); 779 ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle second TAB\n"); 780 ok ((GetFocus() == g_hwndButtonCancel), 781 "Focus did not move to cancel button\n"); 782 FormEnterMsg (&msg, g_hwndButtonCancel); 783 ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n"); 784 ok (g_terminated, "ENTER did not terminate\n"); 785 786 /* matching but invalid window handles, NULL */ 787 hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId()); 788 789 FormTabMsg (&msg, NULL); 790 ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n"); 791 792 /* matching but invalid window handles, not NULL */ 793 FormTabMsg (&msg, (HWND)0xbeefbeef); 794 ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n"); 795 796 UnhookWindowsHookEx(hook); 797 DestroyWindow(g_hwndMain); 798 799 g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass", WS_OVERLAPPEDWINDOW, 800 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hinst, 0); 801 SetFocus(g_hwndButton1); 802 g_button1Clicked = FALSE; 803 FormEnterMsg(&msg, g_hwndButton1); 804 ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n"); 805 ok(g_button1Clicked, "Did not receive button 1 click notification\n"); 806 807 g_button1Clicked = FALSE; 808 FormEnterMsg(&msg, g_hwndMain); 809 ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n"); 810 ok(g_button1Clicked, "Did not receive button 1 click notification\n"); 811 812 g_button1Clicked = FALSE; 813 FormEnterMsg(&msg, g_hwndButton2); 814 ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n"); 815 ok(g_button1Clicked, "Did not receive button 1 click notification\n"); 816 817 /* Button with id larger than 0xFFFF should also work */ 818 g_button1Clicked = FALSE; 819 FormEnterMsg(&msg, g_hwndMain); 820 SetWindowLongPtrW(g_hwndButton1, GWLP_ID, 0x1FFFF); 821 ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n"); 822 ok(g_button1Clicked, "Did not receive button 1 click notification\n"); 823 824 DestroyWindow(g_hwndMain); 825 } 826 827 828 static INT_PTR CALLBACK delayFocusDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam, 829 LPARAM lParam) 830 { 831 switch (uiMsg) 832 { 833 case WM_INITDIALOG: 834 g_hwndMain = hDlg; 835 g_hwndInitialFocusGroupBox = GetDlgItem(hDlg,100); 836 g_hwndButton1 = GetDlgItem(hDlg,200); 837 g_hwndButton2 = GetDlgItem(hDlg,201); 838 g_hwndButtonCancel = GetDlgItem(hDlg,IDCANCEL); 839 g_styleInitialFocusT1 = GetWindowLongA(g_hwndInitialFocusGroupBox, GWL_STYLE); 840 841 /* Initially check the second radio button */ 842 SendMessageA(g_hwndButton1, BM_SETCHECK, BST_UNCHECKED, 0); 843 SendMessageA(g_hwndButton2, BM_SETCHECK, BST_CHECKED , 0); 844 /* Continue testing after dialog initialization */ 845 PostMessageA(hDlg, WM_USER, 0, 0); 846 return g_bInitialFocusInitDlgResult; 847 848 case WM_COMMAND: 849 if (LOWORD(wParam) == IDCANCEL) 850 { 851 EndDialog(hDlg, LOWORD(wParam)); 852 return TRUE; 853 } 854 return FALSE; 855 856 case WM_USER: 857 g_styleInitialFocusT2 = GetWindowLongA(hDlg, GWL_STYLE); 858 g_hwndInitialFocusT1 = GetFocus(); 859 SetFocus(hDlg); 860 g_hwndInitialFocusT2 = GetFocus(); 861 PostMessageA(hDlg, WM_COMMAND, IDCANCEL, 0); 862 return TRUE; 863 } 864 865 return FALSE; 866 } 867 868 static INT_PTR CALLBACK focusDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam, 869 LPARAM lParam) 870 { 871 switch (uiMsg) 872 { 873 case WM_INITDIALOG: 874 SetWindowTextA(GetDlgItem(hDlg, 200), "new caption"); 875 return TRUE; 876 877 case WM_COMMAND: 878 if (LOWORD(wParam) == 200) 879 { 880 if (HIWORD(wParam) == EN_SETFOCUS) 881 g_hwndInitialFocusT1 = (HWND)lParam; 882 } 883 return FALSE; 884 } 885 886 return FALSE; 887 } 888 889 static INT_PTR CALLBACK EmptyProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 890 { 891 switch(uMsg) { 892 case WM_INITDIALOG: 893 return TRUE; 894 } 895 return FALSE; 896 } 897 898 static INT_PTR CALLBACK focusChildDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam, 899 LPARAM lParam) 900 { 901 static HWND hChildDlg; 902 903 switch (uiMsg) 904 { 905 case WM_INITDIALOG: 906 { 907 RECT rectHwnd; 908 struct { 909 DLGTEMPLATE tmplate; 910 WORD menu,class,title; 911 } temp; 912 913 SetFocus( GetDlgItem(hwnd, 200) ); 914 915 GetClientRect(hwnd,&rectHwnd); 916 temp.tmplate.style = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | DS_CONTROL | DS_3DLOOK; 917 temp.tmplate.dwExtendedStyle = 0; 918 temp.tmplate.cdit = 0; 919 temp.tmplate.x = 0; 920 temp.tmplate.y = 0; 921 temp.tmplate.cx = 0; 922 temp.tmplate.cy = 0; 923 temp.menu = temp.class = temp.title = 0; 924 925 hChildDlg = CreateDialogIndirectParamA(g_hinst, &temp.tmplate, 926 hwnd, (DLGPROC)EmptyProcUserTemplate, 0); 927 ok(hChildDlg != 0, "Failed to create test dialog.\n"); 928 929 return FALSE; 930 } 931 case WM_CLOSE: 932 DestroyWindow(hChildDlg); 933 return TRUE; 934 } 935 936 return FALSE; 937 } 938 939 /* Helper for InitialFocusTest */ 940 static const char * GetHwndString(HWND hw) 941 { 942 if (hw == NULL) 943 return "a null handle"; 944 if (hw == g_hwndMain) 945 return "the dialog handle"; 946 if (hw == g_hwndInitialFocusGroupBox) 947 return "the group box control"; 948 if (hw == g_hwndButton1) 949 return "the first button"; 950 if (hw == g_hwndButton2) 951 return "the second button"; 952 if (hw == g_hwndButtonCancel) 953 return "the cancel button"; 954 955 return "unknown handle"; 956 } 957 958 static void test_focus(void) 959 { 960 /* Test 1: 961 * This test intentionally returns FALSE in response to WM_INITDIALOG 962 * without setting focus to a control. This is what MFC's CFormView does. 963 * 964 * Since the WM_INITDIALOG handler returns FALSE without setting the focus, 965 * the focus should initially be NULL. Later, when we manually set focus to 966 * the dialog, the default handler should set focus to the first control that 967 * is "visible, not disabled, and has the WS_TABSTOP style" (MSDN). Because the 968 * second radio button has been checked, it should be the first control 969 * that meets these criteria and should receive the focus. 970 */ 971 972 g_bInitialFocusInitDlgResult = FALSE; 973 g_hwndInitialFocusT1 = (HWND) -1; 974 g_hwndInitialFocusT2 = (HWND) -1; 975 g_styleInitialFocusT1 = -1; 976 g_styleInitialFocusT2 = -1; 977 978 DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, delayFocusDlgWinProc); 979 980 ok (((g_styleInitialFocusT1 & WS_TABSTOP) == 0), 981 "Error in wrc - Detected WS_TABSTOP as default style for GROUPBOX\n"); 982 983 ok (((g_styleInitialFocusT2 & WS_VISIBLE) == 0), 984 "Modal dialogs should not be shown until the message queue first goes empty\n"); 985 986 ok ((g_hwndInitialFocusT1 == NULL), 987 "Error in initial focus when WM_INITDIALOG returned FALSE: " 988 "Expected NULL focus, got %s (%p).\n", 989 GetHwndString(g_hwndInitialFocusT1), g_hwndInitialFocusT1); 990 991 ok ((g_hwndInitialFocusT2 == g_hwndButton2), 992 "Error after first SetFocus() when WM_INITDIALOG returned FALSE: " 993 "Expected the second button (%p), got %s (%p).\n", 994 g_hwndButton2, GetHwndString(g_hwndInitialFocusT2), 995 g_hwndInitialFocusT2); 996 997 /* Test 2: 998 * This is the same as above, except WM_INITDIALOG is made to return TRUE. 999 * This should cause the focus to go to the second radio button right away 1000 * and stay there (until the user indicates otherwise). 1001 */ 1002 1003 g_bInitialFocusInitDlgResult = TRUE; 1004 g_hwndInitialFocusT1 = (HWND) -1; 1005 g_hwndInitialFocusT2 = (HWND) -1; 1006 g_styleInitialFocusT1 = -1; 1007 g_styleInitialFocusT2 = -1; 1008 1009 DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, delayFocusDlgWinProc); 1010 1011 ok ((g_hwndInitialFocusT1 == g_hwndButton2), 1012 "Error in initial focus when WM_INITDIALOG returned TRUE: " 1013 "Expected the second button (%p), got %s (%p).\n", 1014 g_hwndButton2, GetHwndString(g_hwndInitialFocusT1), 1015 g_hwndInitialFocusT1); 1016 1017 ok ((g_hwndInitialFocusT2 == g_hwndButton2), 1018 "Error after first SetFocus() when WM_INITDIALOG returned TRUE: " 1019 "Expected the second button (%p), got %s (%p).\n", 1020 g_hwndButton2, GetHwndString(g_hwndInitialFocusT2), 1021 g_hwndInitialFocusT2); 1022 1023 /* Test 3: 1024 * If the dialog has DS_CONTROL and it's not visible then we shouldn't change focus */ 1025 { 1026 HWND hDlg; 1027 HRSRC hResource; 1028 HANDLE hTemplate; 1029 DLGTEMPLATE* pTemplate; 1030 HWND hTextbox; 1031 DWORD selectionStart = 0xdead, selectionEnd = 0xbeef; 1032 1033 hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG", (LPCSTR)RT_DIALOG); 1034 hTemplate = LoadResource(g_hinst, hResource); 1035 pTemplate = LockResource(hTemplate); 1036 1037 g_hwndInitialFocusT1 = 0; 1038 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0); 1039 ok (hDlg != 0, "Failed to create test dialog.\n"); 1040 1041 ok ((g_hwndInitialFocusT1 == 0), 1042 "Focus should not be set for an invisible DS_CONTROL dialog %p.\n", g_hwndInitialFocusT1); 1043 1044 /* Also make sure that WM_SETFOCUS selects the textbox's text */ 1045 hTextbox = GetDlgItem(hDlg, 200); 1046 SendMessageA(hTextbox, WM_SETTEXT, 0, (LPARAM)"Hello world"); 1047 1048 SendMessageA(hDlg, WM_SETFOCUS, 0, 0); 1049 SendMessageA(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd); 1050 ok(selectionStart == 0 && selectionEnd == 11, "Text selection after WM_SETFOCUS is [%i, %i) expected [0, 11)\n", selectionStart, selectionEnd); 1051 1052 /* but WM_ACTIVATE does not */ 1053 SendMessageA(hTextbox, EM_SETSEL, 0, 0); 1054 SendMessageA(hDlg, WM_ACTIVATE, WA_ACTIVE, 0); 1055 SendMessageA(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd); 1056 ok(selectionStart == 0 && selectionEnd == 0, "Text selection after WM_ACTIVATE is [%i, %i) expected [0, 0)\n", selectionStart, selectionEnd); 1057 1058 DestroyWindow(hDlg); 1059 } 1060 1061 /* Test 4: 1062 * If the dialog has no tab-accessible controls, set focus to first control */ 1063 { 1064 HWND hDlg; 1065 HRSRC hResource; 1066 HANDLE hTemplate; 1067 DLGTEMPLATE* pTemplate; 1068 HWND hLabel; 1069 1070 hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_2", (LPCSTR)RT_DIALOG); 1071 hTemplate = LoadResource(g_hinst, hResource); 1072 pTemplate = LockResource(hTemplate); 1073 1074 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0); 1075 ok(hDlg != 0, "Failed to create test dialog.\n"); 1076 hLabel = GetDlgItem(hDlg, 200); 1077 1078 ok(GetFocus() == hLabel, "Focus not set to label, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel); 1079 1080 DestroyWindow(hDlg); 1081 1082 /* Also check focus after WM_ACTIVATE and WM_SETFOCUS */ 1083 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, NULL, 0); 1084 ok(hDlg != 0, "Failed to create test dialog.\n"); 1085 hLabel = GetDlgItem(hDlg, 200); 1086 1087 SetFocus(NULL); 1088 SendMessageA(hDlg, WM_ACTIVATE, WA_ACTIVE, 0); 1089 ok(GetFocus() == NULL, "Focus set on WM_ACTIVATE, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel); 1090 1091 SetFocus(NULL); 1092 SendMessageA(hDlg, WM_SETFOCUS, 0, 0); 1093 ok(GetFocus() == hLabel, "Focus not set to label on WM_SETFOCUS, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel); 1094 1095 DestroyWindow(hDlg); 1096 } 1097 1098 /* Test 5: 1099 * Select textbox's text on creation */ 1100 { 1101 HWND hDlg; 1102 HRSRC hResource; 1103 HANDLE hTemplate; 1104 DLGTEMPLATE* pTemplate; 1105 HWND edit; 1106 DWORD selectionStart = 0xdead, selectionEnd = 0xbeef; 1107 1108 hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG); 1109 hTemplate = LoadResource(g_hinst, hResource); 1110 pTemplate = LockResource(hTemplate); 1111 1112 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0); 1113 ok(hDlg != 0, "Failed to create test dialog.\n"); 1114 edit = GetDlgItem(hDlg, 200); 1115 1116 ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n", 1117 GetFocus(), hDlg, edit); 1118 SendMessageA(edit, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd); 1119 ok(selectionStart == 0 && selectionEnd == 11, 1120 "Text selection after WM_SETFOCUS is [%i, %i) expected [0, 11)\n", 1121 selectionStart, selectionEnd); 1122 1123 DestroyWindow(hDlg); 1124 } 1125 1126 /* Test 6: 1127 * Select textbox's text on creation when WM_INITDIALOG creates a child dialog. */ 1128 { 1129 HWND hDlg; 1130 HRSRC hResource; 1131 HANDLE hTemplate; 1132 DLGTEMPLATE* pTemplate; 1133 HWND edit; 1134 1135 hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG); 1136 hTemplate = LoadResource(g_hinst, hResource); 1137 pTemplate = LockResource(hTemplate); 1138 1139 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusChildDlgWinProc, 0); 1140 ok(hDlg != 0, "Failed to create test dialog.\n"); 1141 edit = GetDlgItem(hDlg, 200); 1142 1143 ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n", 1144 GetFocus(), hDlg, edit); 1145 1146 DestroyWindow(hDlg); 1147 } 1148 } 1149 1150 static void test_GetDlgItemText(void) 1151 { 1152 char string[64]; 1153 BOOL ret; 1154 1155 strcpy(string, "Overwrite Me"); 1156 ret = GetDlgItemTextA(NULL, 0, string, ARRAY_SIZE(string)); 1157 ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n"); 1158 1159 ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")), 1160 "string retrieved using GetDlgItemText should have been NULL terminated\n"); 1161 } 1162 1163 static INT_PTR CALLBACK getdlgitem_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1164 { 1165 if (msg == WM_INITDIALOG) 1166 { 1167 char text[64]; 1168 LONG_PTR val; 1169 HWND hwnd; 1170 BOOL ret; 1171 1172 hwnd = GetDlgItem(hdlg, -1); 1173 ok(hwnd != NULL, "Expected dialog item.\n"); 1174 1175 *text = 0; 1176 ret = GetDlgItemTextA(hdlg, -1, text, ARRAY_SIZE(text)); 1177 ok(ret && !strcmp(text, "Text1"), "Unexpected item text.\n"); 1178 1179 val = GetWindowLongA(hwnd, GWLP_ID); 1180 ok(val == -1, "Unexpected id.\n"); 1181 1182 val = GetWindowLongPtrA(hwnd, GWLP_ID); 1183 ok(val == -1, "Unexpected id %ld.\n", val); 1184 1185 hwnd = GetDlgItem(hdlg, -2); 1186 ok(hwnd != NULL, "Expected dialog item.\n"); 1187 1188 val = GetWindowLongA(hwnd, GWLP_ID); 1189 ok(val == -2, "Unexpected id.\n"); 1190 1191 val = GetWindowLongPtrA(hwnd, GWLP_ID); 1192 ok(val == -2, "Unexpected id %ld.\n", val); 1193 1194 EndDialog(hdlg, 0xdead); 1195 } 1196 1197 return FALSE; 1198 } 1199 1200 static void test_GetDlgItem(void) 1201 { 1202 HWND hwnd, child1, child2, hwnd2; 1203 INT_PTR retval; 1204 BOOL ret; 1205 1206 hwnd = CreateWindowA("button", "parent", WS_VISIBLE, 0, 0, 100, 100, NULL, 0, g_hinst, NULL); 1207 ok(hwnd != NULL, "failed to created window\n"); 1208 1209 /* created with the same ID */ 1210 child1 = CreateWindowA("button", "child1", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, hwnd, 0, g_hinst, NULL); 1211 ok(child1 != NULL, "failed to create first child\n"); 1212 child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, hwnd, 0, g_hinst, NULL); 1213 ok(child2 != NULL, "failed to create second child\n"); 1214 1215 hwnd2 = GetDlgItem(hwnd, 0); 1216 ok(hwnd2 == child1, "expected first child, got %p\n", hwnd2); 1217 1218 hwnd2 = GetTopWindow(hwnd); 1219 ok(hwnd2 == child1, "expected first child to be top, got %p\n", hwnd2); 1220 1221 ret = SetWindowPos(child1, child2, 0, 0, 0, 0, SWP_NOMOVE); 1222 ok(ret, "got %d\n", ret); 1223 hwnd2 = GetTopWindow(hwnd); 1224 ok(hwnd2 == child2, "expected second child to be top, got %p\n", hwnd2); 1225 1226 /* top window from child list is picked */ 1227 hwnd2 = GetDlgItem(hwnd, 0); 1228 ok(hwnd2 == child2, "expected second child, got %p\n", hwnd2); 1229 1230 /* Now test how GetDlgItem searches */ 1231 DestroyWindow(child2); 1232 child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, child1, 0, g_hinst, NULL); 1233 ok(child2 != NULL, "failed to create second child\n"); 1234 1235 /* give child2 an ID */ 1236 SetWindowLongA(child2, GWLP_ID, 100); 1237 1238 hwnd2 = GetDlgItem(hwnd, 100); 1239 ok(!hwnd2, "expected child to not be found, got %p\n", hwnd2); 1240 1241 /* make the ID of child2 public with a WS_EX_CONTROLPARENT parent */ 1242 SetWindowLongA(child1, GWL_EXSTYLE, WS_EX_CONTROLPARENT); 1243 1244 hwnd2 = GetDlgItem(hwnd, 100); 1245 ok(!hwnd2, "expected child to not be found, got %p\n", hwnd2); 1246 1247 DestroyWindow(child1); 1248 DestroyWindow(child2); 1249 DestroyWindow(hwnd); 1250 1251 retval = DialogBoxParamA(g_hinst, "GETDLGITEM_TEST_DIALOG", NULL, getdlgitem_test_dialog_proc, 0); 1252 ok(retval == 0xdead, "Unexpected return value.\n"); 1253 } 1254 1255 static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg, 1256 WPARAM wParam, LPARAM lParam) 1257 { 1258 if (uiMsg == WM_INITDIALOG) 1259 { 1260 DestroyWindow(hDlg); 1261 return TRUE; 1262 } 1263 return FALSE; 1264 } 1265 1266 static INT_PTR CALLBACK DestroyOnCloseDlgWinProc (HWND hDlg, UINT uiMsg, 1267 WPARAM wParam, LPARAM lParam) 1268 { 1269 switch (uiMsg) 1270 { 1271 case WM_INITDIALOG: 1272 PostMessageA(hDlg, WM_CLOSE, 0, 0); 1273 return TRUE; 1274 case WM_CLOSE: 1275 DestroyWindow(hDlg); 1276 return TRUE; 1277 case WM_DESTROY: 1278 PostQuitMessage(0); 1279 return TRUE; 1280 } 1281 return FALSE; 1282 } 1283 1284 static INT_PTR CALLBACK TestInitDialogHandleProc (HWND hDlg, UINT uiMsg, 1285 WPARAM wParam, LPARAM lParam) 1286 { 1287 if (uiMsg == WM_INITDIALOG) 1288 { 1289 HWND expected = GetNextDlgTabItem(hDlg, NULL, FALSE); 1290 ok(expected == (HWND)wParam, 1291 "Expected wParam to be the handle to the first tabstop control (%p), got %p\n", 1292 expected, (HWND)wParam); 1293 1294 EndDialog(hDlg, LOWORD(SendMessageA(hDlg, DM_GETDEFID, 0, 0))); 1295 return TRUE; 1296 } 1297 return FALSE; 1298 } 1299 1300 static INT_PTR CALLBACK TestDefButtonDlgProc (HWND hDlg, UINT uiMsg, 1301 WPARAM wParam, LPARAM lParam) 1302 { 1303 switch (uiMsg) 1304 { 1305 case WM_INITDIALOG: 1306 EndDialog(hDlg, LOWORD(SendMessageA(hDlg, DM_GETDEFID, 0, 0))); 1307 return TRUE; 1308 } 1309 return FALSE; 1310 } 1311 1312 static INT_PTR CALLBACK TestReturnKeyDlgProc (HWND hDlg, UINT uiMsg, 1313 WPARAM wParam, LPARAM lParam) 1314 { 1315 static int received_idok; 1316 1317 switch (uiMsg) 1318 { 1319 case WM_INITDIALOG: 1320 { 1321 MSG msg = {hDlg, WM_KEYDOWN, VK_RETURN, 0x011c0001}; 1322 1323 received_idok = -1; 1324 IsDialogMessageA(hDlg, &msg); 1325 ok(received_idok == 0xdead, "WM_COMMAND/0xdead not received\n"); 1326 1327 received_idok = -2; 1328 IsDialogMessageA(hDlg, &msg); 1329 ok(received_idok == IDOK, "WM_COMMAND/IDOK not received\n"); 1330 1331 EndDialog(hDlg, 0); 1332 return TRUE; 1333 } 1334 1335 case DM_GETDEFID: 1336 if (received_idok == -1) 1337 { 1338 HWND hwnd = GetDlgItem(hDlg, 0xdead); 1339 ok(!hwnd, "dialog item with ID 0xdead should not exist\n"); 1340 SetWindowLongA(hDlg, DWLP_MSGRESULT, MAKELRESULT(0xdead, DC_HASDEFID)); 1341 return TRUE; 1342 } 1343 return FALSE; 1344 1345 case WM_COMMAND: 1346 received_idok = wParam; 1347 return TRUE; 1348 } 1349 return FALSE; 1350 } 1351 1352 static INT_PTR CALLBACK TestControlStyleDlgProc(HWND hdlg, UINT msg, 1353 WPARAM wparam, LPARAM lparam) 1354 { 1355 HWND control; 1356 DWORD style, exstyle; 1357 char buf[256]; 1358 1359 switch (msg) 1360 { 1361 case WM_INITDIALOG: 1362 control = GetDlgItem(hdlg, 7); 1363 ok(control != 0, "dialog control with id 7 not found\n"); 1364 style = GetWindowLongA(control, GWL_STYLE); 1365 ok(style == (WS_CHILD|WS_VISIBLE), "expected WS_CHILD|WS_VISIBLE, got %#x\n", style); 1366 exstyle = GetWindowLongA(control, GWL_EXSTYLE); 1367 ok(exstyle == (WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT|WS_EX_CLIENTEDGE), "expected WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT|WS_EX_CLIENTEDGE, got %#x\n", exstyle); 1368 buf[0] = 0; 1369 GetWindowTextA(control, buf, sizeof(buf)); 1370 ok(strcmp(buf, "bump7") == 0, "expected bump7, got %s\n", buf); 1371 1372 control = GetDlgItem(hdlg, 8); 1373 ok(control != 0, "dialog control with id 8 not found\n"); 1374 style = GetWindowLongA(control, GWL_STYLE); 1375 ok(style == (WS_CHILD|WS_VISIBLE), "expected WS_CHILD|WS_VISIBLE, got %#x\n", style); 1376 exstyle = GetWindowLongA(control, GWL_EXSTYLE); 1377 ok(exstyle == (WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT), "expected WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT, got %#x\n", exstyle); 1378 buf[0] = 0; 1379 GetWindowTextA(control, buf, sizeof(buf)); 1380 ok(strcmp(buf, "bump8") == 0, "expected bump8, got %s\n", buf); 1381 1382 EndDialog(hdlg, -7); 1383 return TRUE; 1384 } 1385 return FALSE; 1386 } 1387 1388 static const WCHAR testtextW[] = {'W','n','d','T','e','x','t',0}; 1389 static const char *testtext = "WndText"; 1390 1391 enum defdlgproc_text 1392 { 1393 DLGPROCTEXT_SNDMSGA = 0, 1394 DLGPROCTEXT_SNDMSGW, 1395 DLGPROCTEXT_DLGPROCA, 1396 DLGPROCTEXT_DLGPROCW, 1397 DLGPROCTEXT_SETTEXTA, 1398 DLGPROCTEXT_SETTEXTW, 1399 }; 1400 1401 static const char *testmodes[] = 1402 { 1403 "SNDMSGA", 1404 "SNDMSGW", 1405 "DLGPROCA", 1406 "DLGPROCW", 1407 "SETTEXTA", 1408 "SETTEXTW", 1409 }; 1410 1411 static INT_PTR CALLBACK test_aw_conversion_dlgprocA(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1412 { 1413 int mode = HandleToULong(GetPropA(hdlg, "test_mode")); 1414 WCHAR *text = (WCHAR *)lparam; 1415 char *textA = (char *)lparam; 1416 1417 switch (msg) 1418 { 1419 case WM_SETTEXT: 1420 case WM_WININICHANGE: 1421 case WM_DEVMODECHANGE: 1422 case CB_DIR: 1423 case LB_DIR: 1424 case LB_ADDFILE: 1425 case EM_REPLACESEL: 1426 switch (mode) 1427 { 1428 case DLGPROCTEXT_DLGPROCA: 1429 ok(textA == testtext, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", 1430 testmodes[mode], textA); 1431 break; 1432 case DLGPROCTEXT_DLGPROCW: 1433 ok(text == testtextW, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", testmodes[mode], 1434 wine_dbgstr_w(text)); 1435 break; 1436 case DLGPROCTEXT_SNDMSGA: 1437 case DLGPROCTEXT_SETTEXTA: 1438 if (IsWindowUnicode(hdlg)) 1439 { 1440 ok(text != testtextW && !lstrcmpW(text, testtextW), 1441 "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1442 } 1443 else 1444 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA); 1445 break; 1446 case DLGPROCTEXT_SNDMSGW: 1447 case DLGPROCTEXT_SETTEXTW: 1448 if (IsWindowUnicode(hdlg)) 1449 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1450 else 1451 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n", 1452 testmodes[mode], textA); 1453 break; 1454 } 1455 break; 1456 }; 1457 1458 return DefWindowProcW(hdlg, msg, wparam, lparam); 1459 } 1460 1461 static INT_PTR CALLBACK test_aw_conversion_dlgprocW(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1462 { 1463 int mode = HandleToULong(GetPropA(hdlg, "test_mode")); 1464 WCHAR *text = (WCHAR *)lparam; 1465 char *textA = (char *)lparam; 1466 1467 switch (msg) 1468 { 1469 case WM_SETTEXT: 1470 case WM_WININICHANGE: 1471 case WM_DEVMODECHANGE: 1472 case CB_DIR: 1473 case LB_DIR: 1474 case LB_ADDFILE: 1475 case EM_REPLACESEL: 1476 switch (mode) 1477 { 1478 case DLGPROCTEXT_DLGPROCA: 1479 ok(textA == testtext, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", 1480 testmodes[mode], textA); 1481 break; 1482 case DLGPROCTEXT_DLGPROCW: 1483 ok(text == testtextW, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", testmodes[mode], 1484 wine_dbgstr_w(text)); 1485 break; 1486 case DLGPROCTEXT_SNDMSGA: 1487 case DLGPROCTEXT_SETTEXTA: 1488 if (IsWindowUnicode(hdlg)) 1489 ok(text != testtextW && !lstrcmpW(text, testtextW), 1490 "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1491 else 1492 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA); 1493 break; 1494 case DLGPROCTEXT_SNDMSGW: 1495 case DLGPROCTEXT_SETTEXTW: 1496 if (IsWindowUnicode(hdlg)) 1497 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1498 else 1499 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n", 1500 testmodes[mode], textA); 1501 break; 1502 } 1503 break; 1504 } 1505 1506 return DefWindowProcA(hdlg, msg, wparam, lparam); 1507 } 1508 1509 static void dlg_test_aw_message(HWND hdlg, UINT msg) 1510 { 1511 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SNDMSGA)); 1512 SendMessageA(hdlg, msg, 0, (LPARAM)testtext); 1513 1514 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SNDMSGW)); 1515 SendMessageW(hdlg, msg, 0, (LPARAM)testtextW); 1516 1517 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_DLGPROCA)); 1518 DefDlgProcA(hdlg, msg, 0, (LPARAM)testtext); 1519 1520 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_DLGPROCW)); 1521 DefDlgProcW(hdlg, msg, 0, (LPARAM)testtextW); 1522 } 1523 1524 static INT_PTR CALLBACK test_aw_conversion_dlgproc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1525 { 1526 ULONG_PTR dlgproc, originalproc; 1527 WCHAR buffW[64]; 1528 char buff[64]; 1529 BOOL ret; 1530 INT len; 1531 1532 switch (msg) 1533 { 1534 case WM_INITDIALOG: 1535 ok(IsWindowUnicode(hdlg), "Expected unicode window.\n"); 1536 1537 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1538 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1539 dlg_test_aw_message(hdlg, CB_DIR); 1540 dlg_test_aw_message(hdlg, LB_DIR); 1541 dlg_test_aw_message(hdlg, LB_ADDFILE); 1542 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1543 dlg_test_aw_message(hdlg, WM_SETTEXT); 1544 1545 /* WM_SETTEXT/WM_GETTEXT */ 1546 originalproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1547 ok(originalproc == (ULONG_PTR)test_aw_conversion_dlgproc, "Unexpected dlg proc %#lx.\n", originalproc); 1548 1549 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1550 ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgproc, "Unexpected dlg proc %#lx.\n", dlgproc); 1551 1552 dlgproc = SetWindowLongPtrA(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocA); 1553 ok(IsWindowUnicode(hdlg), "Expected unicode window.\n"); 1554 1555 dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1556 ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc); 1557 1558 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1559 ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc); 1560 1561 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA)); 1562 ret = SetWindowTextA(hdlg, testtext); 1563 todo_wine 1564 ok(ret, "Failed to set window text.\n"); 1565 1566 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW)); 1567 ret = SetWindowTextW(hdlg, testtextW); 1568 todo_wine 1569 ok(ret, "Failed to set window text.\n"); 1570 1571 memset(buff, 'A', sizeof(buff)); 1572 len = GetWindowTextA(hdlg, buff, sizeof(buff)); 1573 ok(buff[0] == 0 && buff[1] == 'A' && len == 0, "Unexpected window text %#x, %#x, len %d\n", 1574 (BYTE)buff[0], (BYTE)buff[1], len); 1575 1576 memset(buffW, 0xff, sizeof(buffW)); 1577 len = GetWindowTextW(hdlg, buffW, 64); 1578 ok(!lstrcmpW(buffW, testtextW) && len == 0, "Unexpected window text %s, len %d\n", wine_dbgstr_w(buffW), len); 1579 1580 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1581 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1582 dlg_test_aw_message(hdlg, CB_DIR); 1583 dlg_test_aw_message(hdlg, LB_DIR); 1584 dlg_test_aw_message(hdlg, LB_ADDFILE); 1585 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1586 dlg_test_aw_message(hdlg, WM_SETTEXT); 1587 1588 dlgproc = SetWindowLongPtrW(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocW); 1589 ok(IsWindowUnicode(hdlg), "Expected unicode window.\n"); 1590 1591 dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1592 ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc); 1593 1594 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1595 ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc); 1596 1597 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA)); 1598 ret = SetWindowTextA(hdlg, testtext); 1599 todo_wine 1600 ok(ret, "Failed to set window text.\n"); 1601 1602 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW)); 1603 ret = SetWindowTextW(hdlg, testtextW); 1604 todo_wine 1605 ok(ret, "Failed to set window text.\n"); 1606 1607 memset(buff, 'A', sizeof(buff)); 1608 len = GetWindowTextA(hdlg, buff, sizeof(buff)); 1609 ok(buff[0] == 0 && buff[1] == 'A' && len == 0, "Unexpected window text %#x, %#x, len %d\n", 1610 (BYTE)buff[0], (BYTE)buff[1], len); 1611 1612 memset(buffW, 0xff, sizeof(buffW)); 1613 len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW)); 1614 ok(buffW[0] == 'W' && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n", 1615 buffW[0], buffW[1], len); 1616 1617 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1618 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1619 dlg_test_aw_message(hdlg, CB_DIR); 1620 dlg_test_aw_message(hdlg, LB_DIR); 1621 dlg_test_aw_message(hdlg, LB_ADDFILE); 1622 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1623 dlg_test_aw_message(hdlg, WM_SETTEXT); 1624 1625 SetWindowLongPtrA(hdlg, DWLP_DLGPROC, originalproc); 1626 EndDialog(hdlg, -123); 1627 return TRUE; 1628 } 1629 return FALSE; 1630 } 1631 1632 static INT_PTR CALLBACK test_aw_conversion_dlgproc2(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1633 { 1634 ULONG_PTR dlgproc, originalproc; 1635 WCHAR buffW[64]; 1636 char buff[64]; 1637 BOOL ret; 1638 INT len; 1639 1640 switch (msg) 1641 { 1642 case WM_INITDIALOG: 1643 ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n"); 1644 1645 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1646 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1647 dlg_test_aw_message(hdlg, CB_DIR); 1648 dlg_test_aw_message(hdlg, LB_DIR); 1649 dlg_test_aw_message(hdlg, LB_ADDFILE); 1650 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1651 dlg_test_aw_message(hdlg, WM_SETTEXT); 1652 1653 originalproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1654 ok(originalproc != (ULONG_PTR)test_aw_conversion_dlgproc2, "Unexpected dlg proc %#lx.\n", originalproc); 1655 1656 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1657 ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgproc2, "Unexpected dlg proc %#lx.\n", dlgproc); 1658 1659 dlgproc = SetWindowLongPtrA(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocW); 1660 ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n"); 1661 1662 dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1663 ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc); 1664 1665 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1666 ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc); 1667 1668 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA)); 1669 ret = SetWindowTextA(hdlg, testtext); 1670 todo_wine 1671 ok(ret, "Failed to set window text.\n"); 1672 1673 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW)); 1674 ret = SetWindowTextW(hdlg, testtextW); 1675 todo_wine 1676 ok(ret, "Failed to set window text.\n"); 1677 1678 memset(buff, 'A', sizeof(buff)); 1679 len = GetWindowTextA(hdlg, buff, sizeof(buff)); 1680 ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len); 1681 1682 memset(buffW, 0xff, sizeof(buffW)); 1683 len = GetWindowTextW(hdlg, buffW, 64); 1684 ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %s, len %d\n", 1685 wine_dbgstr_w(buffW), len); 1686 1687 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1688 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1689 dlg_test_aw_message(hdlg, CB_DIR); 1690 dlg_test_aw_message(hdlg, LB_DIR); 1691 dlg_test_aw_message(hdlg, LB_ADDFILE); 1692 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1693 dlg_test_aw_message(hdlg, WM_SETTEXT); 1694 1695 dlgproc = SetWindowLongPtrW(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocA); 1696 ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n"); 1697 1698 dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC); 1699 ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc); 1700 1701 dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC); 1702 ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc); 1703 1704 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA)); 1705 ret = SetWindowTextA(hdlg, testtext); 1706 todo_wine 1707 ok(ret, "Failed to set window text.\n"); 1708 1709 SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW)); 1710 ret = SetWindowTextW(hdlg, testtextW); 1711 todo_wine 1712 ok(ret, "Failed to set window text.\n"); 1713 1714 memset(buff, 'A', sizeof(buff)); 1715 len = GetWindowTextA(hdlg, buff, sizeof(buff)); 1716 ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len); 1717 1718 memset(buffW, 0xff, sizeof(buffW)); 1719 len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW)); 1720 ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n", 1721 buffW[0], buffW[1], len); 1722 1723 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1724 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1725 dlg_test_aw_message(hdlg, CB_DIR); 1726 dlg_test_aw_message(hdlg, LB_DIR); 1727 dlg_test_aw_message(hdlg, LB_ADDFILE); 1728 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1729 dlg_test_aw_message(hdlg, WM_SETTEXT); 1730 1731 SetWindowLongPtrA(hdlg, DWLP_DLGPROC, originalproc); 1732 EndDialog(hdlg, -123); 1733 return TRUE; 1734 } 1735 return FALSE; 1736 } 1737 1738 static LRESULT CALLBACK test_aw_conversion_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 1739 { 1740 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 1741 int mode = HandleToULong(GetPropA(hwnd, "test_mode")); 1742 WCHAR *text = (WCHAR *)lparam; 1743 char *textA = (char *)lparam; 1744 1745 switch (msg) 1746 { 1747 case WM_SETTEXT: 1748 case WM_WININICHANGE: 1749 case WM_DEVMODECHANGE: 1750 case CB_DIR: 1751 case LB_DIR: 1752 case LB_ADDFILE: 1753 case EM_REPLACESEL: 1754 switch (mode) 1755 { 1756 case DLGPROCTEXT_SNDMSGA: 1757 if (IsWindowUnicode(hwnd)) 1758 ok(text != testtextW && !lstrcmpW(text, testtextW), 1759 "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1760 else 1761 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA); 1762 break; 1763 case DLGPROCTEXT_SNDMSGW: 1764 if (IsWindowUnicode(hwnd)) 1765 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text)); 1766 else 1767 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n", 1768 testmodes[mode], textA); 1769 break; 1770 default: 1771 ok(0, "Unexpected test mode %d.\n", mode); 1772 } 1773 break; 1774 } 1775 1776 return IsWindowUnicode(hwnd) ? CallWindowProcW(oldproc, hwnd, msg, wparam, lparam) : 1777 CallWindowProcA(oldproc, hwnd, msg, wparam, lparam); 1778 } 1779 1780 static INT_PTR CALLBACK test_aw_conversion_dlgproc3(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 1781 { 1782 BOOL is_unicode = !!lparam; 1783 LONG_PTR oldproc; 1784 1785 switch (msg) 1786 { 1787 case WM_INITDIALOG: 1788 ok(is_unicode == IsWindowUnicode(hdlg), "Unexpected unicode window property.\n"); 1789 1790 oldproc = SetWindowLongPtrA(hdlg, GWLP_WNDPROC, (LONG_PTR)test_aw_conversion_wndproc); 1791 SetWindowLongPtrA(hdlg, GWLP_USERDATA, oldproc); 1792 ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n"); 1793 1794 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1795 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1796 dlg_test_aw_message(hdlg, CB_DIR); 1797 dlg_test_aw_message(hdlg, LB_DIR); 1798 dlg_test_aw_message(hdlg, LB_ADDFILE); 1799 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1800 dlg_test_aw_message(hdlg, WM_SETTEXT); 1801 1802 SetWindowLongPtrW(hdlg, GWLP_WNDPROC, (LONG_PTR)test_aw_conversion_wndproc); 1803 ok(IsWindowUnicode(hdlg), "Expected unicode window.\n"); 1804 1805 dlg_test_aw_message(hdlg, WM_WININICHANGE); 1806 dlg_test_aw_message(hdlg, WM_DEVMODECHANGE); 1807 dlg_test_aw_message(hdlg, CB_DIR); 1808 dlg_test_aw_message(hdlg, LB_DIR); 1809 dlg_test_aw_message(hdlg, LB_ADDFILE); 1810 dlg_test_aw_message(hdlg, EM_REPLACESEL); 1811 dlg_test_aw_message(hdlg, WM_SETTEXT); 1812 1813 SetWindowLongPtrA(hdlg, GWLP_WNDPROC, oldproc); 1814 EndDialog(hdlg, -123); 1815 return TRUE; 1816 } 1817 return FALSE; 1818 } 1819 1820 static void test_DialogBoxParam(void) 1821 { 1822 static const WCHAR nameW[] = {'T','E','S','T','_','E','M','P','T','Y','_','D','I','A','L','O','G',0}; 1823 INT_PTR ret; 1824 HWND hwnd_invalid = (HWND)0x4444; 1825 1826 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_DLG_CHILD_POPUP", 0, TestControlStyleDlgProc, 0); 1827 ok(ret == -7, "expected -7, got %ld\n", ret); 1828 1829 SetLastError(0xdeadbeef); 1830 ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG" , hwnd_invalid, 0 , 0); 1831 ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %ld, expected 0\n", ret); 1832 ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() || 1833 broken(GetLastError() == 0xdeadbeef), 1834 "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); 1835 1836 /* Test a dialog which destroys itself on WM_INITDIALOG. */ 1837 SetLastError(0xdeadbeef); 1838 ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG", 0, DestroyDlgWinProc, 0); 1839 ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret); 1840 ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() || 1841 GetLastError() == ERROR_SUCCESS || 1842 broken(GetLastError() == 0xdeadbeef), 1843 "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); 1844 1845 /* Test a dialog which destroys itself on WM_CLOSE. */ 1846 ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG", 0, DestroyOnCloseDlgWinProc, 0); 1847 ok(0 == ret, "DialogBoxParamA returned %ld, expected 0\n", ret); 1848 1849 SetLastError(0xdeadbeef); 1850 ret = DialogBoxParamA(GetModuleHandleA(NULL), "RESOURCE_INVALID" , 0, 0, 0); 1851 ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret); 1852 ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError() || 1853 broken(GetLastError() == 0xdeadbeef), 1854 "got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError()); 1855 1856 SetLastError(0xdeadbeef); 1857 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_DIALOG_INVALID_CLASS", 0, DestroyDlgWinProc, 0); 1858 ok(ret == -1, "DialogBoxParamA returned %ld, expected -1\n", ret); 1859 ok(GetLastError() == 0, "got %d\n", GetLastError()); 1860 1861 SetLastError(0xdeadbeef); 1862 ret = DefDlgProcA(0, WM_ERASEBKGND, 0, 0); 1863 ok(ret == 0, "DefDlgProcA returned %ld, expected 0\n", ret); 1864 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 1865 broken(GetLastError() == 0xdeadbeef), 1866 "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError()); 1867 1868 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestInitDialogHandleProc, 0); 1869 ok(ret == IDOK, "Expected IDOK\n"); 1870 1871 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestDefButtonDlgProc, 0); 1872 ok(ret == IDOK, "Expected IDOK\n"); 1873 1874 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestReturnKeyDlgProc, 0); 1875 ok(ret == 0, "Unexpected ret value %ld.\n", ret); 1876 1877 /* WM_SETTEXT handling in case of A/W dialog procedures vs A/W dialog window. */ 1878 ret = DialogBoxParamW(GetModuleHandleA(NULL), nameW, 0, test_aw_conversion_dlgproc, 0); 1879 ok(ret == -123, "Unexpected ret value %ld.\n", ret); 1880 1881 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, test_aw_conversion_dlgproc2, 0); 1882 ok(ret == -123, "Unexpected ret value %ld.\n", ret); 1883 1884 ret = DialogBoxParamW(GetModuleHandleA(NULL), nameW, 0, test_aw_conversion_dlgproc3, 1); 1885 ok(ret == -123, "Unexpected ret value %ld.\n", ret); 1886 1887 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, test_aw_conversion_dlgproc3, 0); 1888 ok(ret == -123, "Unexpected ret value %ld.\n", ret); 1889 } 1890 1891 static void test_DisabledDialogTest(void) 1892 { 1893 g_terminated = FALSE; 1894 DialogBoxParamA(g_hinst, "IDD_DIALOG", NULL, disabled_test_proc, 0); 1895 ok(FALSE == g_terminated, "dialog with disabled ok button has been terminated\n"); 1896 } 1897 1898 static INT_PTR CALLBACK messageBoxFontDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam, 1899 LPARAM lParam) 1900 { 1901 if (uiMsg == WM_INITDIALOG) { 1902 SetFocus(hDlg); 1903 return 1; 1904 } 1905 1906 return 0; 1907 } 1908 1909 static void test_MessageBoxFontTest(void) 1910 { 1911 /* This dialog template defines a dialog template which got 0x7fff as its 1912 * font size and omits the other font members. On WinNT, passing such a 1913 * dialog template to CreateDialogIndirectParamW will result in a dialog 1914 * being created which uses the message box font. We test that here. 1915 */ 1916 1917 static unsigned char dlgTemplate[] = 1918 { 1919 /* Dialog header */ 1920 0x01,0x00, /* Version */ 1921 0xff,0xff, /* Extended template marker */ 1922 0x00,0x00,0x00,0x00, /* Context Help ID */ 1923 0x00,0x00,0x00,0x00, /* Extended style */ 1924 0xc0,0x00,0xc8,0x80, /* Style (WS_SYSMENU|WS_CAPTION|WS_POPUP|DS_SETFONT|DS_MODALFRAME) */ 1925 0x01,0x00, /* Control count */ 1926 0x00,0x00, /* X */ 1927 0x00,0x00, /* Y */ 1928 0x80,0x00, /* Width */ 1929 0x80,0x00, /* Height */ 1930 0x00,0x00, /* Menu name */ 1931 0x00,0x00, /* Class name */ 1932 'T',0x00,'e',0x00, /* Caption (unicode) */ 1933 's',0x00,'t',0x00, 1934 0x00,0x00, 1935 0xff,0x7f, /* Font height (0x7fff = message box font) */ 1936 1937 /* Control #1 */ 1938 0x00,0x00, /* Align to DWORD (header is 42 bytes) */ 1939 0x00,0x00,0x00,0x00, /* Context Help ID */ 1940 0x00,0x00,0x00,0x00, /* Extended style */ 1941 0x00,0x00,0x00,0x50, /* Style (WS_CHILD|WS_VISIBLE) */ 1942 0x00,0x00, /* X */ 1943 0x00,0x00, /* Y */ 1944 0x80,0x00, /* Width */ 1945 0x80,0x00, /* Height */ 1946 0x00,0x01,0x00,0x00, /* Control ID (256) */ 1947 0xff,0xff,0x82,0x00, /* Class (Static) */ 1948 'W',0x00,'I',0x00, /* Caption (unicode) */ 1949 'N',0x00,'E',0x00, 1950 ' ',0x00,'d',0x00, 1951 'i',0x00,'a',0x00, 1952 'l',0x00,'o',0x00, 1953 'g',0x00,' ',0x00, 1954 't',0x00,'e',0x00, 1955 's',0x00,'t',0x00, 1956 '.',0x00,0x00,0x00, 1957 0x00,0x00, /* Size of extended data */ 1958 1959 0x00,0x00 /* Align to DWORD */ 1960 }; 1961 1962 HWND hDlg; 1963 HFONT hFont; 1964 LOGFONTW lfStaticFont; 1965 NONCLIENTMETRICSW ncMetrics; 1966 1967 /* Check if the dialog can be created from the template. On Win9x, this should fail 1968 * because we are calling the W function which is not implemented, but that's what 1969 * we want, because passing such a template to CreateDialogIndirectParamA would crash 1970 * anyway. 1971 */ 1972 hDlg = CreateDialogIndirectParamW(g_hinst, (LPCDLGTEMPLATEW)dlgTemplate, NULL, messageBoxFontDlgWinProc, 0); 1973 if (!hDlg) 1974 { 1975 win_skip("dialog wasn't created\n"); 1976 return; 1977 } 1978 1979 hFont = (HFONT) SendDlgItemMessageW(hDlg, 256, WM_GETFONT, 0, 0); 1980 if (!hFont) 1981 { 1982 skip("dialog uses system font\n"); 1983 DestroyWindow(hDlg); 1984 return; 1985 } 1986 GetObjectW(hFont, sizeof(LOGFONTW), &lfStaticFont); 1987 1988 ncMetrics.cbSize = FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth); 1989 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0); 1990 ok( !memcmp(&lfStaticFont, &ncMetrics.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName)) && 1991 !lstrcmpW(lfStaticFont.lfFaceName, ncMetrics.lfMessageFont.lfFaceName), 1992 "dialog doesn't use message box font\n"); 1993 DestroyWindow(hDlg); 1994 } 1995 1996 static const char msgbox_title[] = "%5!z9ZXw*ia;57n/FGl.bCH,Su\"mfKN;foCqAU\'j6AmoJgAc_D:Z0A\'E6PF_O/w"; 1997 static WCHAR expectedOK[] = 1998 { 1999 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2000 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2001 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2002 'F','_','O','/','w','\r','\n', 2003 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2004 'M','e','s','s','a','g','e','\r','\n', 2005 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2006 'O','K',' ',' ',' ','\r','\n', 2007 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2008 }; 2009 static WCHAR expectedOkCancel[] = 2010 { 2011 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2012 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2013 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2014 'F','_','O','/','w','\r','\n', 2015 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2016 'M','e','s','s','a','g','e','\r','\n', 2017 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2018 'O','K',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n', 2019 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2020 }; 2021 static WCHAR expectedAbortRetryIgnore[] = 2022 { 2023 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2024 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2025 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2026 'F','_','O','/','w','\r','\n', 2027 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2028 'M','e','s','s','a','g','e','\r','\n', 2029 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2030 'A','b','o','r','t',' ',' ',' ','R','e','t','r','y',' ',' ',' ','I','g','n','o','r','e',' ',' ',' ','\r','\n', 2031 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2032 }; 2033 2034 static WCHAR expectedYesNo[] = 2035 { 2036 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2037 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2038 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2039 'F','_','O','/','w','\r','\n', 2040 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2041 'M','e','s','s','a','g','e','\r','\n', 2042 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2043 'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','\r','\n', 2044 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2045 }; 2046 static WCHAR expectedYesNoCancel[] = 2047 { 2048 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2049 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2050 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2051 'F','_','O','/','w','\r','\n', 2052 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2053 'M','e','s','s','a','g','e','\r','\n', 2054 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2055 'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n', 2056 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2057 }; 2058 static WCHAR expectedRetryCancel[] = 2059 { 2060 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2061 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2062 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2063 'F','_','O','/','w','\r','\n', 2064 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2065 'M','e','s','s','a','g','e','\r','\n', 2066 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2067 'R','e','t','r','y',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n', 2068 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2069 }; 2070 static WCHAR expectedCancelTryContinue[] = 2071 { 2072 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2073 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f', 2074 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P', 2075 'F','_','O','/','w','\r','\n', 2076 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2077 'M','e','s','s','a','g','e','\r','\n', 2078 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 2079 'C','a','n','c','e','l',' ',' ',' ','T','r','y',' ','A','g','a','i','n',' ',' ',' ','C','o','n','t','i','n','u','e',' ',' ',' ','\r','\n', 2080 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0 2081 }; 2082 2083 BOOL non_english = FALSE; 2084 2085 DWORD WINAPI WorkerThread(void *param) 2086 { 2087 WCHAR *expected = param; 2088 char windowTitle[sizeof(msgbox_title)]; 2089 HWND hwndMbox; 2090 BOOL succeeded = FALSE; 2091 2092 Sleep(200); 2093 2094 hwndMbox = GetForegroundWindow(); 2095 2096 /* Find the Window, if it doesn't have focus */ 2097 if (!(IsWindow(hwndMbox) && 2098 GetWindowTextA(hwndMbox, windowTitle, sizeof(msgbox_title)) && 2099 lstrcmpA(msgbox_title, windowTitle) == 0)) 2100 { 2101 hwndMbox = FindWindowA(NULL, msgbox_title); 2102 2103 if (!IsWindow(hwndMbox)) 2104 goto cleanup; 2105 } 2106 2107 SendMessageA(hwndMbox, WM_COPY, 0, 0); 2108 2109 if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) 2110 { 2111 HANDLE textHandle = GetClipboardData(CF_UNICODETEXT); 2112 WCHAR *text = GlobalLock(textHandle); 2113 2114 if (text != NULL) 2115 { 2116 if(non_english) 2117 ok(lstrlenW(text) > 0, "Empty string on clipboard\n"); 2118 else 2119 { 2120 succeeded = lstrcmpW(expected, text) == 0; 2121 if(!succeeded) 2122 { 2123 ok(0, "%s\n", wine_dbgstr_w(text)); 2124 ok(0, "%s\n", wine_dbgstr_w(expected)); 2125 } 2126 } 2127 2128 GlobalUnlock(textHandle); 2129 } 2130 else 2131 ok(0, "No text on clipboard.\n"); 2132 2133 CloseClipboard(); 2134 2135 } 2136 else 2137 trace("Clipboard error\n"); 2138 2139 PostMessageA(hwndMbox, WM_COMMAND, IDIGNORE, 0); /* For MB_ABORTRETRYIGNORE dialog. */ 2140 PostMessageA(hwndMbox, WM_CLOSE, 0, 0); 2141 2142 cleanup: 2143 ok(succeeded || non_english, "Failed to get string.\n"); 2144 2145 return 0; 2146 } 2147 2148 static void test_MessageBox_WM_COPY_Test(void) 2149 { 2150 DWORD tid = 0; 2151 2152 non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH); 2153 trace("non_english %d\n", non_english); 2154 2155 CreateThread(NULL, 0, WorkerThread, &expectedOK, 0, &tid); 2156 MessageBoxA(NULL, "Message", msgbox_title, MB_OK); 2157 2158 CreateThread(NULL, 0, WorkerThread, &expectedOkCancel, 0, &tid); 2159 MessageBoxA(NULL, "Message", msgbox_title, MB_OKCANCEL); 2160 2161 CreateThread(NULL, 0, WorkerThread, &expectedAbortRetryIgnore, 0, &tid); 2162 MessageBoxA(NULL, "Message", msgbox_title, MB_ABORTRETRYIGNORE); 2163 2164 CreateThread(NULL, 0, WorkerThread, &expectedYesNo, 0, &tid); 2165 MessageBoxA(NULL, "Message", msgbox_title, MB_YESNO); 2166 2167 CreateThread(NULL, 0, WorkerThread, &expectedYesNoCancel, 0, &tid); 2168 MessageBoxA(NULL, "Message", msgbox_title, MB_YESNOCANCEL); 2169 2170 CreateThread(NULL, 0, WorkerThread, &expectedRetryCancel, 0, &tid); 2171 MessageBoxA(NULL, "Message", msgbox_title, MB_RETRYCANCEL); 2172 2173 CreateThread(NULL, 0, WorkerThread, &expectedCancelTryContinue, 0, &tid); 2174 MessageBoxA(NULL, "Message", msgbox_title, MB_CANCELTRYCONTINUE); 2175 } 2176 2177 static void test_SaveRestoreFocus(void) 2178 { 2179 HWND hDlg; 2180 HRSRC hResource; 2181 HANDLE hTemplate; 2182 DLGTEMPLATE* pTemplate; 2183 LONG_PTR foundId; 2184 HWND foundHwnd; 2185 2186 /* create the dialog */ 2187 hResource = FindResourceA(g_hinst, "MULTI_EDIT_DIALOG", (LPCSTR)RT_DIALOG); 2188 hTemplate = LoadResource(g_hinst, hResource); 2189 pTemplate = LockResource(hTemplate); 2190 2191 hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, messageBoxFontDlgWinProc, 0); 2192 ok (hDlg != 0, "Failed to create test dialog.\n"); 2193 2194 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2195 ok (foundId == 1000, "First edit box should have gained focus on dialog creation. Expected: %d, Found: %ld\n", 1000, foundId); 2196 2197 SetFocus(GetNextDlgTabItem(hDlg, GetFocus(), FALSE)); 2198 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0); 2199 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2200 ok (foundId == 1001, "First edit box should have regained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1001, foundId); 2201 SetFocus(GetNextDlgTabItem(hDlg, NULL, FALSE)); 2202 2203 /* de- then reactivate the dialog */ 2204 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0); 2205 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0); 2206 2207 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2208 ok (foundId == 1000, "First edit box should have regained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1000, foundId); 2209 2210 /* select the next tabbable item */ 2211 SetFocus(GetNextDlgTabItem(hDlg, GetFocus(), FALSE)); 2212 2213 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2214 ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId); 2215 2216 /* de- then reactivate the dialog */ 2217 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0); 2218 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0); 2219 2220 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2221 ok (foundId == 1001, "Second edit box should have gained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1001, foundId); 2222 2223 /* set focus to the dialog */ 2224 SetFocus(hDlg); 2225 2226 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2227 ok (foundId == 1000, "First edit box should have gained focus on dialog focus. Expected: %d, Found: %ld\n", 1000, foundId); 2228 2229 /* select second tabbable item */ 2230 SetFocus(GetNextDlgTabItem(hDlg, GetNextDlgTabItem(hDlg, NULL, FALSE), FALSE)); 2231 2232 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2233 ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId); 2234 2235 /* send WM_ACTIVATE message to already active dialog */ 2236 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0); 2237 2238 foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID); 2239 ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId); 2240 2241 /* disable the 2nd box */ 2242 EnableWindow(GetFocus(), FALSE); 2243 2244 foundHwnd = GetFocus(); 2245 ok (foundHwnd == NULL, "Second edit box should have lost focus after being disabled. Expected: %p, Found: %p\n", NULL, foundHwnd); 2246 2247 /* de- then reactivate the dialog */ 2248 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0); 2249 SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0); 2250 2251 foundHwnd = GetFocus(); 2252 ok (foundHwnd == NULL, "No controls should have gained focus after dialog reactivation. Expected: %p, Found: %p\n", NULL, foundHwnd); 2253 2254 /* clean up */ 2255 DestroyWindow(hDlg); 2256 } 2257 2258 static INT_PTR CALLBACK timer_message_dlg_proc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) 2259 { 2260 static int count; 2261 BOOL visible; 2262 2263 switch (msg) 2264 { 2265 case WM_INITDIALOG: 2266 visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE; 2267 ok(!visible, "Dialog should not be visible.\n"); 2268 SetTimer(wnd, 1, 100, NULL); 2269 Sleep(200); 2270 return FALSE; 2271 2272 case WM_COMMAND: 2273 if (LOWORD(wparam) != IDCANCEL) return FALSE; 2274 EndDialog(wnd, LOWORD(wparam)); 2275 return TRUE; 2276 2277 case WM_TIMER: 2278 if (wparam != 1) return FALSE; 2279 visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE; 2280 if (!count++) 2281 { 2282 ok(!visible, "Dialog should not be visible.\n"); 2283 PostMessageA(wnd, WM_USER, 0, 0); 2284 } 2285 else 2286 { 2287 ok(visible, "Dialog should be visible.\n"); 2288 PostMessageA(wnd, WM_COMMAND, IDCANCEL, 0); 2289 } 2290 return TRUE; 2291 2292 case WM_USER: 2293 visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE; 2294 ok(visible, "Dialog should be visible.\n"); 2295 return TRUE; 2296 2297 default: 2298 return FALSE; 2299 } 2300 } 2301 2302 static void test_timer_message(void) 2303 { 2304 DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, timer_message_dlg_proc); 2305 } 2306 2307 static LRESULT CALLBACK msgbox_hook_proc(INT code, WPARAM wParam, LPARAM lParam) 2308 { 2309 if (code == HCBT_ACTIVATE) 2310 { 2311 HWND msgbox = (HWND)wParam, msghwnd; 2312 char text[64]; 2313 2314 if (msgbox) 2315 { 2316 text[0] = 0; 2317 GetWindowTextA(msgbox, text, sizeof(text)); 2318 ok(!strcmp(text, "MSGBOX caption"), "Unexpected window text \"%s\"\n", text); 2319 2320 msghwnd = GetDlgItem(msgbox, 0xffff); 2321 ok(msghwnd != NULL, "Expected static control\n"); 2322 2323 text[0] = 0; 2324 GetWindowTextA(msghwnd, text, sizeof(text)); 2325 ok(!strcmp(text, "Text"), "Unexpected window text \"%s\"\n", text); 2326 2327 SendDlgItemMessageA(msgbox, IDCANCEL, WM_LBUTTONDOWN, 0, 0); 2328 SendDlgItemMessageA(msgbox, IDCANCEL, WM_LBUTTONUP, 0, 0); 2329 } 2330 } 2331 2332 return CallNextHookEx(NULL, code, wParam, lParam); 2333 } 2334 2335 struct create_window_params 2336 { 2337 BOOL owner; 2338 char caption[64]; 2339 DWORD style; 2340 }; 2341 2342 static DWORD WINAPI create_window_thread(void *param) 2343 { 2344 struct create_window_params *p = param; 2345 HWND owner = 0; 2346 2347 if (p->owner) 2348 { 2349 owner = CreateWindowExA(0, "Static", NULL, WS_POPUP, 10, 10, 10, 10, 0, 0, 0, NULL); 2350 ok(owner != 0, "failed to create owner window\n"); 2351 } 2352 2353 MessageBoxA(owner, NULL, p->caption, p->style); 2354 2355 if (owner) DestroyWindow(owner); 2356 2357 return 0; 2358 } 2359 2360 static HWND wait_for_window(const char *caption) 2361 { 2362 HWND hwnd; 2363 DWORD timeout = 0; 2364 2365 for (;;) 2366 { 2367 hwnd = FindWindowA(NULL, caption); 2368 if (hwnd) break; 2369 2370 Sleep(50); 2371 timeout += 50; 2372 if (timeout > 3000) 2373 { 2374 ok(0, "failed to wait for a window %s\n", caption); 2375 break; 2376 } 2377 } 2378 2379 Sleep(50); 2380 return hwnd; 2381 } 2382 2383 static void test_MessageBox(void) 2384 { 2385 static const struct 2386 { 2387 DWORD mb_style; 2388 DWORD ex_style; 2389 } test[] = 2390 { 2391 { MB_OK, 0 }, 2392 { MB_OK | MB_TASKMODAL, 0 }, 2393 { MB_OK | MB_SYSTEMMODAL, WS_EX_TOPMOST }, 2394 }; 2395 struct create_window_params params; 2396 HANDLE thread; 2397 DWORD tid, i; 2398 HHOOK hook; 2399 int ret; 2400 2401 hook = SetWindowsHookExA(WH_CBT, msgbox_hook_proc, NULL, GetCurrentThreadId()); 2402 2403 ret = MessageBoxA(NULL, "Text", "MSGBOX caption", MB_OKCANCEL); 2404 ok(ret == IDCANCEL, "got %d\n", ret); 2405 2406 UnhookWindowsHookEx(hook); 2407 2408 sprintf(params.caption, "pid %08x, tid %08x, time %08x", 2409 GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentTime()); 2410 2411 params.owner = FALSE; 2412 2413 for (i = 0; i < sizeof(test)/sizeof(test[0]); i++) 2414 { 2415 HWND hwnd; 2416 DWORD ex_style; 2417 2418 params.style = test[i].mb_style; 2419 2420 thread = CreateThread(NULL, 0, create_window_thread, ¶ms, 0, &tid); 2421 2422 hwnd = wait_for_window(params.caption); 2423 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 2424 ok((ex_style & WS_EX_TOPMOST) == test[i].ex_style, "%d: got window ex_style %#x\n", i, ex_style); 2425 2426 PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0); 2427 2428 ok(WaitForSingleObject(thread, 5000) != WAIT_TIMEOUT, "thread failed to terminate\n"); 2429 CloseHandle(thread); 2430 } 2431 2432 params.owner = TRUE; 2433 2434 for (i = 0; i < sizeof(test)/sizeof(test[0]); i++) 2435 { 2436 HWND hwnd; 2437 DWORD ex_style; 2438 2439 params.style = test[i].mb_style; 2440 2441 thread = CreateThread(NULL, 0, create_window_thread, ¶ms, 0, &tid); 2442 2443 hwnd = wait_for_window(params.caption); 2444 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 2445 ok((ex_style & WS_EX_TOPMOST) == test[i].ex_style, "%d: got window ex_style %#x\n", i, ex_style); 2446 2447 PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0); 2448 2449 ok(WaitForSingleObject(thread, 5000) != WAIT_TIMEOUT, "thread failed to terminate\n"); 2450 CloseHandle(thread); 2451 } 2452 } 2453 2454 static INT_PTR CALLBACK custom_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) 2455 { 2456 if (msg == WM_INITDIALOG) 2457 EndDialog(hdlg, 0); 2458 2459 return FALSE; 2460 } 2461 2462 static void test_dialog_custom_data(void) 2463 { 2464 DialogBoxA(g_hinst, "CUSTOM_TEST_DIALOG", NULL, custom_test_dialog_proc); 2465 } 2466 2467 START_TEST(dialog) 2468 { 2469 g_hinst = GetModuleHandleA (0); 2470 2471 if (!RegisterWindowClasses()) assert(0); 2472 2473 test_dialog_custom_data(); 2474 test_GetNextDlgItem(); 2475 test_IsDialogMessage(); 2476 test_WM_NEXTDLGCTL(); 2477 test_focus(); 2478 test_GetDlgItem(); 2479 test_GetDlgItemText(); 2480 test_DialogBoxParam(); 2481 test_DisabledDialogTest(); 2482 test_MessageBoxFontTest(); 2483 test_SaveRestoreFocus(); 2484 test_timer_message(); 2485 test_MessageBox(); 2486 test_MessageBox_WM_COPY_Test(); 2487 } 2488