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 disabled_owner = owner; 940 EnableWindow( disabled_owner, FALSE ); 941 } 942 } 943 *modal_owner = owner; 944 } 945 946 if (unicode) 947 { 948 hwnd = CreateWindowExW(template.exStyle, template.className, template.caption, 949 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy, 950 owner, hMenu, hInst, NULL ); 951 } 952 else 953 { 954 LPCSTR class = (LPCSTR)template.className; 955 LPCSTR caption = (LPCSTR)template.caption; 956 LPSTR class_tmp = NULL; 957 LPSTR caption_tmp = NULL; 958 959 if (!IS_INTRESOURCE(class)) 960 { 961 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL ); 962 class_tmp = HeapAlloc( GetProcessHeap(), 0, len ); 963 WideCharToMultiByte( CP_ACP, 0, template.className, -1, class_tmp, len, NULL, NULL ); 964 class = class_tmp; 965 } 966 if (!IS_INTRESOURCE(caption)) 967 { 968 DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL ); 969 caption_tmp = HeapAlloc( GetProcessHeap(), 0, len ); 970 WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption_tmp, len, NULL, NULL ); 971 caption = caption_tmp; 972 } 973 hwnd = CreateWindowExA(template.exStyle, class, caption, 974 template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy, 975 owner, hMenu, hInst, NULL ); 976 HeapFree( GetProcessHeap(), 0, class_tmp ); 977 HeapFree( GetProcessHeap(), 0, caption_tmp ); 978 } 979 980 if (!hwnd) 981 { 982 if (hUserFont) DeleteObject( hUserFont ); 983 if (hMenu) DestroyMenu( hMenu ); 984 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 985 return 0; 986 } 987 988 /* moved this from the top of the method to here as DIALOGINFO structure 989 will be valid only after WM_CREATE message has been handled in DefDlgProc 990 All the members of the structure get filled here using temp variables */ 991 dlgInfo = DIALOG_get_info( hwnd, TRUE ); 992 // ReactOS 993 if (dlgInfo == NULL) 994 { 995 if (hUserFont) DeleteObject( hUserFont ); 996 if (hMenu) DestroyMenu( hMenu ); 997 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 998 return 0; 999 } 1000 // 1001 dlgInfo->hwndFocus = 0; 1002 dlgInfo->hUserFont = hUserFont; 1003 dlgInfo->hMenu = hMenu; 1004 dlgInfo->xBaseUnit = xBaseUnit; 1005 dlgInfo->yBaseUnit = yBaseUnit; 1006 dlgInfo->flags = flags; 1007 1008 if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId ); 1009 1010 if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); 1011 else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); 1012 1013 if (dlgProc && dlgInfo->hUserFont) 1014 SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 ); 1015 1016 /* Create controls */ 1017 1018 if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode )) 1019 { 1020 /* Send initialisation messages and set focus */ 1021 1022 if (dlgProc) 1023 { 1024 HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE ); 1025 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE ); 1026 if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) && 1027 ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE))) 1028 { 1029 /* By returning TRUE, app has requested a default focus assignment. 1030 * WM_INITDIALOG may have changed the tab order, so find the first 1031 * tabstop control again. */ 1032 focus = GetNextDlgTabItem( hwnd, 0, FALSE ); 1033 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE ); 1034 if (focus) 1035 { 1036 if (SendMessageW( focus, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL) 1037 SendMessageW( focus, EM_SETSEL, 0, MAXLONG ); 1038 SetFocus( focus ); 1039 } 1040 else 1041 { 1042 if (!(template.style & WS_CHILD)) 1043 SetFocus( hwnd ); 1044 } 1045 } 1046 //// ReactOS see 43396, Fixes setting focus on Open and Close dialogs to the FileName edit control in OpenOffice. 1047 //// This now breaks test_SaveRestoreFocus. 1048 //DEFDLG_SaveFocus( hwnd ); 1049 //// 1050 } 1051 //// ReactOS Rev 30613 & 30644 1052 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_CHILD)) 1053 SendMessageW( hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0); 1054 //// 1055 if (template.style & WS_VISIBLE && !(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_VISIBLE)) 1056 { 1057 ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */ 1058 UpdateWindow( hwnd ); 1059 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGSTART, hwnd, OBJID_WINDOW, CHILDID_SELF, 0); 1060 } 1061 return hwnd; 1062 } 1063 if (disabled_owner) EnableWindow( disabled_owner, TRUE ); 1064 IntNotifyWinEvent(EVENT_SYSTEM_DIALOGEND, hwnd, OBJID_WINDOW, CHILDID_SELF, 0); 1065 if( IsWindow(hwnd) ) 1066 { 1067 DestroyWindow( hwnd ); 1068 //// ReactOS 1069 if (owner) 1070 { ERR("DIALOG_CreateIndirect 1\n"); 1071 if ( NtUserGetThreadState(THREADSTATE_FOREGROUNDTHREAD) && // Rule #1. 1072 !NtUserQueryWindow(owner, QUERY_WINDOW_FOREGROUND) ) 1073 { ERR("DIALOG_CreateIndirect SFW\n"); 1074 SetForegroundWindow(owner); 1075 } 1076 } 1077 //// 1078 } 1079 return 0; 1080 } 1081 1082 1083 /*********************************************************************** 1084 * DEFDLG_FindDefButton 1085 * 1086 * Find the current default push-button. 1087 */ 1088 static HWND DEFDLG_FindDefButton( HWND hwndDlg ) 1089 { 1090 HWND hwndChild, hwndTmp; 1091 1092 hwndChild = GetWindow( hwndDlg, GW_CHILD ); 1093 while (hwndChild) 1094 { 1095 if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON) 1096 break; 1097 1098 /* Recurse into WS_EX_CONTROLPARENT controls */ 1099 if (GetWindowLongPtrW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT) 1100 { 1101 LONG dsStyle = GetWindowLongPtrW( hwndChild, GWL_STYLE ); 1102 if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) && 1103 (hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL) 1104 return hwndTmp; 1105 } 1106 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT ); 1107 } 1108 return hwndChild; 1109 } 1110 1111 1112 /*********************************************************************** 1113 * DEFDLG_SetDefId 1114 * 1115 * Set the default button id. 1116 */ 1117 static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam) 1118 { 1119 DWORD dlgcode=0; /* initialize just to avoid a warning */ 1120 HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam); 1121 INT old_id = dlgInfo->idResult; 1122 1123 dlgInfo->idResult = wParam; 1124 if (hwndNew && 1125 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) 1126 & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON))) 1127 return FALSE; /* Destination is not a push button */ 1128 1129 /* Make sure the old default control is a valid push button ID */ 1130 hwndOld = GetDlgItem( hwndDlg, old_id ); 1131 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 1132 hwndOld = DEFDLG_FindDefButton( hwndDlg ); 1133 if (hwndOld && hwndOld != hwndNew) 1134 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); 1135 1136 if (hwndNew) 1137 { 1138 if(dlgcode & DLGC_UNDEFPUSHBUTTON) 1139 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); 1140 } 1141 return TRUE; 1142 } 1143 1144 1145 /*********************************************************************** 1146 * DEFDLG_SetDefButton 1147 * 1148 * Set the new default button to be hwndNew. 1149 */ 1150 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew ) 1151 { 1152 DWORD dlgcode=0; /* initialize just to avoid a warning */ 1153 HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult ); 1154 1155 if (hwndNew && 1156 !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 )) 1157 & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON))) 1158 { 1159 /** 1160 * Need to draw only default push button rectangle. 1161 * Since the next control is not a push button, need to draw the push 1162 * button rectangle for the default control. 1163 */ 1164 hwndNew = hwndOld; 1165 dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ); 1166 } 1167 1168 /* Make sure the old default control is a valid push button ID */ 1169 if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 1170 hwndOld = DEFDLG_FindDefButton( hwndDlg ); 1171 if (hwndOld && hwndOld != hwndNew) 1172 SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE ); 1173 1174 if (hwndNew) 1175 { 1176 if(dlgcode & DLGC_UNDEFPUSHBUTTON) 1177 SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE ); 1178 } 1179 return TRUE; 1180 } 1181 1182 #ifdef __REACTOS__ 1183 static void DEFDLG_Reposition(HWND hwnd) 1184 { 1185 HMONITOR hMon; 1186 MONITORINFO mi = { sizeof(mi) }; 1187 RECT rc; 1188 LONG cx, cy; 1189 1190 if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) 1191 return; 1192 1193 if (IsIconic(hwnd)) 1194 return; 1195 1196 hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 1197 1198 if (!GetMonitorInfoW(hMon, &mi) || !GetWindowRect(hwnd, &rc)) 1199 return; 1200 1201 cx = rc.right - rc.left; 1202 cy = rc.bottom - rc.top; 1203 1204 if (rc.right > mi.rcWork.right) 1205 { 1206 rc.right = mi.rcWork.right; 1207 rc.left = rc.right - cx; 1208 } 1209 if (rc.bottom > mi.rcWork.bottom - 4) 1210 { 1211 rc.bottom = mi.rcWork.bottom - 4; 1212 rc.top = rc.bottom - cy; 1213 } 1214 1215 if (rc.left < mi.rcWork.left) 1216 { 1217 rc.left = mi.rcWork.left; 1218 } 1219 if (rc.top < mi.rcWork.top) 1220 { 1221 rc.top = mi.rcWork.top; 1222 } 1223 1224 SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, 1225 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | 1226 SWP_NOZORDER); 1227 } 1228 #endif 1229 /*********************************************************************** 1230 * DEFDLG_Proc 1231 * 1232 * Implementation of DefDlgProc(). Only handle messages that need special 1233 * handling for dialogs. 1234 */ 1235 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam, 1236 LPARAM lParam, DIALOGINFO *dlgInfo ) 1237 { 1238 switch(msg) 1239 { 1240 case WM_ERASEBKGND: 1241 { 1242 HBRUSH brush = GetControlColor( hwnd, hwnd, (HDC)wParam, WM_CTLCOLORDLG); 1243 if (brush) 1244 { 1245 RECT rect; 1246 HDC hdc = (HDC)wParam; 1247 GetClientRect( hwnd, &rect ); 1248 DPtoLP( hdc, (LPPOINT)&rect, 2 ); 1249 FillRect( hdc, &rect, brush ); 1250 } 1251 return 1; 1252 } 1253 case WM_NCDESTROY: 1254 //// ReactOS 1255 if ((dlgInfo = (DIALOGINFO *)SetWindowLongPtrW( hwnd, DWLP_ROS_DIALOGINFO, 0 ))) 1256 { 1257 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont ); 1258 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu ); 1259 HeapFree( GetProcessHeap(), 0, dlgInfo ); 1260 NtUserSetThreadState(0,DF_DIALOGACTIVE); 1261 NtUserxSetDialogPointer( hwnd, 0 ); 1262 } 1263 /* Window clean-up */ 1264 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1265 1266 case WM_SHOWWINDOW: 1267 if (!wParam) DEFDLG_SaveFocus( hwnd ); 1268 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1269 1270 case WM_ACTIVATE: 1271 { // ReactOS 1272 DWORD dwSetFlag; 1273 HWND hwndparent = DIALOG_FindMsgDestination( hwnd ); 1274 // if WA_CLICK/ACTIVE ? set dialog is active. 1275 dwSetFlag = wParam ? DF_DIALOGACTIVE : 0; 1276 if (hwndparent != hwnd) NtUserSetThreadState(dwSetFlag, DF_DIALOGACTIVE); 1277 } 1278 if (wParam) DEFDLG_RestoreFocus( hwnd, TRUE ); 1279 else DEFDLG_SaveFocus( hwnd ); 1280 return 0; 1281 1282 case WM_SETFOCUS: 1283 DEFDLG_RestoreFocus( hwnd, FALSE ); 1284 return 0; 1285 1286 case DM_SETDEFID: 1287 if (dlgInfo && !(dlgInfo->flags & DF_END)) 1288 DEFDLG_SetDefId( hwnd, dlgInfo, wParam ); 1289 return 1; 1290 1291 case DM_GETDEFID: 1292 if (dlgInfo && !(dlgInfo->flags & DF_END)) 1293 { 1294 HWND hwndDefId; 1295 if (dlgInfo->idResult) 1296 return MAKELONG( dlgInfo->idResult, DC_HASDEFID ); 1297 if ((hwndDefId = DEFDLG_FindDefButton( hwnd ))) 1298 return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID); 1299 } 1300 return 0; 1301 1302 #ifdef __REACTOS__ 1303 case DM_REPOSITION: 1304 DEFDLG_Reposition(hwnd); 1305 return 0; 1306 #endif 1307 case WM_NEXTDLGCTL: 1308 if (dlgInfo) 1309 { 1310 HWND hwndDest = (HWND)wParam; 1311 if (!lParam) 1312 hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam); 1313 if (hwndDest) DEFDLG_SetFocus( hwndDest ); 1314 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest ); 1315 } 1316 return 0; 1317 1318 case WM_ENTERMENULOOP: 1319 case WM_LBUTTONDOWN: 1320 case WM_NCLBUTTONDOWN: 1321 { 1322 HWND hwndFocus = GetFocus(); 1323 if (hwndFocus) 1324 { 1325 /* always make combo box hide its listbox control */ 1326 if (!SendMessageW( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 )) 1327 SendMessageW( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 ); 1328 } 1329 } 1330 return DefWindowProcA( hwnd, msg, wParam, lParam ); 1331 1332 case WM_GETFONT: 1333 return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0; 1334 1335 case WM_CLOSE: 1336 PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 1337 (LPARAM)GetDlgItem( hwnd, IDCANCEL ) ); 1338 return 0; 1339 } 1340 return 0; 1341 } 1342 1343 /*********************************************************************** 1344 * DEFDLG_Epilog 1345 */ 1346 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fResult, BOOL fAnsi) 1347 { 1348 if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) || 1349 msg == WM_CTLCOLOR) 1350 { 1351 if (fResult) return fResult; 1352 1353 return fAnsi ? DefWindowProcA(hwnd, msg, wParam, lParam): 1354 DefWindowProcW(hwnd, msg, wParam, lParam); 1355 } 1356 if ( msg == WM_COMPAREITEM || 1357 msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM || 1358 msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG) 1359 return fResult; 1360 1361 return GetWindowLongPtrW( hwnd, DWLP_MSGRESULT ); 1362 } 1363 1364 /*********************************************************************** 1365 * DIALOG_GetNextTabItem 1366 * 1367 * Helper for GetNextDlgTabItem 1368 */ 1369 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious ) 1370 { 1371 LONG dsStyle; 1372 LONG exStyle; 1373 UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT; 1374 HWND retWnd = 0; 1375 HWND hChildFirst = 0; 1376 1377 if(!hwndCtrl) 1378 { 1379 hChildFirst = GetWindow(hwndDlg,GW_CHILD); 1380 if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST); 1381 } 1382 else if (IsChild( hwndMain, hwndCtrl )) 1383 { 1384 hChildFirst = GetWindow(hwndCtrl,wndSearch); 1385 if(!hChildFirst) 1386 { 1387 if(GetParent(hwndCtrl) != hwndMain) 1388 /* i.e. if we are not at the top level of the recursion */ 1389 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch); 1390 else 1391 hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST); 1392 } 1393 } 1394 1395 while(hChildFirst) 1396 { 1397 dsStyle = GetWindowLongPtrA(hChildFirst,GWL_STYLE); 1398 exStyle = GetWindowLongPtrA(hChildFirst,GWL_EXSTYLE); 1399 if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED)) 1400 { 1401 HWND retWnd; 1402 retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious ); 1403 if (retWnd) return (retWnd); 1404 } 1405 else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED)) 1406 { 1407 return (hChildFirst); 1408 } 1409 hChildFirst = GetWindow(hChildFirst,wndSearch); 1410 } 1411 if(hwndCtrl) 1412 { 1413 HWND hParent = GetParent(hwndCtrl); 1414 while(hParent) 1415 { 1416 if(hParent == hwndMain) break; 1417 retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious ); 1418 if(retWnd) break; 1419 hParent = GetParent(hParent); 1420 } 1421 if(!retWnd) 1422 retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious ); 1423 } 1424 return retWnd ? retWnd : hwndCtrl; 1425 } 1426 1427 1428 /********************************************************************** 1429 * DIALOG_DlgDirListW 1430 * 1431 * Helper function for DlgDirList*W 1432 */ 1433 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox, 1434 INT idStatic, UINT attrib, BOOL combo ) 1435 { 1436 HWND hwnd; 1437 LPWSTR orig_spec = spec; 1438 WCHAR any[] = {'*','.','*',0}; 1439 WCHAR star[] = {'*',0}; 1440 1441 #define SENDMSG(msg,wparam,lparam) \ 1442 ((attrib & DDL_POSTMSGS) ? PostMessageW( hwnd, msg, wparam, lparam ) \ 1443 : SendMessageW( hwnd, msg, wparam, lparam )) 1444 1445 TRACE("%p %s %d %d %04x\n", hDlg, debugstr_w(spec), idLBox, idStatic, attrib ); 1446 1447 /* If the path exists and is a directory, chdir to it */ 1448 if (!spec || !spec[0] || SetCurrentDirectoryW( spec )) spec = star; 1449 else 1450 { 1451 WCHAR *p, *p2; 1452 1453 if (!strchrW(spec, '*') && !strchrW(spec, '?')) 1454 { 1455 SetLastError(ERROR_NO_WILDCARD_CHARACTERS); 1456 return FALSE; 1457 } 1458 p = spec; 1459 if ((p2 = strchrW( p, ':' ))) p = p2 + 1; 1460 if ((p2 = strrchrW( p, '\\' ))) p = p2; 1461 if ((p2 = strrchrW( p, '/' ))) p = p2; 1462 if (p != spec) 1463 { 1464 WCHAR sep = *p; 1465 *p = 0; 1466 if (!SetCurrentDirectoryW( spec )) 1467 { 1468 *p = sep; /* Restore the original spec */ 1469 return FALSE; 1470 } 1471 spec = p + 1; 1472 } 1473 } 1474 1475 TRACE( "mask=%s\n", spec ); 1476 1477 if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0)) 1478 { 1479 if (attrib == DDL_DRIVES) attrib |= DDL_EXCLUSIVE; 1480 1481 SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 ); 1482 if (attrib & DDL_DIRECTORY) 1483 { 1484 if (!(attrib & DDL_EXCLUSIVE)) 1485 { 1486 SENDMSG( combo ? CB_DIR : LB_DIR, 1487 attrib & ~(DDL_DIRECTORY | DDL_DRIVES), 1488 (LPARAM)spec ); 1489 } 1490 SENDMSG( combo ? CB_DIR : LB_DIR, 1491 (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE, 1492 (LPARAM)any ); 1493 } 1494 else 1495 { 1496 SENDMSG( combo ? CB_DIR : LB_DIR, attrib, (LPARAM)spec ); 1497 } 1498 } 1499 1500 /* Convert path specification to uppercase */ 1501 if (spec) CharUpperW(spec); 1502 1503 if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0)) 1504 { 1505 WCHAR temp[MAX_PATH]; 1506 GetCurrentDirectoryW( sizeof(temp)/sizeof(WCHAR), temp ); 1507 CharLowerW( temp ); 1508 /* Can't use PostMessage() here, because the string is on the stack */ 1509 SetDlgItemTextW( hDlg, idStatic, temp ); 1510 } 1511 1512 if (orig_spec && (spec != orig_spec)) 1513 { 1514 /* Update the original file spec */ 1515 WCHAR *p = spec; 1516 while ((*orig_spec++ = *p++)); 1517 } 1518 1519 return TRUE; 1520 #undef SENDMSG 1521 } 1522 1523 1524 /********************************************************************** 1525 * DIALOG_DlgDirListA 1526 * 1527 * Helper function for DlgDirList*A 1528 */ 1529 static INT DIALOG_DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox, 1530 INT idStatic, UINT attrib, BOOL combo ) 1531 { 1532 if (spec) 1533 { 1534 INT ret, len = MultiByteToWideChar( CP_ACP, 0, spec, -1, NULL, 0 ); 1535 LPWSTR specW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); 1536 if (specW == NULL) 1537 return FALSE; 1538 MultiByteToWideChar( CP_ACP, 0, spec, -1, specW, len ); 1539 ret = DIALOG_DlgDirListW( hDlg, specW, idLBox, idStatic, attrib, combo ); 1540 WideCharToMultiByte( CP_ACP, 0, specW, -1, spec, 0x7fffffff, NULL, NULL ); 1541 HeapFree( GetProcessHeap(), 0, specW ); 1542 return ret; 1543 } 1544 return DIALOG_DlgDirListW( hDlg, NULL, idLBox, idStatic, attrib, combo ); 1545 } 1546 1547 /********************************************************************** 1548 * DIALOG_DlgDirSelect 1549 * 1550 * Helper function for DlgDirSelect* 1551 */ 1552 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPWSTR str, INT len, 1553 INT id, BOOL unicode, BOOL combo ) 1554 { 1555 WCHAR *buffer, *ptr; 1556 INT item, size; 1557 BOOL ret; 1558 HWND listbox = GetDlgItem( hwnd, id ); 1559 1560 TRACE("%p %s %d\n", hwnd, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str), id ); 1561 if (!listbox) return FALSE; 1562 1563 item = SendMessageW(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 ); 1564 if (item == LB_ERR) return FALSE; 1565 1566 size = SendMessageW(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, item, 0 ); 1567 if (size == LB_ERR) return FALSE; 1568 1569 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size+2) * sizeof(WCHAR) ))) return FALSE; 1570 1571 SendMessageW( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer ); 1572 1573 if ((ret = (buffer[0] == '['))) /* drive or directory */ 1574 { 1575 if (buffer[1] == '-') /* drive */ 1576 { 1577 buffer[3] = ':'; 1578 buffer[4] = 0; 1579 ptr = buffer + 2; 1580 } 1581 else 1582 { 1583 buffer[strlenW(buffer)-1] = '\\'; 1584 ptr = buffer + 1; 1585 } 1586 } 1587 else 1588 { 1589 /* Filenames without a dot extension must have one tacked at the end */ 1590 if (strchrW(buffer, '.') == NULL) 1591 { 1592 buffer[strlenW(buffer)+1] = '\0'; 1593 buffer[strlenW(buffer)] = '.'; 1594 } 1595 ptr = buffer; 1596 } 1597 1598 if (!unicode) 1599 { 1600 if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, ptr, -1, (LPSTR)str, len, 0, 0 )) 1601 ((LPSTR)str)[len-1] = 0; 1602 } 1603 else lstrcpynW( str, ptr, len ); 1604 HeapFree( GetProcessHeap(), 0, buffer ); 1605 TRACE("Returning %d %s\n", ret, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str) ); 1606 return ret; 1607 } 1608 1609 1610 /* FUNCTIONS *****************************************************************/ 1611 1612 /* 1613 * @implemented 1614 */ 1615 HWND 1616 WINAPI 1617 CreateDialogIndirectParamAorW( 1618 HINSTANCE hInstance, 1619 LPCDLGTEMPLATE lpTemplate, 1620 HWND hWndParent, 1621 DLGPROC lpDialogFunc, 1622 LPARAM lParamInit, 1623 DWORD Flags) 1624 { 1625 /* FIXME: 1626 * This function might be obsolete since I don't think it is exported by NT 1627 * Also wine has one more parameter identifying weather it should call 1628 * the function with unicode or not 1629 */ 1630 return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit , Flags == DLG_ISANSI ? FALSE : TRUE, NULL ); 1631 } 1632 1633 1634 /* 1635 * @implemented 1636 */ 1637 HWND 1638 WINAPI 1639 CreateDialogIndirectParamA( 1640 HINSTANCE hInstance, 1641 LPCDLGTEMPLATE lpTemplate, 1642 HWND hWndParent, 1643 DLGPROC lpDialogFunc, 1644 LPARAM lParamInit) 1645 { 1646 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, DLG_ISANSI); 1647 } 1648 1649 1650 /* 1651 * @implemented 1652 */ 1653 HWND 1654 WINAPI 1655 CreateDialogIndirectParamW( 1656 HINSTANCE hInstance, 1657 LPCDLGTEMPLATE lpTemplate, 1658 HWND hWndParent, 1659 DLGPROC lpDialogFunc, 1660 LPARAM lParamInit) 1661 { 1662 return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, 0); 1663 } 1664 1665 1666 /* 1667 * @implemented 1668 */ 1669 HWND 1670 WINAPI 1671 CreateDialogParamA( 1672 HINSTANCE hInstance, 1673 LPCSTR lpTemplateName, 1674 HWND hWndParent, 1675 DLGPROC lpDialogFunc, 1676 LPARAM dwInitParam) 1677 { 1678 HRSRC hrsrc; 1679 LPCDLGTEMPLATE ptr; 1680 1681 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0; 1682 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0; 1683 return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam ); 1684 } 1685 1686 1687 /* 1688 * @implemented 1689 */ 1690 HWND 1691 WINAPI 1692 CreateDialogParamW( 1693 HINSTANCE hInstance, 1694 LPCWSTR lpTemplateName, 1695 HWND hWndParent, 1696 DLGPROC lpDialogFunc, 1697 LPARAM dwInitParam) 1698 { 1699 HRSRC hrsrc; 1700 LPCDLGTEMPLATE ptr; 1701 1702 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0; 1703 if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0; 1704 return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam ); 1705 } 1706 1707 1708 /* 1709 * @implemented 1710 */ 1711 LRESULT 1712 WINAPI 1713 DefDlgProcA( 1714 HWND hDlg, 1715 UINT Msg, 1716 WPARAM wParam, 1717 LPARAM lParam) 1718 { 1719 DIALOGINFO *dlgInfo; 1720 WNDPROC dlgproc; 1721 BOOL result = FALSE; 1722 1723 /* Perform DIALOGINFO initialization if not done */ 1724 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass. 1725 1726 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 ); 1727 1728 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC ))) 1729 { 1730 /* Call dialog procedure */ 1731 result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam ); 1732 } 1733 1734 if (!result && IsWindow(hDlg)) 1735 { 1736 /* callback didn't process this message */ 1737 1738 switch(Msg) 1739 { 1740 case WM_ERASEBKGND: 1741 case WM_SHOWWINDOW: 1742 case WM_ACTIVATE: 1743 case WM_SETFOCUS: 1744 case DM_SETDEFID: 1745 case DM_GETDEFID: 1746 #ifdef __REACTOS__ 1747 case DM_REPOSITION: 1748 #endif 1749 case WM_NEXTDLGCTL: 1750 case WM_GETFONT: 1751 case WM_CLOSE: 1752 case WM_NCDESTROY: 1753 case WM_ENTERMENULOOP: 1754 case WM_LBUTTONDOWN: 1755 case WM_NCLBUTTONDOWN: 1756 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo ); 1757 case WM_INITDIALOG: 1758 case WM_VKEYTOITEM: 1759 case WM_COMPAREITEM: 1760 case WM_CHARTOITEM: 1761 break; 1762 1763 default: 1764 return DefWindowProcA( hDlg, Msg, wParam, lParam ); 1765 } 1766 } 1767 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, TRUE); 1768 } 1769 1770 1771 /* 1772 * @implemented 1773 */ 1774 LRESULT 1775 WINAPI 1776 DefDlgProcW( 1777 HWND hDlg, 1778 UINT Msg, 1779 WPARAM wParam, 1780 LPARAM lParam) 1781 { 1782 DIALOGINFO *dlgInfo; 1783 WNDPROC dlgproc; 1784 BOOL result = FALSE; 1785 1786 /* Perform DIALOGINFO initialization if not done */ 1787 if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass. 1788 1789 SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 ); 1790 1791 if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC ))) 1792 { 1793 /* Call dialog procedure */ 1794 result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam ); 1795 } 1796 1797 if (!result && IsWindow(hDlg)) 1798 { 1799 /* callback didn't process this message */ 1800 1801 switch(Msg) 1802 { 1803 case WM_ERASEBKGND: 1804 case WM_SHOWWINDOW: 1805 case WM_ACTIVATE: 1806 case WM_SETFOCUS: 1807 case DM_SETDEFID: 1808 case DM_GETDEFID: 1809 #ifdef __REACTOS__ 1810 case DM_REPOSITION: 1811 #endif 1812 case WM_NEXTDLGCTL: 1813 case WM_GETFONT: 1814 case WM_CLOSE: 1815 case WM_NCDESTROY: 1816 case WM_ENTERMENULOOP: 1817 case WM_LBUTTONDOWN: 1818 case WM_NCLBUTTONDOWN: 1819 return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo ); 1820 case WM_INITDIALOG: 1821 case WM_VKEYTOITEM: 1822 case WM_COMPAREITEM: 1823 case WM_CHARTOITEM: 1824 break; 1825 1826 default: 1827 return DefWindowProcW( hDlg, Msg, wParam, lParam ); 1828 } 1829 } 1830 return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, FALSE); 1831 } 1832 1833 1834 /* 1835 * @implemented 1836 */ 1837 INT_PTR 1838 WINAPI 1839 DialogBoxIndirectParamAorW( 1840 HINSTANCE hInstance, 1841 LPCDLGTEMPLATE hDialogTemplate, 1842 HWND hWndParent, 1843 DLGPROC lpDialogFunc, 1844 LPARAM dwInitParam, 1845 DWORD Flags) 1846 { 1847 /* FIXME: 1848 * This function might be obsolete since I don't think it is exported by NT 1849 * Also wine has one more parameter identifying weather it should call 1850 * the function with unicode or not 1851 */ 1852 HWND hWnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, Flags == DLG_ISANSI ? FALSE : TRUE, &hWndParent ); 1853 if (hWnd) return DIALOG_DoDialogBox( hWnd, hWndParent ); 1854 return -1; 1855 } 1856 1857 1858 /* 1859 * @implemented 1860 */ 1861 INT_PTR 1862 WINAPI 1863 DialogBoxIndirectParamA( 1864 HINSTANCE hInstance, 1865 LPCDLGTEMPLATE hDialogTemplate, 1866 HWND hWndParent, 1867 DLGPROC lpDialogFunc, 1868 LPARAM dwInitParam) 1869 { 1870 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, DLG_ISANSI); 1871 } 1872 1873 1874 /* 1875 * @implemented 1876 */ 1877 INT_PTR 1878 WINAPI 1879 DialogBoxIndirectParamW( 1880 HINSTANCE hInstance, 1881 LPCDLGTEMPLATE hDialogTemplate, 1882 HWND hWndParent, 1883 DLGPROC lpDialogFunc, 1884 LPARAM dwInitParam) 1885 { 1886 return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, 0); 1887 } 1888 1889 1890 /* 1891 * @implemented 1892 */ 1893 INT_PTR 1894 WINAPI 1895 DialogBoxParamA( 1896 HINSTANCE hInstance, 1897 LPCSTR lpTemplateName, 1898 HWND hWndParent, 1899 DLGPROC lpDialogFunc, 1900 LPARAM dwInitParam) 1901 { 1902 HWND hwnd; 1903 HRSRC hrsrc; 1904 LPCDLGTEMPLATE ptr; 1905 //// ReactOS rev 33532 1906 if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG )) || 1907 !(ptr = LoadResource(hInstance, hrsrc))) 1908 { 1909 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1910 return -1; 1911 } 1912 if (hWndParent != NULL && !IsWindow(hWndParent)) 1913 { 1914 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1915 return 0; 1916 } 1917 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, &hWndParent ); 1918 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent); 1919 return -1; 1920 } 1921 1922 1923 /* 1924 * @implemented 1925 */ 1926 INT_PTR 1927 WINAPI 1928 DialogBoxParamW( 1929 HINSTANCE hInstance, 1930 LPCWSTR lpTemplateName, 1931 HWND hWndParent, 1932 DLGPROC lpDialogFunc, 1933 LPARAM dwInitParam) 1934 { 1935 HWND hwnd; 1936 HRSRC hrsrc; 1937 LPCDLGTEMPLATE ptr; 1938 //// ReactOS rev 33532 1939 if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG )) || 1940 !(ptr = LoadResource(hInstance, hrsrc))) 1941 { 1942 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1943 return -1; 1944 } 1945 if (hWndParent != NULL && !IsWindow(hWndParent)) 1946 { 1947 SetLastError(ERROR_INVALID_WINDOW_HANDLE); 1948 return 0; 1949 } 1950 hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, &hWndParent ); 1951 if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent); 1952 return -1; 1953 } 1954 1955 1956 /* 1957 * @implemented 1958 */ 1959 int 1960 WINAPI 1961 DlgDirListA( 1962 HWND hDlg, 1963 LPSTR lpPathSpec, 1964 int nIDListBox, 1965 int nIDStaticPath, 1966 UINT uFileType) 1967 { 1968 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE ); 1969 } 1970 1971 1972 /* 1973 * @implemented 1974 */ 1975 int 1976 WINAPI 1977 DlgDirListComboBoxA( 1978 HWND hDlg, 1979 LPSTR lpPathSpec, 1980 int nIDComboBox, 1981 int nIDStaticPath, 1982 UINT uFiletype) 1983 { 1984 return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE ); 1985 } 1986 1987 1988 /* 1989 * @implemented 1990 */ 1991 int 1992 WINAPI 1993 DlgDirListComboBoxW( 1994 HWND hDlg, 1995 LPWSTR lpPathSpec, 1996 int nIDComboBox, 1997 int nIDStaticPath, 1998 UINT uFiletype) 1999 { 2000 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE ); 2001 } 2002 2003 2004 /* 2005 * @implemented 2006 */ 2007 int 2008 WINAPI 2009 DlgDirListW( 2010 HWND hDlg, 2011 LPWSTR lpPathSpec, 2012 int nIDListBox, 2013 int nIDStaticPath, 2014 UINT uFileType) 2015 { 2016 return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE ); 2017 } 2018 2019 2020 /* 2021 * @implemented 2022 */ 2023 BOOL 2024 WINAPI 2025 DlgDirSelectComboBoxExA( 2026 HWND hDlg, 2027 LPSTR lpString, 2028 int nCount, 2029 int nIDComboBox) 2030 { 2031 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, FALSE, TRUE ); 2032 } 2033 2034 2035 /* 2036 * @implemented 2037 */ 2038 BOOL 2039 WINAPI 2040 DlgDirSelectComboBoxExW( 2041 HWND hDlg, 2042 LPWSTR lpString, 2043 int nCount, 2044 int nIDComboBox) 2045 { 2046 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, TRUE, TRUE ); 2047 } 2048 2049 2050 /* 2051 * @implemented 2052 */ 2053 BOOL 2054 WINAPI 2055 DlgDirSelectExA( 2056 HWND hDlg, 2057 LPSTR lpString, 2058 int nCount, 2059 int nIDListBox) 2060 { 2061 return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDListBox, FALSE, FALSE ); 2062 } 2063 2064 2065 /* 2066 * @implemented 2067 */ 2068 BOOL 2069 WINAPI 2070 DlgDirSelectExW( 2071 HWND hDlg, 2072 LPWSTR lpString, 2073 int nCount, 2074 int nIDListBox) 2075 { 2076 return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, TRUE, FALSE ); 2077 } 2078 2079 2080 /* 2081 * @implemented Modified for ReactOS. Do not Port Sync!!! 2082 */ 2083 BOOL 2084 WINAPI 2085 EndDialog( 2086 HWND hwnd, 2087 INT_PTR retval) 2088 { 2089 DIALOGINFO * dlgInfo; 2090 HWND owner; 2091 BOOL wasActive; 2092 2093 TRACE("%p %ld\n", hwnd, retval ); 2094 2095 if (!(dlgInfo = GETDLGINFO(hwnd))) 2096 { 2097 ERR("got invalid window handle (%p); buggy app !?\n", hwnd); 2098 return FALSE; 2099 } 2100 wasActive = (hwnd == GetActiveWindow()); 2101 dlgInfo->idResult = retval; 2102 dlgInfo->flags |= DF_END; 2103 2104 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD) 2105 { 2106 owner = GetAncestor( hwnd, GA_PARENT); 2107 } 2108 else 2109 owner = GetWindow( hwnd, GW_OWNER ); 2110 2111 if (owner) 2112 EnableWindow( owner, TRUE ); 2113 2114 /* Windows sets the focus to the dialog itself in EndDialog */ 2115 2116 if (wasActive && IsChild(hwnd, GetFocus())) 2117 SetFocus( hwnd ); 2118 2119 /* Don't have to send a ShowWindow(SW_HIDE), just do 2120 SetWindowPos with SWP_HIDEWINDOW as done in Windows */ 2121 2122 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE 2123 | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW); 2124 2125 if (wasActive && owner) 2126 { 2127 /* If this dialog was given an owner then set the focus to that owner. */ 2128 SetActiveWindow(owner); 2129 } 2130 else if (hwnd == GetActiveWindow()) // Check it again! 2131 { 2132 NtUserCallNoParam(NOPARAM_ROUTINE_ZAPACTIVEANDFOUS); 2133 } 2134 2135 /* unblock dialog loop */ 2136 PostMessageA(hwnd, WM_NULL, 0, 0); 2137 return TRUE; 2138 } 2139 2140 2141 /* 2142 * @implemented 2143 */ 2144 LONG 2145 WINAPI 2146 GetDialogBaseUnits(VOID) 2147 { 2148 static DWORD units; 2149 2150 if (!units) 2151 { 2152 HDC hdc; 2153 SIZE size; 2154 2155 if ((hdc = GetDC(0))) 2156 { 2157 size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy ); 2158 if (size.cx) units = MAKELONG( size.cx, size.cy ); 2159 ReleaseDC( 0, hdc ); 2160 } 2161 } 2162 return units; 2163 } 2164 2165 2166 /* 2167 * @implemented 2168 */ 2169 int 2170 WINAPI 2171 GetDlgCtrlID( 2172 HWND hwndCtl) 2173 { 2174 return GetWindowLongPtrW( hwndCtl, GWLP_ID ); 2175 } 2176 2177 2178 /* 2179 * @implemented 2180 */ 2181 HWND 2182 WINAPI 2183 GetDlgItem( 2184 HWND hDlg, 2185 int nIDDlgItem) 2186 { 2187 int i; 2188 HWND *list; 2189 HWND ret = 0; 2190 2191 if (!hDlg) return 0; 2192 2193 list = WIN_ListChildren(hDlg); 2194 if (!list) return 0; 2195 2196 for (i = 0; list[i]; i++) if (GetWindowLongPtrW(list[i], GWLP_ID) == nIDDlgItem) break; 2197 ret = list[i]; 2198 HeapFree(GetProcessHeap(), 0, list); 2199 // if (!ret) SetLastError(ERROR_CONTROL_ID_NOT_FOUND); 2200 return ret; 2201 } 2202 2203 2204 /* 2205 * @implemented 2206 */ 2207 UINT 2208 WINAPI 2209 GetDlgItemInt( 2210 HWND hDlg, 2211 int nIDDlgItem, 2212 BOOL *lpTranslated, 2213 BOOL bSigned) 2214 { 2215 char str[30]; 2216 char * endptr; 2217 LONG_PTR result = 0; 2218 2219 if (lpTranslated) *lpTranslated = FALSE; 2220 if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str)) 2221 return 0; 2222 if (bSigned) 2223 { 2224 result = strtol( str, &endptr, 10 ); 2225 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ 2226 return 0; 2227 if (((result == LONG_MIN) || (result == LONG_MAX))) 2228 return 0; 2229 } 2230 else 2231 { 2232 result = strtoul( str, &endptr, 10 ); 2233 if (!endptr || (endptr == str)) /* Conversion was unsuccessful */ 2234 return 0; 2235 if (result == ULONG_MAX) return 0; 2236 } 2237 if (lpTranslated) *lpTranslated = TRUE; 2238 return (UINT)result; 2239 } 2240 2241 2242 /* 2243 * @implemented 2244 */ 2245 UINT 2246 WINAPI 2247 GetDlgItemTextA( 2248 HWND hDlg, 2249 int nIDDlgItem, 2250 LPSTR lpString, 2251 int nMaxCount) 2252 { 2253 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem); 2254 if ( hWnd ) return GetWindowTextA(hWnd, lpString, nMaxCount); 2255 if ( nMaxCount ) lpString[0] = '\0'; 2256 return 0; 2257 } 2258 2259 2260 /* 2261 * @implemented 2262 */ 2263 UINT 2264 WINAPI 2265 GetDlgItemTextW( 2266 HWND hDlg, 2267 int nIDDlgItem, 2268 LPWSTR lpString, 2269 int nMaxCount) 2270 { 2271 HWND hWnd = GetDlgItem(hDlg, nIDDlgItem); 2272 if ( hWnd ) return GetWindowTextW(hWnd, lpString, nMaxCount); 2273 if ( nMaxCount ) lpString[0] = '\0'; 2274 return 0; 2275 } 2276 2277 /* 2278 * @implemented 2279 */ 2280 HWND 2281 WINAPI 2282 GetNextDlgGroupItem( 2283 HWND hDlg, 2284 HWND hCtl, 2285 BOOL bPrevious) 2286 { 2287 HWND hwnd, hwndNext, retvalue, hwndLastGroup = 0; 2288 BOOL fLooped=FALSE; 2289 BOOL fSkipping=FALSE; 2290 2291 if (hDlg == hCtl) hCtl = NULL; 2292 if (!hCtl && bPrevious) return 0; 2293 2294 /* if the hwndCtrl is the child of the control in the hwndDlg, 2295 * then the hwndDlg has to be the parent of the hwndCtrl */ 2296 2297 if (hCtl) 2298 { 2299 if (!IsChild (hDlg, hCtl)) return 0; 2300 /* Make sure hwndCtrl is a top-level child */ 2301 2302 } 2303 else 2304 { 2305 /* No ctrl specified -> start from the beginning */ 2306 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0; 2307 /* MSDN is wrong. fPrevious does not result in the last child */ 2308 2309 /* No ctrl specified -> start from the beginning */ 2310 if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0; 2311 2312 /* MSDN is wrong. fPrevious does not result in the last child */ 2313 2314 /* Maybe that first one is valid. If so then we don't want to skip it*/ 2315 if ((GetWindowLongPtrW( hCtl, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE) 2316 { 2317 return hCtl; 2318 } 2319 2320 } 2321 2322 /* Always go forward around the group and list of controls; for the 2323 * previous control keep track; for the next break when you find one 2324 */ 2325 retvalue = hCtl; 2326 hwnd = hCtl; 2327 while (1) 2328 { 2329 hwndNext = GetWindow (hwnd, GW_HWNDNEXT); 2330 while (!hwndNext) 2331 { 2332 /* Climb out until there is a next sibling of the ancestor or we 2333 * reach the top (in which case we loop back to the start) 2334 */ 2335 if (hDlg == GetParent (hwnd)) 2336 { 2337 /* Wrap around to the beginning of the list, within the same 2338 * group. (Once only) 2339 */ 2340 if (fLooped) goto end; 2341 fLooped = TRUE; 2342 hwndNext = GetWindow (hDlg, GW_CHILD); 2343 } 2344 else 2345 { 2346 hwnd = GetParent (hwnd); 2347 hwndNext = GetWindow (hwnd, GW_HWNDNEXT); 2348 } 2349 } 2350 hwnd = hwndNext; 2351 2352 /* Wander down the leading edge of controlparents */ 2353 while ( (GetWindowLongPtrW (hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && 2354 ((GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) && 2355 (hwndNext = GetWindow (hwnd, GW_CHILD))) 2356 hwnd = hwndNext; 2357 /* Question. If the control is a control parent but either has no 2358 * children or is not visible/enabled then if it has a WS_GROUP does 2359 * it count? For that matter does it count anyway? 2360 * I believe it doesn't count. 2361 */ 2362 2363 if ((GetWindowLongPtrW (hwnd, GWL_STYLE) & WS_GROUP)) 2364 { 2365 hwndLastGroup = hwnd; 2366 if (!fSkipping) 2367 { 2368 /* Look for the beginning of the group */ 2369 fSkipping = TRUE; 2370 } 2371 } 2372 2373 if (hwnd == hCtl) 2374 { 2375 if (!fSkipping) break; 2376 if (hwndLastGroup == hwnd) break; 2377 hwnd = hwndLastGroup; 2378 fSkipping = FALSE; 2379 fLooped = FALSE; 2380 } 2381 2382 if (!fSkipping && 2383 (GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE|WS_DISABLED)) == 2384 WS_VISIBLE) 2385 { 2386 retvalue = hwnd; 2387 if (!bPrevious) break; 2388 } 2389 } 2390 end: 2391 return retvalue; 2392 } 2393 2394 2395 /* 2396 * @implemented 2397 */ 2398 HWND 2399 WINAPI 2400 GetNextDlgTabItem( 2401 HWND hDlg, 2402 HWND hCtl, 2403 BOOL bPrevious) 2404 { 2405 PWND pWindow; 2406 2407 pWindow = ValidateHwnd( hDlg ); 2408 if (!pWindow) return NULL; 2409 if (hCtl) 2410 { 2411 pWindow = ValidateHwnd( hCtl ); 2412 if (!pWindow) return NULL; 2413 } 2414 2415 /* Undocumented but tested under Win2000 and WinME */ 2416 if (hDlg == hCtl) hCtl = NULL; 2417 2418 /* Contrary to MSDN documentation, tested under Win2000 and WinME 2419 * NB GetLastError returns whatever was set before the function was 2420 * called. 2421 */ 2422 if (!hCtl && bPrevious) return 0; 2423 2424 return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious); 2425 } 2426 2427 2428 #if 0 2429 BOOL 2430 WINAPI 2431 IsDialogMessage( 2432 HWND hDlg, 2433 LPMSG lpMsg) 2434 { 2435 return IsDialogMessageW(hDlg, lpMsg); 2436 } 2437 #endif 2438 2439 /*********************************************************************** 2440 * DIALOG_FixOneChildOnChangeFocus 2441 * 2442 * Callback helper for DIALOG_FixChildrenOnChangeFocus 2443 */ 2444 2445 static BOOL CALLBACK DIALOG_FixOneChildOnChangeFocus (HWND hwndChild, 2446 LPARAM lParam) 2447 { 2448 /* If a default pushbutton then no longer default */ 2449 if (DLGC_DEFPUSHBUTTON & SendMessageW (hwndChild, WM_GETDLGCODE, 0, 0)) 2450 SendMessageW (hwndChild, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); 2451 return TRUE; 2452 } 2453 2454 /*********************************************************************** 2455 * DIALOG_FixChildrenOnChangeFocus 2456 * 2457 * Following the change of focus that occurs for example after handling 2458 * a WM_KEYDOWN VK_TAB in IsDialogMessage, some tidying of the dialog's 2459 * children may be required. 2460 */ 2461 static void DIALOG_FixChildrenOnChangeFocus (HWND hwndDlg, HWND hwndNext) 2462 { 2463 INT dlgcode_next = SendMessageW (hwndNext, WM_GETDLGCODE, 0, 0); 2464 /* INT dlgcode_dlg = SendMessageW (hwndDlg, WM_GETDLGCODE, 0, 0); */ 2465 /* Windows does ask for this. I don't know why yet */ 2466 2467 EnumChildWindows (hwndDlg, DIALOG_FixOneChildOnChangeFocus, 0); 2468 2469 /* If the button that is getting the focus WAS flagged as the default 2470 * pushbutton then ask the dialog what it thinks the default is and 2471 * set that in the default style. 2472 */ 2473 if (dlgcode_next & DLGC_DEFPUSHBUTTON) 2474 { 2475 DWORD def_id = SendMessageW (hwndDlg, DM_GETDEFID, 0, 0); 2476 if (HIWORD(def_id) == DC_HASDEFID) 2477 { 2478 HWND hwndDef; 2479 def_id = LOWORD(def_id); 2480 hwndDef = GetDlgItem (hwndDlg, def_id); 2481 if (hwndDef) 2482 { 2483 INT dlgcode_def = SendMessageW (hwndDef, WM_GETDLGCODE, 0, 0); 2484 /* I know that if it is a button then it should already be a 2485 * UNDEFPUSHBUTTON, since we have just told the buttons to 2486 * change style. But maybe they ignored our request 2487 */ 2488 if ((dlgcode_def & DLGC_BUTTON) && 2489 (dlgcode_def & DLGC_UNDEFPUSHBUTTON)) 2490 { 2491 SendMessageW (hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); 2492 } 2493 } 2494 } 2495 } 2496 else if ((dlgcode_next & DLGC_BUTTON) && (dlgcode_next & DLGC_UNDEFPUSHBUTTON)) 2497 { 2498 SendMessageW (hwndNext, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); 2499 /* I wonder why it doesn't send a DM_SETDEFID */ 2500 } 2501 } 2502 2503 /*********************************************************************** 2504 * DIALOG_IdToHwnd 2505 * 2506 * A recursive version of GetDlgItem 2507 * 2508 * RETURNS 2509 * The HWND for a Child ID. 2510 */ 2511 static HWND DIALOG_IdToHwnd( HWND hwndDlg, INT id ) 2512 { 2513 int i; 2514 HWND *list = WIN_ListChildren( hwndDlg ); 2515 HWND ret = 0; 2516 2517 if (!list) return 0; 2518 2519 for (i = 0; list[i]; i++) 2520 { 2521 if (GetWindowLongPtrW( list[i], GWLP_ID ) == id) 2522 { 2523 ret = list[i]; 2524 break; 2525 } 2526 2527 /* Recurse into every child */ 2528 if ((ret = DIALOG_IdToHwnd( list[i], id ))) break; 2529 } 2530 2531 HeapFree( GetProcessHeap(), 0, list ); 2532 return ret; 2533 } 2534 2535 2536 /* 2537 * @implemented 2538 */ 2539 BOOL 2540 WINAPI 2541 IsDialogMessageW( 2542 HWND hDlg, 2543 LPMSG lpMsg) 2544 { 2545 INT dlgCode = 0; 2546 2547 if (!IsWindow( hDlg )) 2548 return FALSE; 2549 2550 if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE; 2551 2552 if (hDlg == GetDesktopWindow()) return FALSE; 2553 if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE; 2554 2555 hDlg = DIALOG_FindMsgDestination(hDlg); 2556 2557 switch(lpMsg->message) 2558 { 2559 case WM_KEYDOWN: 2560 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); 2561 if (dlgCode & DLGC_WANTMESSAGE) break; 2562 2563 switch(lpMsg->wParam) 2564 { 2565 case VK_TAB: 2566 if (!(dlgCode & DLGC_WANTTAB)) 2567 { 2568 BOOL fIsDialog = TRUE; 2569 WND *pWnd = ValidateHwnd(hDlg); 2570 2571 if (pWnd && TestWindowProcess(pWnd)) 2572 { 2573 fIsDialog = (GETDLGINFO(hDlg) != NULL); 2574 } 2575 2576 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0); 2577 2578 /* I am not sure under which circumstances the TAB is handled 2579 * each way. All I do know is that it does not always simply 2580 * send WM_NEXTDLGCTL. (Personally I have never yet seen it 2581 * do so but I presume someone has) 2582 */ 2583 if (fIsDialog) 2584 SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 ); 2585 else 2586 { 2587 /* It would appear that GetNextDlgTabItem can handle being 2588 * passed hwndDlg rather than NULL but that is undocumented 2589 * so let's do it properly 2590 */ 2591 HWND hwndFocus = GetFocus(); 2592 HWND hwndNext = GetNextDlgTabItem (hDlg, 2593 hwndFocus == hDlg ? NULL : hwndFocus, 2594 GetKeyState (VK_SHIFT) & 0x8000); 2595 if (hwndNext) 2596 { 2597 dlgCode = SendMessageW (hwndNext, WM_GETDLGCODE, 2598 lpMsg->wParam, (LPARAM)lpMsg); 2599 if (dlgCode & DLGC_HASSETSEL) 2600 { 2601 INT maxlen = 1 + SendMessageW (hwndNext, WM_GETTEXTLENGTH, 0, 0); 2602 WCHAR *buffer = HeapAlloc (GetProcessHeap(), 0, maxlen * sizeof(WCHAR)); 2603 if (buffer) 2604 { 2605 SIZE_T length; 2606 SendMessageW (hwndNext, WM_GETTEXT, maxlen, (LPARAM) buffer); 2607 length = strlenW (buffer); 2608 HeapFree (GetProcessHeap(), 0, buffer); 2609 SendMessageW (hwndNext, EM_SETSEL, 0, length); 2610 } 2611 } 2612 SetFocus (hwndNext); 2613 DIALOG_FixChildrenOnChangeFocus (hDlg, hwndNext); 2614 } 2615 else 2616 return FALSE; 2617 } 2618 return TRUE; 2619 } 2620 break; 2621 2622 case VK_RIGHT: 2623 case VK_DOWN: 2624 case VK_LEFT: 2625 case VK_UP: 2626 if (!(dlgCode & DLGC_WANTARROWS)) 2627 { 2628 BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP); 2629 HWND hwndNext = GetNextDlgGroupItem( hDlg, lpMsg->hwnd, fPrevious ); 2630 if (hwndNext && SendMessageW( hwndNext, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ) == (DLGC_BUTTON | DLGC_RADIOBUTTON)) 2631 { 2632 SetFocus( hwndNext ); 2633 if ((GetWindowLongW( hwndNext, GWL_STYLE ) & BS_TYPEMASK) == BS_AUTORADIOBUTTON && 2634 SendMessageW( hwndNext, BM_GETCHECK, 0, 0 ) != BST_CHECKED) 2635 SendMessageW( hwndNext, BM_CLICK, 1, 0 ); 2636 } 2637 else 2638 SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 ); 2639 return TRUE; 2640 } 2641 break; 2642 2643 case VK_CANCEL: 2644 case VK_ESCAPE: 2645 SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) ); 2646 return TRUE; 2647 2648 case VK_EXECUTE: 2649 case VK_RETURN: 2650 { 2651 DWORD dw; 2652 HWND hwndFocus = GetFocus(); 2653 if (IsChild( hDlg, hwndFocus ) && 2654 (SendMessageW (hwndFocus, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)) 2655 { 2656 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( GetDlgCtrlID( hwndFocus ), BN_CLICKED ), (LPARAM)hwndFocus ); 2657 } 2658 else if (DC_HASDEFID == HIWORD(dw = SendMessageW (hDlg, DM_GETDEFID, 0, 0))) 2659 { 2660 HWND hwndDef = DIALOG_IdToHwnd(hDlg, LOWORD(dw)); 2661 if (!hwndDef || IsWindowEnabled(hwndDef)) 2662 SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), (LPARAM)hwndDef); 2663 } 2664 else 2665 { 2666 SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) ); 2667 } 2668 } 2669 return TRUE; 2670 } 2671 break; 2672 2673 case WM_CHAR: 2674 /* FIXME Under what circumstances does WM_GETDLGCODE get sent? 2675 * It does NOT get sent in the test program I have 2676 */ 2677 dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg ); 2678 if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break; 2679 if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break; 2680 /* drop through */ 2681 2682 case WM_SYSCHAR: 2683 if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam )) 2684 { 2685 /* don't translate or dispatch */ 2686 return TRUE; 2687 } 2688 break; 2689 //// ReactOS 2690 case WM_SYSKEYDOWN: 2691 /* If the ALT key is being pressed display the keyboard cues */ 2692 if ( HIWORD(lpMsg->lParam) & KF_ALTDOWN && 2693 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) ) 2694 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0); 2695 break; 2696 2697 case WM_SYSCOMMAND: 2698 /* If the ALT key is being pressed display the keyboard cues */ 2699 if ( lpMsg->wParam == SC_KEYMENU && 2700 !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) ) 2701 { 2702 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0); 2703 } 2704 break; 2705 } 2706 2707 TranslateMessage( lpMsg ); 2708 DispatchMessageW( lpMsg ); 2709 return TRUE; 2710 } 2711 2712 2713 /* 2714 * @implemented 2715 */ 2716 UINT 2717 WINAPI 2718 IsDlgButtonChecked( 2719 HWND hDlg, 2720 int nIDButton) 2721 { 2722 return (UINT)SendDlgItemMessageW( hDlg, nIDButton, BM_GETCHECK, 0, 0 ); 2723 } 2724 2725 2726 /* 2727 * @implemented 2728 */ 2729 BOOL 2730 WINAPI 2731 MapDialogRect( 2732 HWND hDlg, 2733 LPRECT lpRect) 2734 { 2735 DIALOGINFO * dlgInfo; 2736 if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE; 2737 lpRect->left = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4); 2738 lpRect->right = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4); 2739 lpRect->top = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8); 2740 lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8); 2741 return TRUE; 2742 } 2743 2744 2745 /* 2746 * @implemented 2747 */ 2748 LRESULT 2749 WINAPI 2750 SendDlgItemMessageA( 2751 HWND hDlg, 2752 int nIDDlgItem, 2753 UINT Msg, 2754 WPARAM wParam, 2755 LPARAM lParam) 2756 { 2757 HWND hwndCtrl; 2758 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS 2759 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); 2760 if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam ); 2761 else return 0; 2762 } 2763 2764 2765 /* 2766 * @implemented 2767 */ 2768 LRESULT 2769 WINAPI 2770 SendDlgItemMessageW( 2771 HWND hDlg, 2772 int nIDDlgItem, 2773 UINT Msg, 2774 WPARAM wParam, 2775 LPARAM lParam) 2776 { 2777 HWND hwndCtrl; 2778 if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS 2779 hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); 2780 if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam ); 2781 else return 0; 2782 } 2783 2784 2785 /* 2786 * @implemented 2787 */ 2788 BOOL 2789 WINAPI 2790 SetDlgItemInt( 2791 HWND hDlg, 2792 int nIDDlgItem, 2793 UINT uValue, 2794 BOOL bSigned) 2795 { 2796 char str[20]; 2797 2798 if (bSigned) sprintf( str, "%d", (INT)uValue ); 2799 else sprintf( str, "%u", uValue ); 2800 SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str ); 2801 return TRUE; 2802 } 2803 2804 2805 /* 2806 * @implemented 2807 */ 2808 BOOL 2809 WINAPI 2810 SetDlgItemTextA( 2811 HWND hDlg, 2812 int nIDDlgItem, 2813 LPCSTR lpString) 2814 { 2815 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes 2816 if (hwndCtrl) return SetWindowTextA( hwndCtrl, lpString ); 2817 return FALSE; 2818 } 2819 2820 2821 /* 2822 * @implemented 2823 */ 2824 BOOL 2825 WINAPI 2826 SetDlgItemTextW( 2827 HWND hDlg, 2828 int nIDDlgItem, 2829 LPCWSTR lpString) 2830 { 2831 HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes 2832 if (hwndCtrl) return SetWindowTextW( hwndCtrl, lpString ); 2833 return FALSE; 2834 } 2835 2836 2837 /* 2838 * @implemented 2839 */ 2840 BOOL 2841 WINAPI 2842 CheckDlgButton( 2843 HWND hDlg, 2844 int nIDButton, 2845 UINT uCheck) 2846 { 2847 SendDlgItemMessageW( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 ); 2848 return TRUE; 2849 } 2850 2851 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam) 2852 { 2853 LONG lChildID = GetWindowLongPtrW(hwnd, GWLP_ID); 2854 RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam; 2855 2856 if((lChildID >= lpRadioGroup->firstID) && 2857 (lChildID <= lpRadioGroup->lastID)) 2858 { 2859 if (lChildID == lpRadioGroup->checkID) 2860 { 2861 SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0); 2862 } 2863 else 2864 { 2865 SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); 2866 } 2867 } 2868 2869 return TRUE; 2870 } 2871 2872 /* 2873 * @implemented 2874 */ 2875 BOOL 2876 WINAPI 2877 CheckRadioButton( 2878 HWND hDlg, 2879 int nIDFirstButton, 2880 int nIDLastButton, 2881 int nIDCheckButton) 2882 { 2883 RADIOGROUP radioGroup; 2884 2885 radioGroup.firstID = nIDFirstButton; 2886 radioGroup.lastID = nIDLastButton; 2887 radioGroup.checkID = nIDCheckButton; 2888 2889 return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup); 2890 } 2891