00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015 #define TT_XOFFSET 2
00016 #define TT_YOFFSET 1
00017 #define TTT_SHOW 1
00018 #define TTT_HIDE 2
00019 #define TTT_ANIMATE 3
00020 #define TT_ANIMATEDELAY 20
00021
00022 #define TTF_POSITIVE 0x00000001
00023
00024 #define bitsizeof(x) (sizeof(x) * 8)
00025
00026
UINT MNItemHitTest(
PMENU,
PWND, POINT);
00027 HANDLE
NtGdiGetDCObject(HDC,
int);
00028 LONG
GreGetBitmapBits(HBITMAP, ULONG, PBYTE, PLONG);
00029
DWORD CalcCaptionButton(
PWND pwnd,
int hit, LPWORD pcmd, LPRECT prcBtn, LPWORD pbm);
00030
int HitTestScrollBar(
PWND pwnd,
int ht, POINT pt);
00031
BOOL xxxHotTrackSB(
PWND pwnd,
int htEx, BOOL fDraw);
00032
00033 __inline
void ZeroTooltip(
PTOOLTIPWND pttwnd)
00034 {
00035 RtlZeroMemory((
PBYTE)pttwnd + (
sizeof(
TOOLTIPWND) -
sizeof(
TOOLTIP)),
00036
sizeof(
TOOLTIP));
00037 }
00038
00039
00040
00041
00042
00043
00044
00045 HDC
GetTooltipDC(
PTOOLTIPWND pttwnd)
00046 {
00047 HDC hdc =
_GetDCEx((
PWND)pttwnd,
NULL, DCX_WINDOW | DCX_CACHE |
00048 DCX_USESTYLE);
00049
00050
if (hdc ==
NULL)
00051
return NULL;
00052
00053 GreSelectFont(hdc,
ghStatusFont);
00054
return hdc;
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 void InitTooltipAnimation(
PTOOLTIPWND pttwnd)
00067 {
00068 HDC hdc =
GetTooltipDC(pttwnd);
00069
00070
if ((pttwnd->
hdcMem = GreCreateCompatibleDC(hdc)) ==
NULL) {
00071
return;
00072 }
00073
_ReleaseDC(hdc);
00074 GreSetDCOwner(pttwnd->
hdcMem, OBJECT_OWNER_PUBLIC);
00075 }
00076
00077
00078
00079
00080
00081
00082 void DestroyTooltipBitmap(
PTOOLTIPWND pttwnd)
00083 {
00084
if (pttwnd->
hbmMem ==
NULL)
00085
return;
00086
00087 GreSelectBitmap(pttwnd->
hdcMem, GreGetStockObject(PRIV_STOCK_BITMAP));
00088 GreDeleteObject(pttwnd->
hbmMem);
00089 pttwnd->
hbmMem =
NULL;
00090 }
00091
00092
00093
00094
00095
00096
00097 BOOL CreateTooltipBitmap(
PTOOLTIPWND pttwnd, UINT cx, UINT cy)
00098 {
00099 HDC hdc;
00100
00101
if (pttwnd->
hdcMem ==
NULL) {
00102 RIPMSG0(RIP_WARNING,
"CreateTooltipBitmap: pttwnd->hdcMem is NULL");
00103
return FALSE;
00104 }
00105
00106
DestroyTooltipBitmap(pttwnd);
00107
00108 hdc =
GetTooltipDC(pttwnd);
00109 pttwnd->
hbmMem = GreCreateCompatibleBitmap(hdc, cx,
cy);
00110
_ReleaseDC(hdc);
00111
00112
if (pttwnd->
hbmMem ==
NULL) {
00113 RIPMSG0(RIP_WARNING,
"CreateTooltipBitmap: hbmMem is NULL");
00114
return FALSE;
00115 }
00116 GreSelectBitmap(pttwnd->
hdcMem, pttwnd->
hbmMem);
00117
return TRUE;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 void CleanupTooltipAnimation(
PTOOLTIPWND pttwnd)
00130 {
00131
DestroyTooltipBitmap(pttwnd);
00132
00133
if (pttwnd->
hdcMem !=
NULL) {
00134 GreSetDCOwner(pttwnd->
hdcMem, OBJECT_OWNER_CURRENT);
00135 GreDeleteDC(pttwnd->
hdcMem);
00136 }
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 BOOL TooltipAnimate(
PTOOLTIPWND pttwnd)
00149 {
00150
int y, yMem, yReal, ny, iy, cx,
cy;
00151
DWORD dwElapsed;
00152 HDC hdc;
00153
BOOL fRet =
FALSE;
00154
00155
if (pttwnd->pstr ==
NULL)
00156
return TRUE;
00157
00158 hdc =
GetTooltipDC(pttwnd);
00159 cx = pttwnd->rcWindow.right - pttwnd->rcWindow.left;
00160
cy = pttwnd->rcWindow.bottom - pttwnd->rcWindow.top;
00161 dwElapsed =
NtGetTickCount() - pttwnd->dwAnimStart;
00162 iy =
MultDiv(
cy, dwElapsed,
CMS_TOOLTIP);
00163
00164
if (dwElapsed >
CMS_TOOLTIP || iy ==
cy) {
00165 GreBitBlt(hdc, 0, 0, cx,
cy, pttwnd->
hdcMem, 0, 0, SRCCOPY | NOMIRRORBITMAP, 0);
00166 fRet =
TRUE;
00167
goto Cleanup;
00168 }
else if (pttwnd->iyAnim == iy) {
00169
goto Cleanup;
00170 }
00171
00172
if (pttwnd->dwFlags &
TTF_POSITIVE) {
00173 y = 0;
00174 ny = 0;
00175 }
else {
00176 y =
cy;
00177 ny = -1;
00178 }
00179
00180 yReal = y + ny * iy;
00181 yMem = (pttwnd->dwFlags &
TTF_POSITIVE) ?
cy - iy : 0;
00182 pttwnd->iyAnim = iy;
00183
00184 GreBitBlt(hdc, 0, yReal, cx, iy, pttwnd->
hdcMem, 0, yMem, SRCCOPY | NOMIRRORBITMAP, 0);
00185
00186 Cleanup:
00187
_ReleaseDC(hdc);
00188
return fRet;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 int GetCursorHeight(
void)
00203 {
00204
int iAnd, iXor, dy = 16;
00205 WORD wMask[128];
00206 ICONINFO ii;
00207 BITMAP bm;
00208
PCURSOR pcur;
00209
long lOffset = 0;
00210
00211
if ((pcur =
PtiCurrent()->pq->spcurCurrent) ==
NULL) {
00212
return dy;
00213 }
00214
00215
if (!
_InternalGetIconInfo(pcur, &ii,
NULL,
NULL,
NULL,
FALSE)) {
00216
return dy;
00217 }
00218
00219
if (!GreExtGetObjectW(ii.hbmMask,
sizeof(bm), (LPSTR)&bm)) {
00220
goto Bail;
00221 }
00222
00223
00224
00225
00226
if (!
GreGetBitmapBits(ii.hbmMask,
sizeof(wMask), (
BYTE*)wMask, &lOffset)) {
00227
goto Bail;
00228 }
00229
00230 iAnd = (
int)(bm.bmWidth * bm.bmHeight /
bitsizeof(WORD));
00231
00232
if (ii.hbmColor ==
NULL) {
00233
00234
00235
00236
00237
00238 iXor = iAnd - 1;
00239 iAnd /= 2;
00240 }
else {
00241 iXor = 0;
00242 }
00243
00244
if (iAnd >=
sizeof(wMask)) {
00245 iAnd =
sizeof(wMask) - 1;
00246 }
00247
00248
if (iXor >=
sizeof(wMask)) {
00249 iXor = 0;
00250 }
00251
00252
for (iAnd--; iAnd >= 0; iAnd--) {
00253
if ((iXor != 0 && wMask[iXor--] != 0) || wMask[iAnd] != 0xFFFF) {
00254
break;
00255 }
00256 }
00257
00258
00259
00260
00261 dy = (iAnd + 1) *
bitsizeof(WORD) / (
int)bm.bmWidth - (
int)ii.yHotspot;
00262
00263 Bail:
00264
if (ii.hbmColor) {
00265 GreDeleteObject(ii.hbmColor);
00266 }
00267
00268
if (ii.hbmMask) {
00269 GreDeleteObject(ii.hbmMask);
00270 }
00271
00272
return dy;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 void TooltipGetPosition(
PTOOLTIPWND pttwnd, SIZE *psize, POINT *ppt)
00286 {
00287
PMONITOR pMonitor;
00288
00289 *ppt =
gpsi->ptCursor;
00290 pMonitor =
_MonitorFromPoint(*ppt, MONITOR_DEFAULTTONULL);
00291 UserAssert(pMonitor);
00292
00293
if (ppt->y + psize->cy >= pMonitor->
rcMonitor.bottom) {
00294 ppt->y = ppt->y - psize->cy;
00295 pttwnd->dwFlags &= ~
TTF_POSITIVE;
00296 }
else {
00297 ppt->y +=
GetCursorHeight();
00298 pttwnd->dwFlags |=
TTF_POSITIVE;
00299 }
00300
00301
if (ppt->x + psize->cx >= pMonitor->
rcMonitor.right) {
00302 ppt->x = pMonitor->
rcMonitor.right - psize->cx;
00303 }
00304
00305
if (ppt->x < pMonitor->
rcMonitor.left) {
00306 ppt->x = pMonitor->
rcMonitor.left;
00307 }
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 void TooltipGetSize(
PTOOLTIPWND pttwnd, SIZE *psize)
00319 {
00320 HDC hdc =
GetTooltipDC(pttwnd);
00321 GreGetTextExtentW(hdc, pttwnd->pstr, wcslen(pttwnd->pstr),
00322 psize, GGTE_WIN3_EXTENT);
00323
_ReleaseDC(hdc);
00324 psize->cx +=
SYSMET(CXEDGE) + 2 *
SYSMET(CXBORDER) *
TT_XOFFSET;
00325 psize->cy +=
SYSMET(CYEDGE) + 2 *
SYSMET(CYBORDER) *
TT_YOFFSET;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 void TooltipRender(
PTOOLTIPWND pttwnd, HDC hdc)
00337 {
00338 COLORREF crBk;
00339
UINT uFlags;
00340 RECT rc;
00341
00342
if (pttwnd->pstr ==
NULL)
00343
return;
00344
00345 GreSelectFont(hdc,
ghStatusFont);
00346 GreSetTextColor(hdc,
gpsi->argbSystem[COLOR_INFOTEXT]);
00347 crBk =
gpsi->argbSystem[COLOR_INFOBK];
00348
00349
CopyOffsetRect(&rc, &pttwnd->rcClient, -pttwnd->rcClient.left,
00350 -pttwnd->rcClient.top);
00351
00352
00353
00354
00355
if (crBk == GreGetNearestColor(hdc, crBk)) {
00356 GreSetBkColor(hdc, crBk);
00357 uFlags = ETO_OPAQUE;
00358 }
else {
00359
FillRect(hdc, &rc,
SYSHBR(INFOBK));
00360 GreSetBkMode(hdc, TRANSPARENT);
00361 uFlags = ETO_CLIPPED;
00362 }
00363
00364 GreExtTextOutW(hdc,
SYSMET(CXBORDER) *
TT_XOFFSET,
00365
SYSMET(CYBORDER) *
TT_YOFFSET, uFlags, &rc, pttwnd->pstr,
00366 wcslen(pttwnd->pstr),
NULL);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 int FindNCHitEx(
PWND pwnd,
int ht, POINT pt)
00376 {
00377
00378
00379
00380
00381
00382
00383
if (ht == HTMENU && pwnd->
spmenu &&
TestWF(pwnd,
WFMPRESENT)) {
00384
PMENU spmenu = pwnd->
spmenu;
00385
PITEM pitem;
00386
int nItem;
00387
00388 nItem =
MNItemHitTest(spmenu, pwnd, pt);
00389
if (nItem >= 0) {
00390 pitem = (
PITEM)&spmenu->
rgItems[nItem];
00391
switch ((ULONG_PTR)pitem->
hbmp) {
00392
case (ULONG_PTR)HBMMENU_SYSTEM:
00393 ht =
HTMDISYSMENU;
00394
break;
00395
case (ULONG_PTR)HBMMENU_MBAR_RESTORE:
00396 ht =
HTMDIMAXBUTTON;
00397
break;
00398
case (ULONG_PTR)HBMMENU_MBAR_MINIMIZE:
00399
case (ULONG_PTR)HBMMENU_MBAR_MINIMIZE_D:
00400 ht =
HTMDIMINBUTTON;
00401
break;
00402
case (ULONG_PTR)HBMMENU_MBAR_CLOSE:
00403
case (ULONG_PTR)HBMMENU_MBAR_CLOSE_D:
00404 ht =
HTMDICLOSE;
00405
break;
00406
case (ULONG_PTR)HBMMENU_CALLBACK:
00407 ht = HTERROR;
00408
break;
00409
default:
00410 ht =
HTMENUITEM;
00411
break;
00412 }
00413 }
00414
return MAKELONG(ht, nItem);
00415 }
else if (ht == HTVSCROLL &&
TestWF(pwnd,
WFVPRESENT)) {
00416
return MAKELONG(
HitTestScrollBar(pwnd,
TRUE, pt), 1);
00417 }
else if (ht == HTHSCROLL &&
TestWF(pwnd,
WFHPRESENT)) {
00418
return MAKELONG(
HitTestScrollBar(pwnd,
FALSE, pt), 0);
00419 }
00420
00421
return ht;
00422 }
00423
00424
00425
00426
00427
00428
00429 void KillTooltipTimer (
PTOOLTIPWND pttwnd)
00430 {
00431
UINT uTID = pttwnd->uTID;
00432
if (uTID != 0) {
00433 pttwnd->uTID = 0;
00434
_KillTimer((
PWND)pttwnd, uTID);
00435 }
00436 }
00437
00438
00439
00440
00441 void SetTooltipTimer (
PTOOLTIPWND pttwnd, UINT uTID, UINT uDelay)
00442 {
00443
KillTooltipTimer(pttwnd);
00444 pttwnd->uTID = uTID;
00445
InternalSetTimer((
PWND)pttwnd, uTID, uDelay,
NULL, 0);
00446 }
00447
00448
00449
00450
00451
00452
00453 void xxxResetTooltip(
PTOOLTIPWND pttwnd)
00454 {
00455
KillTooltipTimer(pttwnd);
00456
00457
CheckLock(pttwnd);
00458
00459
if (
TestWF(pttwnd,
WFVISIBLE)) {
00460
PWND spwndMessage;
00461
TL tlpwnd;
00462
00463
xxxSetWindowPos((
PWND)pttwnd,
NULL, 0, 0, 0, 0, SWP_NOSIZE |
00464 SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
00465
00466 spwndMessage =
PWNDMESSAGE(pttwnd);
00467
ThreadLockAlways(spwndMessage, &tlpwnd);
00468
xxxSetParent((
PWND)pttwnd, spwndMessage);
00469
ThreadUnlock(&tlpwnd);
00470 }
00471
00472
ZeroTooltip(pttwnd);
00473 pttwnd->head.rpdesk->dwDTFlags &= ~
DF_TOOLTIP;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 void xxxShowTooltip(
PTOOLTIPWND pttwnd)
00485 {
00486 SIZE size;
00487 POINT pt;
00488
DWORD dwFlags;
00489
00490
CheckLock(pttwnd);
00491
00492
if (pttwnd->pstr ==
NULL)
00493
return;
00494
00495
if (pttwnd->pstr ==
gszCAPTIONTOOLTIP) {
00496
00497
PWND pwnd =
PtiCurrent()->rpdesk->spwndTrack;
00498
00499
00500
00501
if (
TestWF(pwnd,
WEFTRUNCATEDCAPTION) && pwnd->
strName.
Length) {
00502
wcsncpycch(
gszCAPTIONTOOLTIP, pwnd->
strName.
Buffer,
CAPTIONTOOLTIPLEN-1);
00503
gszCAPTIONTOOLTIP[
CAPTIONTOOLTIPLEN-1] = 0;
00504 }
else {
00505
return;
00506 }
00507 }
00508
00509
TooltipGetSize(pttwnd, &size);
00510
TooltipGetPosition(pttwnd, &size, &pt);
00511
00512
dwFlags = SWP_CREATESPB | SWP_SHOWWINDOW | SWP_NOACTIVATE;
00513
if (
TestEffectUP(TOOLTIPANIMATION)) {
00514
dwFlags |= SWP_NOREDRAW;
00515 }
00516
xxxSetWindowPos((
PWND)pttwnd,
PWND_TOP, pt.x, pt.y, size.cx, size.cy,
00517
dwFlags);
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 void xxxTooltipHandleTimer(
PTOOLTIPWND pttwnd, UINT uTID)
00527 {
00528
00529
switch(uTID) {
00530
case TTT_SHOW: {
00531
00532
00533
00534
00535
PWND pwndDesktop =
PWNDDESKTOP(pttwnd);
00536
TL tlpwnd;
00537
ThreadLockAlways(pwndDesktop, &tlpwnd);
00538
xxxSetParent((
PWND)pttwnd, pwndDesktop);
00539
ThreadUnlock(&tlpwnd);
00540
00541
xxxShowTooltip(pttwnd);
00542
break;
00543 }
00544
00545
case TTT_ANIMATE:
00546
00547
00548
00549
if (
TooltipAnimate(pttwnd)) {
00550
SetTooltipTimer(pttwnd,
TTT_HIDE, pttwnd->
dwHideDelay);
00551 }
00552
break;
00553
00554
case TTT_HIDE:
00555
00556
00557
00558
xxxResetTooltip(pttwnd);
00559
break;
00560 }
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570 LRESULT
xxxTooltipWndProc(
PWND pwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00571 {
00572 PAINTSTRUCT ps;
00573
PTOOLTIPWND pttwnd;
00574
00575
CheckLock(pwnd);
00576
VALIDATECLASSANDSIZE(pwnd, uMsg, wParam, lParam,
FNID_TOOLTIP, WM_NCCREATE);
00577 pttwnd = (
PTOOLTIPWND)pwnd;
00578
00579
switch(uMsg) {
00580
case WM_TIMER:
00581
xxxTooltipHandleTimer(pttwnd, (
UINT)wParam);
00582
break;
00583
00584
case WM_PAINT:
00585
xxxBeginPaint(pwnd, &ps);
00586
TooltipRender(pttwnd, ps.hdc);
00587
xxxEndPaint(pwnd, &ps);
00588
break;
00589
00590
case WM_PRINTCLIENT:
00591
TooltipRender(pttwnd, (HDC)wParam);
00592
break;
00593
00594
case WM_ERASEBKGND:
00595
break;
00596
00597
case WM_NCCREATE:
00598
InitTooltipDelay(pttwnd);
00599
InitTooltipAnimation(pttwnd);
00600
goto CallDWP;
00601
00602
case WM_NCDESTROY:
00603
CleanupTooltipAnimation(pttwnd);
00604
GETPDESK(pttwnd)->dwDTFlags &= ~
DF_TOOLTIP;
00605
goto CallDWP;
00606
00607
case WM_WINDOWPOSCHANGED:
00608
if (((LPWINDOWPOS)lParam)->flags & SWP_SHOWWINDOW) {
00609 HDC hdc;
00610
int cx;
00611
int cy;
00612
00613
if (!
TestEffectUP(TOOLTIPANIMATION)) {
00614
SetTooltipTimer(pttwnd,
TTT_HIDE, pttwnd->
dwHideDelay);
00615
goto CallDWP;
00616 }
00617
00618 hdc =
NULL;
00619 cx = pttwnd->rcWindow.right - pttwnd->rcWindow.left;
00620
cy = pttwnd->rcWindow.bottom - pttwnd->rcWindow.top;
00621
00622
00623
00624
00625
00626
if (
TestALPHA(TOOLTIPFADE)) {
00627 hdc =
CreateFade((
PWND)pttwnd,
NULL,
CMS_TOOLTIP,
00628
FADE_SHOW |
FADE_TOOLTIP);
00629 }
else {
00630
if (
CreateTooltipBitmap(pttwnd, cx,
cy)) {
00631 hdc = pttwnd->
hdcMem;
00632 }
00633 }
00634
00635
if (hdc ==
NULL) {
00636
SetTooltipTimer(pttwnd,
TTT_HIDE, 0);
00637
goto CallDWP;
00638 }
00639
00640
xxxSendMessage((
PWND)pttwnd, WM_PRINT, (WPARAM)hdc,
00641 PRF_CLIENT | PRF_NONCLIENT | PRF_CHILDREN | PRF_ERASEBKGND);
00642
00643
00644
00645
00646
00647
if (
TestFadeFlags(
FADE_TOOLTIP)) {
00648
StartFade();
00649
SetTooltipTimer(pttwnd,
TTT_HIDE, pttwnd->dwHideDelay);
00650 }
else {
00651 pttwnd->dwAnimStart =
NtGetTickCount();
00652
SetTooltipTimer(pttwnd,
TTT_ANIMATE,
TT_ANIMATEDELAY);
00653 }
00654 }
else if (((LPWINDOWPOS)lParam)->flags & SWP_HIDEWINDOW) {
00655
if (
TestFadeFlags(
FADE_TOOLTIP)) {
00656
StopFade();
00657 }
else {
00658
DestroyTooltipBitmap(pttwnd);
00659 }
00660 }
00661
goto CallDWP;
00662
00663
default:
00664 CallDWP:
00665
return xxxDefWindowProc(pwnd, uMsg, wParam, lParam);
00666 }
00667
00668
return 0;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678 LPWSTR
IsTooltipHittest(
PWND pwnd, UINT ht)
00679 {
00680
switch (ht) {
00681
case HTMINBUTTON:
00682
if (
TestWF(pwnd,
WFMINBOX)) {
00683
return (
TestWF(pwnd,
WFMINIMIZED)) ?
gszRESUP :
gszMIN;
00684 }
00685
break;
00686
00687
case HTMAXBUTTON:
00688
if (
TestWF(pwnd,
WFMAXBOX)) {
00689
return (
TestWF(pwnd,
WFMAXIMIZED)) ?
gszRESDOWN :
gszMAX;
00690 }
00691
break;
00692
00693
case HTCLOSE:
00694
case HTMDICLOSE:
00695
return gszSCLOSE;
00696
00697
00698
00699
00700
00701
00702
case HTHELP:
00703
return GETGPSIMBPSTR(
SEB_HELP);
00704
00705
case HTMDIMINBUTTON:
00706
return gszMIN;
00707
00708
case HTMDIMAXBUTTON:
00709
return gszRESDOWN;
00710
00711
case HTCAPTION:
00712
00713
00714
00715
00716
00717
if (
TestWF(pwnd,
WEFTRUNCATEDCAPTION)) {
00718
return gszCAPTIONTOOLTIP;
00719 }
00720
break;
00721
00722
default:
00723
break;
00724 }
00725
return NULL;
00726 }
00727
00728
00729
00730
00731
00732
00733 BOOL xxxHotTrackMenu(
PWND pwnd, UINT nItem, BOOL fDraw)
00734 {
00735
PMENU pmenu = pwnd->
spmenu;
00736
PITEM pItem;
00737 HDC hdc;
00738
UINT oldAlign;
00739
TL tlpmenu;
00740
00741
CheckLock(pwnd);
00742
00743
00744
00745
00746
00747
if (!
TestWF(pwnd,
WFMPRESENT) || pmenu ==
NULL)
00748
return FALSE;
00749
00750
if (nItem >= pmenu->
cItems) {
00751 RIPMSG0(RIP_WARNING,
"xxxHotTrackMenu: menu too large");
00752
return FALSE;
00753 }
00754
00755 pItem = &pmenu->
rgItems[nItem];
00756
00757
00758
00759
00760
ThreadLock(pmenu, &tlpmenu);
00761
xxxMNRecomputeBarIfNeeded(pwnd, pmenu);
00762 ValidateThreadLocks(
NULL,
PtiCurrent()->ptl, (ULONG_PTR)&tlpmenu,
TRUE);
00763
00764
if (fDraw) {
00765
if (
TestMFS(pItem, MF_GRAYED)) {
00766
ThreadUnlock(&tlpmenu);
00767
return FALSE;
00768 }
00769
SetMFS(pItem, MFS_HOTTRACK);
00770 }
else {
00771
ClearMFS(pItem, MFS_HOTTRACK);
00772 }
00773
00774 hdc =
_GetDCEx(pwnd,
NULL, DCX_WINDOW | DCX_USESTYLE | DCX_CACHE);
00775 GreSelectBrush(hdc,
SYSHBR(MENUTEXT));
00776 GreSelectFont(hdc,
ghMenuFont);
00777
00778 oldAlign =
GreGetTextAlign(hdc);
00779
if (pmenu->
rgItems &&
TestMFT(pmenu->
rgItems, MFT_RIGHTORDER))
00780
GreSetTextAlign(hdc, oldAlign | TA_RTLREADING);
00781
00782
00783
00784
00785
00786
xxxDrawMenuItem(hdc, pmenu, pItem, 0);
00787
GreSetTextAlign(hdc, oldAlign);
00788
ThreadUnlock(&tlpmenu);
00789
00790
_ReleaseDC(hdc);
00791
return TRUE;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
#ifdef COLOR_HOTTRACKING
00802
00803
BOOL xxxHotTrackCaption(
PWND pwnd,
int ht, BOOL fDraw)
00804 {
00805
DWORD dwWhere;
00806
int x, y;
00807 WORD bm, cmd;
00808 RECT rcBtn;
00809 HDC hdc;
00810
00811
CheckLock(pwnd);
00812
00813
if (!
TestWF(pwnd, WFCPRESENT))
00814
return FALSE;
00815
00816 dwWhere =
xxxCalcCaptionButton(pwnd, ht, &cmd, &rcBtn, &bm);
00817 x =
GET_X_LPARAM(dwWhere);
00818 y =
GET_Y_LPARAM(dwWhere);
00819
00820
if (!cmd)
00821
return FALSE;
00822
00823 hdc =
_GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE | DCX_CACHE);
00824
BitBltSysBmp(hdc, x, y, bm + (fDraw ? DOBI_HOT : 0));
00825
_ReleaseDC(hdc);
00826
return TRUE;
00827 }
00828
00829
#endif // COLOR_HOTTRACKING
00830
00831
00832
00833
00834
00835
00836 BOOL xxxHotTrack(
PWND pwnd,
int htEx, BOOL fDraw)
00837 {
00838
int ht = LOWORD(htEx);
00839
00840
CheckLock(pwnd);
00841
00842
switch(ht) {
00843
#ifdef COLOR_HOTTRACKING
00844
case HTMINBUTTON:
00845
case HTMAXBUTTON:
00846
case HTHELP:
00847
case HTCLOSE:
00848
return xxxHotTrackCaption(pwnd, ht, fDraw);
00849
00850
case HTSCROLLUP:
00851
case HTSCROLLDOWN:
00852
case HTSCROLLUPPAGE:
00853
case HTSCROLLDOWNPAGE:
00854
case HTSCROLLTHUMB:
00855
return xxxHotTrackSB(pwnd, htEx, fDraw);
00856
00857
case HTMDIMINBUTTON:
00858
case HTMDIMAXBUTTON:
00859
case HTMDICLOSE:
00860
#endif // COLOR_HOTTRACKING
00861
case HTMENUITEM:
00862
return xxxHotTrackMenu(pwnd, HIWORD(htEx), fDraw);
00863
00864 }
00865
00866
return FALSE;
00867 }
00868
00869
00870
00871
00872
00873
00874
00875 void xxxCreateTooltip(
PTOOLTIPWND pttwnd, LPWSTR pstr)
00876 {
00877
CheckLock(pttwnd);
00878
00879
00880
00881
00882 pttwnd->pstr = pstr;
00883
00884
00885
00886
00887
if (
TestWF(pttwnd,
WFVISIBLE)) {
00888
xxxSetWindowPos((
PWND)pttwnd,
NULL, 0, 0, 0, 0, SWP_NOSIZE |
00889 SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);
00890
xxxShowTooltip(pttwnd);
00891 }
else {
00892
SetTooltipTimer(pttwnd,
TTT_SHOW, pttwnd->
dwShowDelay);
00893 }
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 void xxxTrackMouseMove(
PWND pwnd,
int htEx, UINT message)
00905 {
00906
BOOL fNewpwndTrack;
00907
DWORD dwDTCancel = 0;
00908
TL tlpwnd;
00909 LPWSTR pstr;
00910
PDESKTOP pdesk =
PtiCurrent()->rpdesk;
00911
PTHREADINFO ptiTrack;
00912
00913
00914
#if DBG
00915
00916
00917
00918
00919
00920
static UINT gcReEntered = 0;
00921
static PTHREADINFO gptiReEntered;
00922
if(gcReEntered++ != 0){
00923 RIPMSG2(RIP_WARNING,
"Reentered xxxTrackMouseMove; previous thread was %#p, current thread is %#p", gptiReEntered,
PtiCurrent());
00924 }
00925 gptiReEntered =
PtiCurrent();
00926
00927
CheckLock(pwnd);
00928
00929
00930
00931
00932
if (pdesk->
rpwinstaParent !=
NULL &&
00933 pdesk->
rpwinstaParent->
dwWSF_Flags &
WSF_NOIO) {
00934 RIPMSG0(RIP_ERROR,
"Can't use tooltips on non-interactive winsta");
00935 }
00936
00937 {
00938
static POINT pt = {0, 0};
00939
00940
#ifdef UNDONE
00941
00942
00943
00944
00945
00946
if ((pt.x ==
gpsi->ptCursor.x)
00947 && (pt.y ==
gpsi->ptCursor.y)
00948 && (pdesk->
spwndTrack == pwnd)) {
00949 RIPMSG1(RIP_WARNING,
"xxxTrackMouseMove: Same point & window. %#p", pwnd);
00950 }
00951
#endif
00952
00953
00954
00955
00956 UserAssert((pt.x !=
gpsi->ptCursor.x)
00957 || (pt.y !=
gpsi->ptCursor.y)
00958 || (pdesk->
spwndTrack != pwnd)
00959 || (pdesk->
htEx != htEx)
00960 || (message != WM_MOUSEMOVE));
00961
00962
00963
00964 pt =
gpsi->ptCursor;
00965 }
00966
00967
00968
00969 UserAssert(
PtiCurrent() ==
GETPTI(pwnd));
00970 UserAssert(
PtiCurrent()->pq ==
GETPTI(pwnd)->pq);
00971
#endif
00972
00973
00974
00975
00976 fNewpwndTrack = (pdesk->
spwndTrack != pwnd);
00977
00978
00979
00980
00981
if (!(pdesk->
dwDTFlags &
DF_MOUSEMOVETRK)) {
00982
goto SetNewState;
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
if (pdesk->
spwndTrack ==
NULL) {
00993
goto SetNewState;
00994 }
00995
00996
00997
00998
00999
01000
01001 ptiTrack =
GETPTI(pdesk->
spwndTrack);
01002
if (
PtiCurrent()->pq == ptiTrack->
pq) {
01003 dwDTCancel |=
DF_HOTTRACKING;
01004 }
else if (pdesk->
dwDTFlags & (
DF_HOTTRACKING |
DF_TOOLTIPACTIVE)) {
01005
PostEventMessage(ptiTrack, ptiTrack->
pq,
01006
QEVENT_CANCELMOUSEMOVETRK,
01007 pdesk->
spwndTrack,
01008 pdesk->
dwDTFlags,
01009 pdesk->
htEx,
DF_HOTTRACKING);
01010
01011
01012
01013
01014
01015 UserAssert(pwnd != pdesk->
spwndTrack);
01016 pdesk->
dwDTFlags &= ~(
DF_HOTTRACKING |
DF_TOOLTIPACTIVE);
01017 }
01018
01019
01020
01021
01022
01023
01024
if ((htEx == HTCLIENT) || (message != WM_MOUSEMOVE)) {
01025 dwDTCancel |=
DF_TOOLTIPACTIVE;
01026 }
01027
01028
01029
01030
01031
if (fNewpwndTrack || ((pdesk->
htEx == HTCLIENT) ^ (htEx == HTCLIENT))) {
01032 dwDTCancel |=
DF_TRACKMOUSEEVENT;
01033 }
01034
01035
01036
01037
ThreadLockAlways(pdesk->
spwndTrack, &tlpwnd);
01038
xxxCancelMouseMoveTracking(pdesk->
dwDTFlags,
01039 pdesk->
spwndTrack,
01040 pdesk->
htEx,
01041 dwDTCancel);
01042
ThreadUnlock(&tlpwnd);
01043 pdesk->
dwDTFlags &= ~dwDTCancel;
01044
01045
01046
01047 SetNewState:
01048
01049
01050
01051
if ((htEx != HTCLIENT) && (message == WM_MOUSEMOVE) &&
TestEffectUP(HOTTRACKING)) {
01052
01053
01054
01055
if (
xxxHotTrack(pwnd, htEx,
TRUE)) {
01056 pdesk->
dwDTFlags |=
DF_HOTTRACKING;
01057 }
01058
01059
01060
01061
01062
01063
01064
if ((pstr =
IsTooltipHittest(pwnd, LOWORD(htEx))) !=
NULL) {
01065
PTOOLTIPWND pttwnd = (
PTOOLTIPWND)pdesk->
spwndTooltip;
01066
ThreadLockAlways(pttwnd, &tlpwnd);
01067
xxxCreateTooltip(pttwnd, pstr);
01068
ThreadUnlock(&tlpwnd);
01069 pdesk->
dwDTFlags |=
DF_TOOLTIP;
01070 }
else {
01071
PTOOLTIPWND pttwnd = (
PTOOLTIPWND)pdesk->
spwndTooltip;
01072
ThreadLockAlways(pttwnd, &tlpwnd);
01073
xxxResetTooltip(pttwnd);
01074
ThreadUnlock(&tlpwnd);
01075 }
01076 }
01077
01078
01079 ValidateThreadLocks(
NULL,
PtiCurrent()->ptl, (ULONG_PTR)&pwnd,
TRUE);
01080
01081
01082
01083
01084
if (fNewpwndTrack) {
01085
PWND pwndActivate;
01086
01087
Lock(&pdesk->
spwndTrack, pwnd);
01088
01089
01090
01091
01092
01093
01094
if ((message == WM_MOUSEMOVE) &&
TestUP(ACTIVEWINDOWTRACKING)) {
01095
if (
UP(ACTIVEWNDTRKTIMEOUT) != 0) {
01096 pwndActivate =
GetActiveTrackPwnd(pwnd,
NULL);
01097
if (pwndActivate !=
NULL) {
01098
InternalSetTimer(pwndActivate,
IDSYS_WNDTRACKING,
01099
UP(ACTIVEWNDTRKTIMEOUT),
01100
xxxSystemTimerProc, TMRF_SYSTEM);
01101 }
01102 }
else {
01103
PtiCurrent()->pq->QF_flags |=
QF_ACTIVEWNDTRACKING;
01104 }
01105 }
01106
01107 }
01108
01109
01110
01111
01112 pdesk->
htEx = htEx;
01113
01114
#if DBG
01115
--gcReEntered;
01116
#endif
01117
}
01118
01119
01120
01121
01122
01123
01124
01125 void xxxCancelMouseMoveTracking (DWORD dwDTFlags,
PWND pwndTrack,
int htEx, DWORD dwDTCancel)
01126 {
01127
01128
CheckLock(pwndTrack);
01129
01130
01131
01132
if ((dwDTFlags &
DF_HOTTRACKING) && (dwDTCancel &
DF_HOTTRACKING)) {
01133
01134
01135
01136
01137 UserAssert(
PtiCurrent()->pq ==
GETPTI(pwndTrack)->pq);
01138
01139
xxxHotTrack(pwndTrack, htEx,
FALSE);
01140 }
01141
01142
01143
01144
01145
if ((dwDTFlags &
DF_TOOLTIPSHOWING) && (dwDTCancel &
DF_TOOLTIP)) {
01146
PTOOLTIPWND pttwnd = (
PTOOLTIPWND)
PWNDTOOLTIP(pwndTrack);
01147
TL tlpwnd;
01148
01149
ThreadLockAlways(pttwnd, &tlpwnd);
01150
xxxResetTooltip(pttwnd);
01151
ThreadUnlock(&tlpwnd);
01152 }
01153
01154
01155
01156
01157
if ((dwDTFlags &
DF_TRACKMOUSELEAVE) && (dwDTCancel &
DF_TRACKMOUSELEAVE)) {
01158
_PostMessage(pwndTrack,
01159 ((htEx == HTCLIENT) ? WM_MOUSELEAVE : WM_NCMOUSELEAVE),
01160 0, 0);
01161 }
01162
01163
01164
01165
01166
if ((dwDTFlags &
DF_TRACKMOUSEHOVER) && (dwDTCancel &
DF_TRACKMOUSEHOVER)) {
01167
_KillSystemTimer(pwndTrack,
IDSYS_MOUSEHOVER);
01168 }
01169 }