Pager Control: Rewritten
Robert Shearman
rob at codeweavers.com
Wed Sep 15 13:54:44 CDT 2004
Hi,
This is a large patch that rewrites a lot of the layout and button state
code in the pager control. The pager control was previously in a broken
state where the scroll buttons wouldn't stay hot. It seems that
TrackMouseEvents got changed after this control was implemented in a way
that was incompatible. This has now been changed to simple mouse capture
stuff, like the native control. Also, the control unnecessarily played
about with WM_NCHITTEST. This has now been changed to just returning
either HTTRANSPARENT or HTCLIENT for the buttons (and WM_MOUSEMOVE
forwarding will now work). Also, the control had a horribly complex way
of changing states, including from within WM_NCCALCSIZE. This has now
been changed so that the state changes happen directly from the
WM_MOUSEMOVE message handler or from the PAGER_SetPos function. With
this patch, the control works better, but is still not perfect. That can
be the subject of future (much smaller) patches.
Rob
Changelog:
- Don't use TrackMouseEvents/WM_MOUSELEAVE API for handling the hot
button; use plain mouse capture instead like native.
- Return only HTTRANSPARENT/HTCLIENT from WM_NCHITTEST and remove
associated hacks of WM_SETCURSOR, WM_NCLBUTTONDOWN and WM_NCLBUTTONUP.
- Refactor state change code so that state changes don't happen as side
effects from messages such as WM_NCCALCSIZE, instead only from user
input messages like WM_MOUSEMOVE.
-------------- next part --------------
Index: wine/dlls/comctl32/pager.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/pager.c,v
retrieving revision 1.48
diff -u -p -r1.48 pager.c
--- wine/dlls/comctl32/pager.c 14 Sep 2004 00:44:38 -0000 1.48
+++ wine/dlls/comctl32/pager.c 15 Sep 2004 15:32:40 -0000
@@ -70,6 +70,34 @@ typedef struct
#define INITIAL_DELAY 500
#define REPEAT_DELAY 50
+static void
+PAGER_GetButtonRects(HWND hwnd, PAGER_INFO* infoPtr, RECT* prcTopLeft, RECT* prcBottomRight, BOOL bClientCoords)
+{
+ RECT rcWindow;
+ GetWindowRect (hwnd, &rcWindow);
+
+ if (bClientCoords)
+ {
+ POINT pt = {rcWindow.left, rcWindow.top};
+ ScreenToClient(hwnd, &pt);
+ OffsetRect(&rcWindow, -(rcWindow.left-pt.x), -(rcWindow.top-pt.y));
+ }
+ else
+ OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
+
+ *prcTopLeft = *prcBottomRight = rcWindow;
+ if (PAGER_IsHorizontal(hwnd))
+ {
+ prcTopLeft->right = prcTopLeft->left + infoPtr->nButtonSize;
+ prcBottomRight->left = prcBottomRight->right - infoPtr->nButtonSize;
+ }
+ else
+ {
+ prcTopLeft->bottom = prcTopLeft->top + infoPtr->nButtonSize;
+ prcBottomRight->top = prcBottomRight->bottom - infoPtr->nButtonSize;
+ }
+}
+
/* the horizontal arrows are:
*
* 01234 01234
@@ -178,7 +206,9 @@ PAGER_DrawButton(HDC hdc, COLORREF clrBk
HBRUSH hBrush, hOldBrush;
RECT rc = arrowRect;
- if (!btnState) /* PGF_INVISIBLE */
+ TRACE("arrowRect = %s, btnState = %d\n", wine_dbgstr_rect(&arrowRect), btnState);
+
+ if (btnState == PGF_INVISIBLE)
return;
if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
@@ -234,33 +264,6 @@ PAGER_DrawButton(HDC hdc, COLORREF clrBk
DeleteObject(hBrush);
}
-static void PAGER_CaptureandTrack(PAGER_INFO *infoPtr, HWND hwnd)
-{
- TRACKMOUSEEVENT trackinfo;
-
- TRACE("[%p] SetCapture\n", hwnd);
- SetCapture(hwnd);
- infoPtr->bCapture = TRUE;
-
- trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
- trackinfo.dwFlags = TME_QUERY;
- trackinfo.hwndTrack = hwnd;
- trackinfo.dwHoverTime = HOVER_DEFAULT;
-
- /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
- _TrackMouseEvent(&trackinfo);
-
- /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
- if(!(trackinfo.dwFlags & TME_LEAVE)) {
- trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
-
- /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
- /* and can properly deactivate the hot button */
- _TrackMouseEvent(&trackinfo);
- }
-}
-
-
/* << PAGER_GetDropTarget >> */
static inline LRESULT
@@ -425,95 +428,60 @@ PAGER_GetScrollRange(HWND hwnd, PAGER_IN
}
static void
-PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
- BOOL* needsResize, BOOL* needsRepaint)
+PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
+ INT scrollRange, BOOL hideGrayBtns)
{
+ BOOL resizeClient;
+ BOOL repaintBtns;
+ INT oldTLbtnState = infoPtr->TLbtnState;
+ INT oldBRbtnState = infoPtr->BRbtnState;
+ POINT pt;
+ RECT rcTopLeft, rcBottomRight;
+
+ /* get button rects */
+ PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, FALSE);
+
+ GetCursorPos(&pt);
+
+ /* update states based on scroll position */
if (infoPtr->nPos > 0)
{
- *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
- if (infoPtr->TLbtnState != PGF_DEPRESSED)
+ if (infoPtr->TLbtnState == PGF_INVISIBLE || infoPtr->TLbtnState == PGF_GRAYED)
infoPtr->TLbtnState = PGF_NORMAL;
}
- else
- {
- *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
+ else if (PtInRect(&rcTopLeft, pt))
infoPtr->TLbtnState = PGF_GRAYED;
- }
+ else
+ infoPtr->TLbtnState = PGF_INVISIBLE;
if (scrollRange <= 0)
{
- *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
- infoPtr->TLbtnState = PGF_GRAYED;
- *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
- infoPtr->BRbtnState = PGF_GRAYED;
+ infoPtr->TLbtnState = PGF_INVISIBLE;
+ infoPtr->BRbtnState = PGF_INVISIBLE;
}
else if (infoPtr->nPos < scrollRange)
{
- *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
- if (infoPtr->BRbtnState != PGF_DEPRESSED)
+ if (infoPtr->BRbtnState == PGF_INVISIBLE || infoPtr->BRbtnState == PGF_GRAYED)
infoPtr->BRbtnState = PGF_NORMAL;
}
- else
- {
- *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
+ else if (PtInRect(&rcBottomRight, pt))
infoPtr->BRbtnState = PGF_GRAYED;
- }
-}
-
-
-static void
-PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
-{
- if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
- {
- infoPtr->TLbtnState = PGF_NORMAL;
- *needsRepaint = TRUE;
- }
-
- if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
- {
- infoPtr->BRbtnState = PGF_NORMAL;
- *needsRepaint = TRUE;
- }
-}
-
-static void
-PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
-{
- if (infoPtr->TLbtnState == PGF_GRAYED)
- {
- infoPtr->TLbtnState = PGF_INVISIBLE;
- *needsResize = TRUE;
- }
-
- if (infoPtr->BRbtnState == PGF_GRAYED)
- {
- infoPtr->BRbtnState = PGF_INVISIBLE;
- *needsResize = TRUE;
- }
-}
-
-static void
-PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
- INT scrollRange, BOOL hideGrayBtns)
-{
- BOOL resizeClient = FALSE;
- BOOL repaintBtns = FALSE;
-
- if (scrollRange < 0)
- PAGER_NormalizeBtns(infoPtr, &repaintBtns);
else
- PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
-
- if (hideGrayBtns)
- PAGER_HideGrayBtns(infoPtr, &resizeClient);
+ infoPtr->BRbtnState = PGF_INVISIBLE;
- if (resizeClient) /* initiate NCCalcSize to resize client wnd */ {
+ /* only need to resize when entering or leaving PGF_INVISIBLE state */
+ resizeClient =
+ ((oldTLbtnState == PGF_INVISIBLE) != (infoPtr->TLbtnState == PGF_INVISIBLE)) ||
+ ((oldBRbtnState == PGF_INVISIBLE) != (infoPtr->BRbtnState == PGF_INVISIBLE));
+ /* initiate NCCalcSize to resize client wnd if necessary */
+ if (resizeClient)
SetWindowPos(hwnd, 0,0,0,0,0,
SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
SWP_NOZORDER | SWP_NOACTIVATE);
- }
+ /* repaint when changing any state */
+ repaintBtns = (oldTLbtnState != infoPtr->TLbtnState) ||
+ (oldBRbtnState != infoPtr->BRbtnState);
if (repaintBtns)
SendMessageW(hwnd, WM_NCPAINT, 0, 0);
}
@@ -667,10 +635,7 @@ PAGER_RecalcSize(HWND hwnd)
PAGER_SetPos(hwnd, 0, FALSE);
}
else
- {
- PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
PAGER_PositionChildWnd(hwnd, infoPtr);
- }
}
return 1;
@@ -891,10 +856,7 @@ PAGER_NCCalcSize(HWND hwnd, WPARAM wPara
{
PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
LPRECT lpRect = (LPRECT)lParam;
- RECT rcChildw, rcmyw, wnrc, ltrc, rbrc;
- POINT cursor;
- BOOL resizeClient = FALSE;
- BOOL repaintBtns = FALSE;
+ RECT rcChild, rcWindow;
INT scrollRange;
/*
@@ -906,43 +868,19 @@ PAGER_NCCalcSize(HWND hwnd, WPARAM wPara
DefWindowProcW (hwnd, WM_NCCALCSIZE, wParam, lParam);
- TRACE("orig rect=(%ld,%ld)-(%ld,%ld)\n",
- lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+ TRACE("orig rect=%s\n", wine_dbgstr_rect(lpRect));
+
+ GetWindowRect (infoPtr->hwndChild, &rcChild);
+ MapWindowPoints (0, hwnd, (LPPOINT)&rcChild, 2); /* FIXME: RECT != 2 POINTS */
+ GetWindowRect (hwnd, &rcWindow);
if (PAGER_IsHorizontal(hwnd))
{
infoPtr->nWidth = lpRect->right - lpRect->left;
PAGER_CalcSize (hwnd, &infoPtr->nWidth, TRUE);
- GetWindowRect (infoPtr->hwndChild, &rcChildw);
- MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
- GetCursorPos (&cursor);
- GetWindowRect (hwnd, &rcmyw);
-
- /* Reset buttons and hide any grey ones */
- scrollRange = infoPtr->nWidth - (rcmyw.right - rcmyw.left);
-
- TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
- infoPtr->nPos, scrollRange, infoPtr->nHeight,
- rcmyw.left, rcmyw.top,
- rcmyw.right, rcmyw.bottom,
- cursor.x, cursor.y);
- PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
- PAGER_HideGrayBtns(infoPtr, &resizeClient);
-
- if (PtInRect (&rcmyw, cursor)) {
- GetWindowRect (hwnd, &wnrc);
- ltrc = wnrc;
- ltrc.right = ltrc.left + infoPtr->nButtonSize;
- rbrc = wnrc;
- rbrc.left = rbrc.right - infoPtr->nButtonSize;
- TRACE("horz lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
- ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
- rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
- if (PtInRect (<rc, cursor) && infoPtr->TLbtnState)
- RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
- if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
- RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
- }
+
+ scrollRange = infoPtr->nWidth - (rcWindow.right - rcWindow.left);
+
if (infoPtr->TLbtnState && (lpRect->left + infoPtr->nButtonSize < lpRect->right))
lpRect->left += infoPtr->nButtonSize;
if (infoPtr->BRbtnState && (lpRect->right - infoPtr->nButtonSize > lpRect->left))
@@ -950,65 +888,21 @@ PAGER_NCCalcSize(HWND hwnd, WPARAM wPara
}
else
{
- /* native does: (from trace of IE4 opening "Favorites" frame)
- * DefWindowProc
- * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
- * GetWindowRect (child, &rc)
- * MapWindowPoints (0, syspager, &rc, 2)
- * GetCursorPos( &cur )
- * GetWindowRect (syspager, &rc2)
- * PtInRect (&rc2, cur.x, cur.y) rtns 0
- * returns with rect empty
- */
infoPtr->nHeight = lpRect->bottom - lpRect->top;
PAGER_CalcSize (hwnd, &infoPtr->nHeight, FALSE);
- GetWindowRect (infoPtr->hwndChild, &rcChildw);
- MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
- GetCursorPos (&cursor);
- GetWindowRect (hwnd, &rcmyw);
-
- /* Reset buttons and hide any grey ones */
- scrollRange = infoPtr->nHeight - (rcmyw.bottom - rcmyw.top);
-
- TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
- infoPtr->nPos, scrollRange, infoPtr->nHeight,
- rcmyw.left, rcmyw.top,
- rcmyw.right, rcmyw.bottom,
- cursor.x, cursor.y);
- PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
- PAGER_HideGrayBtns(infoPtr, &resizeClient);
-
- if (PtInRect (&rcmyw, cursor)) {
-
- /* native does:
- * GetWindowRect(pager, &rc)
- * PtInRect(btn-left????, cur.x, cur.y)
- * if true -> ???
- * PtInRect(btn-right????, cur.x, cur.y)
- * if true
- * RedrawWindow(pager, 0, 0, 5)
- * return TRUE
- */
-
- GetWindowRect (hwnd, &wnrc);
- ltrc = wnrc;
- ltrc.right = ltrc.left + infoPtr->nButtonSize;
- rbrc = wnrc;
- rbrc.left = rbrc.right - infoPtr->nButtonSize;
- TRACE("vert lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
- ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
- rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
- if (PtInRect (<rc, cursor) && infoPtr->TLbtnState)
- RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
- if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
- RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
- }
+
+ scrollRange = infoPtr->nHeight - (rcWindow.bottom - rcWindow.top);
+
if (infoPtr->TLbtnState && (lpRect->top + infoPtr->nButtonSize < lpRect->bottom))
lpRect->top += infoPtr->nButtonSize;
if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top))
lpRect->bottom -= infoPtr->nButtonSize;
}
+ TRACE("nPos=%d, nHeigth=%d, window=%s\n",
+ infoPtr->nPos, infoPtr->nHeight,
+ wine_dbgstr_rect(&rcWindow));
+
TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n",
hwnd, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top,
lpRect->left, lpRect->top,
@@ -1022,7 +916,7 @@ PAGER_NCPaint (HWND hwnd, WPARAM wParam,
{
PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
- RECT rcWindow, rcBottomRight, rcTopLeft;
+ RECT rcBottomRight, rcTopLeft;
HDC hdc;
BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
@@ -1034,20 +928,7 @@ PAGER_NCPaint (HWND hwnd, WPARAM wParam,
if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
return 0;
- GetWindowRect (hwnd, &rcWindow);
- OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
-
- rcTopLeft = rcBottomRight = rcWindow;
- if (bHorizontal)
- {
- rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
- rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
- }
- else
- {
- rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
- rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
- }
+ PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, FALSE);
PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
bHorizontal, TRUE, infoPtr->TLbtnState);
@@ -1059,135 +940,52 @@ PAGER_NCPaint (HWND hwnd, WPARAM wParam,
}
static INT
-PAGER_HitTest (HWND hwnd, LPPOINT pt)
+PAGER_HitTest (HWND hwnd, const POINT * pt)
{
PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
- RECT clientRect;
- BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
+ RECT clientRect, rcTopLeft, rcBottomRight;
+ POINT ptWindow;
GetClientRect (hwnd, &clientRect);
if (PtInRect(&clientRect, *pt))
{
- TRACE("HTCLIENT\n");
- return HTCLIENT;
+ TRACE("child\n");
+ return -1;
}
- if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
+ ptWindow = *pt;
+ PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, TRUE);
+
+ if ((infoPtr->TLbtnState != PGF_INVISIBLE) && PtInRect(&rcTopLeft, ptWindow))
{
- if (bHorizontal)
- {
- if (pt->x < clientRect.left)
- {
- TRACE("HTLEFT\n");
- return HTLEFT;
- }
- }
- else
- {
- if (pt->y < clientRect.top)
- {
- TRACE("HTTOP\n");
- return HTTOP;
- }
- }
+ TRACE("PGB_TOPORLEFT\n");
+ return PGB_TOPORLEFT;
}
-
- if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
+ else if ((infoPtr->BRbtnState != PGF_INVISIBLE) && PtInRect(&rcBottomRight, ptWindow))
{
- if (bHorizontal)
- {
- if (pt->x > clientRect.right)
- {
- TRACE("HTRIGHT\n");
- return HTRIGHT;
- }
- }
- else
- {
- if (pt->y > clientRect.bottom)
- {
- TRACE("HTBOTTOM\n");
- return HTBOTTOM;
- }
- }
+ TRACE("PGB_BOTTOMORRIGHT\n");
+ return PGB_BOTTOMORRIGHT;
}
- TRACE("HTNOWHERE\n");
- return HTNOWHERE;
+ TRACE("nowhere\n");
+ return -1;
}
static LRESULT
PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
POINT pt;
+ INT nHit;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
ScreenToClient (hwnd, &pt);
- return PAGER_HitTest(hwnd, &pt);
-}
-
-static LRESULT
-PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
-{
- PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
- BOOL notCaptured = FALSE;
-
- switch(LOWORD(lParam))
- {
- case HTLEFT:
- case HTTOP:
- if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
- infoPtr->TLbtnState = PGF_HOT;
- break;
- case HTRIGHT:
- case HTBOTTOM:
- if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
- infoPtr->BRbtnState = PGF_HOT;
- break;
- default:
- return FALSE;
- }
-
- if (notCaptured)
- {
- PAGER_CaptureandTrack(infoPtr, hwnd);
-
- SendMessageW(hwnd, WM_NCPAINT, 0, 0);
- }
-
- return TRUE;
-}
-
-static LRESULT
-PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
- PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-
- KillTimer (hwnd, TIMERID1);
- KillTimer (hwnd, TIMERID2);
-
- TRACE("[%p] ReleaseCapture\n", hwnd);
- ReleaseCapture();
- infoPtr->bCapture = FALSE;
-
- /* Notify parent of released mouse capture */
- {
- NMHDR nmhdr;
- ZeroMemory (&nmhdr, sizeof (NMHDR));
- nmhdr.hwndFrom = hwnd;
- nmhdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID);
- nmhdr.code = NM_RELEASEDCAPTURE;
- SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
- (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
- }
-
- /* make HOT btns NORMAL and hide gray btns */
- PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
-
- return TRUE;
+ nHit = PAGER_HitTest(hwnd, &pt);
+ if (nHit < 0)
+ return HTTRANSPARENT;
+ return HTCLIENT;
}
static LRESULT
@@ -1195,7 +993,7 @@ PAGER_MouseMove (HWND hwnd, WPARAM wPara
{
PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
POINT clpt, pt;
- RECT wnrect, TLbtnrect, BRbtnrect, *btnrect = NULL;
+ RECT wnrect, *btnrect = NULL;
DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
BOOL topLeft = FALSE;
INT btnstate = 0;
@@ -1209,75 +1007,103 @@ PAGER_MouseMove (HWND hwnd, WPARAM wPara
ClientToScreen(hwnd, &pt);
GetWindowRect(hwnd, &wnrect);
if (PtInRect(&wnrect, pt)) {
- TLbtnrect = wnrect;
- BRbtnrect = wnrect;
- if (dwStyle & PGS_HORZ) {
- TLbtnrect.right = TLbtnrect.left + infoPtr->nButtonSize;
- BRbtnrect.left = BRbtnrect.right - infoPtr->nButtonSize;
- }
- else {
- TLbtnrect.bottom = TLbtnrect.top + infoPtr->nButtonSize;
- BRbtnrect.top = BRbtnrect.bottom - infoPtr->nButtonSize;
- }
+ RECT TLbtnrect, BRbtnrect;
+ PAGER_GetButtonRects(hwnd, infoPtr, &TLbtnrect, &BRbtnrect, FALSE);
clpt = pt;
MapWindowPoints(0, hwnd, &clpt, 1);
hit = PAGER_HitTest(hwnd, &clpt);
- if (hit == HTLEFT || hit == HTTOP) {
+ if ((hit == PGB_TOPORLEFT) && (infoPtr->TLbtnState == PGF_NORMAL))
+ {
topLeft = TRUE;
btnrect = &TLbtnrect;
- infoPtr->TLbtnState = PGF_DEPRESSED;
+ infoPtr->TLbtnState = PGF_HOT;
btnstate = infoPtr->TLbtnState;
}
- else if (hit == HTRIGHT || hit == HTBOTTOM) {
+ else if ((hit == PGB_BOTTOMORRIGHT) && (infoPtr->BRbtnState == PGF_NORMAL))
+ {
topLeft = FALSE;
btnrect = &BRbtnrect;
- infoPtr->BRbtnState = PGF_DEPRESSED;
+ infoPtr->BRbtnState = PGF_HOT;
btnstate = infoPtr->BRbtnState;
}
/* If in one of the buttons the capture and draw buttons */
- if (btnrect) {
+ if (btnrect)
+ {
TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n",
hwnd, btnrect->left, btnrect->top,
btnrect->right, btnrect->bottom,
(infoPtr->bCapture) ? "TRUE" : "FALSE",
dwStyle);
if (!infoPtr->bCapture)
- PAGER_CaptureandTrack(infoPtr, hwnd);
+ {
+ TRACE("[%p] SetCapture\n", hwnd);
+ SetCapture(hwnd);
+ infoPtr->bCapture = TRUE;
+ }
if (dwStyle & PGS_AUTOSCROLL)
SetTimer(hwnd, TIMERID1, 0x3e, 0);
- MapWindowPoints(0, hwnd, (LPPOINT)btnrect, 2);
hdc = GetWindowDC(hwnd);
/* OffsetRect(wnrect, 0 | 1, 0 | 1) */
PAGER_DrawButton(hdc, infoPtr->clrBk, *btnrect,
PAGER_IsHorizontal(hwnd), topLeft, btnstate);
ReleaseDC(hwnd, hdc);
- return DefWindowProcW (hwnd, WM_MOUSEMOVE, wParam, lParam);
+ return 0;
}
}
/* If we think we are captured, then do release */
- if (infoPtr->bCapture) {
- infoPtr->bCapture = FALSE;
+ if (infoPtr->bCapture && (WindowFromPoint(pt) != hwnd))
+ {
+ NMHDR nmhdr;
- if (GetCapture() == hwnd) {
- ReleaseCapture();
- /* Notify parent of released mouse capture */
- {
- NMHDR nmhdr;
- ZeroMemory (&nmhdr, sizeof (NMHDR));
- nmhdr.hwndFrom = hwnd;
- nmhdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID);
- nmhdr.code = NM_RELEASEDCAPTURE;
- SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
- (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
- }
- }
- if (IsWindow(hwnd))
- KillTimer(hwnd, TIMERID1);
+ infoPtr->bCapture = FALSE;
+
+ if (GetCapture() == hwnd)
+ {
+ ReleaseCapture();
+
+ if (infoPtr->TLbtnState == PGF_GRAYED)
+ {
+ infoPtr->TLbtnState = PGF_INVISIBLE;
+ SetWindowPos(hwnd, 0,0,0,0,0,
+ SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ else if (infoPtr->TLbtnState == PGF_HOT)
+ {
+ infoPtr->TLbtnState = PGF_NORMAL;
+ /* FIXME: just invalidate button rect */
+ RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
+ }
+
+ if (infoPtr->BRbtnState == PGF_GRAYED)
+ {
+ infoPtr->BRbtnState = PGF_INVISIBLE;
+ SetWindowPos(hwnd, 0,0,0,0,0,
+ SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ else if (infoPtr->BRbtnState == PGF_HOT)
+ {
+ infoPtr->BRbtnState = PGF_NORMAL;
+ /* FIXME: just invalidate button rect */
+ RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
+ }
+
+ /* Notify parent of released mouse capture */
+ memset(&nmhdr, 0, sizeof(NMHDR));
+ nmhdr.hwndFrom = hwnd;
+ nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
+ nmhdr.code = NM_RELEASEDCAPTURE;
+ SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
+ (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+ }
+ if (IsWindow(hwnd))
+ KillTimer(hwnd, TIMERID1);
}
- return DefWindowProcW (hwnd, WM_MOUSEMOVE, wParam, lParam);
+ return 0;
}
static LRESULT
@@ -1296,13 +1122,13 @@ PAGER_LButtonDown (HWND hwnd, WPARAM wPa
hit = PAGER_HitTest(hwnd, &pt);
/* put btn in DEPRESSED state */
- if (hit == HTLEFT || hit == HTTOP)
+ if (hit == PGB_TOPORLEFT)
{
repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
infoPtr->TLbtnState = PGF_DEPRESSED;
SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
}
- else if (hit == HTRIGHT || hit == HTBOTTOM)
+ else if (hit == PGB_BOTTOMORRIGHT)
{
repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
infoPtr->BRbtnState = PGF_DEPRESSED;
@@ -1314,21 +1140,29 @@ PAGER_LButtonDown (HWND hwnd, WPARAM wPa
switch(hit)
{
- case HTLEFT:
- TRACE("[%p] PGF_SCROLLLEFT\n", hwnd);
- PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
- break;
- case HTTOP:
- TRACE("[%p] PGF_SCROLLUP\n", hwnd);
- PAGER_Scroll(hwnd, PGF_SCROLLUP);
- break;
- case HTRIGHT:
- TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd);
- PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
+ case PGB_TOPORLEFT:
+ if (PAGER_IsHorizontal(hwnd))
+ {
+ TRACE("[%p] PGF_SCROLLLEFT\n", hwnd);
+ PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
+ }
+ else
+ {
+ TRACE("[%p] PGF_SCROLLUP\n", hwnd);
+ PAGER_Scroll(hwnd, PGF_SCROLLUP);
+ }
break;
- case HTBOTTOM:
- TRACE("[%p] PGF_SCROLLDOWN\n", hwnd);
- PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
+ case PGB_BOTTOMORRIGHT:
+ if (PAGER_IsHorizontal(hwnd))
+ {
+ TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd);
+ PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
+ }
+ else
+ {
+ TRACE("[%p] PGF_SCROLLDOWN\n", hwnd);
+ PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
+ }
break;
default:
break;
@@ -1347,26 +1181,15 @@ PAGER_LButtonUp (HWND hwnd, WPARAM wPara
KillTimer (hwnd, TIMERID2);
/* make PRESSED btns NORMAL but don't hide gray btns */
- PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
+ if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
+ infoPtr->TLbtnState = PGF_NORMAL;
+ if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
+ infoPtr->BRbtnState = PGF_NORMAL;
return 0;
}
static LRESULT
-PAGER_NCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
- POINT pt;
-
- pt.x = (short)LOWORD(lParam);
- pt.y = (short)HIWORD(lParam);
-
- TRACE("[%p] at (%ld,%ld)\n", hwnd, pt.x, pt.y );
- MapWindowPoints(0, hwnd, &pt, 1);
- lParam = MAKELONG(pt.x, pt.y);
- return PAGER_LButtonDown (hwnd, wParam, lParam);
-}
-
-static LRESULT
PAGER_Timer (HWND hwnd, WPARAM wParam)
{
PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
@@ -1375,14 +1198,12 @@ PAGER_Timer (HWND hwnd, WPARAM wParam)
/* if initial timer, kill it and start the repeat timer */
if (wParam == TIMERID1) {
- if (PAGER_IsHorizontal(hwnd)) {
- dir = (infoPtr->TLbtnState & PGF_DEPRESSED) ?
- PGF_SCROLLLEFT : PGF_SCROLLRIGHT;
- }
- else {
- dir = (infoPtr->TLbtnState & PGF_DEPRESSED) ?
- PGF_SCROLLUP : PGF_SCROLLDOWN;
- }
+ if (infoPtr->TLbtnState == PGF_HOT)
+ dir = PAGER_IsHorizontal(hwnd) ?
+ PGF_SCROLLLEFT : PGF_SCROLLUP;
+ else
+ dir = PAGER_IsHorizontal(hwnd) ?
+ PGF_SCROLLRIGHT : PGF_SCROLLDOWN;
TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n", hwnd, dwStyle, dir);
KillTimer(hwnd, TIMERID1);
SetTimer(hwnd, TIMERID1, REPEAT_DELAY, 0);
@@ -1412,15 +1233,6 @@ PAGER_EraseBackground (HWND hwnd, WPARAM
HDC hdc = (HDC)wParam;
HWND parent;
- /* native does:
- * parent = GetParent(pager)
- * pt.x=0; pt.y=0; ?????
- * MapWindowPoints(pager, parent, &pt, 1)
- * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
- * SendMessageW(parent, WM_ERASEBKGND, hdc, 0)
- * SetWindowOrgEx(hdc, 0, 0, 0)
- */
-
pt.x = 0;
pt.y = 0;
parent = GetParent(hwnd);
@@ -1429,25 +1241,6 @@ PAGER_EraseBackground (HWND hwnd, WPARAM
SendMessageW (parent, WM_ERASEBKGND, wParam, lParam);
SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
-
-#if 0
- PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
- HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
- RECT rect;
-
- GetClientRect (hwnd, &rect);
- FillRect ((HDC)wParam, &rect, hBrush);
-
- /* background color of the child should be the same as the pager */
- if (infoPtr->hwndChild)
- {
- GetClientRect (infoPtr->hwndChild, &rect);
- FillRect ((HDC)wParam, &rect, hBrush);
- }
-
- DeleteObject (hBrush);
-#endif
-
return TRUE;
}
@@ -1541,40 +1334,22 @@ PAGER_WindowProc (HWND hwnd, UINT uMsg,
case WM_NCHITTEST:
return PAGER_NCHitTest (hwnd, wParam, lParam);
- case WM_SETCURSOR:
- {
- if (hwnd == (HWND)wParam)
- return PAGER_SetCursor(hwnd, wParam, lParam);
- else /* its for the child */
- return 0;
- }
-
case WM_MOUSEMOVE:
if (infoPtr->bForward && infoPtr->hwndChild)
PostMessageW(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
return PAGER_MouseMove (hwnd, wParam, lParam);
- case WM_MOUSELEAVE:
- return PAGER_MouseLeave (hwnd, wParam, lParam);
-
- case WM_NCLBUTTONDOWN:
- return PAGER_NCLButtonDown (hwnd, wParam, lParam);
-
case WM_LBUTTONDOWN:
return PAGER_LButtonDown (hwnd, wParam, lParam);
- case WM_NCLBUTTONUP:
case WM_LBUTTONUP:
return PAGER_LButtonUp (hwnd, wParam, lParam);
case WM_ERASEBKGND:
return PAGER_EraseBackground (hwnd, wParam, lParam);
-/*
- case WM_PAINT:
- return PAGER_Paint (hwnd, wParam);
-*/
+
case WM_TIMER:
- return PAGER_Timer (hwnd, wParam);
+ return PAGER_Timer (hwnd, wParam);
case WM_NOTIFY:
case WM_COMMAND:
More information about the wine-patches
mailing list