test: dlgmgr2.c Source File

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 }