test: dlgmgrc.c Source File

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

# dlgmgrc.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: dlgmgrc.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * This module contains client side dialog functionality
    00007 *
    00008 * History:
    00009 * 15-Dec-1993 JohnC      Pulled functions from user\server.
    00010 \***************************************************************************/
    00011
    00012 #include "precomp.h"
    00013 #pragma hdrstop
    00014
    00015
    00016 /***************************************************************************\
    00017 * UT_PrevGroupItem
    00018 *
    00019 * History:
    00020 \***************************************************************************/
    00021
    00022 PWND UT_PrevGroupItem(
    00023     PWND pwndDlg,
    00024     PWND pwndCurrent)
    00025 {
    00026     PWND pwnd, pwndPrev;
    00027
    00028     if (pwndCurrent == NULL || !TestWF(pwndCurrent, WFGROUP))
    00029         return _PrevControl(pwndDlg, pwndCurrent, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
    00030
    00031     pwndPrev = pwndCurrent;
    00032
    00033     while (TRUE) {
    00034         pwnd = _NextControl(pwndDlg, pwndPrev, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
    00035
    00036         if (TestWF(pwnd, WFGROUP) || pwnd == pwndCurrent)
    00037             return pwndPrev;
    00038
    00039         pwndPrev = pwnd;
    00040     }
    00041 }
    00042
    00043
    00044 /***************************************************************************\
    00045 * UT_NextGroupItem
    00046 *
    00047 * History:
    00048 \***************************************************************************/
    00049
    00050 PWND UT_NextGroupItem(
    00051     PWND pwndDlg,
    00052     PWND pwndCurrent)
    00053 {
    00054     PWND pwnd, pwndNext;
    00055
    00056     pwnd = _NextControl(pwndDlg, pwndCurrent, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
    00057
    00058     if (pwndCurrent == NULL || !TestWF(pwnd, WFGROUP))
    00059         return pwnd;
    00060
    00061     pwndNext = pwndCurrent;
    00062
    00063     while (!TestWF(pwndNext, WFGROUP)) {
    00064         pwnd = _PrevControl(pwndDlg, pwndNext, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
    00065         if (pwnd == pwndCurrent)
    00066             return pwndNext;
    00067         pwndNext = pwnd;
    00068     }
    00069
    00070     return pwndNext;
    00071 }
    00072
    00073 /***************************************************************************\
    00074 * _PrevControl
    00075 *
    00076 * History:
    00077 \***************************************************************************/
    00078 PWND _PrevControl(
    00079     PWND pwndRoot,
    00080     PWND pwndStart,
    00081     UINT uFlags)
    00082 {
    00083     BOOL fFirstFound;
    00084     PWND pwndNext;
    00085     PWND pwnd, pwndFirst;
    00086
    00087     if (!pwndStart)
    00088         return(NULL);
    00089
    00090     UserAssert(pwndRoot != pwndStart);
    00091     UserAssert(!TestWF(pwndStart, WEFCONTROLPARENT));
    00092
    00093     pwnd = _NextControl(pwndRoot, NULL, uFlags);
    00094
    00095     pwndFirst = pwnd;
    00096     fFirstFound = FALSE;
    00097     while (pwndNext = _NextControl(pwndRoot, pwnd, uFlags)) {
    00098
    00099         if (pwndNext == pwndStart)
    00100             break;
    00101
    00102         if (pwndNext == pwndFirst) {
    00103             if (fFirstFound) {
    00104                 RIPMSG0(RIP_WARNING, "_PrevControl: Loop Detected");
    00105                 break;
    00106             } else {
    00107                 fFirstFound = TRUE;
    00108             }
    00109         }
    00110
    00111         pwnd = pwndNext;
    00112     }
    00113
    00114     return pwnd;
    00115 }
    00116 /***************************************************************************\
    00117 *
    00118 *  GetChildControl()
    00119 *
    00120 *  Gets valid ancestor of given window.
    00121 *  A valid dialog control is a direct descendant of a "form" control.
    00122 *
    00123 \***************************************************************************/
    00124
    00125 PWND  _GetChildControl(PWND pwndRoot, PWND pwndChild) {
    00126     PWND    pwndControl = NULL;
    00127
    00128     while (pwndChild && TestwndChild(pwndChild) && (pwndChild != pwndRoot)) {
    00129         pwndControl = pwndChild;
    00130         pwndChild = REBASEPWND(pwndChild, spwndParent);
    00131
    00132         if (TestWF(pwndChild, WEFCONTROLPARENT))
    00133             break;
    00134     }
    00135
    00136     return(pwndControl);
    00137 }
    00138
    00139 /***************************************************************************\
    00140 *
    00141 *  _NextSibblingOrAncestor
    00142 *
    00143 * Called by _NextControl. It returns the next control to pwndStart. If there
    00144 * is a next window (pwndStart->spwndNext), then that is it.
    00145 * Otherwise, the next control is up the parent chain. However, if it's already
    00146 * at the top of the chain (pwndRoot == pwndStart->spwndParent), then the next
    00147 * control is the first child of pwndRoot. But if it's not at the top of the chain,
    00148 * then the next control is pwndStart->spwndParent or an ancestor.
    00149 *
    00150 \***************************************************************************/
    00151 PWND _NextSibblingOrAncestor (PWND pwndRoot, PWND pwndStart)
    00152 {
    00153     PWND pwndParent;
    00154 #if DBG
    00155     PWND pwndNext;
    00156 #endif
    00157
    00158     // If there is a sibbling, go for it
    00159     if (pwndStart->spwndNext != NULL) {
    00160         return (REBASEALWAYS(pwndStart, spwndNext));
    00161     }
    00162
    00163     // If it cannot go up the parent chain, then return the first sibbling.
    00164     pwndParent = REBASEALWAYS(pwndStart, spwndParent);
    00165     if (pwndParent == pwndRoot) {
    00166         // Note that if pwndStart doesn't have any sibblings,
    00167         //  this will return pwndStart again
    00168         return (REBASEALWAYS(pwndParent, spwndChild));
    00169     }
    00170
    00171
    00172     // Otherwise walk up the parent chain looking for the first window with
    00173     // a WS_EX_CONTROLPARENT parent.
    00174
    00175 #if DBG
    00176     pwndNext =
    00177 #else
    00178     return
    00179 #endif
    00180         _GetChildControl(pwndRoot, pwndParent);
    00181
    00182 #if DBG
    00183     if ((pwndNext != pwndParent) || !TestWF(pwndParent, WEFCONTROLPARENT)) {
    00184         // Code looping through the controls in a dialog might go into an infinite
    00185         //  loop because of this (i.e., xxxRemoveDefaultButton, _GetNextDlgTabItem,..)
    00186         // We've walked up the parent chain but will never walk down the child chain again
    00187         //  because there is a NON WS_EX_CONTROLPARENT parent window somewhere in the chain.
    00188         RIPMSG0 (RIP_ERROR, "_NextSibblingOrAncestor: Non WS_EX_CONTROLPARENT window in parent chain");
    00189     }
    00190     return pwndNext;
    00191 #endif
    00192 }
    00193 /***************************************************************************\
    00194 *
    00195 *  _NextControl()
    00196 *
    00197 * It searches for the next NON WS_EX_CONTROLPARENT control following pwndStart.
    00198 * If pwndStart is NULL, the search begins with pwndRoot's first child;
    00199 * otherwise, it starts with the control next to pwndStart.
    00200 * This is a depth-first search that can start anywhere in the window tree.
    00201 * uFlags determine what WS_EX_CONTROLPARENT windows should be skipped or recursed into.
    00202 * If skipping a window, the search moves to the next control (see _NextSibblingOrAncestor);
    00203 * otherwise, the search walks down the child chain (recursive call).
    00204 * If the search fails, it returns pwndRoot.
    00205 *
    00206 \***************************************************************************/
    00207 PWND _NextControl(
    00208     PWND pwndRoot,
    00209     PWND pwndStart,
    00210     UINT uFlags)
    00211 {
    00212     BOOL fSkip, fAncestor;
    00213     PWND pwndLast, pwndSibblingLoop;
    00214     /* Bug 272874 - joejo
    00215      *
    00216      * Stop infinite loop by only looping a finite number of times and
    00217      * then bailing.
    00218      */
    00219     int nLoopCount = 0;
    00220
    00221     UserAssert (pwndRoot != NULL);
    00222
    00223     if (pwndStart == NULL) {
    00224         // Start with pwndRoot's first child
    00225         pwndStart = REBASEPWND(pwndRoot, spwndChild);
    00226         pwndLast = pwndStart;
    00227         fAncestor = FALSE;
    00228     } else {
    00229         UserAssert ((pwndRoot != pwndStart) && _IsDescendant(pwndRoot, pwndStart));
    00230
    00231         // Save starting handle and get next one
    00232         pwndLast = pwndStart;
    00233         pwndSibblingLoop = pwndStart;
    00234         fAncestor = TRUE;
    00235         goto TryNextOne;
    00236     }
    00237
    00238
    00239     // If no more controls, game over
    00240     if (pwndStart == NULL) {
    00241         return pwndRoot;
    00242     }
    00243
    00244     // Search for a non WS_EX_CONTROLPARENT window; if a window should be skipped,
    00245     // try its spwndNext; otherwise, walk down its child chain.
    00246     pwndSibblingLoop = pwndStart;
    00247     do {
    00248
    00249         //If not WS_EX_CONTROLPARENT parent, done.
    00250         if (!TestWF(pwndStart, WEFCONTROLPARENT)) {
    00251             return pwndStart;
    00252         }
    00253
    00254         // Do they want to skip this window?
    00255         fSkip = ((uFlags & CWP_SKIPINVISIBLE) && !TestWF(pwndStart, WFVISIBLE))
    00256                 || ((uFlags & CWP_SKIPDISABLED) && TestWF(pwndStart, WFDISABLED));
    00257
    00258
    00259         // Remember the current window
    00260         pwndLast = pwndStart;
    00261
    00262         // Walk down child chain?
    00263         if (!fSkip && !fAncestor) {
    00264             pwndStart = _NextControl (pwndStart, NULL, uFlags);
    00265             // If it found one, done.
    00266             if (pwndStart != pwndLast) {
    00267                 return pwndStart;
    00268             }
    00269         }
    00270
    00271 TryNextOne:
    00272         // Try the next one.
    00273         pwndStart = _NextSibblingOrAncestor (pwndRoot, pwndStart);
    00274         if (pwndStart == NULL) {
    00275             break;
    00276         }
    00277
    00278         // If parents are the same, we are still in the same sibbling chain
    00279         if (pwndLast->spwndParent == pwndStart->spwndParent) {
    00280             // If we had just moved up the parent chain last time around,
    00281             //  mark this as the beginning of the new sibbling chain.
    00282             // Otherwise, check if we've looped through all sibblings already.
    00283             if (fAncestor) {
    00284                 // Beggining of new sibbling chain.
    00285                 pwndSibblingLoop = pwndStart;
    00286             } else if (pwndStart == pwndSibblingLoop) {
    00287                 // Already visited all sibblings, so done.
    00288                 break;
    00289             }
    00290             fAncestor = FALSE;
    00291         } else {
    00292             // We must have moved up the parent chain, so don't
    00293             //  walk down the child chain right away (try the next window first)
    00294             // Eventhough we are on a new sibbling chain, we don't update
    00295             // pwndSibblingLoop yet; this is because we must walk down this
    00296             // child chain again to make sure we visit all the descendents
    00297             fAncestor = TRUE;
    00298         }
    00299
    00300     /* Bug 272874 - joejo
    00301      *
    00302      * Stop infinite loop by only looping a finite number of times and
    00303      * then bailing.
    00304      */
    00305     } while (nLoopCount++ < 256 * 4);
    00306
    00307     // It couldn't find one...
    00308     return pwndRoot;
    00309 }
    00310
    00311 /***************************************************************************\
    00312 * GetNextDlgTabItem
    00313 *
    00314 * History:
    00315 * 19-Feb-1991 JimA      Added access check
    00316 \***************************************************************************/
    00317
    00318 HWND WINAPI GetNextDlgTabItem(
    00319     HWND hwndDlg,
    00320     HWND hwnd,
    00321     BOOL fPrev)
    00322 {
    00323
    00324     PWND pwnd;
    00325     PWND pwndDlg;
    00326     PWND pwndNext;
    00327
    00328     pwndDlg = ValidateHwnd(hwndDlg);
    00329
    00330     if (pwndDlg == NULL)
    00331         return NULL;
    00332
    00333     if (hwnd != (HWND)0) {
    00334         pwnd = ValidateHwnd(hwnd);
    00335
    00336         if (pwnd == NULL)
    00337             return NULL;
    00338
    00339     } else {
    00340         pwnd = (PWND)NULL;
    00341     }
    00342
    00343     pwndNext = _GetNextDlgTabItem(pwndDlg, pwnd, fPrev);
    00344
    00345     return (HW(pwndNext));
    00346 }
    00347
    00348 PWND _GetNextDlgTabItem(
    00349     PWND pwndDlg,
    00350     PWND pwnd,
    00351     BOOL fPrev)
    00352 {
    00353     PWND pwndSave;
    00354
    00355     if (pwnd == pwndDlg)
    00356         pwnd = NULL;
    00357     else
    00358     {
    00359         pwnd = _GetChildControl(pwndDlg, pwnd);
    00360         if (pwnd && !_IsDescendant(pwndDlg, pwnd))
    00361             return(NULL);
    00362     }
    00363
    00364     //
    00365     // BACKWARD COMPATIBILITY
    00366     //
    00367     // Note that the result when there are no tabstops of
    00368     // IGetNextDlgTabItem(pwndDlg, NULL, FALSE) was the last item, now
    00369     // will be the first item.  We could put a check for fRecurse here
    00370     // and do the old thing if not set.
    00371     //
    00372
    00373     // We are going to bug out if we hit the first child a second time.
    00374
    00375     pwndSave = pwnd;
    00376
    00377     pwnd = (fPrev ? _PrevControl(pwndDlg, pwnd, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) :
    00378                     _NextControl(pwndDlg, pwnd, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED));
    00379
    00380     if (!pwnd)
    00381         goto AllOver;
    00382
    00383     while ((pwnd != pwndSave) && (pwnd != pwndDlg)) {
    00384         UserAssert(pwnd);
    00385
    00386         if (!pwndSave)
    00387             pwndSave = pwnd;
    00388
    00389         if ((pwnd->style & (WS_TABSTOP | WS_VISIBLE | WS_DISABLED))  == (WS_TABSTOP | WS_VISIBLE))
    00390             // Found it.
    00391             break;
    00392
    00393         pwnd = (fPrev ? _PrevControl(pwndDlg, pwnd, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) :
    00394                         _NextControl(pwndDlg, pwnd, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED));
    00395     }
    00396
    00397 AllOver:
    00398     return pwnd;
    00399 }
    00400
    00401 /***************************************************************************\
    00402 *
    00403 *  _GetNextDlgGroupItem()
    00404 *
    00405 \***************************************************************************/
    00406
    00407 HWND GetNextDlgGroupItem(
    00408     HWND hwndDlg,
    00409     HWND hwndCtl,
    00410     BOOL bPrevious)
    00411 {
    00412     PWND pwndDlg;
    00413     PWND pwndCtl;
    00414     PWND pwndNext;
    00415
    00416     pwndDlg = ValidateHwnd(hwndDlg);
    00417
    00418     if (pwndDlg == NULL)
    00419         return 0;
    00420
    00421
    00422     if (hwndCtl != (HWND)0) {
    00423         pwndCtl = ValidateHwnd(hwndCtl);
    00424
    00425         if (pwndCtl == NULL)
    00426             return 0;
    00427     } else {
    00428         pwndCtl = (PWND)NULL;
    00429     }
    00430
    00431     if (pwndCtl == pwndDlg)
    00432         pwndCtl = pwndDlg;
    00433
    00434     pwndNext = _GetNextDlgGroupItem(pwndDlg, pwndCtl, bPrevious);
    00435
    00436     return (HW(pwndNext));
    00437 }
    00438
    00439 PWND _GetNextDlgGroupItem(
    00440     PWND pwndDlg,
    00441     PWND pwnd,
    00442     BOOL fPrev)
    00443 {
    00444     PWND pwndCurrent;
    00445     BOOL fOnceAround = FALSE;
    00446
    00447     pwnd = pwndCurrent = _GetChildControl(pwndDlg, pwnd);
    00448
    00449     do {
    00450         pwnd = (fPrev ? UT_PrevGroupItem(pwndDlg, pwnd) :
    00451                         UT_NextGroupItem(pwndDlg, pwnd));
    00452
    00453         if (pwnd == pwndCurrent)
    00454             fOnceAround = TRUE;
    00455
    00456         if (!pwndCurrent)
    00457             pwndCurrent = pwnd;
    00458     }
    00459     while (!fOnceAround && ((TestWF(pwnd, WFDISABLED) || !TestWF(pwnd, WFVISIBLE))));
    00460
    00461     return pwnd;
    00462 }