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

mnpopup.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define RECT_ONLEFT   0
#define RECT_ONTOP   1
#define RECT_ONRIGHT   2
#define RECT_ONBOTTOM   3
#define RECT_ORG   4

Functions

BOOL TryRect (UINT wRect, int x, int y, int cx, int cy, LPRECT prcExclude, LPPOINT ppt, PMONITOR pMonitor)
int xxxTrackPopupMenuEx (PMENU pMenu, UINT dwFlags, int x, int y, PWND pwndOwner, CONST TPMPARAMS *lpTpm)
LONG FindBestPos (int x, int y, int cx, int cy, LPRECT prcExclude, UINT wFlags, PPOPUPMENU ppopupmenu, PMONITOR pMonitor)


Define Documentation

#define RECT_ONBOTTOM   3
 

Definition at line 19 of file mnpopup.c.

Referenced by FindBestPos(), and TryRect().

#define RECT_ONLEFT   0
 

Definition at line 16 of file mnpopup.c.

Referenced by FindBestPos(), and TryRect().

#define RECT_ONRIGHT   2
 

Definition at line 18 of file mnpopup.c.

Referenced by FindBestPos(), and TryRect().

#define RECT_ONTOP   1
 

Definition at line 17 of file mnpopup.c.

Referenced by FindBestPos(), and TryRect().

#define RECT_ORG   4
 

Definition at line 20 of file mnpopup.c.

Referenced by FindBestPos().


Function Documentation

LONG FindBestPos int  x,
int  y,
int  cx,
int  cy,
LPRECT  prcExclude,
UINT  wFlags,
PPOPUPMENU  ppopupmenu,
PMONITOR  pMonitor
 

Definition at line 496 of file mnpopup.c.

References COPY_FLAG, CopyRect, cy, tagPOPUPMENU::iDropDir, IntersectRect(), NULL, PAS_DOWN, PAS_HORZ, PAS_LEFT, PAS_RIGHT, PAS_UP, PAS_VERT, tagMONITOR::rcMonitor, RECT_ONBOTTOM, RECT_ONLEFT, RECT_ONRIGHT, RECT_ONTOP, RECT_ORG, SetRect(), TryRect(), and UINT.

Referenced by xxxMenuWindowProc(), and xxxTrackPopupMenuEx().

00505 { 00506 int iRect; 00507 int iT; 00508 UINT awRect[4]; 00509 POINT ptT; 00510 RECT rcExclude; 00511 // 00512 // Clip our coords on screen first. We use the same algorithm to clip 00513 // as in Win3.1 for dudes with no exclude rect. 00514 // 00515 00516 if (prcExclude!=NULL) { 00517 // Clip exclude rect to monitor! 00518 CopyRect(&rcExclude, prcExclude); 00519 IntersectRect(&rcExclude, &rcExclude, &pMonitor->rcMonitor); 00520 } else { 00521 SetRect(&rcExclude, x, y, x, y); 00522 } 00523 00524 00525 /* 00526 * Make sure popup fits completely on the screen 00527 * At least the x,y point will be on the screen. 00528 */ 00529 if (x + cx > pMonitor->rcMonitor.right) { 00530 if ((wFlags & TPM_CENTERALIGN) 00531 || (x - cx < pMonitor->rcMonitor.left) 00532 || (x >= pMonitor->rcMonitor.right)) { 00533 x = pMonitor->rcMonitor.right - cx; 00534 } else { 00535 x -= cx; 00536 } 00537 if (ppopupmenu->iDropDir & PAS_HORZ) { 00538 COPY_FLAG(ppopupmenu->iDropDir, PAS_LEFT, PAS_HORZ); 00539 } 00540 } 00541 00542 if (x < pMonitor->rcMonitor.left) { 00543 x += cx; 00544 if ((wFlags & TPM_CENTERALIGN) 00545 || (x >= pMonitor->rcMonitor.right) 00546 || (x < pMonitor->rcMonitor.left)) { 00547 x = pMonitor->rcMonitor.left; 00548 } 00549 if (ppopupmenu->iDropDir & PAS_HORZ) { 00550 COPY_FLAG(ppopupmenu->iDropDir, PAS_RIGHT, PAS_HORZ); 00551 } 00552 } 00553 00554 00555 if (y + cy > pMonitor->rcMonitor.bottom) { 00556 if ((wFlags & TPM_VCENTERALIGN) 00557 || (y - cy < pMonitor->rcMonitor.top) 00558 || (y >= pMonitor->rcMonitor.bottom)) { 00559 y = pMonitor->rcMonitor.bottom - cy; 00560 } else { 00561 y -= cy; 00562 } 00563 if (ppopupmenu->iDropDir & PAS_VERT) { 00564 COPY_FLAG(ppopupmenu->iDropDir, PAS_UP, PAS_VERT); 00565 } 00566 } 00567 00568 if (y < pMonitor->rcMonitor.top) { 00569 y += cy; 00570 if ((wFlags & TPM_VCENTERALIGN) 00571 || (y >= pMonitor->rcMonitor.bottom) 00572 || (y < pMonitor->rcMonitor.top)) { 00573 y = pMonitor->rcMonitor.top; 00574 } 00575 if (ppopupmenu->iDropDir & PAS_VERT) { 00576 COPY_FLAG(ppopupmenu->iDropDir, PAS_DOWN, PAS_VERT); 00577 } 00578 } 00579 00580 // 00581 // Try first point 00582 // 00583 if (TryRect(RECT_ORG, x, y, cx, cy, &rcExclude, &ptT, pMonitor)) 00584 goto FOUND; 00585 00586 // 00587 // Sort possibilities. Get offset of horizontal rects. 00588 // 00589 iRect = (wFlags & TPM_VERTICAL) ? 2 : 0; 00590 00591 // 00592 // Sort horizontally. Note that we treat TPM_CENTERALIGN like 00593 // TPM_LEFTALIGN. 00594 // 00595 // 00596 // If we're right-aligned, try to right-align on left side first. 00597 // Otherwise, try to left-align on right side first. 00598 // 00599 iT = (wFlags & TPM_RIGHTALIGN) ? 0 : 2; 00600 00601 awRect[0 + iRect] = RECT_ONLEFT + iT; 00602 awRect[1 + iRect] = RECT_ONRIGHT - iT; 00603 00604 // 00605 // Sort vertically. Note that we treat TPM_VCENTERALIGN like 00606 // TPM_TOPALIGN. 00607 // 00608 // If we're bottom-aligned, try to bottom-align with top of rect 00609 // first. Otherwise, try to top-align with bottom of exclusion first. 00610 // 00611 iT = (wFlags & TPM_BOTTOMALIGN) ? 0 : 2; 00612 00613 awRect[2 - iRect] = RECT_ONTOP + iT; 00614 awRect[3 - iRect] = RECT_ONBOTTOM - iT; 00615 00616 // 00617 // Loop through sorted alternatives. Note that TryRect fails immediately 00618 // if an exclusion coordinate is too close to screen edge. 00619 // 00620 00621 for (iRect = 0; iRect < 4; iRect++) { 00622 if (TryRect(awRect[iRect], x, y, cx, cy, &rcExclude, &ptT, pMonitor)) { 00623 switch (awRect[iRect]) 00624 { 00625 case RECT_ONTOP: 00626 ppopupmenu->iDropDir = PAS_UP; 00627 break; 00628 case RECT_ONLEFT: 00629 ppopupmenu->iDropDir = PAS_LEFT; 00630 break; 00631 case RECT_ONBOTTOM: 00632 ppopupmenu->iDropDir = PAS_DOWN; 00633 break; 00634 case RECT_ONRIGHT: 00635 ppopupmenu->iDropDir = PAS_RIGHT; 00636 break; 00637 } 00638 00639 x = ptT.x; 00640 y = ptT.y; 00641 break; 00642 } 00643 } 00644 00645 FOUND: 00646 return MAKELONG(x, y); 00647 }

BOOL TryRect UINT  wRect,
int  x,
int  y,
int  cx,
int  cy,
LPRECT  prcExclude,
LPPOINT  ppt,
PMONITOR  pMonitor
 

Definition at line 661 of file mnpopup.c.

References cy, FALSE, IntersectRect(), tagMONITOR::rcMonitor, RECT_ONBOTTOM, RECT_ONLEFT, RECT_ONRIGHT, and RECT_ONTOP.

Referenced by FindBestPos().

00670 { 00671 RECT rcTry; 00672 00673 switch (wRect) { 00674 case RECT_ONRIGHT: 00675 x = prcExclude->right; 00676 if (x + cx > pMonitor->rcMonitor.right) 00677 return FALSE; 00678 break; 00679 00680 case RECT_ONBOTTOM: 00681 y = prcExclude->bottom; 00682 if (y + cy > pMonitor->rcMonitor.bottom) 00683 return FALSE; 00684 break; 00685 00686 case RECT_ONLEFT: 00687 x = prcExclude->left - cx; 00688 if (x < pMonitor->rcMonitor.left) 00689 return FALSE; 00690 break; 00691 00692 case RECT_ONTOP: 00693 y = prcExclude->top - cy; 00694 if (y < pMonitor->rcMonitor.top) 00695 return FALSE; 00696 break; 00697 00698 // 00699 // case RECT_ORG: 00700 // NOP; 00701 // break; 00702 // 00703 } 00704 00705 ppt->x = x; 00706 ppt->y = y; 00707 00708 rcTry.left = x; 00709 rcTry.top = y; 00710 rcTry.right = x + cx; 00711 rcTry.bottom = y + cy; 00712 00713 return(!IntersectRect(&rcTry, &rcTry, prcExclude)); 00714 }

int xxxTrackPopupMenuEx PMENU  pMenu,
UINT  dwFlags,
int  x,
int  y,
PWND  pwndOwner,
CONST TPMPARAMS *  lpTpm
 

Definition at line 52 of file mnpopup.c.

References _GetKeyState(), _KillTimer(), _MonitorFromPoint(), BOOL, CheckLock, ClrWF, dwFlags, tagLASTINPUT::dwFlags, ExitMenuLoop(), FALSE, tagMENUSTATE::fButtonDown, tagPOPUPMENU::fDelayedFree, tagMENUSTATE::fDragAndDrop, tagPOPUPMENU::fDroppedLeft, tagPOPUPMENU::fFirstClick, FindBestPos(), tagPOPUPMENU::fIsSysMenu, tagPOPUPMENU::fIsTrackPopup, tagMENUSTATE::fModelessMenu, tagPOPUPMENU::fNoNotify, tagPOPUPMENU::fRightButton, tagPOPUPMENU::fSendUninit, tagPOPUPMENU::fShowTimer, tagPOPUPMENU::fSynchronous, tagMENUSTATE::fUnderline, FWINABLE, GET_X_LPARAM, GET_Y_LPARAM, GETPTI, glinp, HW, tagPOPUPMENU::iDropDir, IDSYS_MNSHOW, L, LINP_KEYBOARD, Lock, LockPopupMenu(), MENUCLASS, MFRTL, MFUNDERLINE, MNAnimate(), MNSW_SIZE, MOUSEHOLD, NULL, PAS_DOWN, PAS_HORZ, PAS_LEFT, PAS_OUT, PAS_RIGHT, PAS_UP, PAS_VERT, tagMENUSTATE::pGlobalPopupMenu, PlayEventSound(), tagTHREADINFO::pMenuState, tagPOPUPMENU::ppopupmenuRoot, tagTHREADINFO::pq, PtiCurrent, tagMENUSTATE::ptiMenuStateOwner, PtoHq, PWND_TOP, PWND_TOPMOST, QF_CAPTURELOCKED, tagQ::QF_flags, SetMF, SetWF, tagPOPUPMENU::spmenu, tagPOPUPMENU::spwndActivePopup, tagPOPUPMENU::spwndNotify, tagPOPUPMENU::spwndPopupMenu, SYSMET, TestMF, TestWF, ThreadLock, ThreadLockAlways, ThreadUnlock, TRUE, USER_SOUND_MENUPOPUP, WFDESTROYED, WFOLDUI, xxxClientRegisterDragDrop(), xxxCreateWindowEx(), xxxDestroyWindow(), xxxMNAllocMenuState(), xxxMNEndMenuState(), xxxMNLoop(), xxxMNReleaseCapture(), xxxMNStartMenu(), xxxSendMessage(), xxxSetWindowPos(), and xxxWindowEvent().

Referenced by NtUserTrackPopupMenuEx(), xxxDefWindowProc(), and xxxDoScrollMenu().

00059 { 00060 PMENUSTATE pMenuState; 00061 PWND pwndHierarchy; 00062 PPOPUPMENU ppopupMenuHierarchy; 00063 LONG sizeHierarchy; 00064 int cxPopup, 00065 cyPopup; 00066 BOOL fSync; 00067 int cmd; 00068 BOOL fButtonDown; 00069 TL tlpwndHierarchy; 00070 TL tlpwndT; 00071 RECT rcExclude; 00072 PTHREADINFO ptiCurrent, 00073 ptiOwner; 00074 PMONITOR pMonitor; 00075 POINT pt; 00076 00077 CheckLock(pMenu); 00078 CheckLock(pwndOwner); 00079 00080 /* 00081 * Capture the things we care about in case lpTpm goes away. 00082 */ 00083 if (lpTpm != NULL) { 00084 if (lpTpm->cbSize != sizeof(TPMPARAMS)) { 00085 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "TrackPopupMenuEx: cbSize is invalid"); 00086 return(FALSE); 00087 } 00088 rcExclude = lpTpm->rcExclude; 00089 } 00090 00091 ptiCurrent = PtiCurrent(); 00092 ptiOwner = GETPTI(pwndOwner); 00093 00094 /* 00095 * Win95 compatibility: pwndOwner must be owned by ptiCurrent. 00096 */ 00097 if (ptiCurrent != ptiOwner) { 00098 RIPMSG0(RIP_WARNING, "xxxTrackPopupMenuEx: pwndOwner not owned by ptiCurrent"); 00099 return FALSE; 00100 } 00101 00102 UserAssert(pMenu != NULL); 00103 if (ptiCurrent->pMenuState != NULL) { 00104 00105 if (dwFlags & TPM_RECURSE) { 00106 /* 00107 * Only allow recursion if: 00108 * -The current menu mode is not about to exit 00109 * -Both menus notify the same window 00110 * -Only one thread is involved in the current menu mode 00111 * This will prevent us from getting into some random 00112 * scenarios we don't want to deal with 00113 */ 00114 ppopupMenuHierarchy = ptiCurrent->pMenuState->pGlobalPopupMenu; 00115 pwndHierarchy = ppopupMenuHierarchy->spwndNotify; 00116 if (ExitMenuLoop(ptiCurrent->pMenuState, ppopupMenuHierarchy) 00117 || (pwndHierarchy == NULL) 00118 || (pwndHierarchy != pwndOwner) 00119 || (ptiCurrent->pMenuState->ptiMenuStateOwner != GETPTI(pwndHierarchy))) { 00120 00121 RIPMSG0(RIP_WARNING, "xxxTrackPopupMenuEx: Failing TPM_RECURSE request"); 00122 return FALSE; 00123 } 00124 /* 00125 * Terminate any animation 00126 */ 00127 MNAnimate(ptiCurrent->pMenuState, FALSE); 00128 /* 00129 * Cancel pending show timer if any. ie, the app wants to 00130 * pop up a context menu on a popup before we drop it. 00131 */ 00132 ppopupMenuHierarchy = ((ppopupMenuHierarchy->spwndActivePopup != NULL) 00133 ? ((PMENUWND)(ppopupMenuHierarchy->spwndActivePopup))->ppopupmenu 00134 : NULL); 00135 if ((ppopupMenuHierarchy != NULL) && ppopupMenuHierarchy->fShowTimer) { 00136 00137 _KillTimer(ppopupMenuHierarchy->spwndPopupMenu, IDSYS_MNSHOW); 00138 ppopupMenuHierarchy->fShowTimer = FALSE; 00139 } 00140 /* 00141 * If we're currently on a modal menu, let's unlock the capture 00142 * so the recursive menu can get it. 00143 */ 00144 if (!ptiCurrent->pMenuState->fModelessMenu) { 00145 ptiCurrent->pq->QF_flags &= ~QF_CAPTURELOCKED; 00146 } 00147 } else { 00148 /* 00149 * Allow only one guy to have a popup menu up at a time... 00150 */ 00151 RIPERR0(ERROR_POPUP_ALREADY_ACTIVE, RIP_VERBOSE, ""); 00152 return FALSE; 00153 } 00154 } 00155 00156 // Is button down? 00157 00158 if (dwFlags & TPM_RIGHTBUTTON) 00159 { 00160 fButtonDown = (_GetKeyState(VK_RBUTTON) & 0x8000) != 0; 00161 } else { 00162 fButtonDown = (_GetKeyState(VK_LBUTTON) & 0x8000) != 0; 00163 } 00164 00165 /* 00166 * Create the menu window. 00167 */ 00168 pwndHierarchy = xxxCreateWindowEx( 00169 WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, 00170 (PLARGE_STRING)MENUCLASS, 00171 NULL, 00172 WS_POPUP | WS_BORDER, 00173 x, y, 100, 100, 00174 TestMF(pMenu, MNS_MODELESS) ? pwndOwner : NULL, 00175 NULL, (HANDLE)pwndOwner->hModule, 00176 NULL, 00177 WINVER); 00178 00179 if (pwndHierarchy == NULL) { 00180 return FALSE; 00181 } 00182 00183 #ifdef USE_MIRRORING 00184 if (TestWF(pwndOwner, WEFLAYOUTRTL)) 00185 SetWF(pwndHierarchy, WEFLAYOUTRTL); 00186 #endif 00187 00188 // 00189 // Do this so that old apps don't get weird borders on tracked popups due 00190 // to the app hack used in CreateWindowEx32. 00191 // 00192 ClrWF(pwndHierarchy, WFOLDUI); 00193 00194 ThreadLockAlways(pwndHierarchy, &tlpwndHierarchy); 00195 00196 #ifdef HAVE_MN_GETPPOPUPMENU 00197 ppopupMenuHierarchy = (PPOPUPMENU)xxxSendMessage(pwndHierarchy, 00198 MN_GETPPOPUPMENU, 0, 0); 00199 #else 00200 ppopupMenuHierarchy = ((PMENUWND)pwndHierarchy)->ppopupmenu; 00201 #endif 00202 00203 00204 ppopupMenuHierarchy->fDelayedFree = TRUE; 00205 Lock(&(ppopupMenuHierarchy->spwndNotify), pwndOwner); 00206 LockPopupMenu(ppopupMenuHierarchy, &ppopupMenuHierarchy->spmenu, pMenu); 00207 Lock(&(ppopupMenuHierarchy->spwndActivePopup), pwndHierarchy); 00208 ppopupMenuHierarchy->ppopupmenuRoot = ppopupMenuHierarchy; 00209 ppopupMenuHierarchy->fIsTrackPopup = TRUE; 00210 ppopupMenuHierarchy->fFirstClick = fButtonDown; 00211 ppopupMenuHierarchy->fRightButton = ((dwFlags & TPM_RIGHTBUTTON) != 0); 00212 if (SYSMET(MENUDROPALIGNMENT) || TestMF(pMenu, MFRTL)) { 00213 // 00214 // popup's below this one need to follow the same direction as 00215 // the other menu's on the desktop. 00216 // 00217 ppopupMenuHierarchy->fDroppedLeft = TRUE; 00218 } 00219 ppopupMenuHierarchy->fNoNotify = ((dwFlags & TPM_NONOTIFY) != 0); 00220 00221 if (fSync = (dwFlags & TPM_RETURNCMD)) 00222 ppopupMenuHierarchy->fSynchronous = TRUE; 00223 00224 ppopupMenuHierarchy->fIsSysMenu = ((dwFlags & TPM_SYSMENU) != 0); 00225 00226 // Set the GlobalPopupMenu variable so that EndMenu works for popupmenus so 00227 // that WinWart II people can continue to abuse undocumented functions. 00228 // This is nulled out in MNCancel. 00229 /* 00230 * This is actually needed for cleanup in case this thread ends 00231 * execution before we can free the popup. (See xxxDestroyThreadInfo) 00232 * 00233 * Note that one thread might own pwndOwner and another one might call 00234 * TrackPopupMenu (pretty normal if the two threads are attached). So 00235 * properly setting (and initializing) pMenuState is a must here. 00236 */ 00237 pMenuState = xxxMNAllocMenuState(ptiCurrent, ptiOwner, ppopupMenuHierarchy); 00238 if (pMenuState == NULL) { 00239 /* 00240 * Get out. The app never knew we were here so don't notify it 00241 */ 00242 dwFlags |= TPM_NONOTIFY; 00243 goto AbortTrackPopupMenuEx; 00244 } 00245 00246 /* 00247 * Notify the app we are entering menu mode. wParam is 1 since this is a 00248 * TrackPopupMenu. 00249 */ 00250 00251 if (!ppopupMenuHierarchy->fNoNotify) 00252 xxxSendMessage(pwndOwner, WM_ENTERMENULOOP, 00253 (ppopupMenuHierarchy->fIsSysMenu ? FALSE : TRUE), 0); 00254 00255 /* 00256 * Send off the WM_INITMENU, set ourselves up for menu mode etc... 00257 */ 00258 if (!xxxMNStartMenu(ppopupMenuHierarchy, MOUSEHOLD)) { 00259 /* 00260 * ppopupMenuHierarchy has been destroyed already; let's bail 00261 */ 00262 goto AbortTrackPopupMenuEx; 00263 } 00264 00265 /* 00266 * If drag and drop, register the window as a target. 00267 */ 00268 if (pMenuState->fDragAndDrop) { 00269 if (!SUCCEEDED(xxxClientRegisterDragDrop(HW(pwndHierarchy)))) { 00270 RIPMSG0(RIP_ERROR, "xxxTrackPopupMenuEx: xxxClientRegisterDragDrop failed"); 00271 } 00272 } 00273 00274 if (!ppopupMenuHierarchy->fNoNotify) { 00275 ThreadLock(ppopupMenuHierarchy->spwndNotify, &tlpwndT); 00276 xxxSendMessage(ppopupMenuHierarchy->spwndNotify, WM_INITMENUPOPUP, 00277 (WPARAM)PtoHq(pMenu), MAKELONG(0, (ppopupMenuHierarchy->fIsSysMenu ? 1: 0))); 00278 ThreadUnlock(&tlpwndT); 00279 ppopupMenuHierarchy->fSendUninit = TRUE; 00280 } 00281 00282 /* 00283 * Size the menu window if needed... 00284 */ 00285 sizeHierarchy = (LONG)xxxSendMessage(pwndHierarchy, MN_SIZEWINDOW, MNSW_SIZE, 0); 00286 00287 if (!sizeHierarchy) { 00288 00289 AbortTrackPopupMenuEx: 00290 if (FWINABLE()) { 00291 xxxWindowEvent(EVENT_SYSTEM_MENUEND, pwndOwner, OBJID_WINDOW, INDEXID_CONTAINER, 0); 00292 } 00293 /* 00294 * Release the mouse capture we set when we called StartMenuState... 00295 */ 00296 xxxMNReleaseCapture(); 00297 00298 /* Notify the app we have exited menu mode. wParam is 1 for real 00299 * tracked popups, not sys menu. Check wFlags since ppopupHierarchy 00300 * will be gone. 00301 */ 00302 if (!(dwFlags & TPM_NONOTIFY)) 00303 xxxSendMessage(pwndOwner, WM_EXITMENULOOP, ((dwFlags & TPM_SYSMENU) ? 00304 FALSE : TRUE), 0L); 00305 00306 /* 00307 * Make sure we return failure 00308 */ 00309 fSync = TRUE; 00310 cmd = FALSE; 00311 goto CleanupTrackPopupMenuEx; 00312 } 00313 00314 if (glinp.dwFlags & LINP_KEYBOARD) { 00315 pMenuState->fUnderline = TRUE; 00316 SetMF(pMenu, MFUNDERLINE); 00317 } 00318 00319 // 00320 // Setup popup window dimensions 00321 // 00322 cxPopup = LOWORD(sizeHierarchy) + 2*SYSMET(CXFIXEDFRAME); 00323 cyPopup = HIWORD(sizeHierarchy) + 2*SYSMET(CYFIXEDFRAME); 00324 00325 // 00326 // Calculate the monitor BEFORE we adjust the point. Otherwise, we might 00327 // move the point offscreen. In which case, we will end up pinning the 00328 // popup to the primary display, which is wrong. 00329 // 00330 pt.x = x; 00331 pt.y = y; 00332 pMonitor = _MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); 00333 00334 // 00335 // Horizontal alignment 00336 // 00337 #ifdef USE_MIRRORING 00338 if (TestWF(pwndOwner, WEFLAYOUTRTL) && !(dwFlags & TPM_CENTERALIGN)) { 00339 dwFlags = dwFlags ^ TPM_RIGHTALIGN; 00340 } 00341 #endif 00342 if (dwFlags & TPM_RIGHTALIGN) { 00343 #if DBG 00344 if (dwFlags & TPM_CENTERALIGN) { 00345 RIPMSG0(RIP_WARNING, "TrackPopupMenuEx: TPM_CENTERALIGN ignored"); 00346 } 00347 #endif // DBG 00348 00349 x -= cxPopup; 00350 ppopupMenuHierarchy->iDropDir = PAS_LEFT; 00351 } else if (dwFlags & TPM_CENTERALIGN) { 00352 x -= (cxPopup / 2); 00353 } else { 00354 ppopupMenuHierarchy->iDropDir = (ppopupMenuHierarchy->fDroppedLeft ? PAS_LEFT : PAS_RIGHT); 00355 } 00356 00357 // 00358 // Vertical alignment 00359 // 00360 if (dwFlags & TPM_BOTTOMALIGN) { 00361 #if DBG 00362 if (dwFlags & TPM_VCENTERALIGN) { 00363 RIPMSG0(RIP_WARNING, "TrackPopupMenuEx: TPM_VCENTERALIGN ignored"); 00364 } 00365 #endif // DBG 00366 00367 y -= cyPopup; 00368 ppopupMenuHierarchy->iDropDir |= PAS_UP; 00369 } else if (dwFlags & TPM_VCENTERALIGN) { 00370 y -= (cyPopup / 2); 00371 } else { 00372 ppopupMenuHierarchy->iDropDir |= PAS_DOWN; 00373 } 00374 /* 00375 * If the caller provided an animation direction, use that instead 00376 */ 00377 if (dwFlags & TPM_ANIMATIONBITS) { 00378 ppopupMenuHierarchy->iDropDir = ((dwFlags >> TPM_FIRSTANIBITPOS) & (PAS_VERT | PAS_HORZ)); 00379 } 00380 // 00381 // Get coords to move to. 00382 // 00383 sizeHierarchy = FindBestPos( 00384 x, 00385 y, 00386 cxPopup, 00387 cyPopup, 00388 ((lpTpm != NULL) ? &rcExclude : NULL), 00389 dwFlags, 00390 ppopupMenuHierarchy, 00391 pMonitor); 00392 00393 #ifdef USE_MIRRORING 00394 if (TestWF(pwndOwner, WEFLAYOUTRTL) && (ppopupMenuHierarchy->iDropDir & PAS_HORZ)) { 00395 ppopupMenuHierarchy->iDropDir ^= PAS_HORZ; 00396 } 00397 #endif 00398 00399 /* 00400 * If we have an animation direction and the caller wants animation, 00401 * set the bit to get it going. 00402 */ 00403 if ((ppopupMenuHierarchy->iDropDir != 0) && !(dwFlags & TPM_NOANIMATION)) { 00404 ppopupMenuHierarchy->iDropDir |= PAS_OUT; 00405 } 00406 00407 /* 00408 * Show the window. Modeless menus are not topmost and get activated. 00409 * Modal menus are topmost but don't get activated. 00410 */ 00411 PlayEventSound(USER_SOUND_MENUPOPUP); 00412 xxxSetWindowPos(pwndHierarchy, 00413 (pMenuState->fModelessMenu ? PWND_TOP : PWND_TOPMOST), 00414 GET_X_LPARAM(sizeHierarchy), GET_Y_LPARAM(sizeHierarchy), 0, 0, 00415 SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOOWNERZORDER 00416 | (pMenuState->fModelessMenu ? 0 : SWP_NOACTIVATE)); 00417 00418 if (FWINABLE()) { 00419 xxxWindowEvent(EVENT_SYSTEM_MENUPOPUPSTART, pwndHierarchy, OBJID_CLIENT, INDEXID_CONTAINER, 0); 00420 } 00421 // 00422 // We need to return TRUE for compatibility w/ async TrackPopupMenu(). 00423 // It is conceivable that a menu ID could have ID 0, in which case just 00424 // returning the cmd chosen would return FALSE instead of TRUE. 00425 // 00426 00427 // 00428 // If mouse is in client of popup, act like clicked down 00429 // 00430 pMenuState->fButtonDown = fButtonDown; 00431 00432 cmd = xxxMNLoop(ppopupMenuHierarchy, pMenuState, 0, FALSE); 00433 00434 /* 00435 * If this is a modeless menu, return without clenning up because 00436 * the menu is up. 00437 */ 00438 if (pMenuState->fModelessMenu) { 00439 ThreadUnlock(&tlpwndHierarchy); 00440 goto ReturnCmdOrTrue; 00441 } 00442 00443 CleanupTrackPopupMenuEx: 00444 00445 if (ThreadUnlock(&tlpwndHierarchy)) { 00446 if (!TestWF(pwndHierarchy, WFDESTROYED)) { 00447 xxxDestroyWindow(pwndHierarchy); 00448 } 00449 } 00450 00451 if (pMenuState != NULL) { 00452 xxxMNEndMenuState (TRUE); 00453 } 00454 00455 /* 00456 * Capture must be unlocked if no menu is active. 00457 */ 00458 UserAssert(!(ptiCurrent->pq->QF_flags & QF_CAPTURELOCKED) 00459 || ((ptiCurrent->pMenuState != NULL) 00460 && !ptiCurrent->pMenuState->fModelessMenu)); 00461 00462 00463 ReturnCmdOrTrue: 00464 return(fSync ? cmd : TRUE); 00465 }


Generated on Sat May 15 19:44:47 2004 for test by doxygen 1.3.7