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