Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dlgmgr2.c

Go to the documentation of this file.
00001 /***************************************************************************\ 00002 * 00003 * DLGMGR2.C 00004 * 00005 * Copyright (c) 1985 - 1999, Microsoft Corporation 00006 * 00007 * Dialog Management Routines 00008 * 00009 * ??-???-???? mikeke Ported from Win 3.0 sources 00010 * 12-Feb-1991 mikeke Added Revalidation code 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 /***************************************************************************\ 00017 * xxxRemoveDefaultButton 00018 * 00019 * Scan through all the controls in the dialog box and remove the default 00020 * button style from any button that has it. This is done since at times we 00021 * do not know who has the default button. 00022 * 00023 * History: 00024 * 00025 * Bug 19449 - joejo 00026 * 00027 * Stop infinite loop when pwnd != pwndStart but pwnd == pwnd after calling 00028 * _NextControl! 00029 \***************************************************************************/ 00030 00031 void xxxRemoveDefaultButton( 00032 PWND pwndRoot, 00033 PWND pwndStart) 00034 { 00035 UINT code; 00036 PWND pwnd; 00037 PWND pwndDup; 00038 TL tlpwnd; 00039 00040 CheckLock(pwndRoot); 00041 CheckLock(pwndStart); 00042 00043 if (!pwndStart || TestWF(pwndStart, WEFCONTROLPARENT)) 00044 pwndStart = _NextControl(pwndRoot, NULL, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED); 00045 else 00046 pwndStart = _GetChildControl(pwndRoot, pwndStart); 00047 00048 if (!pwndStart) 00049 return; 00050 00051 pwnd = pwndStart; 00052 do { 00053 pwndDup = pwnd; 00054 00055 ThreadLock(pwnd, &tlpwnd); 00056 00057 code = (UINT)SendMessage(HWq(pwnd), WM_GETDLGCODE, 0, 0L); 00058 00059 if (code & DLGC_DEFPUSHBUTTON) { 00060 SendMessage(HWq(pwnd), BM_SETSTYLE, BS_PUSHBUTTON, (LONG)TRUE); 00061 } 00062 00063 pwnd = _NextControl(pwndRoot, pwnd, 0); 00064 00065 ThreadUnlock(&tlpwnd); 00066 00067 } while (pwnd && (pwnd != pwndStart) && (pwnd != pwndDup)); 00068 00069 #if DBG 00070 if (pwnd && (pwnd != pwndStart) && (pwnd != pwndDup)) { 00071 RIPMSG0(RIP_WARNING, "xxxRemoveDefaultButton bailing potential infinite loop!"); 00072 } 00073 #endif 00074 00075 } 00076 00077 00078 /***************************************************************************\ 00079 * xxxCheckDefPushButton 00080 * 00081 * History: 00082 \***************************************************************************/ 00083 00084 void xxxCheckDefPushButton( 00085 PWND pwndDlg, 00086 HWND hwndOldFocus, 00087 HWND hwndNewFocus) 00088 { 00089 PWND pwndNewFocus; 00090 PWND pwndOldFocus; 00091 TL tlpwndT; 00092 PWND pwndT; 00093 UINT codeNewFocus = 0; 00094 UINT styleT; 00095 LONG lT; 00096 int id; 00097 00098 if (hwndNewFocus) 00099 pwndNewFocus = ValidateHwnd(hwndNewFocus); 00100 else 00101 pwndNewFocus = NULL; 00102 00103 if (hwndOldFocus) 00104 pwndOldFocus = ValidateHwnd(hwndOldFocus); 00105 else 00106 pwndOldFocus = NULL; 00107 00108 CheckLock(pwndDlg); 00109 CheckLock(pwndNewFocus); 00110 CheckLock(pwndOldFocus); 00111 00112 if (pwndNewFocus) 00113 { 00114 // Do nothing if clicking on dialog background or recursive dialog 00115 // background. 00116 if (TestWF(pwndNewFocus, WEFCONTROLPARENT)) 00117 return; 00118 00119 codeNewFocus = (UINT)SendMessage(hwndNewFocus, WM_GETDLGCODE, 0, 0L); 00120 } 00121 00122 if (SAMEWOWHANDLE(hwndOldFocus, hwndNewFocus)) { 00123 // 00124 // NEW FOR 4.0: 00125 // 00126 // There is a very common frustrating scenario for ISVs who try to 00127 // set the default ID. Our dialog manager assumes that if a push 00128 // button has the focus, it is the default button also. As such 00129 // it passes in the focus window to this routine. If someone tries 00130 // to change the focus or set the def ID such that they reside with 00131 // two different push buttons, the double-default-push button case 00132 // will result shortly. 00133 // 00134 // As such, for 4.0 dialogs, we will go check the def ID and see if 00135 // is the same as hwndOldFocus' ID. If not, then we will find IT 00136 // and use that dude as hwndOldFocus 00137 // 00138 if (codeNewFocus & DLGC_UNDEFPUSHBUTTON) 00139 { 00140 if (TestWF(pwndDlg, WFWIN40COMPAT) && hwndOldFocus) 00141 { 00142 lT = (LONG)SendMessage(HWq(pwndDlg), DM_GETDEFID, 0, 0L); 00143 id = (HIWORD(lT) == DC_HASDEFID ? LOWORD(lT) : IDOK); 00144 lT = MAKELONG(id, 0); 00145 00146 if (lT != PtrToLong(pwndNewFocus->spmenu)) 00147 { 00148 if (pwndOldFocus = _FindDlgItem(pwndDlg, lT)) 00149 { 00150 hwndOldFocus = HW(pwndOldFocus); 00151 if (SendMessage(hwndOldFocus, WM_GETDLGCODE, 0, 0L) & DLGC_DEFPUSHBUTTON) 00152 { 00153 xxxRemoveDefaultButton(pwndDlg, pwndOldFocus); 00154 goto SetNewDefault; 00155 } 00156 } 00157 } 00158 } 00159 00160 SendMessage(hwndNewFocus, BM_SETSTYLE, BS_DEFPUSHBUTTON, (LONG)TRUE); 00161 } 00162 return; 00163 } 00164 00165 /* 00166 * If the focus is changing to or from a pushbutton, then remove the 00167 * default style from the current default button 00168 */ 00169 if ((hwndOldFocus != NULL && (SendMessage(hwndOldFocus, WM_GETDLGCODE, 00170 0, 0) & (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))) || 00171 (hwndNewFocus != NULL && 00172 (codeNewFocus & (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON)))) { 00173 xxxRemoveDefaultButton(pwndDlg, pwndNewFocus); 00174 } 00175 00176 SetNewDefault: 00177 /* 00178 * If moving to a button, make that button the default. 00179 */ 00180 if (codeNewFocus & DLGC_UNDEFPUSHBUTTON) { 00181 SendMessage(hwndNewFocus, BM_SETSTYLE, BS_DEFPUSHBUTTON, (LONG)TRUE); 00182 } else { 00183 00184 /* 00185 * Otherwise, make sure the original default button is default 00186 * and no others. 00187 */ 00188 00189 /* 00190 * Get the original default button handle 00191 */ 00192 lT = (LONG)SendMessage(HWq(pwndDlg), DM_GETDEFID, 0, 0L); 00193 id = (HIWORD(lT) == DC_HASDEFID ? LOWORD(lT) : IDOK); 00194 pwndT = _FindDlgItem(pwndDlg, id); 00195 00196 if (pwndT == NULL) 00197 return; 00198 ThreadLockAlways(pwndT, &tlpwndT); 00199 00200 /* 00201 * If it already has the default button style, do nothing. 00202 */ 00203 if ((styleT = (UINT)SendMessage(HWq(pwndT), WM_GETDLGCODE, 0, 0L)) & DLGC_DEFPUSHBUTTON) { 00204 ThreadUnlock(&tlpwndT); 00205 return; 00206 } 00207 00208 /* 00209 * Also check to make sure it is really a button. 00210 */ 00211 if (!(styleT & DLGC_UNDEFPUSHBUTTON)) { 00212 ThreadUnlock(&tlpwndT); 00213 return; 00214 } 00215 00216 if (!TestWF(pwndT, WFDISABLED)) { 00217 SendMessage(HWq(pwndT), BM_SETSTYLE, BS_DEFPUSHBUTTON, (LONG)TRUE); 00218 } 00219 ThreadUnlock(&tlpwndT); 00220 } 00221 } 00222 00223 00224 /***************************************************************************\ 00225 * IsDialogMessage (API) 00226 * 00227 * History: 00228 \***************************************************************************/ 00229 00230 BOOL IsDialogMessageA( 00231 HWND hwndDlg, 00232 LPMSG lpmsg) 00233 { 00234 WPARAM wParamSaved = lpmsg->wParam; 00235 BOOL bRet; 00236 00237 switch (lpmsg->message) { 00238 #ifdef FE_SB // IsDialogMessageA() 00239 case WM_CHAR: 00240 case EM_SETPASSWORDCHAR: 00241 /* 00242 * BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA() macro will return TRUE 00243 * for DBCS leadbyte message everytime, then we check there is some 00244 * possibility the return value become FALSE, here. 00245 * 00246 * These code originally come from IsDialogMessageW(). 00247 */ 00248 if (IS_DBCS_ENABLED()) { 00249 PWND pwndDlg, pwnd; 00250 TL tlpwndDlg; 00251 BOOL fLockDlg = FALSE; 00252 00253 if ((pwndDlg = ValidateHwndNoRip(hwndDlg)) == NULL) { 00254 return FALSE; 00255 } 00256 00257 if (lpmsg->hwnd == NULL) { 00258 return FALSE; 00259 } 00260 00261 pwnd = ValidateHwnd(lpmsg->hwnd); 00262 // 00263 // THIS IS FOR MFC. 00264 // 00265 // This solves many problems with apps that use MFC but want to take 00266 // advantage of DS_CONTROL. MFC blindly passes in child dialogs sometimes 00267 // to IsDialogMessage, which can screw up tabbing etc. 00268 // 00269 if (TestWF(pwndDlg, WEFCONTROLPARENT) && TestWF(pwndDlg, WFCHILD)) { 00270 pwndDlg = GetParentDialog(pwndDlg); 00271 ThreadLock(pwndDlg, &tlpwndDlg); 00272 fLockDlg = TRUE; 00273 hwndDlg = HWq(pwndDlg); 00274 } 00275 00276 if (pwnd != pwndDlg && !_IsChild(pwndDlg, pwnd)) { 00277 if (fLockDlg) 00278 ThreadUnlock(&tlpwndDlg); 00279 return FALSE; 00280 } 00281 00282 /* 00283 * Build DBCS-aware message. 00284 */ 00285 BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA(lpmsg->message,lpmsg->wParam,TRUE); 00286 00287 /* 00288 * Fall through..... 00289 */ 00290 } 00291 #else 00292 case WM_CHAR: 00293 case EM_SETPASSWORDCHAR: 00294 #endif // FE_SB 00295 case WM_CHARTOITEM: 00296 case WM_DEADCHAR: 00297 case WM_SYSCHAR: 00298 case WM_SYSDEADCHAR: 00299 case WM_MENUCHAR: 00300 #ifdef FE_IME // IsDialogMessageA() 00301 case WM_IME_CHAR: 00302 case WM_IME_COMPOSITION: 00303 #endif // FE_IME 00304 00305 RtlMBMessageWParamCharToWCS(lpmsg->message, &lpmsg->wParam); 00306 } 00307 00308 bRet = IsDialogMessageW(hwndDlg, lpmsg); 00309 00310 /* 00311 * Restore the original ANSI char. 00312 */ 00313 lpmsg->wParam = wParamSaved; 00314 return bRet; 00315 } 00316 00317 BOOL IsDialogMessageW( 00318 HWND hwndDlg, 00319 LPMSG lpMsg) 00320 { 00321 PWND pwndDlg; 00322 PWND pwnd; 00323 PWND pwnd2; 00324 HWND hwnd2; 00325 HWND hwndFocus; 00326 int iOK; 00327 BOOL fBack; 00328 UINT code; 00329 LONG lT; 00330 TL tlpwnd; 00331 TL tlpwndDlg; 00332 BOOL fLockDlg = FALSE; 00333 TL tlpwnd2; 00334 WORD langID; 00335 00336 langID = PRIMARYLANGID(LANGIDFROMLCID(GetUserDefaultLCID())); 00337 00338 if ((pwndDlg = ValidateHwndNoRip(hwndDlg)) == NULL) { 00339 return FALSE; 00340 } 00341 00342 CheckLock(pwndDlg); 00343 00344 /* 00345 * If this is a synchronous-only message (takes a pointer in wParam or 00346 * lParam), then don't allow this message to go through since those 00347 * parameters have not been thunked, and are pointing into outer-space 00348 * (which would case exceptions to occur). 00349 * 00350 * (This api is only called in the context of a message loop, and you 00351 * don't get synchronous-only messages in a message loop). 00352 */ 00353 if (TESTSYNCONLYMESSAGE(lpMsg->message, lpMsg->wParam)) { 00354 /* 00355 * Fail if 32 bit app is calling. 00356 */ 00357 if (!(GetClientInfo()->dwTIFlags & TIF_16BIT)) { 00358 RIPERR0(ERROR_MESSAGE_SYNC_ONLY, RIP_WARNING, "IsDialogMessage: must be sync only"); 00359 return FALSE; 00360 } 00361 00362 /* 00363 * For wow apps, allow it to go through (for compatibility). Change 00364 * the message id so our code doesn't understand the message - wow 00365 * will get the message and strip out this bit before dispatching 00366 * the message to the application. 00367 */ 00368 lpMsg->message |= MSGFLAG_WOW_RESERVED; 00369 } 00370 00371 if (CallMsgFilter(lpMsg, MSGF_DIALOGBOX)) 00372 return TRUE; 00373 00374 if (lpMsg->hwnd == NULL) { 00375 return FALSE; 00376 } 00377 00378 pwnd = ValidateHwnd(lpMsg->hwnd); 00379 // 00380 // THIS IS FOR MFC. 00381 // 00382 // This solves many problems with apps that use MFC but want to take 00383 // advantage of DS_CONTROL. MFC blindly passes in child dialogs sometimes 00384 // to IsDialogMessage, which can screw up tabbing etc. 00385 // 00386 if (TestWF(pwndDlg, WEFCONTROLPARENT) && TestWF(pwndDlg, WFCHILD)) { 00387 pwndDlg = GetParentDialog(pwndDlg); 00388 ThreadLock(pwndDlg, &tlpwndDlg); 00389 fLockDlg = TRUE; 00390 hwndDlg = HWq(pwndDlg); 00391 } 00392 00393 if (pwnd != pwndDlg && !_IsChild(pwndDlg, pwnd)) { 00394 if (fLockDlg) 00395 ThreadUnlock(&tlpwndDlg); 00396 return FALSE; 00397 } 00398 ThreadLock(pwnd, &tlpwnd); 00399 00400 fBack = FALSE; 00401 iOK = IDCANCEL; 00402 switch (lpMsg->message) { 00403 case WM_LBUTTONDOWN: 00404 00405 /* 00406 * Move the default button styles around on button clicks in the 00407 * same way as TABs. 00408 */ 00409 if ((pwnd != pwndDlg) && ((hwndFocus = GetFocus()) != NULL)) { 00410 xxxCheckDefPushButton(pwndDlg, hwndFocus, lpMsg->hwnd); 00411 } 00412 break; 00413 00414 case WM_SYSCHAR: 00415 00416 /* 00417 * If no control has focus, and Alt not down, then ignore. 00418 */ 00419 if ((GetFocus() == NULL) && (GetKeyState(VK_MENU) >= 0)) { 00420 if (lpMsg->wParam == VK_RETURN && TestWF(pwnd, WFMINIMIZED)) { 00421 00422 /* 00423 * If this is an iconic dialog box window and the user hits 00424 * return, send the message off to DefWindowProc so that it 00425 * can be restored. Especially useful for apps whose top 00426 * level window is a dialog box. 00427 */ 00428 goto CallDefWindowProcAndReturnTrue; 00429 } else { 00430 NtUserMessageBeep(0); 00431 } 00432 00433 ThreadUnlock(&tlpwnd); 00434 if (fLockDlg) 00435 ThreadUnlock(&tlpwndDlg); 00436 return TRUE; 00437 } 00438 00439 /* 00440 * If alt+menuchar, process as menu. 00441 */ 00442 if (lpMsg->wParam == MENUSYSMENU) { 00443 DefWindowProcWorker(pwndDlg, lpMsg->message, lpMsg->wParam, 00444 lpMsg->lParam, FALSE); 00445 ThreadUnlock(&tlpwnd); 00446 if (fLockDlg) 00447 ThreadUnlock(&tlpwndDlg); 00448 return TRUE; 00449 } 00450 00451 /* 00452 *** FALL THRU ** 00453 */ 00454 00455 case WM_CHAR: 00456 00457 /* 00458 * Ignore chars sent to the dialog box (rather than the control). 00459 */ 00460 if (pwnd == pwndDlg) { 00461 ThreadUnlock(&tlpwnd); 00462 if (fLockDlg) 00463 ThreadUnlock(&tlpwndDlg); 00464 return TRUE; 00465 } 00466 00467 code = (UINT)SendMessage(lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, 00468 (LPARAM)lpMsg); 00469 00470 /* 00471 * If the control wants to process the message, then don't check for 00472 * possible mnemonic key. 00473 */ 00474 if ((lpMsg->message == WM_CHAR) && (code & (DLGC_WANTCHARS | DLGC_WANTMESSAGE))) 00475 break; 00476 00477 /* If the control wants tabs, then don't let tab fall thru here 00478 */ 00479 if ((lpMsg->wParam == VK_TAB) && (code & DLGC_WANTTAB)) 00480 break; 00481 00482 00483 /* 00484 * HACK ALERT 00485 * 00486 * If ALT is held down (i.e., SYSCHARs), then ALWAYS do mnemonic 00487 * processing. If we do away with SYSCHARS, then we should 00488 * check key state of ALT instead. 00489 */ 00490 00491 /* 00492 * Space is not a valid mnemonic, but it IS the char that toggles 00493 * button states. Don't look for it as a mnemonic or we will 00494 * beep when it is typed.... 00495 */ 00496 if (lpMsg->wParam == VK_SPACE) { 00497 ThreadUnlock(&tlpwnd); 00498 if (fLockDlg) 00499 ThreadUnlock(&tlpwndDlg); 00500 return TRUE; 00501 } 00502 00503 if (!(pwnd2 = xxxGotoNextMnem(pwndDlg, pwnd, (WCHAR)lpMsg->wParam))) { 00504 00505 if (code & DLGC_WANTMESSAGE) 00506 break; 00507 00508 /* 00509 * No mnemonic could be found so we will send the sys char over 00510 * to xxxDefWindowProc so that any menu bar on the dialog box is 00511 * handled properly. 00512 */ 00513 if (lpMsg->message == WM_SYSCHAR) { 00514 CallDefWindowProcAndReturnTrue: 00515 DefWindowProcWorker(pwndDlg, lpMsg->message, lpMsg->wParam, 00516 lpMsg->lParam, FALSE); 00517 00518 ThreadUnlock(&tlpwnd); 00519 if (fLockDlg) 00520 ThreadUnlock(&tlpwndDlg); 00521 return TRUE; 00522 } 00523 NtUserMessageBeep(0); 00524 } else { 00525 00526 /* 00527 * pwnd2 is 1 if the mnemonic took us to a pushbutton. We 00528 * don't change the default button status here since doing this 00529 * doesn't change the focus. 00530 */ 00531 if (pwnd2 != (PWND)1) { 00532 ThreadLockAlways(pwnd2, &tlpwnd2); 00533 xxxCheckDefPushButton(pwndDlg, lpMsg->hwnd, HWq(pwnd2)); 00534 ThreadUnlock(&tlpwnd2); 00535 } 00536 } 00537 00538 ThreadUnlock(&tlpwnd); 00539 if (fLockDlg) 00540 ThreadUnlock(&tlpwndDlg); 00541 return TRUE; 00542 00543 case WM_SYSKEYDOWN: 00544 /* 00545 * If Alt is down, deal with keyboard cues 00546 */ 00547 if ((HIWORD(lpMsg->lParam) & SYS_ALTERNATE) && TEST_KbdCuesPUSIF) { 00548 if (TestWF(pwnd, WEFPUIFOCUSHIDDEN) || (TestWF(pwnd, WEFPUIACCELHIDDEN))) { 00549 SendMessageWorker(pwndDlg, WM_CHANGEUISTATE, 00550 MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0, FALSE); 00551 } 00552 } 00553 break; 00554 00555 case WM_KEYDOWN: 00556 code = (UINT)SendMessage(lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, 00557 (LPARAM)lpMsg); 00558 if (code & (DLGC_WANTALLKEYS | DLGC_WANTMESSAGE)) 00559 break; 00560 00561 switch (lpMsg->wParam) { 00562 case VK_TAB: 00563 if (code & DLGC_WANTTAB) 00564 break; 00565 pwnd2 = _GetNextDlgTabItem(pwndDlg, pwnd, 00566 (GetKeyState(VK_SHIFT) & 0x8000)); 00567 00568 if (TEST_KbdCuesPUSIF) { 00569 if (TestWF(pwnd, WEFPUIFOCUSHIDDEN)) { 00570 SendMessageWorker(pwndDlg, WM_CHANGEUISTATE, 00571 MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0, FALSE); 00572 } 00573 } 00574 00575 if (pwnd2 != NULL) { 00576 hwnd2 = HWq(pwnd2); 00577 ThreadLockAlways(pwnd2, &tlpwnd2); 00578 DlgSetFocus(hwnd2); 00579 xxxCheckDefPushButton(pwndDlg, lpMsg->hwnd, hwnd2); 00580 ThreadUnlock(&tlpwnd2); 00581 } 00582 ThreadUnlock(&tlpwnd); 00583 if (fLockDlg) 00584 ThreadUnlock(&tlpwndDlg); 00585 return TRUE; 00586 00587 /* 00588 * For Arabic and Hebrew locales the arrow keys are reversed. Also reverse them if 00589 * the dialog is RTL mirrored. 00590 */ 00591 case VK_LEFT: 00592 if ((((langID == LANG_ARABIC) || (langID == LANG_HEBREW)) && TestWF(pwndDlg,WEFRTLREADING)) 00593 #ifdef USE_MIRRORING 00594 ^ (!!TestWF(pwndDlg, WEFLAYOUTRTL)) 00595 #endif 00596 ) 00597 goto DoKeyStuff; 00598 case VK_UP: 00599 fBack = TRUE; 00600 goto DoKeyStuff; 00601 00602 /* 00603 *** FALL THRU ** 00604 */ 00605 case VK_RIGHT: 00606 if ((((langID == LANG_ARABIC) || (langID == LANG_HEBREW)) && TestWF(pwndDlg,WEFRTLREADING)) 00607 #ifdef USE_MIRRORING 00608 ^ (!!TestWF(pwndDlg, WEFLAYOUTRTL)) 00609 #endif 00610 ) 00611 fBack = TRUE; 00612 case VK_DOWN: 00613 DoKeyStuff: 00614 if (code & DLGC_WANTARROWS) 00615 break; 00616 00617 if (TEST_KbdCuesPUSIF) { 00618 if (TestWF(pwnd, WEFPUIFOCUSHIDDEN)) { 00619 SendMessageWorker(pwndDlg, WM_CHANGEUISTATE, 00620 MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0, FALSE); 00621 } 00622 } 00623 00624 pwnd2 = _GetNextDlgGroupItem(pwndDlg, pwnd, fBack); 00625 if (pwnd2 == NULL) { 00626 ThreadUnlock(&tlpwnd); 00627 if (fLockDlg) 00628 ThreadUnlock(&tlpwndDlg); 00629 return TRUE; 00630 } 00631 hwnd2 = HWq(pwnd2); 00632 ThreadLockAlways(pwnd2, &tlpwnd2); 00633 00634 code = (UINT)SendMessage(hwnd2, WM_GETDLGCODE, lpMsg->wParam, 00635 (LPARAM)lpMsg); 00636 00637 /* 00638 * We are just moving the focus rect around! So, do not send 00639 * BN_CLICK messages, when WM_SETFOCUSing. Fix for Bug 00640 * #4358. 00641 */ 00642 if (code & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON)) { 00643 PBUTN pbutn; 00644 BOOL fIsNTButton = (GETFNID(pwnd2) == FNID_BUTTON); 00645 if (fIsNTButton) { 00646 pbutn = ((PBUTNWND)pwnd2)->pbutn; 00647 BUTTONSTATE(pbutn) |= BST_DONTCLICK; 00648 } 00649 DlgSetFocus(hwnd2); 00650 if (fIsNTButton) { 00651 BUTTONSTATE(pbutn) &= ~BST_DONTCLICK; 00652 } 00653 xxxCheckDefPushButton(pwndDlg, lpMsg->hwnd, hwnd2); 00654 } else if (code & DLGC_RADIOBUTTON) { 00655 DlgSetFocus(hwnd2); 00656 xxxCheckDefPushButton(pwndDlg, lpMsg->hwnd, hwnd2); 00657 if (TestWF(pwnd2, BFTYPEMASK) == LOBYTE(BS_AUTORADIOBUTTON)) { 00658 00659 /* 00660 * So that auto radio buttons get clicked on 00661 */ 00662 if (!SendMessage(hwnd2, BM_GETCHECK, 0, 0L)) { 00663 SendMessage(hwnd2, BM_CLICK, TRUE, 0L); 00664 } 00665 } 00666 } else if (!(code & DLGC_STATIC)) { 00667 DlgSetFocus(hwnd2); 00668 xxxCheckDefPushButton(pwndDlg, lpMsg->hwnd, hwnd2); 00669 } 00670 ThreadUnlock(&tlpwnd2); 00671 ThreadUnlock(&tlpwnd); 00672 if (fLockDlg) 00673 ThreadUnlock(&tlpwndDlg); 00674 return TRUE; 00675 00676 case VK_EXECUTE: 00677 case VK_RETURN: 00678 00679 /* 00680 * Guy pressed return - if button with focus is 00681 * defpushbutton, return its ID. Otherwise, return id 00682 * of original defpushbutton. 00683 */ 00684 if (!(hwndFocus = GetFocus())) 00685 code = 0; 00686 else 00687 { 00688 code = (WORD)(DWORD)SendMessage(hwndFocus, WM_GETDLGCODE, 00689 0, 0L); 00690 } 00691 00692 if (code & DLGC_DEFPUSHBUTTON) 00693 { 00694 iOK = GetDlgCtrlID(hwndFocus); 00695 pwnd2 = ValidateHwnd(hwndFocus); 00696 goto HaveWindow; 00697 } 00698 else 00699 { 00700 lT = (LONG)SendMessage(hwndDlg, DM_GETDEFID, 0, 0L); 00701 iOK = MAKELONG( 00702 (HIWORD(lT)==DC_HASDEFID ? LOWORD(lT) : IDOK), 00703 0); 00704 } 00705 // FALL THRU 00706 00707 case VK_ESCAPE: 00708 case VK_CANCEL: 00709 00710 /* 00711 * Make sure button is not disabled. 00712 */ 00713 pwnd2 = _FindDlgItem(pwndDlg, iOK); 00714 HaveWindow: 00715 if (pwnd2 != NULL && TestWF(pwnd2, WFDISABLED)) { 00716 NtUserMessageBeep(0); 00717 } else { 00718 SendMessage(hwndDlg, WM_COMMAND, 00719 MAKELONG(iOK, BN_CLICKED), (LPARAM)HW(pwnd2)); 00720 } 00721 00722 ThreadUnlock(&tlpwnd); 00723 if (fLockDlg) 00724 ThreadUnlock(&tlpwndDlg); 00725 return TRUE; 00726 } 00727 break; 00728 } 00729 00730 ThreadUnlock(&tlpwnd); 00731 if (fLockDlg) 00732 ThreadUnlock(&tlpwndDlg); 00733 00734 TranslateMessage(lpMsg); 00735 DispatchMessage(lpMsg); 00736 00737 return TRUE; 00738 } 00739 00740 /***************************************************************************\ 00741 * 00742 * FindDlgItem32() 00743 * 00744 * Given a dialog, finds the window with the given ID anywhere w/in the 00745 * descendant chain. 00746 * 00747 \***************************************************************************/ 00748 00749 PWND _FindDlgItem(PWND pwndParent, DWORD id) 00750 { 00751 PWND pwndChild; 00752 PWND pwndOrig; 00753 00754 // QUICK TRY: 00755 pwndChild = _GetDlgItem(pwndParent, id); 00756 if (pwndChild || !TestWF(pwndParent, WFWIN40COMPAT)) 00757 return(pwndChild); 00758 00759 pwndOrig = _NextControl(pwndParent, NULL, CWP_SKIPINVISIBLE); 00760 if (pwndOrig == pwndParent) 00761 return(NULL); 00762 00763 pwndChild = pwndOrig; 00764 00765 // VerifyWindow(pwndChild); 00766 00767 do 00768 { 00769 if (PtrToUlong(pwndChild->spmenu) == id) 00770 return(pwndChild); 00771 00772 pwndChild = _NextControl(pwndParent, pwndChild, CWP_SKIPINVISIBLE); 00773 } 00774 while (pwndChild && (pwndChild != pwndOrig)); 00775 00776 return(NULL); 00777 }

Generated on Sat May 15 19:39:45 2004 for test by doxygen 1.3.7