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

winwhere.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: winwhere.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * History: 00007 * 08-Nov-1990 DavidPe Created. 00008 * 23-Jan-1991 IanJa Serialization: Handle revalidation added 00009 * 19-Feb-1991 JimA Added enum access checks 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 /***************************************************************************\ 00016 * LayerHitTest 00017 * 00018 * 9/21/1998 vadimg created 00019 \***************************************************************************/ 00020 00021 __inline BOOL LayerHitTest(PWND pwnd, POINT pt) 00022 { 00023 ASSERT(TestWF(pwnd, WEFLAYERED)); 00024 00025 if (TestWF(pwnd, WEFTRANSPARENT)) 00026 return FALSE; 00027 00028 if (!GrePtInSprite(gpDispInfo->hDev, PtoHq(pwnd), pt.x, pt.y)) 00029 return FALSE; 00030 00031 return TRUE; 00032 } 00033 00034 /***************************************************************************\ 00035 * ChildWindowFromPoint (API) 00036 * 00037 * Returns NULL if pt is not in parent's client area at all, 00038 * hwndParent if point is not over any children, and a child window if it is 00039 * over a child. Will return hidden and disabled windows if they are at the 00040 * given point. 00041 * 00042 * History: 00043 * 19-Nov-1990 DavidPe Created. 00044 * 19-Feb-1991 JimA Added enum access check 00045 \***************************************************************************/ 00046 00047 PWND _ChildWindowFromPointEx( 00048 PWND pwnd, 00049 POINT pt, 00050 UINT uFlags) 00051 { 00052 if (pwnd != PWNDDESKTOP(pwnd)) { 00053 #ifdef USE_MIRRORING 00054 if (TestWF(pwnd, WEFLAYOUTRTL)) { 00055 pt.x = pwnd->rcClient.right - pt.x; 00056 } else 00057 #endif 00058 { 00059 pt.x += pwnd->rcClient.left; 00060 } 00061 pt.y += pwnd->rcClient.top; 00062 } 00063 00064 // _ClientToScreen(pwndParent, (LPPOINT)&pt); 00065 00066 if (PtInRect(&pwnd->rcClient, pt)) { 00067 00068 PWND pwndChild; 00069 00070 if (pwnd->hrgnClip != NULL) { 00071 if (!GrePtInRegion(pwnd->hrgnClip, pt.x, pt.y)) 00072 return NULL; 00073 } 00074 00075 if (TestWF(pwnd, WEFLAYERED)) { 00076 if (!LayerHitTest(pwnd, pt)) 00077 return NULL; 00078 } 00079 00080 /* 00081 * Enumerate the children, skipping disabled and invisible ones 00082 * if so desired. Still doesn't work for WS_EX_TRANSPARENT windows. 00083 */ 00084 for (pwndChild = pwnd->spwndChild; 00085 pwndChild; 00086 pwndChild = pwndChild->spwndNext) { 00087 00088 /* 00089 * Skip windows as desired. 00090 */ 00091 if ((uFlags & CWP_SKIPINVISIBLE) && !TestWF(pwndChild, WFVISIBLE)) 00092 continue; 00093 00094 if ((uFlags & CWP_SKIPDISABLED) && TestWF(pwndChild, WFDISABLED)) 00095 continue; 00096 00097 if ((uFlags & CWP_SKIPTRANSPARENT) && TestWF(pwndChild, WEFTRANSPARENT)) 00098 continue; 00099 00100 if (PtInRect(&pwndChild->rcWindow, pt)) { 00101 00102 if (pwndChild->hrgnClip != NULL) { 00103 if (!GrePtInRegion(pwndChild->hrgnClip, pt.x, pt.y)) 00104 continue; 00105 } 00106 if (TestWF(pwndChild, WEFLAYERED)) { 00107 if (!LayerHitTest(pwndChild, pt)) 00108 continue; 00109 } 00110 return(pwndChild); 00111 } 00112 } 00113 00114 return pwnd; 00115 } 00116 00117 return NULL; 00118 } 00119 00120 /***************************************************************************\ 00121 * xxxWindowFromPoint (API) 00122 * 00123 * History: 00124 * 19-Nov-1990 DavidPe Created. 00125 * 19-Feb-1991 JimA Added enum access check 00126 \***************************************************************************/ 00127 00128 PWND xxxWindowFromPoint( 00129 POINT pt) 00130 { 00131 HWND hwnd; 00132 PWND pwndT; 00133 TL tlpwndT; 00134 00135 pwndT = _GetDesktopWindow(); 00136 ThreadLock(pwndT, &tlpwndT); 00137 00138 hwnd = xxxWindowHitTest2(pwndT, pt, NULL, WHT_IGNOREDISABLED); 00139 00140 ThreadUnlock(&tlpwndT); 00141 00142 return RevalidateHwnd(hwnd); 00143 } 00144 00145 #ifdef REDIRECTION 00146 00147 /***************************************************************************\ 00148 * xxxCallSpeedHitTestHook 00149 * 00150 * Call the speed hit test hook to give the opportunity to the hook to fake 00151 * where the mouse pointer is. 00152 * 00153 * 25-Jan-1999 CLupu Created. 00154 \***************************************************************************/ 00155 00156 PWND xxxCallSpeedHitTestHook(POINT* ppt) 00157 { 00158 PHOOK pHook; 00159 PWND pwnd = NULL; 00160 00161 /* 00162 * Call the hit test hooks to give them the opportunity to change 00163 * the coordinates and the hwnd 00164 */ 00165 if ((pHook = PhkFirstValid(PtiCurrent(), WH_HITTEST)) != NULL) { 00166 HTHOOKSTRUCT ht; 00167 BOOL bAnsiHook; 00168 00169 ht.pt = *ppt; 00170 ht.hwndHit = NULL; 00171 00172 xxxCallHook2(pHook, HC_ACTION, 0, (LPARAM)&ht, &bAnsiHook); 00173 00174 if (ht.hwndHit != NULL) { 00175 00176 pwnd = HMValidateHandle(ht.hwndHit, TYPE_WINDOW); 00177 00178 if (pwnd != NULL) { 00179 ppt->x = ht.pt.x; 00180 ppt->y = ht.pt.y; 00181 } 00182 } 00183 } 00184 return pwnd; 00185 } 00186 00187 #endif // REDIRECTION 00188 00189 /***************************************************************************\ 00190 * SpeedHitTest 00191 * 00192 * This routine quickly finds out what top level window this mouse point 00193 * belongs to. Used purely for ownership purposes. 00194 * 00195 * 12-Nov-1992 ScottLu Created. 00196 \***************************************************************************/ 00197 00198 PWND SpeedHitTest( 00199 PWND pwndParent, 00200 POINT pt) 00201 { 00202 PWND pwndT; 00203 PWND pwnd; 00204 00205 if (pwndParent == NULL) 00206 return NULL; 00207 00208 for (pwnd = pwndParent->spwndChild; pwnd != NULL; pwnd = pwnd->spwndNext) { 00209 00210 /* 00211 * Are we looking at an hidden window? 00212 */ 00213 if (!TestWF(pwnd, WFVISIBLE)) 00214 continue; 00215 00216 /* 00217 * Are we barking up the wrong tree? 00218 */ 00219 if (!PtInRect((LPRECT)&pwnd->rcWindow, pt)) { 00220 continue; 00221 } 00222 00223 /* 00224 * Check to see if in window region (if it has one) 00225 */ 00226 if (pwnd->hrgnClip != NULL) { 00227 if (!GrePtInRegion(pwnd->hrgnClip, pt.x, pt.y)) 00228 continue; 00229 } 00230 00231 /* 00232 * Is this a sprite? 00233 */ 00234 if (TestWF(pwnd, WEFLAYERED)) { 00235 if (!LayerHitTest(pwnd, pt)) 00236 continue; 00237 } 00238 00239 #ifdef REDIRECTION 00240 if (TestWF(pwnd, WEFREDIRECTED)) { 00241 continue; 00242 } 00243 #endif // REDIRECTION 00244 00245 /* 00246 * Children? 00247 */ 00248 if ((pwnd->spwndChild != NULL) && 00249 PtInRect((LPRECT)&pwnd->rcClient, pt)) { 00250 00251 pwndT = SpeedHitTest(pwnd, pt); 00252 if (pwndT != NULL) 00253 return pwndT; 00254 } 00255 00256 return pwnd; 00257 } 00258 00259 return pwndParent; 00260 } 00261 00262 /***************************************************************************\ 00263 * xxxWindowHitTest 00264 * 00265 * History: 00266 * 08-Nov-1990 DavidPe Ported. 00267 * 28-Nov-1990 DavidPe Add pwndTransparent support for HTTRANSPARENT. 00268 * 25-Jan-1991 IanJa change PWNDPOS parameter to int * 00269 * 19-Feb-1991 JimA Added enum access check 00270 * 02-Nov-1992 ScottLu Removed pwndTransparent. 00271 * 12-Nov-1992 ScottLu Took out fSendHitTest, fixed locking bug 00272 \***************************************************************************/ 00273 00274 HWND xxxWindowHitTest( 00275 PWND pwnd, 00276 POINT pt, 00277 int *piPos, 00278 DWORD dwHitTestFlags) 00279 { 00280 HWND hwndT; 00281 TL tlpwnd; 00282 00283 CheckLock(pwnd); 00284 00285 hwndT = NULL; 00286 ThreadLockNever(&tlpwnd); 00287 while (pwnd != NULL) { 00288 ThreadLockExchangeAlways(pwnd, &tlpwnd); 00289 hwndT = xxxWindowHitTest2(pwnd, pt, piPos, dwHitTestFlags); 00290 if (hwndT != NULL) 00291 break; 00292 00293 pwnd = pwnd->spwndNext; 00294 } 00295 00296 ThreadUnlock(&tlpwnd); 00297 return hwndT; 00298 } 00299 00300 /***************************************************************************\ 00301 * xxxWindowHitTest2 00302 * 00303 * When this routine is entered, all windows must be locked. When this 00304 * routine returns a window handle, it locks that window handle and unlocks 00305 * all windows. If this routine returns NULL, all windows are still locked. 00306 * Ignores disabled and hidden windows. 00307 * 00308 * History: 00309 * 08-Nov-1990 DavidPe Ported. 00310 * 25-Jan-1991 IanJa change PWNDPOS parameter to int * 00311 * 19-Feb-1991 JimA Added enum access check 00312 * 12-Nov-1992 ScottLu Took out fSendHitTest 00313 \***************************************************************************/ 00314 00315 HWND xxxWindowHitTest2( 00316 PWND pwnd, 00317 POINT pt, 00318 int *piPos, 00319 DWORD dwHitTestFlags) 00320 { 00321 int ht = HTERROR, htGrip=HTBOTTOMRIGHT; 00322 HWND hwndT; 00323 TL tlpwndChild; 00324 00325 CheckLock(pwnd); 00326 00327 /* 00328 * Are we at the bottom of the window chain? 00329 */ 00330 if (pwnd == NULL) 00331 return NULL; 00332 00333 /* 00334 * Are we looking at an hidden window? 00335 */ 00336 if (!TestWF(pwnd, WFVISIBLE)) 00337 return NULL; 00338 00339 /* 00340 * Are we barking up the wrong tree? 00341 */ 00342 if (!PtInRect((LPRECT)&pwnd->rcWindow, pt)) { 00343 return NULL; 00344 } 00345 00346 if (pwnd->hrgnClip != NULL) { 00347 if (!GrePtInRegion(pwnd->hrgnClip, pt.x, pt.y)) 00348 return(NULL); 00349 } 00350 00351 if (TestWF(pwnd, WEFLAYERED)) { 00352 if (!LayerHitTest(pwnd, pt)) 00353 return NULL; 00354 } 00355 00356 #ifdef REDIRECTION 00357 /* 00358 * If this is called when the layered window is actually trying 00359 * to process the message then let it see the hit test 00360 */ 00361 if (TestWF(pwnd, WEFREDIRECTED) && PpiCurrent() != GETPTI(pwnd)->ppi) { 00362 return NULL; 00363 } 00364 #endif // REDIRECTION 00365 00366 /* 00367 * Are we looking at an disabled window? 00368 */ 00369 if (TestWF(pwnd, WFDISABLED) && (dwHitTestFlags & WHT_IGNOREDISABLED)) { 00370 if (TestwndChild(pwnd)) { 00371 return NULL; 00372 } else { 00373 ht = HTERROR; 00374 goto Exit; 00375 } 00376 } 00377 00378 #ifdef SYSMODALWINDOWS 00379 /* 00380 * If SysModal window present and we're not in it, return an error. 00381 * Be sure to assign the point to the SysModal window, so the message 00382 * will be sure to be removed from the queue. 00383 */ 00384 if (!CheckPwndFilter(pwnd, gspwndSysModal)) { 00385 pwnd = gspwndSysModal; 00386 00387 /* 00388 * Fix notorious stack overflow bug (some WINABLE fix from Memphis) 00389 */ 00390 ht = HTCLIENT; 00391 goto Exit; 00392 } 00393 #endif 00394 00395 /* 00396 * Are we on a minimized window? 00397 */ 00398 if (!TestWF(pwnd, WFMINIMIZED)) { 00399 /* 00400 * Are we in the window's client area? 00401 */ 00402 if (PtInRect((LPRECT)&pwnd->rcClient, pt)) { 00403 /* 00404 * Recurse through the children. 00405 */ 00406 ThreadLock(pwnd->spwndChild, &tlpwndChild); 00407 hwndT = xxxWindowHitTest(pwnd->spwndChild, 00408 pt, 00409 piPos, 00410 dwHitTestFlags); 00411 00412 ThreadUnlock(&tlpwndChild); 00413 if (hwndT != NULL) 00414 return hwndT; 00415 } 00416 00417 } 00418 00419 /* 00420 * If window not in same task, don't send WM_NCHITTEST. 00421 */ 00422 if (GETPTI(pwnd) != PtiCurrent()) { 00423 ht = HTCLIENT; 00424 goto Exit; 00425 } 00426 00427 /* 00428 * Send the message. 00429 */ 00430 ht = (int)xxxSendMessage(pwnd, WM_NCHITTEST, 0, MAKELONG(pt.x, pt.y)); 00431 00432 /* 00433 * If window is transparent keep enumerating. 00434 */ 00435 if (ht == HTTRANSPARENT) { 00436 return NULL; 00437 } 00438 00439 Exit: 00440 00441 /* 00442 * Set wndpos accordingly. 00443 */ 00444 if (piPos) { 00445 *piPos = ht; 00446 } 00447 00448 /* 00449 * If this is a RTL mirrored window, then the grip is at 00450 * HTBOTTOMLEFT (in terms of screen coordinates since they are 00451 * not RTL mirrored). 00452 */ 00453 if (TestWF(pwnd, WEFLAYOUTRTL)) { 00454 htGrip = HTBOTTOMLEFT; 00455 } 00456 00457 /* 00458 * if the click is in the sizebox of the window and this window itself is 00459 * not sizable, return the window that will be sized by this sizebox 00460 */ 00461 if ((ht == htGrip) && !TestWF(pwnd, WFSIZEBOX)) { 00462 00463 PWND pwndT; 00464 /* 00465 * SizeBoxHwnd() can return NULL! We don't want to act like this 00466 * is transparent if the sizebox isn't a grip 00467 */ 00468 pwnd = (pwndT = SizeBoxHwnd(pwnd)) ? pwndT : pwnd; 00469 } 00470 00471 return HWq(pwnd); 00472 }

Generated on Sat May 15 19:42:26 2004 for test by doxygen 1.3.7