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