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
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
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
00108
00109
00110
00111
00112
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
00126
00127
MNAnimate(ptiCurrent->
pMenuState, FALSE);
00128
00129
00130
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
00142
00143
00144
if (!ptiCurrent->
pMenuState->
fModelessMenu) {
00145 ptiCurrent->
pq->
QF_flags &= ~
QF_CAPTURELOCKED;
00146 }
00147 }
else {
00148
00149
00150
00151 RIPERR0(ERROR_POPUP_ALREADY_ACTIVE, RIP_VERBOSE,
"");
00152
return FALSE;
00153 }
00154 }
00155
00156
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
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
00190
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
00215
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
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 pMenuState =
xxxMNAllocMenuState(ptiCurrent, ptiOwner, ppopupMenuHierarchy);
00238
if (pMenuState ==
NULL) {
00239
00240
00241
00242
dwFlags |= TPM_NONOTIFY;
00243
goto AbortTrackPopupMenuEx;
00244 }
00245
00246
00247
00248
00249
00250
00251
if (!ppopupMenuHierarchy->
fNoNotify)
00252
xxxSendMessage(pwndOwner, WM_ENTERMENULOOP,
00253 (ppopupMenuHierarchy->
fIsSysMenu ? FALSE : TRUE), 0);
00254
00255
00256
00257
00258
if (!
xxxMNStartMenu(ppopupMenuHierarchy, MOUSEHOLD)) {
00259
00260
00261
00262
goto AbortTrackPopupMenuEx;
00263 }
00264
00265
00266
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
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
00295
00296
xxxMNReleaseCapture();
00297
00298
00299
00300
00301
00302
if (!(
dwFlags & TPM_NONOTIFY))
00303
xxxSendMessage(pwndOwner, WM_EXITMENULOOP, ((dwFlags & TPM_SYSMENU) ?
00304 FALSE : TRUE), 0L);
00305
00306
00307
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
00321
00322 cxPopup = LOWORD(sizeHierarchy) + 2*
SYSMET(CXFIXEDFRAME);
00323 cyPopup = HIWORD(sizeHierarchy) + 2*
SYSMET(CYFIXEDFRAME);
00324
00325
00326
00327
00328
00329
00330 pt.x = x;
00331 pt.y = y;
00332 pMonitor =
_MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
00333
00334
00335
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
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
00376
00377
if (
dwFlags & TPM_ANIMATIONBITS) {
00378 ppopupMenuHierarchy->
iDropDir = ((
dwFlags >> TPM_FIRSTANIBITPOS) & (
PAS_VERT |
PAS_HORZ));
00379 }
00380
00381
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
00401
00402
00403
if ((ppopupMenuHierarchy->
iDropDir != 0) && !(
dwFlags & TPM_NOANIMATION)) {
00404 ppopupMenuHierarchy->
iDropDir |=
PAS_OUT;
00405 }
00406
00407
00408
00409
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
00423
00424
00425
00426
00427
00428
00429
00430 pMenuState->
fButtonDown = fButtonDown;
00431
00432 cmd =
xxxMNLoop(ppopupMenuHierarchy, pMenuState, 0, FALSE);
00433
00434
00435
00436
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
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 }