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