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