PWND GetPrevPwnd( PWND pwndList, PWND pwndFind) { PWND pwndFound, pwndNext; if (pwndList == NULL) return NULL; if (pwndList->spwndParent == NULL) return NULL; pwndNext = REBASEPWND(pwndList, spwndParent); pwndNext = REBASEPWND(pwndNext, spwndChild); pwndFound = NULL; while (pwndNext != NULL) { if (pwndNext == pwndFind) break; pwndFound = pwndNext; pwndNext = REBASEPWND(pwndNext, spwndNext); } return (pwndNext == pwndFind) ? pwndFound : NULL; }
BOOL IsVisible( PWND pwnd) { PWND pwndT; for (pwndT = pwnd; pwndT; pwndT = REBASEPWND(pwndT, spwndParent)) { /* * Invisible windows are always invisible */ if (!TestWF(pwndT, WFVISIBLE)) return FALSE; if (TestWF(pwndT, WFMINIMIZED)) { /* * Children of minimized windows are always invisible. */ if (pwndT != pwnd) return FALSE; } /* * If we're at the desktop, then we don't want to go any further. */ if (GETFNID(pwndT) == FNID_DESKTOP) break; } return TRUE; }
DWORD GetContextHelpId( PWND pwnd) { DWORD dwContextId; while (!(dwContextId = (DWORD)_GetProp(pwnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), PROPF_INTERNAL))) { pwnd = (TestwndChild(pwnd) ? REBASEPWND(pwnd, spwndParent) : REBASEPWND(pwnd, spwndOwner)); if (!pwnd || (GETFNID(pwnd) == FNID_DESKTOP)) break; } return dwContextId; }
PWND _GetLastActivePopup( PWND pwnd) { if (pwnd->spwndLastActive == NULL) return pwnd; return REBASEPWND(pwnd, spwndLastActive); }
PWND GetTopLevelWindow( PWND pwnd) { if (pwnd != NULL) { while (TestwndChild(pwnd)) pwnd = REBASEPWND(pwnd, spwndParent); } return pwnd; }
BOOL _FChildVisible( PWND pwnd) { while (TestwndChild(pwnd)) { pwnd = REBASEPWND(pwnd, spwndParent); if (pwnd == NULL) break; if (!TestWF(pwnd, WFVISIBLE)) return FALSE; } return TRUE; }
PWND _GetChildControl(PWND pwndRoot, PWND pwndChild) { PWND pwndControl = NULL; while (pwndChild && TestwndChild(pwndChild) && (pwndChild != pwndRoot)) { pwndControl = pwndChild; pwndChild = REBASEPWND(pwndChild, spwndParent); if (TestWF(pwndChild, WEFCONTROLPARENT)) break; } return(pwndControl); }
BOOL _IsDescendant( PWND pwndParent, PWND pwndChild) { while (1) { if (pwndParent == pwndChild) return TRUE; if (GETFNID(pwndChild) == FNID_DESKTOP) break; pwndChild = REBASEPWND(pwndChild, spwndParent); } return FALSE; }
PWND _GetParent( PWND pwnd) { /* * For 1.03 compatibility reasons, we should return NULL * for top level "tiled" windows and owner for other popups. * pwndOwner is set to NULL in xxxCreateWindow for top level * "tiled" windows. */ if (!(TestwndTiled(pwnd))) { if (TestwndChild(pwnd)) pwnd = REBASEPWND(pwnd, spwndParent); else pwnd = REBASEPWND(pwnd, spwndOwner); return pwnd; } /* * The window was not a child window; they may have been just testing * if it was */ return NULL; }
BOOL _IsChild( PWND pwndParent, PWND pwnd) { /* * Don't need a test to get out of the loop because the * desktop is not a child. */ while (pwnd != NULL) { if (!TestwndChild(pwnd)) return FALSE; pwnd = REBASEPWND(pwnd, spwndParent); if (pwndParent == pwnd) return TRUE; } return FALSE; }
PWND SizeBoxHwnd( PWND pwnd) { int xbrChild = pwnd->rcWindow.right; int ybrChild = pwnd->rcWindow.bottom; while (GETFNID(pwnd) != FNID_DESKTOP) { if (TestWF(pwnd, WFSIZEBOX)) { // First sizeable parent found int xbrParent; int ybrParent; if (TestWF(pwnd, WFMAXIMIZED)) return(NULL); xbrParent = pwnd->rcClient.right; ybrParent = pwnd->rcClient.bottom; /* If the sizebox dude is within an EDGE of the client's bottom * right corner, let this succeed. That way people who draw * their own sunken clients will be happy. */ if ((xbrChild + SYSMET(CXEDGE) < xbrParent) || (ybrChild + SYSMET(CYEDGE) < ybrParent)) { // // Child's bottom, right corner of SIZEBOX isn't close enough // to bottom right of parent's client. // return(NULL); } return(pwnd); } if (!TestWF(pwnd, WFCHILD) || TestWF(pwnd, WFCPRESENT)) break; pwnd = REBASEPWND(pwnd, spwndParent); } return(NULL); }
BOOL _IsWindowVisible( PWND pwnd) { /* * Check if this is the iconic window being moved around with a mouse * If so, return a TRUE, though, strictly speaking, it is hidden. * This helps the Tracer guys from going crazy! * Fix for Bug #57 -- SANKAR -- 08-08-89 -- */ if (pwnd == NULL) return TRUE; for (;;) { if (!TestWF(pwnd, WFVISIBLE)) return FALSE; if (GETFNID(pwnd) == FNID_DESKTOP) break; pwnd = REBASEPWND(pwnd, spwndParent); } return TRUE; }
PWND _GetWindow( PWND pwnd, UINT cmd) { PWND pwndT; BOOL fRebase = FALSE; /* * If this is a desktop window, return NULL for sibling or * parent information. */ if (GETFNID(pwnd) == FNID_DESKTOP) { switch (cmd) { case GW_CHILD: break; default: return NULL; break; } } /* * Rebase the returned window at the end of the routine * to avoid multiple test for pwndT == NULL. */ pwndT = NULL; switch (cmd) { case GW_HWNDNEXT: pwndT = pwnd->spwndNext; fRebase = TRUE; break; case GW_HWNDFIRST: if (pwnd->spwndParent) { pwndT = REBASEPWND(pwnd, spwndParent); pwndT = REBASEPWND(pwndT, spwndChild); if (GetAppCompatFlags(NULL) & GACF_IGNORETOPMOST) { while (pwndT != NULL) { if (!TestWF(pwndT, WEFTOPMOST)) break; pwndT = REBASEPWND(pwndT, spwndNext); } } } break; case GW_HWNDLAST: pwndT = GetPrevPwnd(pwnd, NULL); break; case GW_HWNDPREV: pwndT = GetPrevPwnd(pwnd, pwnd); break; case GW_OWNER: pwndT = pwnd->spwndOwner; fRebase = TRUE; break; case GW_CHILD: pwndT = pwnd->spwndChild; fRebase = TRUE; break; #if !defined(_USERK_) case GW_ENABLEDPOPUP: pwndT = (PWND)NtUserCallHwnd(PtoHq(pwnd), SFI_DWP_GETENABLEDPOPUP); fRebase = TRUE; break; #endif default: RIPERR0(ERROR_INVALID_GW_COMMAND, RIP_VERBOSE, ""); return NULL; } if (pwndT != NULL && fRebase) pwndT = REBASEPTR(pwnd, pwndT); return pwndT; }
/***************************************************************************\ * * _NextControl() * * It searches for the next NON WS_EX_CONTROLPARENT control following pwndStart. * If pwndStart is NULL, the search begins with pwndRoot's first child; * otherwise, it starts with the control next to pwndStart. * This is a depth-first search that can start anywhere in the window tree. * uFlags determine what WS_EX_CONTROLPARENT windows should be skipped or recursed into. * If skipping a window, the search moves to the next control (see _NextSibblingOrAncestor); * otherwise, the search walks down the child chain (recursive call). * If the search fails, it returns pwndRoot. * \***************************************************************************/ PWND _NextControl( PWND pwndRoot, PWND pwndStart, UINT uFlags) { BOOL fSkip, fAncestor; PWND pwndLast, pwndSibblingLoop; UserAssert (pwndRoot != NULL); if (pwndStart == NULL) { // Start with pwndRoot's first child pwndStart = REBASEPWND(pwndRoot, spwndChild); pwndLast = pwndStart; fAncestor = FALSE; } else { UserAssert ((pwndRoot != pwndStart) && _IsDescendant(pwndRoot, pwndStart)); // Save starting handle and get next one pwndLast = pwndStart; pwndSibblingLoop = pwndStart; fAncestor = TRUE; goto TryNextOne; } // If no more controls, game over if (pwndStart == NULL) { return pwndRoot; } // Search for a non WS_EX_CONTROLPARENT window; if a window should be skipped, // try its spwndNext; otherwise, walk down its child chain. pwndSibblingLoop = pwndStart; do { //If not WS_EX_CONTROLPARENT parent, done. if (!TestWF(pwndStart, WEFCONTROLPARENT)) { return pwndStart; } // Do they want to skip this window? fSkip = ((uFlags & CWP_SKIPINVISIBLE) && !TestWF(pwndStart, WFVISIBLE)) || ((uFlags & CWP_SKIPDISABLED) && TestWF(pwndStart, WFDISABLED)); // Remember the current window pwndLast = pwndStart; // Walk down child chain? if (!fSkip && !fAncestor) { pwndStart = _NextControl (pwndStart, NULL, uFlags); // If it found one, done. if (pwndStart != pwndLast) { return pwndStart; } } TryNextOne: // Try the next one. pwndStart = _NextSibblingOrAncestor (pwndRoot, pwndStart); if (pwndStart == NULL) { break; } // If parents are the same, we are still in the same sibbling chain if (pwndLast->spwndParent == pwndStart->spwndParent) { // If we had just moved up the parent chain last time around, // mark this as the beginning of the new sibbling chain. // Otherwise, check if we've looped through all sibblings already. if (fAncestor) { // Beggining of new sibbling chain. pwndSibblingLoop = pwndStart; } else if (pwndStart == pwndSibblingLoop) { // Already visited all sibblings, so done. break; } fAncestor = FALSE; } else { // We must have moved up the parent chain, so don't // walk down the child chain right away (try the next window first) // Eventhough we are on a new sibbling chain, we don't update // pwndSibblingLoop yet; this is because we must walk down this // child chain again to make sure we visit all the descendents fAncestor = TRUE; } } while (TRUE); // It couldn't find one... return pwndRoot; }