1 /* 2 * ReactOS kernel 3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program 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 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 /* 20 * PROJECT: ReactOS user32.dll 21 * FILE: win32ss/user/user32/windows/dialog.c 22 * PURPOSE: Dialog Manager 23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 24 * Thomas Weidenmueller (w3seek@users.sourceforge.net) 25 * Steven Edwards (Steven_Ed4153@yahoo.com) 26 * UPDATE HISTORY: 27 * 07-26-2003 Code ported from wine 28 * 09-05-2001 CSH Created 29 */ 30 31 #include <user32.h> 32 33 WINE_DEFAULT_DEBUG_CHANNEL(user32); 34 35 /* MACROS/DEFINITIONS ********************************************************/ 36 37 #define DF_END 0x0001 38 #define DF_DIALOGACTIVE 0x4000 // ReactOS 39 #define DWLP_ROS_DIALOGINFO (DWLP_USER+sizeof(ULONG_PTR)) 40 #define GETDLGINFO(hwnd) DIALOG_get_info(hwnd, FALSE) 41 #define SETDLGINFO(hwnd, info) SetWindowLongPtrW((hwnd), DWLP_ROS_DIALOGINFO, (LONG_PTR)(info)) 42 #define GET_WORD(ptr) (*(WORD *)(ptr)) 43 #define GET_DWORD(ptr) (*(DWORD *)(ptr)) 44 #define GET_LONG(ptr) (*(const LONG *)(ptr)) 45 #define DLG_ISANSI 2 46 47 /* INTERNAL STRUCTS **********************************************************/ 48 49 /* Dialog info structure */ 50 typedef struct 51 { 52 HWND hwndFocus; /* Current control with focus */ 53 HFONT hUserFont; /* Dialog font */ 54 HMENU hMenu; /* Dialog menu */ 55 UINT xBaseUnit; /* Dialog units (depends on the font) */ 56 UINT yBaseUnit; 57 INT idResult; /* EndDialog() result / default pushbutton ID */ 58 UINT flags; /* EndDialog() called for this dialog */ 59 } DIALOGINFO; 60 61 /* Dialog control information */ 62 typedef struct 63 { 64 DWORD style; 65 DWORD exStyle; 66 DWORD helpId; 67 short x; 68 short y; 69 short cx; 70 short cy; 71 UINT id; 72 LPCWSTR className; 73 LPCWSTR windowName; 74 BOOL windowNameFree; // ReactOS 75 LPCVOID data; 76 } DLG_CONTROL_INFO; 77 78 /* Dialog template */ 79 typedef struct 80 { 81 DWORD style; 82 DWORD exStyle; 83 DWORD helpId; 84 WORD nbItems; 85 short x; 86 short y; 87 short cx; 88 short cy; 89 LPCWSTR menuName; 90 LPCWSTR className; 91 LPCWSTR caption; 92 WORD pointSize; 93 WORD weight; 94 BOOL italic; 95 LPCWSTR faceName; 96 BOOL dialogEx; 97 } DLG_TEMPLATE; 98 99 /* CheckRadioButton structure */ 100 typedef struct 101 { 102 UINT firstID; 103 UINT lastID; 104 UINT checkID; 105 } RADIOGROUP; 106 107 108 /********************************************************************* 109 * dialog class descriptor 110 */ 111 const struct builtin_class_descr DIALOG_builtin_class = 112 { 113 WC_DIALOG, /* name */ 114 CS_SAVEBITS | CS_DBLCLKS, /* style */ 115 DefDlgProcA, /* procA */ 116 DefDlgProcW, /* procW */ 117 DLGWINDOWEXTRA, /* extra */ 118 (LPCWSTR) IDC_ARROW, /* cursor */ 119 0 /* brush */ 120 }; 121 122 123 /* INTERNAL FUNCTIONS ********************************************************/ 124 125 /*********************************************************************** 126 * DIALOG_get_info 127 * 128 * Get the DIALOGINFO structure of a window, allocating it if needed 129 * and 'create' is TRUE. 130 * 131 * ReactOS 132 */ 133 DIALOGINFO *DIALOG_get_info( HWND hWnd, BOOL create ) 134 { 135 PWND pWindow; 136 DIALOGINFO* dlgInfo; 137 138 pWindow = ValidateHwnd( hWnd ); 139 if (!pWindow) 140 { 141 return NULL; 142 } 143 144 dlgInfo = (DIALOGINFO *)GetWindowLongPtrW( hWnd, DWLP_ROS_DIALOGINFO ); 145 146 if (!dlgInfo && create) 147 { 148 if (pWindow && pWindow->cbwndExtra >= DLGWINDOWEXTRA) 149 { 150 if (!(dlgInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dlgInfo) ))) 151 return NULL; 152 153 dlgInfo->idResult = IDOK; 154 SETDLGINFO( hWnd, dlgInfo ); 155 } 156 else 157 { 158 return NULL; 159 } 160 } 161 162 if (dlgInfo) 163 { 164 if (!(pWindow->state & WNDS_DIALOGWINDOW)) 165 { 166 NtUserxSetDialogPointer( hWnd, dlgInfo ); 167 } 168 } 169 return dlgInfo; 170 } 171 172 /*********************************************************************** 173 * DIALOG_GetControl32 174 * 175 * Return the class and text of the control pointed to by ptr, 176 * fill the header structure and return a pointer to the next control. 177 */ 178 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info, 179 BOOL dialogEx ) 180 { 181 if (dialogEx) 182 { 183 info->helpId = GET_DWORD(p); p += 2; 184 info->exStyle = GET_DWORD(p); p += 2; 185 info->style = GET_DWORD(p); p += 2; 186 } 187 else 188 { 189 info->helpId = 0; 190 info->style = GET_DWORD(p); p += 2; 191 info->exStyle = GET_DWORD(p); p += 2; 192 } 193 info->x = GET_WORD(p); p++; 194 info->y = GET_WORD(p); p++; 195 info->cx = GET_WORD(p); p++; 196 info->cy = GET_WORD(p); p++; 197 198 if (dialogEx) 199 { 200 /* id is 4 bytes for DIALOGEX */ 201 info->id = GET_LONG(p); 202 p += 2; 203 } 204 else 205 { 206 info->id = GET_WORD(p); 207 p++; 208 } 209 210 if (GET_WORD(p) == 0xffff) 211 { 212 static const WCHAR class_names[6][10] = 213 { 214 { 'B','u','t','t','o','n', }, /* 0x80 */ 215 { 'E','d','i','t', }, /* 0x81 */ 216 { 'S','t','a','t','i','c', }, /* 0x82 */ 217 { 'L','i','s','t','B','o','x', }, /* 0x83 */ 218 { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */ 219 { 'C','o','m','b','o','B','o','x', } /* 0x85 */ 220 }; 221 WORD id = GET_WORD(p+1); 222 /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */ 223 if ((id >= 0x80) && (id <= 0x85)) id -= 0x80; 224 if (id <= 5) 225 { 226 info->className = class_names[id]; 227 } 228 else 229 { 230 info->className = NULL; 231 /* FIXME: load other classes here? */ 232 ERR("Unknown built-in class id %04x\n", id ); 233 } 234 p += 2; 235 } 236 else 237 { 238 info->className = (LPCWSTR)p; 239 p += strlenW( info->className ) + 1; 240 } 241 242 if (GET_WORD(p) == 0xffff) /* Is it an integer id? */ 243 { 244 //// ReactOS Rev 6478 245 info->windowName = HeapAlloc( GetProcessHeap(), 0, sizeof(L"#65535") ); 246 if (info->windowName != NULL) 247 { 248 wsprintf((LPWSTR)info->windowName, L"#%u", GET_WORD(p + 1)); 249 info->windowNameFree = TRUE; 250 } 251 else 252 { 253 info->windowNameFree = FALSE; 254 } 255 p += 2; 256 } 257 else 258 { 259 info->windowName = (LPCWSTR)p; 260 info->windowNameFree = FALSE; 261 p += strlenW( info->windowName ) + 1; 262 } 263 264 TRACE(" %s %s %ld, %d, %d, %d, %d, %08x, %08x, %08x\n", 265 debugstr_w( info->className ), debugstr_w( info->windowName ), 266 info->id, info->x, info->y, info->cx, info->cy, 267 info->style, info->exStyle, info->helpId ); 268 269 if (GET_WORD(p)) 270 { 271 info->data = p; 272 p += GET_WORD(p) / sizeof(WORD); 273 } 274 else info->data = NULL; 275 p++; 276 277 /* Next control is on dword boundary */ 278 return (const WORD *)(((UINT_PTR)p + 3) & ~3); 279 } 280 281 282 /*********************************************************************** 283 * DIALOG_CreateControls32 284 * 285 * Create the control windows for a dialog. 286 */ 287 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate, 288 HINSTANCE hInst, BOOL unicode ) 289 { 290 DIALOGINFO * dlgInfo; 291 DLG_CONTROL_INFO info; 292 HWND hwndCtrl, hwndDefButton = 0; 293 INT items = dlgTemplate->nbItems; 294 295 if (!(dlgInfo = GETDLGINFO(hwnd))) return FALSE; 296 297 TRACE(" BEGIN\n" ); 298 while (items--) 299 { 300 template = (LPCSTR)DIALOG_GetControl32( (const WORD *)template, &info, 301 dlgTemplate->dialogEx ); 302 info.style &= ~WS_POPUP; 303 info.style |= WS_CHILD; 304 305 if (info.style & WS_BORDER) 306 { 307 info.style &= ~WS_BORDER; 308 info.exStyle |= WS_EX_CLIENTEDGE; 309 } 310 311 if (unicode) 312 { 313 hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY, 314 info.className, info.windowName, 315 info.style | WS_CHILD, 316 MulDiv(info.x, dlgInfo->xBaseUnit, 4), 317 MulDiv(info.y, dlgInfo->yBaseUnit, 8), 318 MulDiv(info.cx, dlgInfo->xBaseUnit, 4), 319 MulDiv(info.cy, dlgInfo->yBaseUnit, 8), 320 hwnd, (HMENU)(ULONG_PTR)info.id, 321 hInst, (LPVOID)info.data ); 322 } 323 else 324 { 325 LPSTR class = (LPSTR)info.className; 326 LPSTR caption = (LPSTR)info.windowName; 327 328 if (!IS_INTRESOURCE(class)) 329 { 330 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL ); 331 class = HeapAlloc( GetProcessHeap(), 0, len ); 332 if (class != NULL) 333 WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL ); 334 } 335 if (!IS_INTRESOURCE(caption)) 336 { 337 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL ); 338 caption = HeapAlloc( GetProcessHeap(), 0, len ); 339 if (caption != NULL) 340 WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL ); 341 } 342 343 if (class != NULL && caption != NULL) 344 { 345 hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY, 346 class, caption, info.style | WS_CHILD, 347 MulDiv(info.x, dlgInfo->xBaseUnit, 4), 348 MulDiv(info.y, dlgInfo->yBaseUnit, 8), 349 MulDiv(info.cx, dlgInfo->xBaseUnit, 4), 350 MulDiv(info.cy, dlgInfo->yBaseUnit, 8), 351 hwnd, (HMENU)(ULONG_PTR)info.id, 352 hInst, (LPVOID)info.data ); 353 } 354 else 355 hwndCtrl = NULL; 356 if (!IS_INTRESOURCE(class)) HeapFree( GetProcessHeap(), 0, class ); 357 if (!IS_INTRESOURCE(caption)) HeapFree( GetProcessHeap(), 0, caption ); 358 } 359 360 if (info.windowNameFree) 361 { 362 HeapFree( GetProcessHeap(), 0, (LPVOID)info.windowName ); 363 } 364 365 if (!hwndCtrl) 366 { 367 WARN("control %s %s creation failed\n", debugstr_w(info.className), 368 debugstr_w(info.windowName)); 369 if (dlgTemplate->style & DS_NOFAILCREATE) continue; 370 return FALSE; 371 } 372 373 /* Send initialisation messages to the control */ 374 if (dlgInfo->hUserFont) SendMessageW( hwndCtrl, WM_SETFONT, 375 (WPARAM)dlgInfo->hUserFont, 0 ); 376 if (SendMessageW(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON) 377 { 378 /* If there's already a default push-button, set it back */ 379 /* to normal and use this one instead. */ 380 if (hwndDefButton) 381 SendMessageW( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE ); 382 hwndDefButton = hwndCtrl; 383 dlgInfo->idResult = GetWindowLongPtrA( hwndCtrl, GWLP_ID ); 384 } 385 } 386 TRACE(" END\n" ); 387 return TRUE; 388 } 389 390 391 /*********************************************************************** 392 * DIALOG_IsAccelerator 393 */ 394 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam ) 395 { 396 HWND hwndControl = hwnd; 397 HWND hwndNext; 398 INT dlgCode; 399 WCHAR buffer[128]; 400 401 do 402 { 403 DWORD style = GetWindowLongPtrW( hwndControl, GWL_STYLE ); 404 if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) 405 { 406 dlgCode = SendMessageW( hwndControl, WM_GETDLGCODE, 0, 0 ); 407 if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) && 408 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) )) 409 { 410 /* find the accelerator key */ 411 LPWSTR p = buffer - 2; 412 413 do 414 { 415 p = strchrW( p + 2, '&' ); 416 } 417 while (p != NULL && p[1] == '&'); 418 419 /* and check if it's the one we're looking for */ 420 if (p != NULL && toupperW( p[1] ) == toupperW( wParam ) ) 421 { 422 if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX ) 423 { 424 /* set focus to the control */ 425 SendMessageW( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1); 426 /* and bump it on to next */ 427 SendMessageW( hwndDlg, WM_NEXTDLGCTL, 0, 0); 428 } 429 else if (dlgCode & DLGC_BUTTON) 430 { 431 /* send BM_CLICK message to the control */ 432 SendMessageW( hwndControl, BM_CLICK, 0, 0 ); 433 } 434 return TRUE; 435 } 436 } 437 hwndNext = GetWindow( hwndControl, GW_CHILD ); 438 } 439 else hwndNext = 0; 440 441 if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT ); 442 443 while (!hwndNext && hwndControl) 444 { 445 hwndControl = GetParent( hwndControl ); 446 if (hwndControl == hwndDlg) 447 { 448 if(hwnd==hwndDlg) /* prevent endless loop */ 449 { 450 hwndNext=hwnd; 451 break; 452 } 453 hwndNext = GetWindow( hwndDlg, GW_CHILD ); 454 } 455 else 456 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT ); 457 } 458 hwndControl = hwndNext; 459 } 460 while (hwndControl && (hwndControl != hwnd)); 461 462 return FALSE; 463 } 464 465 /*********************************************************************** 466 * DIALOG_FindMsgDestination 467 * 468 * The messages that IsDialogMessage sends may not go to the dialog 469 * calling IsDialogMessage if that dialog is a child, and it has the 470 * DS_CONTROL style set. 471 * We propagate up until we hit one that does not have DS_CONTROL, or 472 * whose parent is not a dialog. 473 * 474 * This is undocumented behaviour. 475 */ 476 static HWND DIALOG_FindMsgDestination( HWND hwndDlg ) 477 { 478 while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL) 479 { 480 PWND pWnd; 481 HWND hParent = GetParent(hwndDlg); 482 if (!hParent) break; 483 // ReactOS 484 if (!IsWindow(hParent)) break; 485 486 pWnd = ValidateHwnd(hParent); 487 // FIXME: Use pWnd->fnid == FNID_DESKTOP 488 if (!pWnd || !TestWindowProcess(pWnd) || hParent == GetDesktopWindow()) break; 489 490 if (!(pWnd->state & WNDS_DIALOGWINDOW)) 491 { 492 break; 493 } 494 495 hwndDlg = hParent; 496 } 497 498 return hwndDlg; 499 } 500 501 /*********************************************************************** 502 * DIALOG_DoDialogBox 503 */ 504 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner ) 505 { 506 DIALOGINFO * dlgInfo; 507 MSG msg; 508 INT retval; 509 BOOL bFirstEmpty; 510 PWND pWnd; 511 512 pWnd = ValidateHwnd(hwnd); 513 if (!pWnd) return -1; 514 515 if (!(dlgInfo = GETDLGINFO(hwnd))) return -1; 516 517 bFirstEmpty = TRUE; 518 if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */ 519 { 520 for (;;) 521 { 522 if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) 523 { 524 if (bFirstEmpty) 525 { 526 /* ShowWindow the first time the queue goes empty */ 527 ShowWindow( hwnd, SW_SHOWNORMAL ); 528 bFirstEmpty = FALSE; 529 } 530 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG)) 531 { 532 /* No message present -> send ENTERIDLE and wait */ 533 SendMessageW( owner, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd ); 534 } 535 GetMessageW( &msg, 0, 0, 0 ); 536 } 537 538 if (msg.message == WM_QUIT) 539 { 540 PostQuitMessage( msg.wParam ); 541 if (!IsWindow( hwnd )) return 0; 542 break; 543 } 544 545 /* 546 * If the user is pressing Ctrl+C, send a WM_COPY message. 547 * Guido Pola, CORE-4829, Is there another way to check if the Dialog is a MessageBox? 548 */ 549 if (msg.message == WM_KEYDOWN && 550 pWnd->state & WNDS_MSGBOX && // Yes! 551 GetForegroundWindow() == hwnd) 552 { 553 if (msg.wParam == L'C' && GetKeyState(VK_CONTROL) < 0) 554 SendMessageW(hwnd, WM_COPY, 0, 0); 555 } 556 557 if (!IsWindow( hwnd )) return 0; 558 if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg)) 559 { 560 TranslateMessage( &msg ); 561 DispatchMessageW( &msg ); 562 } 563 if (!IsWindow( hwnd )) return 0; 564 if (dlgInfo->flags & DF_END) break; 565 566 if (bFirstEmpty && msg.message == WM_TIMER) 567 { 568 ShowWindow( hwnd, SW_SHOWNORMAL ); 569 bFirstEmpty = FALSE; 570 } 571 } 572 } 573 retval = dlgInfo->idResult; 574 DestroyWindow( hwnd ); 575 return retval; 576 } 577 578 /*********************************************************************** 579 * DIALOG_ParseTemplate32 580 * 581 * Fill a DLG_TEMPLATE structure from the dialog template, and return 582 * a pointer to the first control. 583 */ 584 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result ) 585 { 586 const WORD *p = (const WORD *)template; 587 WORD signature; 588 WORD dlgver; 589 590 dlgver = GET_WORD(p); p++; 591 signature = GET_WORD(p); p++; 592 593 if (dlgver == 1 && signature == 0xffff) /* DIALOGEX resource */ 594 { 595 result->dialogEx = TRUE; 596 result->helpId = GET_DWORD(p); p += 2; 597 result->exStyle = GET_DWORD(p); p += 2; 598 result->style = GET_DWORD(p); p += 2; 599 } 600 else 601 { 602 result->style = GET_DWORD(p - 2); 603 result->dialogEx = FALSE; 604 result->helpId = 0; 605 result->exStyle = GET_DWORD(p); p += 2; 606 } 607 result->nbItems = GET_WORD(p); p++; 608 result->x = GET_WORD(p); p++; 609 result->y = GET_WORD(p); p++; 610 result->cx = GET_WORD(p); p++; 611 result->cy = GET_WORD(p); p++; 612 TRACE("DIALOG%s %d, %d, %d, %d, %d\n", 613 result->dialogEx ? "EX" : "", result->x, result->y, 614 result->cx, result->cy, result->helpId ); 615 TRACE(" STYLE 0x%08x\n", result->style ); 616 TRACE(" EXSTYLE 0x%08x\n", result->exStyle ); 617 618 /* Get the menu name */ 619 620 switch(GET_WORD(p)) 621 { 622 case 0x0000: 623 result->menuName = NULL; 624 p++; 625 break; 626 case 0xffff: 627 result->menuName = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 ); 628 p += 2; 629 TRACE(" MENU %04x\n", LOWORD(result->menuName) ); 630 break; 631 default: 632 result->menuName = (LPCWSTR)p; 633 TRACE(" MENU %s\n", debugstr_w(result->menuName) ); 634 p += strlenW( result->menuName ) + 1; 635 break; 636 } 637 638 /* Get the class name */ 639 640 switch(GET_WORD(p)) 641 { 642 case 0x0000: 643 result->className = WC_DIALOG; 644 p++; 645 break; 646 case 0xffff: 647 result->className = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 ); 648 p += 2; 649 TRACE(" CLASS %04x\n", LOWORD(result->className) ); 650 break; 651 default: 652 result->className = (LPCWSTR)p; 653 TRACE(" CLASS %s\n", debugstr_w( result->className )); 654 p += strlenW( result->className ) + 1; 655 break; 656 } 657 658 /* Get the window caption */ 659 660 result->caption = (LPCWSTR)p; 661 p += strlenW( result->caption ) + 1; 662 TRACE(" CAPTION %s\n", debugstr_w( result->caption ) ); 663 664 /* Get the font name */ 665 666 result->pointSize = 0; 667 result->faceName = NULL; 668 result->weight = FW_DONTCARE; 669 result->italic = FALSE; 670 671 if (result->style & DS_SETFONT) 672 { 673 result->pointSize = GET_WORD(p); 674 p++; 675 676 /* If pointSize is 0x7fff, it means that we need to use the font 677 * in NONCLIENTMETRICSW.lfMessageFont, and NOT read the weight, 678 * italic, and facename from the dialog template. 679 */ 680 if (result->pointSize == 0x7fff) 681 { 682 /* We could call SystemParametersInfo here, but then we'd have 683 * to convert from pixel size to point size (which can be 684 * imprecise). 685 */ 686 TRACE(" FONT: Using message box font\n"); 687 } 688 else 689 { 690 if (result->dialogEx) 691 { 692 result->weight = GET_WORD(p); p++; 693 result->italic = LOBYTE(GET_WORD(p)); p++; 694 } 695 result->faceName = (LPCWSTR)p; 696 p += strlenW( result->faceName ) + 1; 697 698 TRACE(" FONT %d, %s, %d, %s\n", 699 result->pointSize, debugstr_w( result->faceName ), 700 result->weight, result->italic ? "TRUE" : "FALSE" ); 701 } 702 } 703 704 /* First control is on dword boundary */ 705 return (LPCSTR)((((UINT_PTR)p) + 3) & ~3); 706 } 707 708 /*********************************************************************** 709 * DEFDLG_SetFocus 710 * 711 * Set the focus to a control of the dialog, selecting the text if 712 * the control is an edit dialog that has DLGC_HASSETSEL. 713 */ 714 static void DEFDLG_SetFocus( HWND hwndCtrl ) 715 { 716 if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL) 717 SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 ); 718 SetFocus( hwndCtrl ); 719 } 720 721 722 /*********************************************************************** 723 * DEFDLG_SaveFocus 724 */ 725 static void DEFDLG_SaveFocus( HWND hwnd ) 726 { 727 DIALOGINFO *infoPtr; 728 HWND hwndFocus = GetFocus(); 729 730 if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return; 731 if (!(infoPtr = GETDLGINFO(hwnd))) return; 732 infoPtr->hwndFocus = hwndFocus; 733 /* Remove default button */ 734 } 735 736 737 /*********************************************************************** 738 * DEFDLG_RestoreFocus 739 */ 740 static void DEFDLG_RestoreFocus( HWND hwnd, BOOL justActivate ) 741 { 742 DIALOGINFO *infoPtr; 743 744 if (IsIconic( hwnd )) return; 745 if (!(infoPtr = GETDLGINFO(hwnd))) return; 746 /* Don't set the focus back to controls if EndDialog is already called.*/ 747 if (infoPtr->flags & DF_END) return; 748 if (!IsWindow(infoPtr->hwndFocus) || infoPtr->hwndFocus == hwnd) { 749 if (justActivate) return; 750 /* If no saved focus control exists, set focus to the first visible, 751 non-disabled, WS_TABSTOP control in the dialog */ 752 infoPtr->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE ); 753 /* If there are no WS_TABSTOP controls, set focus to the first visible, 754 non-disabled control in the dialog */ 755 if (!infoPtr->hwndFocus) infoPtr->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE ); 756 if (!IsWindow( infoPtr->hwndFocus )) return; 757 } 758 if (justActivate) 759 SetFocus( infoPtr->hwndFocus ); 760 else 761 DEFDLG_SetFocus( infoPtr->hwndFocus ); 762 763 infoPtr->hwndFocus = NULL; 764 } 765 766 /*********************************************************************** 767 * DIALOG_CreateIndirect 768 * Creates a dialog box window 769 * 770 * modal = TRUE if we are called from a modal dialog box. 771 * (it's more compatible to do it here, as under Windows the owner 772 * is never disabled if the dialog fails because of an invalid template) 773 */ 774 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, 775 HWND owner, DLGPROC dlgProc, LPARAM param, 776 BOOL unicode, HWND *modal_owner ) 777 { 778 HWND hwnd; 779 RECT rect; 780 POINT pos; 781 SIZE size; 782 DLG_TEMPLATE template; 783 DIALOGINFO * dlgInfo = NULL; 784 DWORD units = GetDialogBaseUnits(); 785 HWND disabled_owner = NULL; 786 HMENU hMenu = 0; 787 HFONT hUserFont = 0; 788 UINT flags = 0; 789 UINT xBaseUnit = LOWORD(units); 790 UINT yBaseUnit = HIWORD(units); 791 792 /* Parse dialog template */ 793 794 if (!dlgTemplate) return 0; 795 dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template ); 796 797 /* Load menu */ 798 799 if (template.menuName) hMenu = LoadMenuW( hInst, template.menuName ); 800 801 /* Create custom font if needed */ 802 803 if (template.style & DS_SETFONT) 804 { 805 HDC dc = GetDC(0); 806 807 if (template.pointSize == 0x7fff) 808 { 809 /* We get the message font from the non-client metrics */ 810 NONCLIENTMETRICSW ncMetrics; 811 812 ncMetrics.cbSize = sizeof(NONCLIENTMETRICSW); 813 if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 814 sizeof(NONCLIENTMETRICSW), &ncMetrics, 0)) 815 { 816 hUserFont = CreateFontIndirectW( &ncMetrics.lfMessageFont ); 817 } 818 } 819 else 820 { 821 /* We convert the size to pixels and then make it -ve. This works 822 * for both +ve and -ve template.pointSize */ 823 int pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72); 824 hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight, 825 template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0, 826 PROOF_QUALITY, FF_DONTCARE, 827 template.faceName ); 828 } 829 830 if (hUserFont) 831 { 832 SIZE charSize; 833 HFONT hOldFont = SelectObject( dc, hUserFont ); 834 charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy ); 835 if (charSize.cx) 836 { 837 xBaseUnit = charSize.cx; 838 yBaseUnit = charSize.cy; 839 } 840 SelectObject( dc, hOldFont ); 841 } 842 ReleaseDC(0, dc); 843 TRACE("units = %d,%d\n", xBaseUnit, yBaseUnit ); 844 } 845 846 /* Create dialog main window */ 847 848 SetRect(&rect, 0, 0, MulDiv(template.cx, xBaseUnit, 4), MulDiv(template.cy, yBaseUnit, 8)); 849 if (template.style & DS_CONTROL) 850 template.style &= ~(WS_CAPTION|WS_SYSMENU); 851 template.style |= DS_3DLOOK; 852 if (template.style & DS_MODALFRAME) 853 template.exStyle |= WS_EX_DLGMODALFRAME; 854 if ((template.style & DS_CONTROL) || !(template.style & WS_CHILD)) 855 template.exStyle |= WS_EX_CONTROLPARENT; 856 AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle ); 857 pos.x = rect.left; 858 pos.y = rect.top; 859 size.cx = rect.right - rect.left; 860 size.cy = rect.bottom - rect.top; 861 862 if (template.x == CW_USEDEFAULT16) 863 { 864 pos.x = pos.y = CW_USEDEFAULT; 865 } 866 else 867 { 868 HMONITOR monitor = 0; 869 MONITORINFO mon_info; 870 871 mon_info.cbSize = sizeof(mon_info); 872 if (template.style & DS_CENTER) 873 { 874 monitor = MonitorFromWindow( owner ? owner : GetActiveWindow(), MONITOR_DEFAULTTOPRIMARY ); 875 GetMonitorInfoW( monitor, &mon_info ); 876 pos.x = (mon_info.rcWork.left + mon_info.rcWork.right - size.cx) / 2; 877 pos.y = (mon_info.rcWork.top + mon_info.rcWork.bottom - size.cy) / 2; 878 } 879 else if (template.style & DS_CENTERMOUSE) 880 { 881 GetCursorPos( &pos ); 882 monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY ); 883 GetMonitorInfoW( monitor, &mon_info ); 884 } 885 else 886 { 887 pos.x += MulDiv(template.x, xBaseUnit, 4); 888 pos.y += MulDiv(template.y, yBaseUnit, 8); 889 // 890 // REACTOS : Need an owner to be passed!!! 891 // 892 if (!(template.style & (WS_CHILD|DS_ABSALIGN)) && owner ) ClientToScreen( owner, &pos ); 893 } 894 if ( !(template.style & WS_CHILD) ) 895 { 896 INT dX, dY; 897 898 /* try to fit it into the desktop */ 899 900 if (!monitor) 901 { 902 SetRect( &rect, pos.x, pos.y, pos.x + size.cx, pos.y + size.cy ); 903 monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY ); 904 GetMonitorInfoW( monitor, &mon_info ); 905 } 906 if ((dX = pos.x + size.cx + GetSystemMetrics(SM_CXDLGFRAME) - mon_info.rcWork.right) > 0) 907 pos.x -= dX; 908 if ((dY = pos.y + size.cy + GetSystemMetrics(SM_CYDLGFRAME) - mon_info.rcWork.bottom) > 0) 909 pos.y -= dY; 910 if( pos.x < mon_info.rcWork.left ) pos.x = mon_info.rcWork.left; 911 if( pos.y < mon_info.rcWork.top ) pos.y = mon_info.rcWork.top; 912 } 913 } 914 915 if (modal_owner && owner) 916 { 917 HWND parent = NULL; 918 /* 919 * Owner needs to be top level window. We need to duplicate the logic from server, 920 * because we need to disable it before creating dialog window. Note that we do that 921 * even if dialog has WS_CHILD, but only for modal dialogs, which matched what 922 * Windows does. 923 */ 924 while ((GetWindowLongW( owner, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD) 925 { 926 parent = GetParent( owner ); 927 if (!parent || parent == GetDesktopWindow()) break; 928 owner = parent; 929 } 930 ////// Wine'ie babies need to fix your code!!!! CORE-11633 931 if (!parent) parent = GetAncestor( owner, GA_ROOT ); 932 933 if (parent) 934 { 935 owner = parent; 936 937 if (IsWindowEnabled( owner )) 938 { 939 HWND captured = NULL; 940 disabled_owner = owner; 941 EnableWindow( disabled_owner, FALSE ); 942 943 captured = GetCapture(); 944 945 if (captured) 946 SendMessageW(captured, WM_CANCELMODE, 0, 0); 947 } 948 } 949 *modal_owner = owner; 950 } 951 952 if (unicode) 953 { 954 hwnd = CreateWindowExW(template.exStyle, template.className, template.caption, 955 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy, 956 owner, hMenu, hInst, NULL ); 957 } 958 else 959 { 960 LPCSTR class = (LPCSTR)template.className; 961 LPCSTR caption = (LPCSTR)template.caption; 962 LPSTR class_tmp = NULL; 963 LPSTR caption_tmp = NULL; 964 965 if (!IS_INTRESOURCE(class)) 966 { 967 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL ); 968 class_tmp = HeapAlloc( GetProcessHeap(), 0, len ); 969 WideCharToMultiByte( CP_ACP, 0, template.className, -1, class_tmp, len, NULL, NULL ); 970 class = class_tmp; 971 } 972 if (!IS_INTRESOURCE(caption)) 973 { 974 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL ); 975 caption_tmp = HeapAlloc( GetProcessHeap(), 0, len ); 976 WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption_tmp, len, NULL, NULL ); 977 caption = caption_tmp; 978 } 979 hwnd = CreateWindowExA(template.exStyle, class, caption, 980 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy, 981 owner, hMenu, hInst, NULL ); 982 HeapFree( GetProcessHeap(), 0, class_tmp ); 983 HeapFree( GetProcessHeap(), 0, caption_tmp ); 984 } 985 986 if (!hwnd) 987 { 988 if (hUserFont) DeleteObject( hUserFont ); 989 if (hMenu) DestroyMenu( hMenu ); 990 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 991 return 0; 992 } 993 994 /* moved this from the top of the method to here as DIALOGINFO structure 995 will be valid only after WM_CREATE message has been handled in DefDlgProc 996 All the members of the structure get filled here using temp variables */ 997 dlgInfo = DIALOG_get_info( hwnd, TRUE ); 998 // ReactOS 999 if (dlgInfo == NULL) 1000 { 1001 if (hUserFont) DeleteObject( hUserFont ); 1002 if (hMenu) DestroyMenu( hMenu ); 1003 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 1004 return 0; 1005 } 1006 // 1007 dlgInfo->hwndFocus = 0; 1008 dlgInfo->hUserFont = hUserFont; 1009 dlgInfo->hMenu = hMenu; 1010 dlgInfo->xBaseUnit = xBaseUnit; 1011 dlgInfo->yBaseUnit = yBaseUnit; 1012 dlgInfo->flags = flags; 1013 1014 if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId ); 1015 1016 if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); 1017 else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); 1018 1019 if (dlgProc && dlgInfo->hUserFont) 1020 SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 ); 1021 1022 /* Create controls */ 1023 1024 if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode )) 1025 { 1026 /* Send initialisation messages and set focus */ 1027 1028 if (dlgProc) 1029 { 1030 HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE ); 1031 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE ); 1032 if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) && 1033 ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE))) 1034 { 1035 /* By returning TRUE, app has requested a default focus assignment. 1036 * WM_INITDIALOG may have changed the tab order, so find the first 1037 * tabstop control again. */ 1038 focus = GetNextDlgTabItem( hwnd, 0, FALSE ); 1039 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE ); 1040 if (focus) 1041 { 1042 if (SendMessageW( focus, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL) 1043 SendMessageW( focus, EM_SETSEL, 0, MAXLONG ); 1044 SetFocus( focus ); 1045 } 1046 else 1047 { 1048 if (!(template.style & WS_CHILD)) 1049 SetFocus( hwnd ); 1050 } 1051 } 1052 //// ReactOS see 43396, Fixes setting focus on Open and Close dialogs to the FileName edit control in OpenOffice. 1053 //// This now breaks test_SaveRestoreFocus. 1054 //DEFDLG_SaveFocus( hwnd ); 1055 //// 1056 } 1057 //// ReactOS Rev 30613 & 30644 1058 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_CHILD)) 1059 SendMessageW( hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); 1060 //// 1061 if (template.style & WS_VISIBLE && !(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_VISIBLE)) 1062 { 1063 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */ 1064 UpdateWindow( hwnd ); 1065 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGSTART, hwnd, OBJID_WINDOW, CHILDID_SELF, 0); 1066 } 1067 return hwnd; 1068 } 1069 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 1070 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGEND, hwnd, OBJID_WINDOW, CHILDID_SELF, 0); 1071 if( IsWindow(hwnd) ) 1072 { 1073 DestroyWindow( hwnd ); 1074 //// ReactOS 1075 if (owner) 1076 { ERR("DIALOG_CreateIndirect 1\n"); 1077 if ( NtUserGetThreadState(THREADSTATE_FOREGROUNDTHREAD) && // Rule #1. 1078 !NtUserQueryWindow(owner, QUERY_WINDOW_FOREGROUND) ) 1079 { ERR("DIALOG_CreateIndirect SFW\n"); 1080 SetForegroundWindow(owner); 1081 } 1082 } 1083 //// 1084 } 1085 return 0; 1086 } 1087 1088 1089 /*********************************************************************** 1090 * DEFDLG_FindDefButton 1091 * 1092 * Find the current default push-button. 1093 */ 1094 static HWND DEFDLG_FindDefButton( HWND hwndDlg ) 1095 { 1096 HWND hwndChild, hwndTmp; 1097 1098 hwndChild = GetWindow( hwndDlg, GW_CHILD ); 1099 while (hwndChild) 1100 { 1101 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON) 1102 break; 1103 1104 /* Recurse into WS_EX_CONTROLPARENT controls */ 1105 if (GetWindowLongPtrW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT) 1106 { 1107 LONG dsStyle = GetWindowLongPtrW( hwndChild, GWL_STYLE ); 1108 if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) && 1109 (hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL) 1110 return hwndTmp; 1111 } 1112 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT ); 1113 } 1114 return hwndChild; 1115 } 1116 1117 1118 /*********************************************************************** 1119 * DEFDLG_SetDefId 1120 * 1121 * Set the default button id. 1122 */ 1123 static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam) 1124 { 1125 DWORD dlgcode=0; /* initialize just to avoid a warning */ 1126 HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam); 1127 INT old_id = dlgInfo->idResult; 1128 1129 dlgInfo->idResult = wParam; 1130 if (hwndNew && 1131 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) 1132 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON))) 1133 return FALSE; /* Destination is not a push button */ 1134 1135 /* Make sure the old default control is a valid push button ID */ 1136 hwndOld = GetDlgItem( hwndDlg, old_id ); 1137 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 1138 hwndOld = DEFDLG_FindDefButton( hwndDlg ); 1139 if (hwndOld && hwndOld != hwndNew) 1140 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); 1141 1142 if (hwndNew) 1143 { 1144 if(dlgcode & DLGC_UNDEFPUSHBUTTON) 1145 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); 1146 } 1147 return TRUE; 1148 } 1149 1150 1151 /*********************************************************************** 1152 * DEFDLG_SetDefButton 1153 * 1154 * Set the new default button to be hwndNew. 1155 */ 1156 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew ) 1157 { 1158 DWORD dlgcode=0; /* initialize just to avoid a warning */ 1159 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult ); 1160 1161 if (hwndNew && 1162 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) 1163 & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON))) 1164 { 1165 /** 1166 * Need to draw only default push button rectangle. 1167 * Since the next control is not a push button, need to draw the push 1168 * button rectangle for the default control. 1169 */ 1170 hwndNew = hwndOld; 1171 dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ); 1172 } 1173 1174 /* Make sure the old default control is a valid push button ID */ 1175 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 1176 hwndOld = DEFDLG_FindDefButton( hwndDlg ); 1177 if (hwndOld && hwndOld != hwndNew) 1178 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); 1179 1180 if (hwndNew) 1181 { 1182 if(dlgcode & DLGC_UNDEFPUSHBUTTON) 1183 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); 1184 } 1185 return TRUE; 1186 } 1187 1188 #ifdef __REACTOS__ 1189 static void DEFDLG_Reposition(HWND hwnd) 1190 { 1191 HMONITOR hMon; 1192 MONITORINFO mi = { sizeof(mi) }; 1193 RECT rc; 1194 LONG cx, cy; 1195 1196 if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) 1197 return; 1198 1199 if (IsIconic(hwnd)) 1200 return; 1201 1202 hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 1203 1204 if (!GetMonitorInfoW(hMon, &mi) || !GetWindowRect(hwnd, &rc)) 1205 return; 1206 1207 cx = rc.right - rc.left; 1208 cy = rc.bottom - rc.top; 1209 1210 if (rc.right > mi.rcWork.right) 1211 { 1212 rc.right = mi.rcWork.right; 1213 rc.left = rc.right - cx; 1214 } 1215 if (rc.bottom > mi.rcWork.bottom - 4) 1216 { 1217 rc.bottom = mi.rcWork.bottom - 4; 1218 rc.top = rc.bottom - cy; 1219 } 1220 1221 if (rc.left < mi.rcWork.left) 1222 { 1223 rc.left = mi.rcWork.left; 1224 } 1225 if (rc.top < mi.rcWork.top) 1226 { 1227 rc.top = mi.rcWork.top; 1228 } 1229 1230 SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, 1231 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | 1232 SWP_NOZORDER); 1233 } 1234 #endif 1235 /*********************************************************************** 1236 * DEFDLG_Proc 1237 * 1238 * Implementation of DefDlgProc(). Only handle messages that need special 1239 * handling for dialogs. 1240 */ 1241 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam, 1242 LPARAM lParam, DIALOGINFO *dlgInfo ) 1243 { 1244 switch(msg) 1245 { 1246 case WM_ERASEBKGND: 1247 { 1248 HBRUSH brush = GetControlColor( hwnd, hwnd, (HDC)wParam, WM_CTLCOLORDLG); 1249 if (brush) 1250 { 1251 RECT rect; 1252 HDC hdc = (HDC)wParam; 1253 GetClientRect( hwnd, &rect ); 1254 DPtoLP( hdc, (LPPOINT)&rect, 2 ); 1255 FillRect( hdc, &rect, brush ); 1256 } 1257 return 1; 1258 } 1259 case WM_NCDESTROY: 1260 //// ReactOS 1261 if ((dlgInfo = (DIALOGINFO *)SetWindowLongPtrW( hwnd, DWLP_ROS_DIALOGINFO, 0 ))) 1262 { 1263 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont ); 1264 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu ); 1265 HeapFree( GetProcessHeap(), 0, dlgInfo ); 1266 NtUserSetThreadState(0,DF_DIALOGACTIVE); 1267 NtUserxSetDialogPointer( hwnd, 0 ); 1268 } 1269 /* Window clean-up */ 1270 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1271 1272 case WM_SHOWWINDOW: 1273 if (!wParam) DEFDLG_SaveFocus( hwnd ); 1274 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1275 1276 case WM_ACTIVATE: 1277 { // ReactOS 1278 DWORD dwSetFlag; 1279 HWND hwndparent = DIALOG_FindMsgDestination( hwnd ); 1280 // if WA_CLICK/ACTIVE ? set dialog is active. 1281 dwSetFlag = wParam ? DF_DIALOGACTIVE : 0; 1282 if (hwndparent != hwnd) NtUserSetThreadState(dwSetFlag, DF_DIALOGACTIVE); 1283 } 1284 if (wParam) DEFDLG_RestoreFocus( hwnd, TRUE ); 1285 else DEFDLG_SaveFocus( hwnd ); 1286 return 0; 1287 1288 case WM_SETFOCUS: 1289 DEFDLG_RestoreFocus( hwnd, FALSE ); 1290 return 0; 1291 1292 case DM_SETDEFID: 1293 if (dlgInfo && !(dlgInfo->flags & DF_END)) 1294 DEFDLG_SetDefId( hwnd, dlgInfo, wParam ); 1295 return 1; 1296 1297 case DM_GETDEFID: 1298 if (dlgInfo && !(dlgInfo->flags & DF_END)) 1299 { 1300 HWND hwndDefId; 1301 if (dlgInfo->idResult) 1302 return MAKELONG( dlgInfo->idResult, DC_HASDEFID ); 1303 if ((hwndDefId = DEFDLG_FindDefButton( hwnd ))) 1304 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID); 1305 } 1306 return 0; 1307 1308 #ifdef __REACTOS__ 1309 case DM_REPOSITION: 1310 DEFDLG_Reposition(hwnd); 1311 return 0; 1312 #endif 1313 case WM_NEXTDLGCTL: 1314 if (dlgInfo) 1315 { 1316 HWND hwndDest = (HWND)wParam; 1317 if (!lParam) 1318 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam); 1319 if (hwndDest) DEFDLG_SetFocus( hwndDest ); 1320 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest ); 1321 } 1322 return 0; 1323 1324 case WM_ENTERMENULOOP: 1325 case WM_LBUTTONDOWN: 1326 case WM_NCLBUTTONDOWN: 1327 { 1328 HWND hwndFocus = GetFocus(); 1329 if (hwndFocus) 1330 { 1331 /* always make combo box hide its listbox control */ 1332 if (!SendMessageW( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 )) 1333 SendMessageW( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 ); 1334 } 1335 } 1336 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1337 1338 case WM_GETFONT: 1339 return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0; 1340 1341 case WM_CLOSE: 1342 PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 1343 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) ); 1344 return 0; 1345 } 1346 return 0; 1347 } 1348 1349 /*********************************************************************** 1350 * DEFDLG_Epilog 1351 */ 1352 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fResult, BOOL fAnsi) 1353 { 1354 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) || 1355 msg == WM_CTLCOLOR) 1356 { 1357 if (fResult) return fResult; 1358 1359 return fAnsi ? DefWindowProcA(hwnd, msg, wParam, lParam): 1360 DefWindowProcW(hwnd, msg, wParam, lParam); 1361 } 1362 if ( msg == WM_COMPAREITEM || 1363 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM || 1364 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG) 1365 return fResult; 1366 1367 return GetWindowLongPtrW( hwnd, DWLP_MSGRESULT ); 1368 } 1369 1370 /*********************************************************************** 1371 * DIALOG_GetNextTabItem 1372 * 1373 * Helper for GetNextDlgTabItem 1374 */ 1375 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious ) 1376 { 1377 LONG dsStyle; 1378 LONG exStyle; 1379 UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT; 1380 HWND retWnd = 0; 1381 HWND hChildFirst = 0; 1382 1383 if(!hwndCtrl) 1384 { 1385 hChildFirst = GetWindow(hwndDlg,GW_CHILD); 1386 if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST); 1387 } 1388 else if (IsChild( hwndMain, hwndCtrl )) 1389 { 1390 hChildFirst = GetWindow(hwndCtrl,wndSearch); 1391 if(!hChildFirst) 1392 { 1393 if(GetParent(hwndCtrl) != hwndMain) 1394 /* i.e. if we are not at the top level of the recursion */ 1395 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch); 1396 else 1397 hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST); 1398 } 1399 } 1400 1401 while(hChildFirst) 1402 { 1403 dsStyle = GetWindowLongPtrA(hChildFirst,GWL_STYLE); 1404 exStyle = GetWindowLongPtrA(hChildFirst,GWL_EXSTYLE); 1405 if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED)) 1406 { 1407 HWND retWnd; 1408 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious ); 1409 if (retWnd) return (retWnd); 1410 } 1411 else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED)) 1412 { 1413 return (hChildFirst); 1414 } 1415 hChildFirst = GetWindow(hChildFirst,wndSearch); 1416 } 1417 if(hwndCtrl) 1418 { 1419 HWND hParent = GetParent(hwndCtrl); 1420 while(hParent) 1421 { 1422 if(hParent == hwndMain) break; 1423 retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious ); 1424 if(retWnd) break; 1425 hParent = GetParent(hParent); 1426 } 1427 if(!retWnd) 1428 retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious ); 1429 } 1430 return retWnd ? retWnd : hwndCtrl; 1431 } 1432 1433 1434 /********************************************************************** 1435 * DIALOG_DlgDirListW 1436 * 1437 * Helper function for DlgDirList*W 1438 */ 1439 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox, 1440 INT idStatic, UINT attrib, BOOL combo ) 1441 { 1442 HWND hwnd; 1443 LPWSTR orig_spec = spec; 1444 WCHAR any[] = {'*','.','*',0}; 1445 WCHAR star[] = {'*',0}; 1446 1447 #define SENDMSG(msg,wparam,lparam) \ 1448 ((attrib & DDL_POSTMSGS) ? PostMessageW( hwnd, msg, wparam, lparam ) \ 1449 : SendMessageW( hwnd, msg, wparam, lparam )) 1450 1451 TRACE("%p %s %d %d %04x\n", hDlg, debugstr_w(spec), idLBox, idStatic, attrib ); 1452 1453 /* If the path exists and is a directory, chdir to it */ 1454 if (!spec || !spec[0] || SetCurrentDirectoryW( spec )) spec = star; 1455 else 1456 { 1457 WCHAR *p, *p2; 1458 1459 if (!strchrW(spec, '*') && !strchrW(spec, '?')) 1460 { 1461 SetLastError(ERROR_NO_WILDCARD_CHARACTERS); 1462 return FALSE; 1463 } 1464 p = spec; 1465 if ((p2 = strchrW( p, ':' ))) p = p2 + 1; 1466 if ((p2 = strrchrW( p, '\\' ))) p = p2; 1467 if ((p2 = strrchrW( p, '/' ))) p = p2; 1468 if (p != spec) 1469 { 1470 WCHAR sep = *p; 1471 *p = 0; 1472 if (!SetCurrentDirectoryW( spec )) 1473 { 1474 *p = sep; /* Restore the original spec */ 1475 return FALSE; 1476 } 1477 spec = p + 1; 1478 } 1479 } 1480 1481 TRACE( "mask=%s\n", spec ); 1482 1483 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0)) 1484 { 1485 if (attrib == DDL_DRIVES) attrib |= DDL_EXCLUSIVE; 1486 1487 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 ); 1488 if (attrib & DDL_DIRECTORY) 1489 { 1490 if (!(attrib & DDL_EXCLUSIVE)) 1491 { 1492 SENDMSG( combo ? CB_DIR : LB_DIR, 1493 attrib & ~(DDL_DIRECTORY | DDL_DRIVES), 1494 (LPARAM)spec ); 1495 } 1496 SENDMSG( combo ? CB_DIR : LB_DIR, 1497 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE, 1498 (LPARAM)any ); 1499 } 1500 else 1501 { 1502 SENDMSG( combo ? CB_DIR : LB_DIR, attrib, (LPARAM)spec ); 1503 } 1504 } 1505 1506 /* Convert path specification to uppercase */ 1507 if (spec) CharUpperW(spec); 1508 1509 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0)) 1510 { 1511 WCHAR temp[MAX_PATH]; 1512 GetCurrentDirectoryW( sizeof(temp)/sizeof(WCHAR), temp ); 1513 CharLowerW( temp ); 1514 /* Can't use PostMessage() here, because the string is on the stack */ 1515 SetDlgItemTextW( hDlg, idStatic, temp ); 1516 } 1517 1518 if (orig_spec && (spec != orig_spec)) 1519 { 1520 /* Update the original file spec */ 1521 WCHAR *p = spec; 1522 while ((*orig_spec++ = *p++)); 1523 } 1524 1525 return TRUE; 1526 #undef SENDMSG 1527 } 1528 1529 1530 /********************************************************************** 1531 * DIALOG_DlgDirListA 1532 * 1533 * Helper function for DlgDirList*A 1534 */ 1535 static INT DIALOG_DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox, 1536 INT idStatic, UINT attrib, BOOL combo ) 1537 { 1538 if (spec) 1539 { 1540 INT ret, len = MultiByteToWideChar( CP_ACP, 0, spec, -1, NULL, 0 ); 1541 LPWSTR specW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); 1542 if (specW == NULL) 1543 return FALSE; 1544 MultiByteToWideChar( CP_ACP, 0, spec, -1, specW, len ); 1545 ret = DIALOG_DlgDirListW( hDlg, specW, idLBox, idStatic, attrib, combo ); 1546 WideCharToMultiByte( CP_ACP, 0, specW, -1, spec, 0x7fffffff, NULL, NULL ); 1547 HeapFree( GetProcessHeap(), 0, specW ); 1548 return ret; 1549 } 1550 return DIALOG_DlgDirListW( hDlg, NULL, idLBox, idStatic, attrib, combo ); 1551 } 1552 1553 /********************************************************************** 1554 * DIALOG_DlgDirSelect 1555 * 1556 * Helper function for DlgDirSelect* 1557 */ 1558 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPWSTR str, INT len, 1559 INT id, BOOL unicode, BOOL combo ) 1560 { 1561 WCHAR *buffer, *ptr; 1562 INT item, size; 1563 BOOL ret; 1564 HWND listbox = GetDlgItem( hwnd, id ); 1565 1566 TRACE("%p %s %d\n", hwnd, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str), id ); 1567 if (!listbox) return FALSE; 1568 1569 item = SendMessageW(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 ); 1570 if (item == LB_ERR) return FALSE; 1571 1572 size = SendMessageW(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, item, 0 ); 1573 if (size == LB_ERR) return FALSE; 1574 1575 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size+2) * sizeof(WCHAR) ))) return FALSE; 1576 1577 SendMessageW( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer ); 1578 1579 if ((ret = (buffer[0] == '['))) /* drive or directory */ 1580 { 1581 if (buffer[1] == '-') /* drive */ 1582 { 1583 buffer[3] = ':'; 1584 buffer[4] = 0; 1585 ptr = buffer + 2; 1586 } 1587 else 1588 { 1589 buffer[strlenW(buffer)-1] = '\\'; 1590 ptr = buffer + 1; 1591 } 1592 } 1593 else 1594 { 1595 /* Filenames without a dot extension must have one tacked at the end */ 1596 if (strchrW(buffer, '.') == NULL) 1597 { 1598 buffer[strlenW(buffer)+1] = '\0'; 1599 buffer[strlenW(buffer)] = '.'; 1600 } 1601 ptr = buffer; 1602 } 1603 1604 if (!unicode) 1605 { 1606 if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, ptr, -1, (LPSTR)str, len, 0, 0 )) 1607 ((LPSTR)str)[len-1] = 0; 1608 } 1609 else lstrcpynW( str, ptr, len ); 1610 HeapFree( GetProcessHeap(), 0, buffer ); 1611 TRACE("Returning %d %s\n", ret, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str) ); 1612 return ret; 1613 } 1614 1615 1616 /* FUNCTIONS *****************************************************************/ 1617 1618 /* 1619 * @implemented 1620 */ 1621 HWND 1622 WINAPI 1623 CreateDialogIndirectParamAorW( 1624 HINSTANCE hInstance, 1625 LPCDLGTEMPLATE lpTemplate, 1626 HWND hWndParent, 1627 DLGPROC lpDialogFunc, 1628 LPARAM lParamInit, 1629 DWORD Flags) 1630 { 1631 /* FIXME: 1632 * This function might be obsolete since I don't think it is exported by NT 1633 * Also wine has one more parameter identifying weather it should call 1634 * the function with unicode or not 1635 */ 1636 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit , Flags == DLG_ISANSI ? FALSE : TRUE, NULL ); 1637 } 1638 1639 1640 /* 1641 * @implemented 1642 */ 1643 HWND 1644 WINAPI 1645 CreateDialogIndirectParamA( 1646 HINSTANCE hInstance, 1647 LPCDLGTEMPLATE lpTemplate, 1648 HWND hWndParent, 1649 DLGPROC lpDialogFunc, 1650 LPARAM lParamInit) 1651 { 1652 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, DLG_ISANSI); 1653 } 1654 1655 1656 /* 1657 * @implemented 1658 */ 1659 HWND 1660 WINAPI 1661 CreateDialogIndirectParamW( 1662 HINSTANCE hInstance, 1663 LPCDLGTEMPLATE lpTemplate, 1664 HWND hWndParent, 1665 DLGPROC lpDialogFunc, 1666 LPARAM lParamInit) 1667 { 1668 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, 0); 1669 } 1670 1671 1672 /* 1673 * @implemented 1674 */ 1675 HWND 1676 WINAPI 1677 CreateDialogParamA( 1678 HINSTANCE hInstance, 1679 LPCSTR lpTemplateName, 1680 HWND hWndParent, 1681 DLGPROC lpDialogFunc, 1682 LPARAM dwInitParam) 1683 { 1684 HRSRC hrsrc; 1685 LPCDLGTEMPLATE ptr; 1686 1687 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0; 1688 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0; 1689 return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam ); 1690 } 1691 1692 1693 /* 1694 * @implemented 1695 */ 1696 HWND 1697 WINAPI 1698 CreateDialogParamW( 1699 HINSTANCE hInstance, 1700 LPCWSTR lpTemplateName, 1701 HWND hWndParent, 1702 DLGPROC lpDialogFunc, 1703 LPARAM dwInitParam) 1704 { 1705 HRSRC hrsrc; 1706 LPCDLGTEMPLATE ptr; 1707 1708 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0; 1709 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0; 1710 return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam ); 1711 } 1712 1713 1714 /* 1715 * @implemented 1716 */ 1717 LRESULT 1718 WINAPI 1719 DefDlgProcA( 1720 HWND hDlg, 1721 UINT Msg, 1722 WPARAM wParam, 1723 LPARAM lParam) 1724 { 1725 DIALOGINFO *dlgInfo; 1726 WNDPROC dlgproc; 1727 BOOL result = FALSE; 1728 1729 /* Perform DIALOGINFO initialization if not done */ 1730 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass. 1731 1732 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 ); 1733 1734 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC ))) 1735 { 1736 /* Call dialog procedure */ 1737 result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam ); 1738 } 1739 1740 if (!result && IsWindow(hDlg)) 1741 { 1742 /* callback didn't process this message */ 1743 1744 switch(Msg) 1745 { 1746 case WM_ERASEBKGND: 1747 case WM_SHOWWINDOW: 1748 case WM_ACTIVATE: 1749 case WM_SETFOCUS: 1750 case DM_SETDEFID: 1751 case DM_GETDEFID: 1752 #ifdef __REACTOS__ 1753 case DM_REPOSITION: 1754 #endif 1755 case WM_NEXTDLGCTL: 1756 case WM_GETFONT: 1757 case WM_CLOSE: 1758 case WM_NCDESTROY: 1759 case WM_ENTERMENULOOP: 1760 case WM_LBUTTONDOWN: 1761 case WM_NCLBUTTONDOWN: 1762 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo ); 1763 case WM_INITDIALOG: 1764 case WM_VKEYTOITEM: 1765 case WM_COMPAREITEM: 1766 case WM_CHARTOITEM: 1767 break; 1768 1769 default: 1770 return DefWindowProcA( hDlg, Msg, wParam, lParam ); 1771 } 1772 } 1773 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, TRUE); 1774 } 1775 1776 1777 /* 1778 * @implemented 1779 */ 1780 LRESULT 1781 WINAPI 1782 DefDlgProcW( 1783 HWND hDlg, 1784 UINT Msg, 1785 WPARAM wParam, 1786 LPARAM lParam) 1787 { 1788 DIALOGINFO *dlgInfo; 1789 WNDPROC dlgproc; 1790 BOOL result = FALSE; 1791 1792 /* Perform DIALOGINFO initialization if not done */ 1793 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass. 1794 1795 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 ); 1796 1797 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC ))) 1798 { 1799 /* Call dialog procedure */ 1800 result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam ); 1801 } 1802 1803 if (!result && IsWindow(hDlg)) 1804 { 1805 /* callback didn't process this message */ 1806 1807 switch(Msg) 1808 { 1809 case WM_ERASEBKGND: 1810 case WM_SHOWWINDOW: 1811 case WM_ACTIVATE: 1812 case WM_SETFOCUS: 1813 case DM_SETDEFID: 1814 case DM_GETDEFID: 1815 #ifdef __REACTOS__ 1816 case DM_REPOSITION: 1817 #endif 1818 case WM_NEXTDLGCTL: 1819 case WM_GETFONT: 1820 case WM_CLOSE: 1821 case WM_NCDESTROY: 1822 case WM_ENTERMENULOOP: 1823 case WM_LBUTTONDOWN: 1824 case WM_NCLBUTTONDOWN: 1825 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo ); 1826 case WM_INITDIALOG: 1827 case WM_VKEYTOITEM: 1828 case WM_COMPAREITEM: 1829 case WM_CHARTOITEM: 1830 break; 1831 1832 default: 1833 return DefWindowProcW( hDlg, Msg, wParam, lParam ); 1834 } 1835 } 1836 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, FALSE); 1837 } 1838 1839 1840 /* 1841 * @implemented 1842 */ 1843 INT_PTR 1844 WINAPI 1845 DialogBoxIndirectParamAorW( 1846 HINSTANCE hInstance, 1847 LPCDLGTEMPLATE hDialogTemplate, 1848 HWND hWndParent, 1849 DLGPROC lpDialogFunc, 1850 LPARAM dwInitParam, 1851 DWORD Flags) 1852 { 1853 /* FIXME: 1854 * This function might be obsolete since I don't think it is exported by NT 1855 * Also wine has one more parameter identifying weather it should call 1856 * the function with unicode or not 1857 */ 1858 HWND hWnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, Flags == DLG_ISANSI ? FALSE : TRUE, &hWndParent ); 1859 if (hWnd) return DIALOG_DoDialogBox( hWnd, hWndParent ); 1860 return -1; 1861 } 1862 1863 1864 /* 1865 * @implemented 1866 */ 1867 INT_PTR 1868 WINAPI 1869 DialogBoxIndirectParamA( 1870 HINSTANCE hInstance, 1871 LPCDLGTEMPLATE hDialogTemplate, 1872 HWND hWndParent, 1873 DLGPROC lpDialogFunc, 1874 LPARAM dwInitParam) 1875 { 1876 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, DLG_ISANSI); 1877 } 1878 1879 1880 /* 1881 * @implemented 1882 */ 1883 INT_PTR 1884 WINAPI 1885 DialogBoxIndirectParamW( 1886 HINSTANCE hInstance, 1887 LPCDLGTEMPLATE hDialogTemplate, 1888 HWND hWndParent, 1889 DLGPROC lpDialogFunc, 1890 LPARAM dwInitParam) 1891 { 1892 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, 0); 1893 } 1894 1895 1896 /* 1897 * @implemented 1898 */ 1899 INT_PTR 1900 WINAPI 1901 DialogBoxParamA( 1902 HINSTANCE hInstance, 1903 LPCSTR lpTemplateName, 1904 HWND hWndParent, 1905 DLGPROC lpDialogFunc, 1906 LPARAM dwInitParam) 1907 { 1908 HWND hwnd; 1909 HRSRC hrsrc; 1910 LPCDLGTEMPLATE ptr; 1911 //// ReactOS rev 33532 1912 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG )) || 1913 !(ptr = LoadResource(hInstance, hrsrc))) 1914 { 1915 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1916 return -1; 1917 } 1918 if (hWndParent != NULL && !IsWindow(hWndParent)) 1919 { 1920 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1921 return 0; 1922 } 1923 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, &hWndParent ); 1924 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent); 1925 return -1; 1926 } 1927 1928 1929 /* 1930 * @implemented 1931 */ 1932 INT_PTR 1933 WINAPI 1934 DialogBoxParamW( 1935 HINSTANCE hInstance, 1936 LPCWSTR lpTemplateName, 1937 HWND hWndParent, 1938 DLGPROC lpDialogFunc, 1939 LPARAM dwInitParam) 1940 { 1941 HWND hwnd; 1942 HRSRC hrsrc; 1943 LPCDLGTEMPLATE ptr; 1944 //// ReactOS rev 33532 1945 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG )) || 1946 !(ptr = LoadResource(hInstance, hrsrc))) 1947 { 1948 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1949 return -1; 1950 } 1951 if (hWndParent != NULL && !IsWindow(hWndParent)) 1952 { 1953 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1954 return 0; 1955 } 1956 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, &hWndParent ); 1957 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent); 1958 return -1; 1959 } 1960 1961 1962 /* 1963 * @implemented 1964 */ 1965 int 1966 WINAPI 1967 DlgDirListA( 1968 HWND hDlg, 1969 LPSTR lpPathSpec, 1970 int nIDListBox, 1971 int nIDStaticPath, 1972 UINT uFileType) 1973 { 1974 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE ); 1975 } 1976 1977 1978 /* 1979 * @implemented 1980 */ 1981 int 1982 WINAPI 1983 DlgDirListComboBoxA( 1984 HWND hDlg, 1985 LPSTR lpPathSpec, 1986 int nIDComboBox, 1987 int nIDStaticPath, 1988 UINT uFiletype) 1989 { 1990 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE ); 1991 } 1992 1993 1994 /* 1995 * @implemented 1996 */ 1997 int 1998 WINAPI 1999 DlgDirListComboBoxW( 2000 HWND hDlg, 2001 LPWSTR lpPathSpec, 2002 int nIDComboBox, 2003 int nIDStaticPath, 2004 UINT uFiletype) 2005 { 2006 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE ); 2007 } 2008 2009 2010 /* 2011 * @implemented 2012 */ 2013 int 2014 WINAPI 2015 DlgDirListW( 2016 HWND hDlg, 2017 LPWSTR lpPathSpec, 2018 int nIDListBox, 2019 int nIDStaticPath, 2020 UINT uFileType) 2021 { 2022 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE ); 2023 } 2024 2025 2026 /* 2027 * @implemented 2028 */ 2029 BOOL 2030 WINAPI 2031 DlgDirSelectComboBoxExA( 2032 HWND hDlg, 2033 LPSTR lpString, 2034 int nCount, 2035 int nIDComboBox) 2036 { 2037 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, FALSE, TRUE ); 2038 } 2039 2040 2041 /* 2042 * @implemented 2043 */ 2044 BOOL 2045 WINAPI 2046 DlgDirSelectComboBoxExW( 2047 HWND hDlg, 2048 LPWSTR lpString, 2049 int nCount, 2050 int nIDComboBox) 2051 { 2052 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, TRUE, TRUE ); 2053 } 2054 2055 2056 /* 2057 * @implemented 2058 */ 2059 BOOL 2060 WINAPI 2061 DlgDirSelectExA( 2062 HWND hDlg, 2063 LPSTR lpString, 2064 int nCount, 2065 int nIDListBox) 2066 { 2067 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDListBox, FALSE, FALSE ); 2068 } 2069 2070 2071 /* 2072 * @implemented 2073 */ 2074 BOOL 2075 WINAPI 2076 DlgDirSelectExW( 2077 HWND hDlg, 2078 LPWSTR lpString, 2079 int nCount, 2080 int nIDListBox) 2081 { 2082 return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, TRUE, FALSE ); 2083 } 2084 2085 2086 /* 2087 * @implemented Modified for ReactOS. Do not Port Sync!!! 2088 */ 2089 BOOL 2090 WINAPI 2091 EndDialog( 2092 HWND hwnd, 2093 INT_PTR retval) 2094 { 2095 DIALOGINFO * dlgInfo; 2096 HWND owner; 2097 BOOL wasActive; 2098 2099 TRACE("%p %ld\n", hwnd, retval ); 2100 2101 if (!(dlgInfo = GETDLGINFO(hwnd))) 2102 { 2103 ERR("got invalid window handle (%p); buggy app !?\n", hwnd); 2104 return FALSE; 2105 } 2106 wasActive = (hwnd == GetActiveWindow()); 2107 dlgInfo->idResult = retval; 2108 dlgInfo->flags |= DF_END; 2109 2110 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD) 2111 { 2112 owner = GetAncestor( hwnd, GA_PARENT); 2113 } 2114 else 2115 owner = GetWindow( hwnd, GW_OWNER ); 2116 2117 if (owner) 2118 EnableWindow( owner, TRUE ); 2119 2120 /* Windows sets the focus to the dialog itself in EndDialog */ 2121 2122 if (wasActive && IsChild(hwnd, GetFocus())) 2123 SetFocus( hwnd ); 2124 2125 /* Don't have to send a ShowWindow(SW_HIDE), just do 2126 SetWindowPos with SWP_HIDEWINDOW as done in Windows */ 2127 2128 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE 2129 | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW); 2130 2131 if (wasActive && owner) 2132 { 2133 /* If this dialog was given an owner then set the focus to that owner. */ 2134 SetActiveWindow(owner); 2135 } 2136 else if (hwnd == GetActiveWindow()) // Check it again! 2137 { 2138 NtUserCallNoParam(NOPARAM_ROUTINE_ZAPACTIVEANDFOUS); 2139 } 2140 2141 /* unblock dialog loop */ 2142 PostMessageA(hwnd, WM_NULL, 0, 0); 2143 return TRUE; 2144 } 2145 2146 2147 /* 2148 * @implemented 2149 */ 2150 LONG 2151 WINAPI 2152 GetDialogBaseUnits(VOID) 2153 { 2154 static DWORD units; 2155 2156 if (!units) 2157 { 2158 HDC hdc; 2159 SIZE size; 2160 2161 if ((hdc = GetDC(0))) 2162 { 2163 size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy ); 2164 if (size.cx) units = MAKELONG( size.cx, size.cy ); 2165 ReleaseDC( 0, hdc ); 2166 } 2167 } 2168 return units; 2169 } 2170 2171 2172 /* 2173 * @implemented 2174 */ 2175 int 2176 WINAPI 2177 GetDlgCtrlID( 2178 HWND hwndCtl) 2179 { 2180 return GetWindowLongPtrW( hwndCtl, GWLP_ID ); 2181 } 2182 2183 2184 /* 2185 * @implemented 2186 */ 2187 HWND 2188 WINAPI 2189 GetDlgItem( 2190 HWND hDlg, 2191 int nIDDlgItem) 2192 { 2193 int i; 2194 HWND *list; 2195 HWND ret = 0; 2196 2197 if (!hDlg) return 0; 2198 2199 list = WIN_ListChildren(hDlg); 2200 if (!list) return 0; 2201 2202 for (i = 0; list[i]; i++) if (GetWindowLongPtrW(list[i], GWLP_ID) == nIDDlgItem) break; 2203 ret = list[i]; 2204 HeapFree(GetProcessHeap(), 0, list); 2205 // if (!ret) SetLastError(ERROR_CONTROL_ID_NOT_FOUND); 2206 return ret; 2207 } 2208 2209 2210 /* 2211 * @implemented 2212 */ 2213 UINT 2214 WINAPI 2215 GetDlgItemInt( 2216 HWND hDlg, 2217 int nIDDlgItem, 2218 BOOL *lpTranslated, 2219 BOOL bSigned) 2220 { 2221 char str[30]; 2222 char * endptr; 2223 LONG_PTR result = 0; 2224 2225 if (lpTranslated) *lpTranslated = FALSE; 2226 if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str)) 2227 return 0; 2228 if (bSigned) 2229 { 2230 result = strtol( str, &endptr, 10 ); 2231 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ 2232 return 0; 2233 if (((result == LONG_MIN) || (result == LONG_MAX))) 2234 return 0; 2235 } 2236 else 2237 { 2238 result = strtoul( str, &endptr, 10 ); 2239 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ 2240 return 0; 2241 if (result == ULONG_MAX) return 0; 2242 } 2243 if (lpTranslated) *lpTranslated = TRUE; 2244 return (UINT)result; 2245 } 2246 2247 2248 /* 2249 * @implemented 2250 */ 2251 UINT 2252 WINAPI 2253 GetDlgItemTextA( 2254 HWND hDlg, 2255 int nIDDlgItem, 2256 LPSTR lpString, 2257 int nMaxCount) 2258 { 2259 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem); 2260 if ( hWnd ) return GetWindowTextA(hWnd, lpString, nMaxCount); 2261 if ( nMaxCount ) lpString[0] = '\0'; 2262 return 0; 2263 } 2264 2265 2266 /* 2267 * @implemented 2268 */ 2269 UINT 2270 WINAPI 2271 GetDlgItemTextW( 2272 HWND hDlg, 2273 int nIDDlgItem, 2274 LPWSTR lpString, 2275 int nMaxCount) 2276 { 2277 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem); 2278 if ( hWnd ) return GetWindowTextW(hWnd, lpString, nMaxCount); 2279 if ( nMaxCount ) lpString[0] = '\0'; 2280 return 0; 2281 } 2282 2283 /* 2284 * @implemented 2285 */ 2286 HWND 2287 WINAPI 2288 GetNextDlgGroupItem( 2289 HWND hDlg, 2290 HWND hCtl, 2291 BOOL bPrevious) 2292 { 2293 HWND hwnd, hwndNext, retvalue, hwndLastGroup = 0; 2294 BOOL fLooped=FALSE; 2295 BOOL fSkipping=FALSE; 2296 2297 if (hDlg == hCtl) hCtl = NULL; 2298 if (!hCtl && bPrevious) return 0; 2299 2300 /* if the hwndCtrl is the child of the control in the hwndDlg, 2301 * then the hwndDlg has to be the parent of the hwndCtrl */ 2302 2303 if (hCtl) 2304 { 2305 if (!IsChild (hDlg, hCtl)) return 0; 2306 /* Make sure hwndCtrl is a top-level child */ 2307 2308 } 2309 else 2310 { 2311 /* No ctrl specified -> start from the beginning */ 2312 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0; 2313 /* MSDN is wrong. fPrevious does not result in the last child */ 2314 2315 /* No ctrl specified -> start from the beginning */ 2316 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0; 2317 2318 /* MSDN is wrong. fPrevious does not result in the last child */ 2319 2320 /* Maybe that first one is valid. If so then we don't want to skip it*/ 2321 if ((GetWindowLongPtrW( hCtl, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE) 2322 { 2323 return hCtl; 2324 } 2325 2326 } 2327 2328 /* Always go forward around the group and list of controls; for the 2329 * previous control keep track; for the next break when you find one 2330 */ 2331 retvalue = hCtl; 2332 hwnd = hCtl; 2333 while (1) 2334 { 2335 hwndNext = GetWindow (hwnd, GW_HWNDNEXT); 2336 while (!hwndNext) 2337 { 2338 /* Climb out until there is a next sibling of the ancestor or we 2339 * reach the top (in which case we loop back to the start) 2340 */ 2341 if (hDlg == GetParent (hwnd)) 2342 { 2343 /* Wrap around to the beginning of the list, within the same 2344 * group. (Once only) 2345 */ 2346 if (fLooped) goto end; 2347 fLooped = TRUE; 2348 hwndNext = GetWindow (hDlg, GW_CHILD); 2349 } 2350 else 2351 { 2352 hwnd = GetParent (hwnd); 2353 hwndNext = GetWindow (hwnd, GW_HWNDNEXT); 2354 } 2355 } 2356 hwnd = hwndNext; 2357 2358 /* Wander down the leading edge of controlparents */ 2359 while ( (GetWindowLongPtrW (hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && 2360 ((GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) && 2361 (hwndNext = GetWindow (hwnd, GW_CHILD))) 2362 hwnd = hwndNext; 2363 /* Question. If the control is a control parent but either has no 2364 * children or is not visible/enabled then if it has a WS_GROUP does 2365 * it count? For that matter does it count anyway? 2366 * I believe it doesn't count. 2367 */ 2368 2369 if ((GetWindowLongPtrW (hwnd, GWL_STYLE) & WS_GROUP)) 2370 { 2371 hwndLastGroup = hwnd; 2372 if (!fSkipping) 2373 { 2374 /* Look for the beginning of the group */ 2375 fSkipping = TRUE; 2376 } 2377 } 2378 2379 if (hwnd == hCtl) 2380 { 2381 if (!fSkipping) break; 2382 if (hwndLastGroup == hwnd) break; 2383 hwnd = hwndLastGroup; 2384 fSkipping = FALSE; 2385 fLooped = FALSE; 2386 } 2387 2388 if (!fSkipping && 2389 (GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE|WS_DISABLED)) == 2390 WS_VISIBLE) 2391 { 2392 retvalue = hwnd; 2393 if (!bPrevious) break; 2394 } 2395 } 2396 end: 2397 return retvalue; 2398 } 2399 2400 2401 /* 2402 * @implemented 2403 */ 2404 HWND 2405 WINAPI 2406 GetNextDlgTabItem( 2407 HWND hDlg, 2408 HWND hCtl, 2409 BOOL bPrevious) 2410 { 2411 PWND pWindow; 2412 2413 pWindow = ValidateHwnd( hDlg ); 2414 if (!pWindow) return NULL; 2415 if (hCtl) 2416 { 2417 pWindow = ValidateHwnd( hCtl ); 2418 if (!pWindow) return NULL; 2419 } 2420 2421 /* Undocumented but tested under Win2000 and WinME */ 2422 if (hDlg == hCtl) hCtl = NULL; 2423 2424 /* Contrary to MSDN documentation, tested under Win2000 and WinME 2425 * NB GetLastError returns whatever was set before the function was 2426 * called. 2427 */ 2428 if (!hCtl && bPrevious) return 0; 2429 2430 return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious); 2431 } 2432 2433 2434 #if 0 2435 BOOL 2436 WINAPI 2437 IsDialogMessage( 2438 HWND hDlg, 2439 LPMSG lpMsg) 2440 { 2441 return IsDialogMessageW(hDlg, lpMsg); 2442 } 2443 #endif 2444 2445 /*********************************************************************** 2446 * DIALOG_FixOneChildOnChangeFocus 2447 * 2448 * Callback helper for DIALOG_FixChildrenOnChangeFocus 2449 */ 2450 2451 static BOOL CALLBACK DIALOG_FixOneChildOnChangeFocus (HWND hwndChild, 2452 LPARAM lParam) 2453 { 2454 /* If a default pushbutton then no longer default */ 2455 if (DLGC_DEFPUSHBUTTON & SendMessageW (hwndChild, WM_GETDLGCODE, 0, 0)) 2456 SendMessageW (hwndChild, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); 2457 return TRUE; 2458 } 2459 2460 /*********************************************************************** 2461 * DIALOG_FixChildrenOnChangeFocus 2462 * 2463 * Following the change of focus that occurs for example after handling 2464 * a WM_KEYDOWN VK_TAB in IsDialogMessage, some tidying of the dialog's 2465 * children may be required. 2466 */ 2467 static void DIALOG_FixChildrenOnChangeFocus (HWND hwndDlg, HWND hwndNext) 2468 { 2469 INT dlgcode_next = SendMessageW (hwndNext, WM_GETDLGCODE, 0, 0); 2470 /* INT dlgcode_dlg = SendMessageW (hwndDlg, WM_GETDLGCODE, 0, 0); */ 2471 /* Windows does ask for this. I don't know why yet */ 2472 2473 EnumChildWindows (hwndDlg, DIALOG_FixOneChildOnChangeFocus, 0); 2474 2475 /* If the button that is getting the focus WAS flagged as the default 2476 * pushbutton then ask the dialog what it thinks the default is and 2477 * set that in the default style. 2478 */ 2479 if (dlgcode_next & DLGC_DEFPUSHBUTTON) 2480 { 2481 DWORD def_id = SendMessageW (hwndDlg, DM_GETDEFID, 0, 0); 2482 if (HIWORD(def_id) == DC_HASDEFID) 2483 { 2484 HWND hwndDef; 2485 def_id = LOWORD(def_id); 2486 hwndDef = GetDlgItem (hwndDlg, def_id); 2487 if (hwndDef) 2488 { 2489 INT dlgcode_def = SendMessageW (hwndDef, WM_GETDLGCODE, 0, 0); 2490 /* I know that if it is a button then it should already be a 2491 * UNDEFPUSHBUTTON, since we have just told the buttons to 2492 * change style. But maybe they ignored our request 2493 */ 2494 if ((dlgcode_def & DLGC_BUTTON) && 2495 (dlgcode_def & DLGC_UNDEFPUSHBUTTON)) 2496 { 2497 SendMessageW (hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); 2498 } 2499 } 2500 } 2501 } 2502 else if ((dlgcode_next & DLGC_BUTTON) && (dlgcode_next & DLGC_UNDEFPUSHBUTTON)) 2503 { 2504 SendMessageW (hwndNext, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); 2505 /* I wonder why it doesn't send a DM_SETDEFID */ 2506 } 2507 } 2508 2509 /*********************************************************************** 2510 * DIALOG_IdToHwnd 2511 * 2512 * A recursive version of GetDlgItem 2513 * 2514 * RETURNS 2515 * The HWND for a Child ID. 2516 */ 2517 static HWND DIALOG_IdToHwnd( HWND hwndDlg, INT id ) 2518 { 2519 int i; 2520 HWND *list = WIN_ListChildren( hwndDlg ); 2521 HWND ret = 0; 2522 2523 if (!list) return 0; 2524 2525 for (i = 0; list[i]; i++) 2526 { 2527 if (GetWindowLongPtrW( list[i], GWLP_ID ) == id) 2528 { 2529 ret = list[i]; 2530 break; 2531 } 2532 2533 /* Recurse into every child */ 2534 if ((ret = DIALOG_IdToHwnd( list[i], id ))) break; 2535 } 2536 2537 HeapFree( GetProcessHeap(), 0, list ); 2538 return ret; 2539 } 2540 2541 2542 /* 2543 * @implemented 2544 */ 2545 BOOL 2546 WINAPI 2547 IsDialogMessageW( 2548 HWND hDlg, 2549 LPMSG lpMsg) 2550 { 2551 INT dlgCode = 0; 2552 2553 if (!IsWindow( hDlg )) 2554 return FALSE; 2555 2556 if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE; 2557 2558 if (hDlg == GetDesktopWindow()) return FALSE; 2559 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE; 2560 2561 hDlg = DIALOG_FindMsgDestination(hDlg); 2562 2563 switch(lpMsg->message) 2564 { 2565 case WM_KEYDOWN: 2566 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); 2567 if (dlgCode & DLGC_WANTMESSAGE) break; 2568 2569 switch(lpMsg->wParam) 2570 { 2571 case VK_TAB: 2572 if (!(dlgCode & DLGC_WANTTAB)) 2573 { 2574 BOOL fIsDialog = TRUE; 2575 WND *pWnd = ValidateHwnd(hDlg); 2576 2577 if (pWnd && TestWindowProcess(pWnd)) 2578 { 2579 fIsDialog = (GETDLGINFO(hDlg) != NULL); 2580 } 2581 2582 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0); 2583 2584 /* I am not sure under which circumstances the TAB is handled 2585 * each way. All I do know is that it does not always simply 2586 * send WM_NEXTDLGCTL. (Personally I have never yet seen it 2587 * do so but I presume someone has) 2588 */ 2589 if (fIsDialog) 2590 SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 ); 2591 else 2592 { 2593 /* It would appear that GetNextDlgTabItem can handle being 2594 * passed hwndDlg rather than NULL but that is undocumented 2595 * so let's do it properly 2596 */ 2597 HWND hwndFocus = GetFocus(); 2598 HWND hwndNext = GetNextDlgTabItem (hDlg, 2599 hwndFocus == hDlg ? NULL : hwndFocus, 2600 GetKeyState (VK_SHIFT) & 0x8000); 2601 if (hwndNext) 2602 { 2603 dlgCode = SendMessageW (hwndNext, WM_GETDLGCODE, 2604 lpMsg->wParam, (LPARAM)lpMsg); 2605 if (dlgCode & DLGC_HASSETSEL) 2606 { 2607 INT maxlen = 1 + SendMessageW (hwndNext, WM_GETTEXTLENGTH, 0, 0); 2608 WCHAR *buffer = HeapAlloc (GetProcessHeap(), 0, maxlen * sizeof(WCHAR)); 2609 if (buffer) 2610 { 2611 SIZE_T length; 2612 SendMessageW (hwndNext, WM_GETTEXT, maxlen, (LPARAM) buffer); 2613 length = strlenW (buffer); 2614 HeapFree (GetProcessHeap(), 0, buffer); 2615 SendMessageW (hwndNext, EM_SETSEL, 0, length); 2616 } 2617 } 2618 SetFocus (hwndNext); 2619 DIALOG_FixChildrenOnChangeFocus (hDlg, hwndNext); 2620 } 2621 else 2622 return FALSE; 2623 } 2624 return TRUE; 2625 } 2626 break; 2627 2628 case VK_RIGHT: 2629 case VK_DOWN: 2630 case VK_LEFT: 2631 case VK_UP: 2632 if (!(dlgCode & DLGC_WANTARROWS)) 2633 { 2634 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP); 2635 HWND hwndNext = GetNextDlgGroupItem( hDlg, lpMsg->hwnd, fPrevious ); 2636 if (hwndNext && SendMessageW( hwndNext, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ) == (DLGC_BUTTON | DLGC_RADIOBUTTON)) 2637 { 2638 SetFocus( hwndNext ); 2639 if ((GetWindowLongW( hwndNext, GWL_STYLE ) & BS_TYPEMASK) == BS_AUTORADIOBUTTON && 2640 SendMessageW( hwndNext, BM_GETCHECK, 0, 0 ) != BST_CHECKED) 2641 SendMessageW( hwndNext, BM_CLICK, 1, 0 ); 2642 } 2643 else 2644 SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 ); 2645 return TRUE; 2646 } 2647 break; 2648 2649 case VK_CANCEL: 2650 case VK_ESCAPE: 2651 SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) ); 2652 return TRUE; 2653 2654 case VK_EXECUTE: 2655 case VK_RETURN: 2656 { 2657 DWORD dw; 2658 HWND hwndFocus = GetFocus(); 2659 if (IsChild( hDlg, hwndFocus ) && 2660 (SendMessageW (hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 2661 { 2662 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( GetDlgCtrlID( hwndFocus ), BN_CLICKED ), (LPARAM)hwndFocus ); 2663 } 2664 else if (DC_HASDEFID == HIWORD(dw = SendMessageW (hDlg, DM_GETDEFID, 0, 0))) 2665 { 2666 HWND hwndDef = DIALOG_IdToHwnd(hDlg, LOWORD(dw)); 2667 if (!hwndDef || IsWindowEnabled(hwndDef)) 2668 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), (LPARAM)hwndDef); 2669 } 2670 else 2671 { 2672 SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) ); 2673 } 2674 } 2675 return TRUE; 2676 } 2677 break; 2678 2679 case WM_CHAR: 2680 /* FIXME Under what circumstances does WM_GETDLGCODE get sent? 2681 * It does NOT get sent in the test program I have 2682 */ 2683 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); 2684 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break; 2685 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break; 2686 /* drop through */ 2687 2688 case WM_SYSCHAR: 2689 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam )) 2690 { 2691 /* don't translate or dispatch */ 2692 return TRUE; 2693 } 2694 break; 2695 //// ReactOS 2696 case WM_SYSKEYDOWN: 2697 /* If the ALT key is being pressed display the keyboard cues */ 2698 if ( HIWORD(lpMsg->lParam) & KF_ALTDOWN && 2699 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) ) 2700 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0); 2701 break; 2702 2703 case WM_SYSCOMMAND: 2704 /* If the ALT key is being pressed display the keyboard cues */ 2705 if ( lpMsg->wParam == SC_KEYMENU && 2706 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) ) 2707 { 2708 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0); 2709 } 2710 break; 2711 } 2712 2713 TranslateMessage( lpMsg ); 2714 DispatchMessageW( lpMsg ); 2715 return TRUE; 2716 } 2717 2718 2719 /* 2720 * @implemented 2721 */ 2722 UINT 2723 WINAPI 2724 IsDlgButtonChecked( 2725 HWND hDlg, 2726 int nIDButton) 2727 { 2728 return (UINT)SendDlgItemMessageW( hDlg, nIDButton, BM_GETCHECK, 0, 0 ); 2729 } 2730 2731 2732 /* 2733 * @implemented 2734 */ 2735 BOOL 2736 WINAPI 2737 MapDialogRect( 2738 HWND hDlg, 2739 LPRECT lpRect) 2740 { 2741 DIALOGINFO * dlgInfo; 2742 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE; 2743 lpRect->left = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4); 2744 lpRect->right = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4); 2745 lpRect->top = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8); 2746 lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8); 2747 return TRUE; 2748 } 2749 2750 2751 /* 2752 * @implemented 2753 */ 2754 LRESULT 2755 WINAPI 2756 SendDlgItemMessageA( 2757 HWND hDlg, 2758 int nIDDlgItem, 2759 UINT Msg, 2760 WPARAM wParam, 2761 LPARAM lParam) 2762 { 2763 HWND hwndCtrl; 2764 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS 2765 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); 2766 if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam ); 2767 else return 0; 2768 } 2769 2770 2771 /* 2772 * @implemented 2773 */ 2774 LRESULT 2775 WINAPI 2776 SendDlgItemMessageW( 2777 HWND hDlg, 2778 int nIDDlgItem, 2779 UINT Msg, 2780 WPARAM wParam, 2781 LPARAM lParam) 2782 { 2783 HWND hwndCtrl; 2784 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS 2785 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); 2786 if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam ); 2787 else return 0; 2788 } 2789 2790 2791 /* 2792 * @implemented 2793 */ 2794 BOOL 2795 WINAPI 2796 SetDlgItemInt( 2797 HWND hDlg, 2798 int nIDDlgItem, 2799 UINT uValue, 2800 BOOL bSigned) 2801 { 2802 char str[20]; 2803 2804 if (bSigned) sprintf( str, "%d", (INT)uValue ); 2805 else sprintf( str, "%u", uValue ); 2806 SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str ); 2807 return TRUE; 2808 } 2809 2810 2811 /* 2812 * @implemented 2813 */ 2814 BOOL 2815 WINAPI 2816 SetDlgItemTextA( 2817 HWND hDlg, 2818 int nIDDlgItem, 2819 LPCSTR lpString) 2820 { 2821 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes 2822 if (hwndCtrl) return SetWindowTextA( hwndCtrl, lpString ); 2823 return FALSE; 2824 } 2825 2826 2827 /* 2828 * @implemented 2829 */ 2830 BOOL 2831 WINAPI 2832 SetDlgItemTextW( 2833 HWND hDlg, 2834 int nIDDlgItem, 2835 LPCWSTR lpString) 2836 { 2837 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes 2838 if (hwndCtrl) return SetWindowTextW( hwndCtrl, lpString ); 2839 return FALSE; 2840 } 2841 2842 2843 /* 2844 * @implemented 2845 */ 2846 BOOL 2847 WINAPI 2848 CheckDlgButton( 2849 HWND hDlg, 2850 int nIDButton, 2851 UINT uCheck) 2852 { 2853 SendDlgItemMessageW( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 ); 2854 return TRUE; 2855 } 2856 2857 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam) 2858 { 2859 LONG lChildID = GetWindowLongPtrW(hwnd, GWLP_ID); 2860 RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam; 2861 2862 if((lChildID >= lpRadioGroup->firstID) && 2863 (lChildID <= lpRadioGroup->lastID)) 2864 { 2865 if (lChildID == lpRadioGroup->checkID) 2866 { 2867 SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0); 2868 } 2869 else 2870 { 2871 SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); 2872 } 2873 } 2874 2875 return TRUE; 2876 } 2877 2878 /* 2879 * @implemented 2880 */ 2881 BOOL 2882 WINAPI 2883 CheckRadioButton( 2884 HWND hDlg, 2885 int nIDFirstButton, 2886 int nIDLastButton, 2887 int nIDCheckButton) 2888 { 2889 RADIOGROUP radioGroup; 2890 2891 radioGroup.firstID = nIDFirstButton; 2892 radioGroup.lastID = nIDLastButton; 2893 radioGroup.checkID = nIDCheckButton; 2894 2895 return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup); 2896 } 2897