* Robert Shearman <rob@codeweavers.com>
*/
-#include <stdarg.h>
-#include <string.h>
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winnls.h"
-#include "commctrl.h"
#include "comctl32.h"
-#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(pager);
INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
} PAGER_INFO;
-#define MIN_ARROW_WIDTH 8
-#define MIN_ARROW_HEIGHT 5
-
#define TIMERID1 1
#define TIMERID2 2
#define INITIAL_DELAY 500
GetWindowRect (infoPtr->hwndSelf, &rcWindow);
if (bClientCoords)
- {
- POINT pt = {rcWindow.left, rcWindow.top};
- ScreenToClient(infoPtr->hwndSelf, &pt);
- OffsetRect(&rcWindow, -(rcWindow.left-pt.x), -(rcWindow.top-pt.y));
- }
+ MapWindowPoints( 0, infoPtr->hwndSelf, (POINT *)&rcWindow, 2 );
else
OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
}
}
-/* the horizontal arrows are:
- *
- * 01234 01234
- * 1 * *
- * 2 ** **
- * 3*** ***
- * 4*** ***
- * 5 ** **
- * 6 * *
- * 7
- *
- */
-static void
-PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
-{
- INT x, y, w, h;
- HPEN hPen, hOldPen;
-
- w = r.right - r.left + 1;
- h = r.bottom - r.top + 1;
- if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
- return; /* refuse to draw partial arrow */
-
- if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
- hOldPen = SelectObject ( hdc, hPen );
- if (left)
- {
- x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
- y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x--, y+5); y++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x--, y+3); y++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x, y+1);
- }
- else
- {
- x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
- y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x++, y+5); y++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x++, y+3); y++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x, y+1);
- }
-
- SelectObject( hdc, hOldPen );
- DeleteObject( hPen );
-}
-
-/* the vertical arrows are:
- *
- * 01234567 01234567
- * 1****** **
- * 2 **** ****
- * 3 ** ******
- * 4
- *
- */
-static void
-PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
-{
- INT x, y, w, h;
- HPEN hPen, hOldPen;
-
- w = r.right - r.left + 1;
- h = r.bottom - r.top + 1;
- if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
- return; /* refuse to draw partial arrow */
-
- if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
- hOldPen = SelectObject ( hdc, hPen );
- if (up)
- {
- x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
- y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+5, y--); x++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+3, y--); x++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+1, y);
- }
- else
- {
- x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
- y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+5, y++); x++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+3, y++); x++;
- MoveToEx (hdc, x, y, NULL);
- LineTo (hdc, x+1, y);
- }
-
- SelectObject( hdc, hOldPen );
- DeleteObject( hPen );
-}
-
static void
-PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
+PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT rc,
BOOL horz, BOOL topLeft, INT btnState)
{
- HBRUSH hBrush, hOldBrush;
- RECT rc = arrowRect;
+ UINT flags;
- TRACE("arrowRect = %s, btnState = %d\n", wine_dbgstr_rect(&arrowRect), btnState);
+ TRACE("rc = %s, btnState = %d\n", wine_dbgstr_rect(&rc), btnState);
if (btnState == PGF_INVISIBLE)
return;
if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
return;
- hBrush = CreateSolidBrush(clrBk);
- hOldBrush = SelectObject(hdc, hBrush);
-
- FillRect(hdc, &rc, hBrush);
+ if (horz)
+ flags = topLeft ? DFCS_SCROLLLEFT : DFCS_SCROLLRIGHT;
+ else
+ flags = topLeft ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
- if (btnState == PGF_HOT)
- {
- DrawEdge( hdc, &rc, BDR_RAISEDINNER, BF_RECT);
- if (horz)
- PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- else
- PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- }
- else if (btnState == PGF_NORMAL)
+ switch (btnState)
{
- DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
- if (horz)
- PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- else
- PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- }
- else if (btnState == PGF_DEPRESSED)
- {
- DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
- if (horz)
- PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- else
- PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
- }
- else if (btnState == PGF_GRAYED)
- {
- DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
- if (horz)
- {
- PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
- rc.left++, rc.top++; rc.right++, rc.bottom++;
- PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
- }
- else
- {
- PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
- rc.left++, rc.top++; rc.right++, rc.bottom++;
- PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
- }
+ case PGF_HOT:
+ break;
+ case PGF_NORMAL:
+ flags |= DFCS_FLAT;
+ break;
+ case PGF_DEPRESSED:
+ flags |= DFCS_PUSHED;
+ break;
+ case PGF_GRAYED:
+ flags |= DFCS_INACTIVE | DFCS_FLAT;
+ break;
}
-
- SelectObject( hdc, hOldBrush );
- DeleteObject(hBrush);
+ DrawFrameControl( hdc, &rc, DFC_SCROLL, flags );
}
/* << PAGER_GetDropTarget >> */
}
static void
-PAGER_CalcSize (const PAGER_INFO *infoPtr, INT* size, BOOL getWidth)
+PAGER_CalcSize( PAGER_INFO *infoPtr )
{
NMPGCALCSIZE nmpgcs;
ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
nmpgcs.hdr.hwndFrom = infoPtr->hwndSelf;
nmpgcs.hdr.idFrom = GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_ID);
nmpgcs.hdr.code = PGN_CALCSIZE;
- nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
- nmpgcs.iWidth = getWidth ? *size : 0;
- nmpgcs.iHeight = getWidth ? 0 : *size;
+ nmpgcs.dwFlag = (infoPtr->dwStyle & PGS_HORZ) ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
+ nmpgcs.iWidth = infoPtr->nWidth;
+ nmpgcs.iHeight = infoPtr->nHeight;
SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
- *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
+ if (infoPtr->dwStyle & PGS_HORZ)
+ infoPtr->nWidth = nmpgcs.iWidth;
+ else
+ infoPtr->nHeight = nmpgcs.iHeight;
- TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", infoPtr->hwndSelf,
- getWidth ? "width" : "height", *size);
+ TRACE("[%p] PGN_CALCSIZE returns %dx%d\n", infoPtr->hwndSelf, nmpgcs.iWidth, nmpgcs.iHeight );
}
static void
RECT wndRect;
GetWindowRect(infoPtr->hwndSelf, &wndRect);
+ PAGER_CalcSize(infoPtr);
if (infoPtr->dwStyle & PGS_HORZ)
{
wndSize = wndRect.right - wndRect.left;
- PAGER_CalcSize(infoPtr, &infoPtr->nWidth, TRUE);
childSize = infoPtr->nWidth;
}
else
{
wndSize = wndRect.bottom - wndRect.top;
- PAGER_CalcSize(infoPtr, &infoPtr->nHeight, FALSE);
childSize = infoPtr->nHeight;
}
RECT rcTopLeft, rcBottomRight;
/* get button rects */
- PAGER_GetButtonRects(infoPtr, &rcTopLeft, &rcBottomRight, FALSE);
+ PAGER_GetButtonRects(infoPtr, &rcTopLeft, &rcBottomRight, TRUE);
GetCursorPos(&pt);
+ ScreenToClient( infoPtr->hwndSelf, &pt );
/* update states based on scroll position */
if (infoPtr->nPos > 0)
if (infoPtr->TLbtnState == PGF_INVISIBLE || infoPtr->TLbtnState == PGF_GRAYED)
infoPtr->TLbtnState = PGF_NORMAL;
}
- else if (PtInRect(&rcTopLeft, pt))
+ else if (!hideGrayBtns && PtInRect(&rcTopLeft, pt))
infoPtr->TLbtnState = PGF_GRAYED;
else
infoPtr->TLbtnState = PGF_INVISIBLE;
if (infoPtr->BRbtnState == PGF_INVISIBLE || infoPtr->BRbtnState == PGF_GRAYED)
infoPtr->BRbtnState = PGF_NORMAL;
}
- else if (PtInRect(&rcBottomRight, pt))
+ else if (!hideGrayBtns && PtInRect(&rcBottomRight, pt))
infoPtr->BRbtnState = PGF_GRAYED;
else
infoPtr->BRbtnState = PGF_INVISIBLE;
return DefWindowProcW (infoPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos);
}
-static INT
-PAGER_SetFixedWidth(PAGER_INFO* infoPtr)
-{
- /* Must set the non-scrollable dimension to be less than the full height/width
- * so that NCCalcSize is called. The Microsoft docs mention 3/4 factor for button
- * size, and experimentation shows that the effect is almost right. */
-
- RECT wndRect;
- INT delta, h;
- GetWindowRect(infoPtr->hwndSelf, &wndRect);
-
- /* see what the app says for btn width */
- PAGER_CalcSize(infoPtr, &infoPtr->nWidth, TRUE);
-
- if (infoPtr->dwStyle & CCS_NORESIZE)
- {
- delta = wndRect.right - wndRect.left - infoPtr->nWidth;
- if (delta > infoPtr->nButtonSize)
- infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
- else if (delta > 0)
- infoPtr->nWidth += infoPtr->nButtonSize / 3;
- }
-
- h = wndRect.bottom - wndRect.top + infoPtr->nButtonSize;
-
- TRACE("[%p] infoPtr->nWidth set to %d\n",
- infoPtr->hwndSelf, infoPtr->nWidth);
-
- return h;
-}
-
-static INT
-PAGER_SetFixedHeight(PAGER_INFO* infoPtr)
-{
- /* Must set the non-scrollable dimension to be less than the full height/width
- * so that NCCalcSize is called. The Microsoft docs mention 3/4 factor for button
- * size, and experimentation shows that the effect is almost right. */
-
- RECT wndRect;
- INT delta, w;
- GetWindowRect(infoPtr->hwndSelf, &wndRect);
-
- /* see what the app says for btn height */
- PAGER_CalcSize(infoPtr, &infoPtr->nHeight, FALSE);
-
- if (infoPtr->dwStyle & CCS_NORESIZE)
- {
- delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
- if (delta > infoPtr->nButtonSize)
- infoPtr->nHeight += infoPtr->nButtonSize;
- else if (delta > 0)
- infoPtr->nHeight += infoPtr->nButtonSize / 3;
- }
-
- w = wndRect.right - wndRect.left + infoPtr->nButtonSize;
-
- TRACE("[%p] infoPtr->nHeight set to %d\n",
- infoPtr->hwndSelf, infoPtr->nHeight);
-
- return w;
-}
-
/******************************************************************
* For the PGM_RECALCSIZE message (but not the other uses in *
* this module), the native control does only the following: *
static LRESULT
PAGER_SetChild (PAGER_INFO* infoPtr, HWND hwndChild)
{
- INT hw;
-
infoPtr->hwndChild = IsWindow (hwndChild) ? hwndChild : 0;
if (infoPtr->hwndChild)
{
TRACE("[%p] hwndChild=%p\n", infoPtr->hwndSelf, infoPtr->hwndChild);
- if (infoPtr->dwStyle & PGS_HORZ) {
- hw = PAGER_SetFixedHeight(infoPtr);
- /* adjust non-scrollable dimension to fit the child */
- SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, hw, infoPtr->nHeight,
- SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
- SWP_NOSIZE | SWP_NOACTIVATE);
- }
- else {
- hw = PAGER_SetFixedWidth(infoPtr);
- /* adjust non-scrollable dimension to fit the child */
- SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, infoPtr->nWidth, hw,
- SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
- SWP_NOSIZE | SWP_NOACTIVATE);
- }
+ SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
/* position child within the page scroller */
SetWindowPos(infoPtr->hwndChild, HWND_TOP,
MapWindowPoints (0, infoPtr->hwndSelf, (LPPOINT)&rcChild, 2); /* FIXME: RECT != 2 POINTS */
GetWindowRect (infoPtr->hwndSelf, &rcWindow);
+ infoPtr->nWidth = lpRect->right - lpRect->left;
+ infoPtr->nHeight = lpRect->bottom - lpRect->top;
+ PAGER_CalcSize( infoPtr );
+
if (infoPtr->dwStyle & PGS_HORZ)
{
- infoPtr->nWidth = lpRect->right - lpRect->left;
- PAGER_CalcSize (infoPtr, &infoPtr->nWidth, TRUE);
-
if (infoPtr->TLbtnState && (lpRect->left + infoPtr->nButtonSize < lpRect->right))
lpRect->left += infoPtr->nButtonSize;
if (infoPtr->BRbtnState && (lpRect->right - infoPtr->nButtonSize > lpRect->left))
}
else
{
- infoPtr->nHeight = lpRect->bottom - lpRect->top;
- PAGER_CalcSize (infoPtr, &infoPtr->nHeight, FALSE);
-
if (infoPtr->TLbtnState && (lpRect->top + infoPtr->nButtonSize < lpRect->bottom))
lpRect->top += infoPtr->nButtonSize;
if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top))
PAGER_MouseMove (PAGER_INFO* infoPtr, INT keys, INT x, INT y)
{
POINT clpt, pt;
- RECT wnrect, *btnrect = NULL;
+ RECT wnrect;
BOOL topLeft = FALSE;
INT btnstate = 0;
INT hit;
ClientToScreen(infoPtr->hwndSelf, &pt);
GetWindowRect(infoPtr->hwndSelf, &wnrect);
if (PtInRect(&wnrect, pt)) {
- RECT TLbtnrect, BRbtnrect;
- PAGER_GetButtonRects(infoPtr, &TLbtnrect, &BRbtnrect, FALSE);
+ RECT topleft, bottomright, *rect = NULL;
+
+ PAGER_GetButtonRects(infoPtr, &topleft, &bottomright, FALSE);
clpt = pt;
MapWindowPoints(0, infoPtr->hwndSelf, &clpt, 1);
if ((hit == PGB_TOPORLEFT) && (infoPtr->TLbtnState == PGF_NORMAL))
{
topLeft = TRUE;
- btnrect = &TLbtnrect;
+ rect = &topleft;
infoPtr->TLbtnState = PGF_HOT;
btnstate = infoPtr->TLbtnState;
}
else if ((hit == PGB_BOTTOMORRIGHT) && (infoPtr->BRbtnState == PGF_NORMAL))
{
topLeft = FALSE;
- btnrect = &BRbtnrect;
+ rect = &bottomright;
infoPtr->BRbtnState = PGF_HOT;
btnstate = infoPtr->BRbtnState;
}
/* If in one of the buttons the capture and draw buttons */
- if (btnrect)
+ if (rect)
{
TRACE("[%p] draw btn (%s), Capture %s, style %08x\n",
- infoPtr->hwndSelf, wine_dbgstr_rect(btnrect),
+ infoPtr->hwndSelf, wine_dbgstr_rect(rect),
(infoPtr->bCapture) ? "TRUE" : "FALSE",
infoPtr->dwStyle);
if (!infoPtr->bCapture)
SetTimer(infoPtr->hwndSelf, TIMERID1, 0x3e, 0);
hdc = GetWindowDC(infoPtr->hwndSelf);
/* OffsetRect(wnrect, 0 | 1, 0 | 1) */
- PAGER_DrawButton(hdc, infoPtr->clrBk, *btnrect,
+ PAGER_DrawButton(hdc, infoPtr->clrBk, *rect,
infoPtr->dwStyle & PGS_HORZ, topLeft, btnstate);
ReleaseDC(infoPtr->hwndSelf, hdc);
return 0;
{
POINT pt, ptorig;
HWND parent;
+ LRESULT ret;
pt.x = 0;
pt.y = 0;
parent = GetParent(infoPtr->hwndSelf);
MapWindowPoints(infoPtr->hwndSelf, parent, &pt, 1);
OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
- SendMessageW (parent, WM_ERASEBKGND, (WPARAM)hdc, 0);
+ ret = SendMessageW (parent, WM_ERASEBKGND, (WPARAM)hdc, 0);
SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
- return 0;
+ return ret;
}