diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp | 3285 |
1 files changed, 3285 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp b/Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp new file mode 100644 index 00000000..64a409b9 --- /dev/null +++ b/Src/Plugins/General/gen_ml/skinnedscrollwnd.cpp @@ -0,0 +1,3285 @@ +// some code taken from (freeware) Cool ScrollBar library by J Brown +#include "./skinnedscrollwnd.h" +#include "main.h" +#include <commctrl.h> +#include <windowsx.h> +#include "../winamp/wa_dlg.h" +#include "api__gen_ml.h" +#include "./colors.h" +#include <tataki/bitmap/bitmap.h> +#include <tataki/bitmap/autobitmap.h> +#include <tataki/canvas/canvas.h> +#include <api/wnd/api_window.h> +#include "./stockobjects.h" + + +/* minimum size of scrollbar before inserted buttons are hidden to make room when the window is sized too small */ +#define MIN_COOLSB_SIZE 24 +/* min size of scrollbar when resizing a button, before the resize is stopped because the scrollbar has gotten too small */ +#define MINSCROLLSIZE 50 +/* a normal scrollbar "snaps" its scroll-thumb back into position if + you move the mouse too far away from the window, whilst you are + dragging the thumb, that is. #undeffing this results in the thumb + never snapping back into position, no matter how far away you move + the mouse */ +#define SNAP_THUMB_BACK +/* distance (in pixels) the mouse must move away from the thumb + during tracking to cause the thumb bar to snap back to its + starting place. Has no effect unless SNAP_THUMB_BACK is defined */ +#define THUMBTRACK_SNAPDIST 128 +// To complement the exisiting SB_HORZ, SB_VERT, SB_BOTH +// scrollbar identifiers +#define COOLSB_NONE (-1) +#define SB_INSBUT (-2) + +// Arrow size defines +#define SYSTEM_METRIC (-1) + + +// general scrollbar styles +// +// use the standard ESB_DISABLE_xxx flags to represent the +// enabled / disabled states. (defined in winuser.h) +// +#define CSBS_THUMBALWAYS 0x0004 +#define CSBS_VISIBLE 0x0008 +#define CSBS_TRACKING 0x0010 +#define CSBS_FLATSB 0x0020 +#define CSBS_BTNVISBEFORE 0x0040 //if the buttons to the left are visible +#define CSBS_BTNVISAFTER 0x0080 //if the buttons to the right are visible +#define CSBS_HOVERING 0x0100 //if the buttons to the right are visible + +//cool scrollbar styles for Flat scrollbars +#define CSBS_NORMAL 0 +#define CSBS_FLAT 1 +#define CSBS_HOTTRACKED 2 + + +// Button mask flags for indicating which members of SCROLLBUT +// to use during a button insertion / modification +#define SBBF_TYPE 0x0001 +#define SBBF_ID 0x0002 +#define SBBF_PLACEMENT 0x0004 +#define SBBF_SIZE 0x0008 +#define SBBF_BITMAP 0x0010 +#define SBBF_ENHMETAFILE 0x0020 +//#define SBBF_OWNERDRAW 0x0040 //unused at present +#define SBBF_CURSOR 0x0080 +#define SBBF_BUTMINMAX 0x0100 +#define SBBF_STATE 0x0200 + +//button styles (states) +#define SBBS_NORMAL 0 +#define SBBS_PUSHED 1 +#define SBBS_CHECKED SBBS_PUSHED + +// scrollbar button types +#define SBBT_PUSHBUTTON 1 //standard push button +#define SBBT_TOGGLEBUTTON 2 //toggle button +#define SBBT_FIXED 3 //fixed button (non-clickable) +#define SBBT_FLAT 4 //blank area (flat, with border) +#define SBBT_BLANK 5 //blank area (flat, no border) +#define SBBT_DARK 6 //dark blank area (flat) +#define SBBT_OWNERDRAW 7 //user draws the button via a WM_NOTIFY + +#define SBBT_MASK 0x1f //mask off low 5 bits + +//button type modifiers +#define SBBM_RECESSED 0x0020 //recessed when clicked (like Word 97) +#define SBBM_LEFTARROW 0x0040 +#define SBBM_RIGHTARROW 0x0080 +#define SBBM_UPARROW 0x0100 +#define SBBM_DOWNARROW 0x0200 +#define SBBM_RESIZABLE 0x0400 +#define SBBM_TYPE2 0x0800 +#define SBBM_TYPE3 0x1000 +#define SBBM_TOOLTIPS 0x2000 //currently unused (define COOLSB_TOOLTIPS in userdefs.h) + +//button placement flags +#define SBBP_LEFT 1 +#define SBBP_RIGHT 2 +#define SBBP_TOP 1 //3 +#define SBBP_BOTTOM 2 //4 + +#define DFCS_HOVER 0x800 +// +// Button command notification codes +// for sending with a WM_COMMAND message +// +#define CSBN_BASE 0 +#define CSBN_CLICKED (1 + CSBN_BASE) +#define CSBN_HILIGHT (2 + CSBN_BASE) + +// Minimum size in pixels of a scrollbar thumb +#define MINTHUMBSIZE_NT4 9 +#define MINTHUMBSIZE_2000 7 + +//define some more hittest values for our cool-scrollbar +#define HTSCROLL_LEFT (SB_LINELEFT) +#define HTSCROLL_RIGHT (SB_LINERIGHT) +#define HTSCROLL_UP (SB_LINEUP) +#define HTSCROLL_DOWN (SB_LINEDOWN) +#define HTSCROLL_THUMB (SB_THUMBTRACK) +#define HTSCROLL_PAGEGUP (SB_PAGEUP) +#define HTSCROLL_PAGEGDOWN (SB_PAGEDOWN) +#define HTSCROLL_PAGELEFT (SB_PAGELEFT) +#define HTSCROLL_PAGERIGHT (SB_PAGERIGHT) + +#define HTSCROLL_NONE (-1) +#define HTSCROLL_NORMAL (-1) + +#define HTSCROLL_INSERTED (128) +#define HTSCROLL_PRE (32 | HTSCROLL_INSERTED) +#define HTSCROLL_POST (64 | HTSCROLL_INSERTED) + +// SCROLLBAR datatype. There are two of these structures per window +typedef struct _SCROLLBAR +{ + UINT fScrollFlags; //flags + BOOL fScrollVisible; //if this scrollbar visible? + SCROLLINFO scrollInfo; //positional data (range, position, page size etc) + + //data for inserted buttons + int nButSizeBefore; //size to the left / above the bar + int nButSizeAfter; //size to the right / below the bar + + int nMinThumbSize; + int nBarType; //SB_HORZ / SB_VERT + +} SCROLLBAR; + +static WORD wCheckPat[8] = +{ + 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 +}; + + +// scrollwnd styles +#define SWS_UPDATEFRAME 0x0001 +#define SWS_LEFT 0x0002 +#define SWS_DISABLENOSCROLL 0x0004 +#define SWS_HIDEHSCROLL 0x0008 +#define SWS_LISTVIEW 0x0010 +#define SWS_TREEVIEW 0x0020 +#define SWS_HIDEVSCROLL 0x0040 +#define SWS_COMBOLBOX 0x0080 +#define SWS_USEFREEFORM 0x0100 + +// +// PRIVATE INTERNAL FUNCTIONS +// +#define COOLSB_TIMERID1 65533 //initial timer +#define COOLSB_TIMERID2 65534 //scroll message timer +#define COOLSB_TIMERID3 -14 //mouse hover timer +#define COOLSB_TIMERINTERVAL1 300 +#define COOLSB_TIMERINTERVAL2 55 +#define COOLSB_TIMERINTERVAL3 20 //mouse hover time + +// +// direction: 0 - same axis as scrollbar (i.e. width of a horizontal bar) +// 1 - perpendicular dimesion (i.e. height of a horizontal bar) +// +#define SM_CXVERTSB 1 +#define SM_CYVERTSB 0 +#define SM_CXHORZSB 0 +#define SM_CYHORZSB 1 +#define SM_SCROLL_WIDTH 1 +#define SM_SCROLL_LENGTH 0 + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A +#endif + + +#define INACTIVEBAR_ALPHA 127 + +// +// Special thumb-tracking variables +// +// +static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT +static UINT uCurrentScrollPortion = HTSCROLL_NONE; +static UINT uCurrentButton = 0; + +static RECT rcThumbBounds; //area that the scroll thumb can travel in +static int nThumbSize; //(pixels) +static int nThumbPos; //(pixels) +static int nThumbMouseOffset; //(pixels) +static int nLastPos = -1; //(scrollbar units) +static int nThumbPos0; //(pixels) initial thumb position +static int trackThumbPos; +// +// Temporary state used to auto-generate timer messages +// +static UINT uScrollTimerMsg = 0; +static UINT uScrollTimerPortion = HTSCROLL_NONE; +static UINT_PTR uScrollTimerId = 0; +static HWND hwndCurCoolSB = 0; + +static INT bUseUpdateRgn = -1; +static BOOL bDoHover=FALSE; +static BOOL ignoreCaptureChange = FALSE; +static BOOL captureSet = FALSE; +static HBRUSH hbrChecked = NULL; + +#define GetSBForeColor() WADlg_getColor(WADLG_SCROLLBAR_FGCOLOR) +#define GetSBBackColor() WADlg_getColor(WADLG_SCROLLBAR_BGCOLOR) + +// Send a WM_VSCROLL or WM_HSCROLL message +#define SendScrollMessage(__hwnd, __srcMsg, __srcId, __pos) ::SendMessageW(__hwnd, __srcMsg, (MAKEWPARAM(__srcId, __pos)), 0) + +static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags); + +static void RenderBaseTexture(Canvas *canvas, const RECT *r, HWND hwnd) +{ + // TODO: find the ifc_window * object for the media library container, and call renderBaseTexture on it + if (WASABI_API_WND) + { + HWND checkWnd = GetParent(hwnd); + while (checkWnd) + { + ifc_window *window = WASABI_API_WND->rootWndFromOSHandle(checkWnd); + if (window && window->getRenderBaseTexture()) + { + window->renderBaseTexture(canvas, r); + return; + } + checkWnd = GetParent(checkWnd); + } + } + + // fallback code + COLORREF bgcolor = WADlg_getColor(WADLG_WNDBG/*WADLG_SCROLLBAR_BGCOLOR*/); + canvas->fillRect(r, bgcolor); +} + +// swap the rectangle's x coords with its y coords +static void __stdcall RotateRect(RECT *rect) +{ + LONG temp; + temp = rect->left; + rect->left = rect->top; + rect->top = temp; + + temp = rect->right; + rect->right = rect->bottom; + rect->bottom = temp; +} + +// swap the coords if the scrollbar is a SB_VERT +#define RotateRect0(__psb, __prc) ((__psb && __psb->nBarType == SB_VERT) ? RotateRect(__prc) : 0) + +static bool UseFreeformScrollbars() +{ + if (config_use_ff_scrollbars && WASABI_API_SKIN && WASABI_API_SKIN->skin_isLoaded()) + { + return WASABI_API_SKIN->skin_getVersion() >= 1.3; + } + else + { + return false; + } +} + +// Calculate if the SCROLLINFO members produce an enabled or disabled scrollbar +static BOOL IsScrollInfoActive(SCROLLINFO *si) +{ + return (si->nPage <= (UINT)si->nMax && si->nMax > si->nMin && si->nMax != 0); +} + +// Return if the specified scrollbar is enabled or not +static BOOL IsScrollbarActive(SCROLLBAR *sb) +{ + return (((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) || + !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(&sb->scrollInfo)) ? FALSE : TRUE; +} + +enum +{ + HORIZ_LEFT, + HORIZ_LEFT_PRESSED, + HORIZ_LEFT_HOVER, + HORIZ_LEFT_INACTIVE, + HORIZ_RIGHT, + HORIZ_RIGHT_PRESSED, + HORIZ_RIGHT_HOVER, + HORIZ_RIGHT_INACTIVE, + VERT_UP, + VERT_UP_PRESSED, + VERT_UP_HOVER, + VERT_UP_INACTIVE, + VERT_DOWN, + VERT_DOWN_PRESSED, + VERT_DOWN_HOVER, + VERT_DOWN_INACTIVE, +}; + +static int GetBitmapEnum(UINT state, BOOL hover) +{ + int offset=0; + if (state&DFCS_PUSHED) + offset=1; + if (state&DFCS_INACTIVE) + offset=3; + else if (hover) + offset=2; + + switch (state&3) + { + case DFCS_SCROLLRIGHT: + return HORIZ_RIGHT+offset; + case DFCS_SCROLLLEFT: + return HORIZ_LEFT+offset; + case DFCS_SCROLLDOWN: + return VERT_DOWN+offset; + default://case DFCS_SCROLLUP: + return VERT_UP+offset; + } +} + +class ScrollBitmaps +{ +public: + ScrollBitmaps() : v_up(L"wasabi.scrollbar.vertical.background.top"), + v_down(L"wasabi.scrollbar.vertical.background.bottom"), + v_mid(L"wasabi.scrollbar.vertical.background.middle"), + h_left(L"wasabi.scrollbar.horizontal.background.left"), + h_mid(L"wasabi.scrollbar.horizontal.background.middle"), + h_right(L"wasabi.scrollbar.horizontal.background.right") + { + } + AutoSkinBitmap v_up, v_down, v_mid, h_left, h_mid, h_right; +}; + +static ScrollBitmaps *scrollBitmaps=0; + +void SkinnedScrollWnd_Init() +{ + scrollBitmaps = new ScrollBitmaps(); +} + +void SkinnedScrollWnd_Quit() +{ + if (scrollBitmaps) + { + delete scrollBitmaps; + scrollBitmaps=0; + } +} + +static HBITMAP hbmpCachedDib = NULL; + +// Paint a checkered rectangle, with each alternate pixel being assigned a different colour + +static BOOL DrawFrameCtrl(HDC hdc, LPRECT lprc, UINT uType, UINT state, BOOL hover, BOOL freeform) +{ + int startx, starty, alpha = 255; + + const wchar_t *bitmapid=0; + const wchar_t *backgroundid=0; + SkinBitmap *bg=0; + switch (GetBitmapEnum(state, hover)) + { + case HORIZ_LEFT: + bitmapid = L"wasabi.scrollbar.horizontal.left"; + if (scrollBitmaps) + bg=scrollBitmaps->h_left.getBitmap(); + startx = 0; starty = 45; break; + case HORIZ_LEFT_PRESSED: + bitmapid = L"wasabi.scrollbar.horizontal.left.pressed"; + if (scrollBitmaps) + bg=scrollBitmaps->h_left.getBitmap(); + startx = 28; starty = 45; break; + case HORIZ_LEFT_HOVER: + bitmapid = L"wasabi.scrollbar.horizontal.left.hover"; + if (scrollBitmaps) + bg=scrollBitmaps->h_left.getBitmap(); + startx = 0; starty = 45; break; + case HORIZ_LEFT_INACTIVE: + alpha = INACTIVEBAR_ALPHA; + bitmapid = L"wasabi.scrollbar.horizontal.left"; + if (scrollBitmaps) + bg=scrollBitmaps->h_left.getBitmap(); + startx = 0; starty = 45; break; + case HORIZ_RIGHT: + bitmapid = L"wasabi.scrollbar.horizontal.right"; + if (scrollBitmaps) + bg=scrollBitmaps->h_right.getBitmap(); + startx = 14; starty = 45; break; + case HORIZ_RIGHT_PRESSED: + bitmapid = L"wasabi.scrollbar.horizontal.right.pressed"; + if (scrollBitmaps) + bg=scrollBitmaps->h_right.getBitmap(); + startx = 42; starty = 45; break; + case HORIZ_RIGHT_HOVER: + bitmapid = L"wasabi.scrollbar.horizontal.right.hover"; + if (scrollBitmaps) + bg=scrollBitmaps->h_right.getBitmap(); + startx = 14; starty = 45; break; + case HORIZ_RIGHT_INACTIVE: + alpha = INACTIVEBAR_ALPHA; + bitmapid = L"wasabi.scrollbar.horizontal.right"; + if (scrollBitmaps) + bg=scrollBitmaps->h_right.getBitmap(); + startx = 14; starty = 45; break; + case VERT_UP: + bitmapid = L"wasabi.scrollbar.vertical.left"; + if (scrollBitmaps) + bg=scrollBitmaps->v_up.getBitmap(); + startx = 0; starty = 31; break; + case VERT_UP_PRESSED: + bitmapid = L"wasabi.scrollbar.vertical.left.pressed"; + if (scrollBitmaps) + bg=scrollBitmaps->v_up.getBitmap(); + startx = 28; starty = 31; break; + case VERT_UP_HOVER: + bitmapid = L"wasabi.scrollbar.vertical.left.hover"; + if (scrollBitmaps) + bg=scrollBitmaps->v_up.getBitmap(); + startx = 0; starty = 31; break; + case VERT_UP_INACTIVE: + alpha = INACTIVEBAR_ALPHA; + bitmapid = L"wasabi.scrollbar.vertical.left"; + if (scrollBitmaps) + bg=scrollBitmaps->v_up.getBitmap(); + startx = 0; starty = 31; break; + + case VERT_DOWN: + bitmapid = L"wasabi.scrollbar.vertical.right"; + if (scrollBitmaps) + bg=scrollBitmaps->v_down.getBitmap(); + startx = 14; starty = 31; break; + case VERT_DOWN_PRESSED: + bitmapid = L"wasabi.scrollbar.vertical.right.pressed"; + if (scrollBitmaps) + bg=scrollBitmaps->v_down.getBitmap(); + startx = 42; starty = 31; break; + case VERT_DOWN_HOVER: + bitmapid = L"wasabi.scrollbar.vertical.right.hover"; + if (scrollBitmaps) + bg=scrollBitmaps->v_down.getBitmap(); + startx = 14; starty = 31; break; + case VERT_DOWN_INACTIVE: + alpha = INACTIVEBAR_ALPHA; + bitmapid = L"wasabi.scrollbar.vertical.right"; + if (scrollBitmaps) + bg=scrollBitmaps->v_down.getBitmap(); + startx = 14; starty = 31; break; + } + + if (freeform) + { + SkinBitmap bmp(bitmapid); + if (!bmp.isInvalid() && bg && !bg->isInvalid()) + { + DCCanvas canvas(hdc); + bg->stretchToRectAlpha(&canvas, lprc, alpha); + bmp.stretchToRectAlpha(&canvas, lprc, alpha); + return 1; + } + } + + // fallback code + HDC hdcbmp; + HBITMAP hbmpOld, hbmp; + + hbmp = WADlg_getBitmap(); + if (!hbmp) return FALSE; + + hdcbmp = (HDC)MlStockObjects_Get(CACHED_DC); + if (!hdcbmp) return FALSE; + + hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp); + + + + if (255 == alpha) + StretchBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY); + else + { + HDC hdcTmp = CreateCompatibleDC(hdc); + + DIBSECTION dibSection; + if (NULL == hbmpCachedDib || + sizeof(DIBSECTION) != GetObjectW(hbmpCachedDib, sizeof(DIBSECTION), &dibSection) + || dibSection.dsBm.bmWidth < (lprc->right - lprc->left) || ABS(dibSection.dsBm.bmHeight) < (lprc->bottom - lprc->top)) + { + if (hbmpCachedDib) DeleteObject(hbmpCachedDib); + + BITMAPINFOHEADER bi; + ZeroMemory(&bi, sizeof(BITMAPINFOHEADER)); + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = lprc->right - lprc->left; + bi.biHeight = -(lprc->bottom - lprc->top); + bi.biPlanes = 1; + bi.biBitCount = 32; + bi.biCompression = BI_RGB; + hbmpCachedDib = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (VOID**)&dibSection.dsBm.bmBits, NULL, 0); + dibSection.dsBm.bmHeight = bi.biHeight; + dibSection.dsBm.bmWidth = bi.biWidth; + } + + ASSERT(hbmpCachedDib != 0); + + HBITMAP hbmpTmp = (HBITMAP)SelectObject(hdcTmp, hbmpCachedDib); + + StretchBlt(hdcTmp, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY); + + LONG pitch = dibSection.dsBm.bmWidth*4, cy = lprc->bottom - lprc->top, x; + LPBYTE cursor, line; + + COLORREF rgbBk = WADlg_getColor(WADLG_WNDBG);// BlendColors(GetSBBackColor(), WADlg_getColor(WADLG_ITEMBG), ((float)INACTIVEBAR_ALPHA)/255.0f); + + BYTE k = (((255 - alpha)*255 + 127)/255); + BYTE r = (GetRValue(rgbBk)*k + 127)/255, g = (GetGValue(rgbBk)*k + 127)>>8, b = (GetBValue(rgbBk)*k + 127)/255; + + for (line = (BYTE*)dibSection.dsBm.bmBits; cy-- != 0; line += pitch ) + { + for (x = (lprc->right - lprc->left), cursor = line; x-- != 0; cursor += 4) + { + cursor[0] = (cursor[0]*alpha)/255 + b; + cursor[1] = (cursor[1]*alpha)/255 + g; + cursor[2] = (cursor[2]*alpha)/255 + r; + cursor[3] = 0xFF; + } + } + + BitBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcTmp, 0, 0, SRCCOPY); + SelectObject(hdcTmp, hbmpTmp); + DeleteDC(hdcTmp); + } + + SelectObject(hdcbmp, hbmpOld); + + return 1; +} + +// Draw a standard scrollbar arrow +static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver, BOOL freeform) +{ + UINT ret; + UINT flags = arrow; + + //HACKY bit so this routine can be called by vertical and horizontal code + if (sbar->nBarType == SB_VERT) + { + if (flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP; + if (flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN; + } + + if (fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED); + + ret = DrawFrameCtrl(hdc, rect, DFC_SCROLL, flags, fMouseOver, freeform); + + return ret; +} + +// Return the size in pixels for the specified scrollbar metric, for the specified scrollbar +static int GetScrollMetric(SCROLLBAR *psb, int metric, DWORD scrollFlags) +{ + int type (psb ? psb->nBarType : SB_VERT); + switch (type) + { + case SB_HORZ: + { + switch (metric) + { + case SM_CXHORZSB: + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap button(L"wasabi.scrollbar.horizontal.left"); // we assume symmetry which isn't necessary safe + if (!button.isInvalid()) + return WASABI_API_APP->getScaleX(button.getWidth()); + } + return WASABI_API_APP->getScaleX(14); // classic skin fixes this at 14 + default: + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap button(L"wasabi.scrollbar.horizontal.left"); // we assume symmetry which isn't necessary safe + if (!button.isInvalid()) + return WASABI_API_APP->getScaleY(button.getHeight()); + } + return WASABI_API_APP->getScaleY(14); // classic skin fixes this at 14 + break; + } + } + break; + + default: // case SB_VERT: + { + switch (metric) + { + case SM_CYVERTSB: + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap button(L"wasabi.scrollbar.vertical.left"); // we assume symmetry which isn't necessary safe + if (!button.isInvalid()) + return WASABI_API_APP->getScaleY(button.getHeight()); + } + return WASABI_API_APP->getScaleY(14); // classic skin fixes this at 14 + default: + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap button(L"wasabi.scrollbar.vertical.left"); // we assume symmetry which isn't necessary safe + if (!button.isInvalid()) + return WASABI_API_APP->getScaleX(button.getWidth()); + } + return WASABI_API_APP->getScaleX(14); // classic skin fixes this at 14 + break; + } + } + break; + } + + /* + if ((SB_HORZ == psb->nBarType && metric == SM_CXHORZSB) || (SB_VERT == psb->nBarType && metric == SM_CYVERTSB)) + return (psb->nArrowLength == SYSTEM_METRIC) * ((psb->nArrowLength < 0) ? -14 : 1); + else return psb->nArrowWidth * ((psb->nArrowWidth < 0) ? -14 : 1); + */ +} + +// Fill the specifed rectangle using a solid colour +static void PaintRect(HDC hdc, RECT *rect, COLORREF color) +{ + COLORREF oldcol = SetBkColor(hdc, color); + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, rect, L"", 0, 0); + SetBkColor(hdc, oldcol); +} + +// +// Set the minimum size, in pixels, that the thumb box will shrink to. +// + +// Draw a simple blank scrollbar push-button. Can be used +// to draw a push button, or the scrollbar thumb +// drawflag - could set to BF_FLAT to make flat scrollbars +static void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag, int pushed, int vertical) +{ + HBITMAP hbmp, hbmpOld; + hbmp = WADlg_getBitmap(); + if (!hbmp) return; + + HDC hdcbmp = (HDC)MlStockObjects_Get(CACHED_DC); + if (!hdcbmp) return; + + hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp); + +#define PART1SIZE 4 //copied top +#define PART2SIZE 5 //stretched top +#define PART3SIZE 10 //copied middle +#define PART4SIZE 5 //stretched bottom +#define PART5SIZE 4 //copied bottom + + if (vertical) + { + int middle = (rect->bottom - rect->top) / 2; + int startx = pushed ? 70 : 56; + //top + StretchBlt(hdc, rect->left, rect->top, rect->right - rect->left, PART1SIZE, hdcbmp, startx, 31, 14, PART1SIZE, SRCCOPY); + int p = PART1SIZE; + //stretched top + int l = middle - PART1SIZE - (PART3SIZE / 2); + if (l > 0) + { + StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE, 14, PART2SIZE, SRCCOPY); + p += middle - PART1SIZE - (PART3SIZE / 2); + } + //copied middle + int m = (rect->bottom - rect->top) - PART1SIZE - PART5SIZE; //space that's available for middle + m = min(m, PART3SIZE); + if (m > 0) + { + StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, m, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE, 14, m, SRCCOPY); + p += m; + } + //stretched bottom + l = rect->bottom - rect->top - p - PART5SIZE; + if (l > 0) StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE, 14, PART4SIZE, SRCCOPY); + //bottom + StretchBlt(hdc, rect->left, rect->bottom - PART5SIZE, rect->right - rect->left, PART5SIZE, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, 14, PART5SIZE, SRCCOPY); + } + else + { + int middle = (rect->right - rect->left) / 2; + int starty = pushed ? 45 : 31; + //top + StretchBlt(hdc, rect->left, rect->top, PART1SIZE, rect->bottom - rect->top, hdcbmp, 84, starty, PART1SIZE, 14, SRCCOPY); + int p = PART1SIZE; + //stretched top + int l = middle - PART1SIZE - (PART3SIZE / 2); + if (l > 0) + { + StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE, starty, PART2SIZE, 14, SRCCOPY); + p += middle - PART1SIZE - (PART3SIZE / 2); + } + //copied middle + int m = (rect->right - rect->left) - PART1SIZE - PART5SIZE; //space that's available for middle + m = min(m, PART3SIZE); + if (m > 0) + { + StretchBlt(hdc, rect->left + p, rect->top, m, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE, starty, m, 14, SRCCOPY); + p += m; + } + //stretched bottom + l = rect->right - rect->left - p - PART5SIZE; + if (l > 0) StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE, starty, PART4SIZE, 14, SRCCOPY); + //bottom + StretchBlt(hdc, rect->right - PART5SIZE, rect->top, PART5SIZE, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, starty, PART5SIZE, 14, SRCCOPY); + } + + SelectObject(hdcbmp, hbmpOld); +} + + +// Calculate the screen coordinates of the area taken by +// the horizontal scrollbar. Take into account the size +// of the window borders +static BOOL GetHScrollRect(SkinnedScrollWnd *pWnd, RECT *prc) +{ + if (pWnd->psbHorz->fScrollVisible) + { + GetClientRect(pWnd->hwnd, prc); + MapWindowPoints(pWnd->hwnd, HWND_DESKTOP, (POINT*)prc, 2); + prc->top = prc->bottom; + prc->bottom += GetScrollMetric(pWnd->psbHorz, SM_CYHORZSB, pWnd->scrollFlags); + } + else SetRect(prc, 0, 0, 0, 0); + return TRUE; +} + +// Calculate the screen coordinates of the area taken by the +// vertical scrollbar +static BOOL GetVScrollRect(SkinnedScrollWnd *pWnd, RECT *prc) +{ + if (pWnd->psbVert->fScrollVisible) + { + GetClientRect(pWnd->hwnd, prc); + MapWindowPoints(pWnd->hwnd, HWND_DESKTOP, (POINT*)prc, 2); + if (SWS_LEFT & pWnd->scrollFlags) + { + prc->right = prc->left; + prc->left -= GetScrollMetric(pWnd->psbVert, SM_CXVERTSB, pWnd->scrollFlags); + } + else + { + prc->left = prc->right; + prc->right += GetScrollMetric(pWnd->psbVert, SM_CXVERTSB, pWnd->scrollFlags); + } + } + else SetRect(prc, 0, 0, 0, 0); + + + return TRUE; +} + +// Depending on what type of scrollbar nBar refers to, call the +// appropriate Get?ScrollRect function +// +static BOOL GetScrollRect(SkinnedScrollWnd *pWnd, UINT nBar, RECT *prc) +{ + if (nBar == SB_HORZ) return GetHScrollRect(pWnd, prc); + else if (nBar == SB_VERT) return GetVScrollRect(pWnd, prc); + else return FALSE; +} + +// +// Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT) +// rect - coords of the scrollbar. +// store results into *thumbsize and *thumbpos +// +static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos, DWORD scrollFlags) +{ + SCROLLINFO *si; + int scrollsize; //total size of the scrollbar including arrow buttons + int workingsize; //working area (where the thumb can slide) + int siMaxMin; + int butsize; + int startcoord; + int thumbpos = 0, thumbsize = 0; + + //work out the width (for a horizontal) or the height (for a vertical) + //of a standard scrollbar button + butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH, scrollFlags); + + if (1) //sbar->nBarType == SB_HORZ) + { + scrollsize = rect->right - rect->left; + startcoord = rect->left; + } + /*else if(sbar->nBarType == SB_VERT) + { + scrollsize = rect->bottom - rect->top; + startcoord = rect->top; + } + else + { + return 0; + }*/ + + si = &sbar->scrollInfo; + siMaxMin = si->nMax - si->nMin + 1; + + workingsize = scrollsize - butsize * 2; + + // + // Work out the scrollbar thumb SIZE + // + if (si->nPage == 0) + { + thumbsize = butsize; + } + else if (siMaxMin > 0) + { + /*if (SWS_HIDEHSCROLL & scrollFlags) + thumbsize = MulDiv(si->nPage, workingsize, si->nMax); + else*/ + thumbsize = MulDiv(si->nPage, workingsize, siMaxMin); + + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap thumb((sbar->nBarType == SB_VERT)?L"wasabi.scrollbar.vertical.button":L"wasabi.scrollbar.horizontal.button"); + if (!thumb.isInvalid()) + thumbsize = (sbar->nBarType == SB_VERT)?thumb.getHeight():thumb.getWidth(); + } + + if (thumbsize < sbar->nMinThumbSize) + thumbsize = sbar->nMinThumbSize; + } + + // + // Work out the scrollbar thumb position + // + if (siMaxMin > 0) + { + int pagesize = max(1, si->nPage); + thumbpos = MulDiv(si->nPos - si->nMin, workingsize - thumbsize, siMaxMin - pagesize); + /*if (SWS_HIDEHSCROLL & scrollFlags) + { + thumbpos = (si->nPos == (si->nMax - si->nPage)) ? + (workingsize - thumbsize) : MulDiv(si->nPos, workingsize, si->nMax); + }*/ + + if (thumbpos < 0) + thumbpos = 0; + + if (thumbpos >= workingsize - thumbsize) + thumbpos = workingsize - thumbsize; + } + + thumbpos += startcoord + butsize; + + *pthumbpos = thumbpos; + *pthumbsize = thumbsize; + + return 1; +} + +// +// return a hit-test value for whatever part of the scrollbar x,y is located in +// rect, x, y: SCREEN coordinates +// the rectangle must not include space for any inserted buttons +// (i.e, JUST the scrollbar area) +// +static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y, DWORD scrollFlags) +{ + int thumbwidth, thumbpos; + int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH, scrollFlags); + int scrollwidth = rect->right - rect->left; + int workingwidth = scrollwidth - butwidth * 2; + + if (y < rect->top || y >= rect->bottom) + return HTSCROLL_NONE; + + CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos, scrollFlags); + + //if we have had to scale the buttons to fit in the rect, + //then adjust the button width accordingly + if (scrollwidth <= butwidth * 2) + { + butwidth = scrollwidth / 2; + } + + //check for left button click + if (x >= rect->left && x < rect->left + butwidth) + { + return (ESB_DISABLE_LEFT & sbar->fScrollFlags) ? HTSCROLL_NONE : HTSCROLL_LEFT; + } + //check for right button click + else if (x >= rect->right - butwidth && x < rect->right) + { + return (ESB_DISABLE_RIGHT & sbar->fScrollFlags) ? HTSCROLL_NONE : HTSCROLL_RIGHT; + } + + //if the thumb is too big to fit (i.e. it isn't visible) + //then return a NULL scrollbar area + if (thumbwidth >= workingwidth) + return HTSCROLL_NONE; + + //check for point in the thumbbar + if (x >= thumbpos && x < thumbpos + thumbwidth) + { + return HTSCROLL_THUMB; + } + //check for left margin + else if (x >= rect->left + butwidth && x < thumbpos) + { + return HTSCROLL_PAGELEFT; + } + else if (x >= thumbpos + thumbwidth && x < rect->right - butwidth) + { + return HTSCROLL_PAGERIGHT; + } + + return HTSCROLL_NONE; +} + +// +// For vertical scrollbars, rotate all coordinates by -90 degrees +// so that we can use the horizontal version of this function +// +static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags) +{ + UINT r; + + RotateRect(rect); + r = GetHorzScrollPortion(sb, hwnd, rect, y, x, scrollFlags); + RotateRect(rect); + return r; +} + +static const wchar_t *GetThumbID(UINT barType, UINT scrollFlags, BOOL hover) +{ + if (barType == SB_VERT) + { + if (scrollFlags & CSBS_TRACKING) + return L"wasabi.scrollbar.vertical.button.pressed"; + else if (hover) + return L"wasabi.scrollbar.vertical.button.hover"; + else + return L"wasabi.scrollbar.vertical.button"; + } + else + { + if (scrollFlags & CSBS_TRACKING) + return L"wasabi.scrollbar.horizontal.button.pressed"; + else if (hover) + return L"wasabi.scrollbar.horizontal.button.hover"; + else + return L"wasabi.scrollbar.horizontal.button"; + } +} + +static HBRUSH SetWindowPatternBrush(HWND hwnd, HDC hdc, UINT nBarType) +{ + RECT rw; + GetWindowRect(hwnd, &rw); + HWND hwndAncestor = GetAncestor(hwnd, GA_ROOT); + if (hwndAncestor) MapWindowPoints(HWND_DESKTOP, hwndAncestor, (POINT*)&rw, 2); + POINT ptOrg; + if (GetViewportOrgEx(hdc, &ptOrg)) OffsetRect(&rw, ptOrg.x, ptOrg.y); + if (nBarType == SB_VERT) + { + if (0 == (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)) rw.left = rw.right; + } + else rw.top = rw.bottom; + + SetBrushOrgEx(hdc, rw.left, rw.top, (POINT*)&rw); + return (HBRUSH)SelectObject(hdc, hbrChecked); +} + +// +// Draw a complete HORIZONTAL scrollbar in the given rectangle +// Don't draw any inserted buttons in this procedure +// +// uDrawFlags - hittest code, to say if to draw the +// specified portion in an active state or not. +// +// +static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags) +{ + SCROLLINFO *si; + RECT ctrl, thumb; + RECT sbm; + int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH, scrollFlags); + int scrollwidth = rect->right - rect->left; + int workingwidth = scrollwidth - butwidth * 2; + int thumbwidth = 0, thumbpos = 0; + int siMaxMin; + + BOOL fMouseDownL = 0, fMouseOverL = (hoverFlags == HTSCROLL_LEFT); + BOOL fMouseDownR = 0, fMouseOverR = (hoverFlags == HTSCROLL_RIGHT); + BOOL fMouseOverThumb = (hoverFlags == HTSCROLL_THUMB); + + COLORREF crCheck1 = GetSBForeColor(); + COLORREF crCheck2 = GetSBBackColor(); + COLORREF crInverse1 = WADlg_getColor(WADLG_SCROLLBAR_INV_FGCOLOR); + COLORREF crInverse2 = WADlg_getColor(WADLG_SCROLLBAR_INV_BGCOLOR); + + UINT uDFCFlat = (CSBS_FLATSB & sb->fScrollFlags) ? DFCS_FLAT : 0; + UINT uDEFlat = (CSBS_FLATSB & sb->fScrollFlags) ? BF_FLAT : 0; + + //drawing flags to modify the appearance of the scrollbar buttons + UINT uLeftButFlags = DFCS_SCROLLLEFT; + UINT uRightButFlags = DFCS_SCROLLRIGHT; + + if (scrollwidth <= 0) + return 0; + + si = &sb->scrollInfo; + siMaxMin = si->nMax - si->nMin; + + if (hwnd != hwndCurCoolSB) + uDrawFlags = HTSCROLL_NONE; + // + // work out the thumb size and position + // + CalcThumbSize(sb, rect, &thumbwidth, &thumbpos, scrollFlags); + if ((CSBS_TRACKING & sb->fScrollFlags) && trackThumbPos != -1) + { + thumbpos=trackThumbPos; + } + + if (sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE; + if (sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE; + + //if we need to grey the arrows because there is no data to scroll + if ((0 == (DFCS_INACTIVE & uLeftButFlags) || 0 == (DFCS_INACTIVE & uRightButFlags)) && + !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si)) + { + uLeftButFlags |= DFCS_INACTIVE; + uRightButFlags |= DFCS_INACTIVE; + } + + if ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags)) + { + COLORREF rgbBk = WADlg_getColor(WADLG_WNDBG); + crCheck1 = BlendColors(crCheck1, rgbBk, INACTIVEBAR_ALPHA); + crCheck2 = BlendColors(crCheck2, rgbBk, INACTIVEBAR_ALPHA); + } + + if (hwnd == hwndCurCoolSB) + { + fMouseDownL = (uDrawFlags == HTSCROLL_LEFT); + fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT); + } + + if (NULL == hbrChecked) //recreate pattern brush if needed + { + HBITMAP hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat); + hbrChecked = CreatePatternBrush(hbmp); + DeleteObject(hbmp); + if (NULL == hbrChecked) return 0; + } + + + + HBRUSH hbrOld = NULL; + + COLORREF rgbFgOld, rgbBkOld; + rgbFgOld = SetTextColor(hdc, crCheck1); + rgbBkOld = SetBkColor(hdc, crCheck2); + + // + // Draw the scrollbar now + // + if (scrollwidth > butwidth*2) + { + DCCanvas canvas(hdc); + if (SWS_USEFREEFORM & scrollFlags) + { + CopyRect(&ctrl, rect); + RotateRect0(sb, &ctrl); + RenderBaseTexture(&canvas, &ctrl, hwnd); + } + + //LEFT ARROW + SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom); + + RotateRect0(sb, &ctrl); + + DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL, (SWS_USEFREEFORM & scrollFlags)); + + RotateRect0(sb, &ctrl); + + //MIDDLE PORTION + //if we can fit the thumbbar in, then draw it + if (thumbwidth > 0 && thumbwidth <= workingwidth + && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH)) + { + SkinBitmap *bg = (scrollBitmaps && (SWS_USEFREEFORM & scrollFlags)) ? + ((sb->nBarType== SB_VERT) ? scrollBitmaps->v_mid.getBitmap(): scrollBitmaps->h_mid.getBitmap()) + : 0; + + if ((SWS_USEFREEFORM & scrollFlags) && bg && !bg->isInvalid()) + { + SetRect(&sbm, rect->left + butwidth, rect->top, rect->right-butwidth, rect->bottom); + RotateRect0(sb, &sbm); + + bg->stretchToRectAlpha(&canvas, &sbm); + + SkinBitmap thumbBitmap(GetThumbID(sb->nBarType, sb->fScrollFlags, fMouseOverThumb)); + SetRect(&sbm, thumbpos, rect->top, thumbpos+thumbwidth, rect->bottom); + RotateRect0(sb, &sbm); + if (!thumbBitmap.isInvalid()) + thumbBitmap.stretchToRectAlpha(&canvas, &sbm); + else + DrawBlankButton(hdc, &sbm, uDEFlat, (CSBS_TRACKING & sb->fScrollFlags), sb->nBarType == SB_VERT); + } + else + { + //Draw the scrollbar margin above the thumb + SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom); + + RotateRect0(sb, &sbm); + + if (HTSCROLL_PAGELEFT == uDrawFlags) + { + SetTextColor(hdc, crInverse1); + SetBkColor(hdc, crInverse2); + } + + if (GetTextColor(hdc) == GetBkColor(hdc)) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &sbm, NULL, 0, NULL); + else + { + if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType); + PatBlt(hdc, sbm.left, sbm.top, sbm.right - sbm.left, sbm.bottom - sbm.top, PATCOPY); + } + + if (HTSCROLL_PAGELEFT == uDrawFlags) + { + SetTextColor(hdc, crCheck1); + SetBkColor(hdc, crCheck2); + } + + RotateRect0(sb, &sbm); + + //Draw the margin below the thumb + sbm.left = thumbpos + thumbwidth; + sbm.right = rect->right - butwidth; + + RotateRect0(sb, &sbm); + + if (HTSCROLL_PAGERIGHT == uDrawFlags) + { + SetTextColor(hdc, crInverse1); + SetBkColor(hdc, crInverse2); + } + + if (GetTextColor(hdc) == GetBkColor(hdc)) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &sbm, NULL, 0, NULL); + else + { + if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType); + PatBlt(hdc, sbm.left, sbm.top, sbm.right - sbm.left, sbm.bottom - sbm.top, PATCOPY); + } + + if (HTSCROLL_PAGERIGHT == uDrawFlags) + { + SetTextColor(hdc, crCheck1); + SetBkColor(hdc, crCheck2); + } + + RotateRect0(sb, &sbm); + + //Draw the THUMB finally + SetRect(&thumb, thumbpos, rect->top, thumbpos + thumbwidth, rect->bottom); + + RotateRect0(sb, &thumb); + + DrawBlankButton(hdc, &thumb, uDEFlat, (CSBS_TRACKING & sb->fScrollFlags), sb->nBarType == SB_VERT); + RotateRect0(sb, &thumb); + } + + } + //otherwise, just leave that whole area blank + else + { + OffsetRect(&ctrl, butwidth, 0); + ctrl.right = rect->right - butwidth; + + //if we always show the thumb covering the whole scrollbar, + //then draw it that way + if (!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS) + && ctrl.right - ctrl.left > sb->nMinThumbSize) + { + //leave a 1-pixel gap between the thumb + right button + ctrl.right --; + RotateRect0(sb, &ctrl); + + DrawBlankButton(hdc, &ctrl, uDEFlat, 0, sb->nBarType == SB_VERT); + RotateRect0(sb, &ctrl); + + //draw the single-line gap + ctrl.left = ctrl.right; + ctrl.right += 1; + + RotateRect0(sb, &ctrl); + + PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR)); + + RotateRect0(sb, &ctrl); + } + //otherwise, paint a blank if the thumb doesn't fit in + else + { + RotateRect0(sb, &ctrl); + BOOL classic(TRUE); + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap background(sb->nBarType== SB_VERT?L"wasabi.scrollbar.vertical.background.middle":L"wasabi.scrollbar.horizontal.background.middle"); + if (!background.isInvalid()) + { + background.stretchToRectAlpha(&canvas, &ctrl, + ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags)) ? INACTIVEBAR_ALPHA : 255); + classic = FALSE; + } + } + + if (classic) + { + if (crCheck1 == crCheck2) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &ctrl, NULL, 0, NULL); + else + { + if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType); + PatBlt(hdc, ctrl.left, ctrl.top, ctrl.right - ctrl.left, ctrl.bottom - ctrl.top, PATCOPY); + } + } + + + RotateRect0(sb, &ctrl); + } + } + + //RIGHT ARROW + SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom); + + RotateRect0(sb, &ctrl); + + DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR, (SWS_USEFREEFORM & scrollFlags)); + + RotateRect0(sb, &ctrl); + } + //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit) + else + { + butwidth = scrollwidth / 2; + + //LEFT ARROW + SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom); + + RotateRect0(sb, &ctrl); + DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL, (SWS_USEFREEFORM & scrollFlags)); + RotateRect0(sb, &ctrl); + + //RIGHT ARROW + OffsetRect(&ctrl, scrollwidth - butwidth, 0); + + RotateRect0(sb, &ctrl); + DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR, (SWS_USEFREEFORM & scrollFlags)); + RotateRect0(sb, &ctrl); + + //if there is a gap between the buttons, fill it with a solid color + //if(butwidth & 0x0001) + if (ctrl.left != rect->left + butwidth) + { + ctrl.left --; + ctrl.right -= butwidth; + RotateRect0(sb, &ctrl); + BOOL classic(TRUE); + + if (SWS_USEFREEFORM & scrollFlags) + { + SkinBitmap background(sb->nBarType== SB_VERT?L"wasabi.scrollbar.vertical.background.middle":L"wasabi.scrollbar.horizontal.background.middle"); + if (!background.isInvalid()) + { + DCCanvas canvas(hdc); + RenderBaseTexture(&canvas, &ctrl, hwnd); + background.stretchToRectAlpha(&canvas, &ctrl, + ((DFCS_INACTIVE & uLeftButFlags) && (DFCS_INACTIVE & uRightButFlags)) ? INACTIVEBAR_ALPHA : 255); + classic = FALSE; + } + } + + if (classic) + { + if (crCheck1 == crCheck2) ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &ctrl, NULL, 0, NULL); + else + { + if (NULL == hbrOld) hbrOld = SetWindowPatternBrush(hwnd, hdc, sb->nBarType); + PatBlt(hdc, ctrl.left, ctrl.top, ctrl.right - ctrl.left, ctrl.bottom - ctrl.top, PATCOPY); + } + } + + RotateRect0(sb, &ctrl); + } + + } + + SetBkColor(hdc, rgbBkOld); + SetTextColor(hdc, rgbFgOld); + if (hbrOld) + { + SelectObject(hdc, hbrOld); + SetBrushOrgEx(hdc, 0, 0, NULL); + } + return 0; +} + +// +// Draw a vertical scrollbar using the horizontal draw routine, but +// with the coordinates adjusted accordingly +// +static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags) +{ + LRESULT ret; + RECT rc; + + rc = *rect; + RotateRect(&rc); + ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags, hoverFlags, scrollFlags); + RotateRect(&rc); + + return ret; +} + +// +// Generic wrapper function for the scrollbar drawing +// +static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags, UINT hoverFlags, DWORD scrollFlags) +{ + if (sb->nBarType == SB_HORZ) + return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags, hoverFlags, scrollFlags); + else + return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags, hoverFlags, scrollFlags); +} + + + +void SkinnedScrollWnd::PaintNonClient(HDC hdc) +{ + RECT winrect, rcH, rcV; + BOOL drawH = FALSE, drawV = FALSE; + + if (!psbHorz->fScrollVisible && !psbVert->fScrollVisible) + { + DrawBorder(hdc); + return; + } + + if (0 == (SWS_UPDATEFRAME & scrollFlags)) + { + HWND hwndActive; + hwndActive = GetActiveWindow(); + if (hwndActive != hwnd && !IsChild(hwndActive, hwnd)) scrollFlags |= SWS_UPDATEFRAME; + } + + GetWindowRect(hwnd, &winrect); + + + if (psbHorz->fScrollVisible) + { + GetHScrollRect(this, &rcH); + OffsetRect(&rcH, -winrect.left, -winrect.top); + if (rcH.right > rcH.left && rcH.bottom > rcH.top && RectVisible(hdc, &rcH)) drawH = TRUE; + } + + if (psbVert->fScrollVisible) + { + GetVScrollRect(this, &rcV); + OffsetRect(&rcV, -winrect.left, -winrect.top); + + if (rcV.right > rcV.left && rcV.bottom > rcV.top && RectVisible(hdc, &rcV)) drawV = TRUE; + } + DrawBorder(hdc); + + POINT ptOrg; + GetViewportOrgEx(hdc, &ptOrg); + + if (drawH) + { + UINT fDraw, fHover; + if (uCurrentScrollbar == SB_HORZ) { fDraw = uScrollTimerPortion; fHover = HTSCROLL_NONE; } + else + { + fDraw = HTSCROLL_NONE; + fHover = (NULL != psbHorz && 0 != (CSBS_HOVERING & psbHorz->fScrollFlags)) ? scrollPortionHover : HTSCROLL_NONE; + } + + if (SWS_USEFREEFORM & scrollFlags) + { + DCBltCanvas buffer; + buffer.cloneDC(hdc, &rcH); + NCDrawHScrollbar(psbHorz, hwnd, buffer.getHDC(), &rcH, fDraw, fHover, scrollFlags); + } + else + { + SetViewportOrgEx(hdc, ptOrg.x + rcH.left, ptOrg.y + rcH.top, NULL); + OffsetRect(&rcH, -rcH.left, -rcH.top); + NCDrawHScrollbar(psbHorz, hwnd, hdc, &rcH, fDraw, fHover, scrollFlags); + SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL); + } + } + + if (drawV) + { + UINT fDraw, fHover; + if (uCurrentScrollbar == SB_VERT) { fDraw = uScrollTimerPortion; fHover = HTSCROLL_NONE; } + else + { + fDraw = HTSCROLL_NONE; + fHover = (NULL != psbVert && 0 != (CSBS_HOVERING & psbVert->fScrollFlags)) ? scrollPortionHover : HTSCROLL_NONE; + } + + if (SWS_USEFREEFORM & scrollFlags) + { + DCBltCanvas buffer; + buffer.cloneDC(hdc, &rcV); + NCDrawVScrollbar(psbVert, hwnd, buffer.getHDC(), &rcV, fDraw, fHover, scrollFlags); + + } + else + { + SetViewportOrgEx(hdc, ptOrg.x + rcV.left, ptOrg.y + rcV.top, NULL); + OffsetRect(&rcV, -rcV.left, -rcV.top); + NCDrawVScrollbar(psbVert, hwnd, hdc, &rcV, fDraw, fHover, scrollFlags); + SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL); + } + + } + + SetViewportOrgEx(hdc, ptOrg.x, ptOrg.y, NULL); + + // DRAW THE DEAD AREA + // only do this if the horizontal and vertical bars are visible + if (psbHorz->fScrollVisible && psbVert->fScrollVisible) + { + GetClientRect(hwnd, &rcH); + MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rcH, 2); + OffsetRect(&rcH, -winrect.left, -winrect.top); + + rcH.top = rcH.bottom; + rcH.bottom += GetScrollMetric(psbHorz, SM_CYHORZSB, scrollFlags); + + if (SWS_LEFT & scrollFlags) + { + rcH.right = rcH.left; + rcH.left -= GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags); + } + else + { + rcH.left = rcH.right; + rcH.right += GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags); + } + + if (RectVisible(hdc, &rcH)) + { + + PaintRect(hdc, &rcH, WADlg_getColor(WADLG_SCROLLBAR_DEADAREA_COLOR)); + } + } + + +} + +void SkinnedScrollWnd::OnNcPaint(HRGN rgnUpdate) +{ + UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS | + DCX_INTERSECTUPDATE | DCX_VALIDATE; + + HDC hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags); + + + if (NULL == hdc) + { + return; + } + + + PaintNonClient(hdc); + + + ReleaseDC(hwnd, hdc); +} + +// +// Need to detect if we have clicked in the scrollbar region or not +// +INT SkinnedScrollWnd::OnNcHitTest(POINTS pts) +{ + RECT rc; + + INT r = __super::OnNcHitTest(pts); + if (r == HTTRANSPARENT) + { + + + return r; + } + + if (psbHorz->fScrollVisible && GetHScrollRect(this, &rc) && + pts.x >= rc.left && pts.x <= rc.right && pts.y >= rc.top && pts.y <= rc.bottom) return HTHSCROLL; + if (psbVert->fScrollVisible && GetVScrollRect(this, &rc) && + pts.x >= rc.left && pts.x <= rc.right && pts.y >= rc.top && pts.y <= rc.bottom) return HTVSCROLL; + + return r; +} + +// +// Return a HT* value indicating what part of the scrollbar was clicked +// Rectangle is not adjusted +// +static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags) +{ + RECT rc = *rect; + + if (y < rc.top || y >= rc.bottom) return HTSCROLL_NONE; + + //Now we have the rectangle for the scrollbar itself, so work out + //what part we clicked on. + return GetHorzScrollPortion(sb, hwnd, &rc, x, y, scrollFlags); +} + +// +// Just call the horizontal version, with adjusted coordinates +// +static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags) +{ + UINT ret; + RotateRect(rect); + ret = GetHorzPortion(sb, hwnd, rect, y, x, scrollFlags); + RotateRect(rect); + return ret; +} + +// +// Wrapper function for GetHorzPortion and GetVertPortion +// +static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y, DWORD scrollFlags) +{ + if (sb->nBarType == SB_HORZ) return GetHorzPortion(sb, hwnd, rect, x, y, scrollFlags); + else if (sb->nBarType == SB_VERT) return GetVertPortion(sb, hwnd, rect, x, y, scrollFlags); + return HTSCROLL_NONE; +} + +// +// Input: rectangle of the total scrollbar area +// Output: adjusted to take the inserted buttons into account +// +static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect) +{ + if (CSBS_BTNVISBEFORE & sb->fScrollFlags) rect->left += sb->nButSizeBefore; + if (CSBS_BTNVISAFTER & sb->fScrollFlags) rect->right -= sb->nButSizeAfter; +} + +// +// Input: rectangle of the total scrollbar area +// Output: adjusted to take the inserted buttons into account +// +static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect) +{ + if (CSBS_BTNVISBEFORE & sb->fScrollFlags) rect->top += sb->nButSizeBefore; + if (CSBS_BTNVISAFTER & sb->fScrollFlags) rect->bottom -= sb->nButSizeAfter; +} + +// +// Decide which type of scrollbar we have before calling +// the real function to do the job +// +static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect, DWORD scrollFlags) +{ + if (sb->nBarType == SB_HORZ) + { + GetRealHorzScrollRect(sb, rect); + } + else if (sb->nBarType == SB_VERT) + { + GetRealVertScrollRect(sb, rect); + } +} + +// +// Left button click in the non-client area +// +void SkinnedScrollWnd::OnNcLButtonDown(UINT nHitTest, POINTS pts) +{ + RECT rect, winrect; + SCROLLBAR *psb; + + hwndCurCoolSB = hwnd; + + // + // HORIZONTAL SCROLLBAR PROCESSING + // + if (HTHSCROLL == nHitTest) + { + psb = psbHorz; + uScrollTimerMsg = WM_HSCROLL; + uCurrentScrollbar = SB_HORZ; + //get the total area of the normal Horz scrollbar area + GetHScrollRect(this, &rect); + uCurrentScrollPortion = GetHorzPortion(psbHorz, hwnd, &rect, pts.x, pts.y, scrollFlags); + } + // + // VERTICAL SCROLLBAR PROCESSING + // + else if (HTVSCROLL== nHitTest) + { + psb = psbVert; + uScrollTimerMsg = WM_VSCROLL; + uCurrentScrollbar = SB_VERT; + //get the total area of the normal Horz scrollbar area + GetVScrollRect(this, &rect); + uCurrentScrollPortion = GetVertPortion(psbVert, hwnd, &rect, pts.x, pts.y, scrollFlags); + } + // + // NORMAL PROCESSING + // + else + { + uCurrentScrollPortion = HTSCROLL_NONE; + __super::WindowProc(WM_NCLBUTTONDOWN, (WPARAM)nHitTest, *(LPARAM*)&pts); + return; + } + + // + // we can now share the same code for vertical + // and horizontal scrollbars + // + switch (uCurrentScrollPortion) + { + //inserted buttons to the left/right + case HTSCROLL_THUMB: + + //if the scrollbar is disabled, then do no further processing + if (!IsScrollbarActive(psb)) return; + + GetRealScrollRect(psb, &rect, scrollFlags); + RotateRect0(psb, &rect); + CalcThumbSize(psb, &rect, &nThumbSize, &nThumbPos, scrollFlags); + RotateRect0(psb, &rect); + + //remember the bounding rectangle of the scrollbar work area + rcThumbBounds = rect; + + trackThumbPos=-1; + psb->fScrollFlags |= CSBS_TRACKING; + psb->scrollInfo.nTrackPos = psb->scrollInfo.nPos; + + if (nHitTest == HTVSCROLL) nThumbMouseOffset = pts.y - nThumbPos; + else nThumbMouseOffset = pts.x - nThumbPos; + + nLastPos = psb->scrollInfo.nPos; + nThumbPos0 = nThumbPos; + + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_POS; + info.nPos = nLastPos; + + SetScrollInfo(hwnd, psb->nBarType, &info, FALSE); + + SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, nLastPos); + //if(sb->fFlatScrollbar) + //{ + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + //} + + break; + + //Any part of the scrollbar + case HTSCROLL_LEFT: + if (psb->fScrollFlags & ESB_DISABLE_LEFT) return; + goto target1; + + case HTSCROLL_RIGHT: + if (psb->fScrollFlags & ESB_DISABLE_RIGHT) return; + goto target1; + + + case HTSCROLL_PAGELEFT: + case HTSCROLL_PAGERIGHT: + +target1: + + //if the scrollbar is disabled, then do no further processing + if (!IsScrollbarActive(psb)) + break; + + //ajust the horizontal rectangle to NOT include + //any inserted buttons + GetRealScrollRect(psb, &rect, scrollFlags); + + SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0); + + // Check what area the mouse is now over : + // If the scroll thumb has moved under the mouse in response to + // a call to SetScrollPos etc, then we don't hilight the scrollbar margin + if (uCurrentScrollbar == SB_HORZ) + uScrollTimerPortion = GetHorzScrollPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags); + else + uScrollTimerPortion = GetVertScrollPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags); + + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + + + //if we aren't hot-tracking, then don't highlight + //the scrollbar thumb unless we click on it + if (uScrollTimerPortion == HTSCROLL_THUMB) uScrollTimerPortion = HTSCROLL_NONE; + + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + + //Post the scroll message!!!! + uScrollTimerPortion = uCurrentScrollPortion; + + //set a timer going on the first click. + //if this one expires, then we can start off a more regular timer + //to generate the auto-scroll behaviour + uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0); + UpdateScrollBars(FALSE); + break; + default: + __super::WindowProc(WM_NCLBUTTONDOWN, (WPARAM)nHitTest, *(LPARAM*)&pts); + return; + + } + + if ((0 == (SWS_COMBOLBOX & scrollFlags)) && hwnd != GetCapture()) + { + ignoreCaptureChange = TRUE; + SetCapture(hwnd); + ignoreCaptureChange = FALSE; + captureSet = TRUE; + + } +} + +// +// Left button released +// +void SkinnedScrollWnd::Emulate_LeftButtonUp(UINT nFlags, POINTS pts, BOOL forwardMessage) +{ + //current scrollportion is the button that we clicked down on + if (uCurrentScrollPortion != HTSCROLL_NONE) + { + RECT rect; + //UINT thisportion; + POINT pt; + RECT winrect; + + SCROLLBAR *psb; + + if (captureSet && (0 == (SWS_COMBOLBOX & scrollFlags)) && hwnd == GetCapture()) + { + ignoreCaptureChange = TRUE; + ReleaseCapture(); + ignoreCaptureChange = FALSE; + } + captureSet = FALSE; + + GetWindowRect(hwnd, &winrect); + POINTSTOPOINT(pt, pts); + + //emulate the mouse input on a scrollbar here... + if (SB_VERT == uCurrentScrollbar) + { + //get the total area of the normal Horz scrollbar area + psb = psbVert; + GetVScrollRect(this, &rect); + } + else + { + //get the total area of the normal Horz scrollbar area + psb = psbHorz; + GetHScrollRect(this, &rect); + } + + //we need to do different things depending on if the + //user is activating the scrollbar itself, or one of + //the inserted buttons + switch (uCurrentScrollPortion) + { + //The scrollbar is active + case HTSCROLL_LEFT: + case HTSCROLL_RIGHT: + case HTSCROLL_PAGELEFT: + case HTSCROLL_PAGERIGHT: + case HTSCROLL_NONE: + KillTimer(hwnd, uScrollTimerId); + case HTSCROLL_THUMB: + UpdateScrollBars(FALSE); + + //In case we were thumb tracking, make sure we stop NOW + if (CSBS_TRACKING & psb->fScrollFlags) + { + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_POS; + info.nPos = nLastPos; + + SetScrollInfo(hwnd, psb->nBarType, &info, FALSE); + SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos); + psb->fScrollFlags &= ~CSBS_TRACKING; + } + + //send the SB_ENDSCROLL message now that scrolling has finished + SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0); + + //adjust the total scroll area to become where the scrollbar + //really is (take into account the inserted buttons) + GetRealScrollRect(psb, &rect, scrollFlags); + OffsetRect(&rect, -winrect.left, -winrect.top); + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + break; + } + + //reset our state to default + uCurrentScrollPortion = HTSCROLL_NONE; + uScrollTimerPortion = HTSCROLL_NONE; + uScrollTimerId = 0; + + uScrollTimerMsg = 0; + uCurrentScrollbar = COOLSB_NONE; + + return; + } + else + { + + /* + // Can't remember why I did this! + if(GetCapture() == hwnd) + { + ReleaseCapture(); + }*/ + } + + //sw->update(); + + if (FALSE != forwardMessage) + { + __super::WindowProc(WM_LBUTTONUP, (WPARAM)nFlags, *(LPARAM*)&pts); + } +} +void SkinnedScrollWnd::OnLButtonUp(UINT nFlags, POINTS pts) +{ + Emulate_LeftButtonUp(nFlags, pts, TRUE); +} + +static int +ListView_ScrollWindow(HWND hwnd, int dy) +{ + RECT rect; + + if (0 == dy) + return NULLREGION; + + if (FALSE == GetClientRect(hwnd, &rect)) + return ERROR; + + if (0 == (LVS_NOCOLUMNHEADER & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + HWND headerWindow; + headerWindow = (HWND)SendMessageW(hwnd, LVM_GETHEADER, 0, 0L); + if (NULL != headerWindow && + 0 != (WS_VISIBLE & GetWindowLongPtrW(headerWindow, GWL_STYLE))) + { + HDLAYOUT headerLayout; + WINDOWPOS headerPos; + + headerLayout.prc = ▭ + headerLayout.pwpos = &headerPos; + SendMessageW(headerWindow, HDM_LAYOUT, 0, (LPARAM)&headerLayout); + } + } + + return ScrollWindowEx(hwnd, 0, dy, &rect, &rect, NULL, NULL, SW_INVALIDATE); +} + +static BOOL ListView_ScrollReportModeVert(HWND hwnd, INT linesVert, BOOL horzBarHidden) +{ + int max, pos, page; + int itemHeight, prevPos, dy; + RECT rect; + unsigned long windowStyle; + + if (0 == linesVert) + return TRUE; + + windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE); + + pos = (int)SendMessageW(hwnd, LVM_GETTOPINDEX, 0, 0L); + max = (int)SendMessageW(hwnd, LVM_GETITEMCOUNT, 0, 0L); + page = (int)SendMessageW(hwnd, LVM_GETCOUNTPERPAGE, 0, 0L); + + if (FALSE == horzBarHidden) + max++; + + if ((linesVert < 0 && pos <= 0) || + (linesVert > 0 && (pos + page) >= max)) + { + return TRUE; + } + + if (linesVert < 0 && (pos + linesVert) < 0) + linesVert = -pos; + else if (linesVert > 0 && (pos + page + linesVert) > max) + linesVert = max - (page + pos); + + rect.left = LVIR_BOUNDS; + if (!SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect)) + return FALSE; + + if (rect.top < 0) + OffsetRect(&rect, 0, -rect.top); + + itemHeight = rect.bottom - rect.top; + + if (0 != (WS_VISIBLE & windowStyle)) + SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE); + + dy = linesVert * itemHeight; + SendMessageW(hwnd, LVM_SCROLL, 0, dy); + + if (0 == (WS_VISIBLE & windowStyle)) + return TRUE; + + SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle); + + prevPos = pos; + pos = (int)SendMessageW(hwnd, LVM_GETTOPINDEX, 0, 0L); + linesVert = pos - prevPos; + + dy = linesVert * itemHeight; + + if (ERROR == ListView_ScrollWindow(hwnd, -dy)) + InvalidateRect(hwnd, NULL, FALSE); + + return TRUE; +} + +static BOOL +ListView_ScrollReportModeVertPx(HWND hwnd, int dy, BOOL horzBarHidden) +{ + int itemHeight, lines; + RECT rect; + unsigned long windowStyle; + + if (0 == dy) + return TRUE; + + windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE); + + rect.left = LVIR_BOUNDS; + if (!SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect)) + return FALSE; + + if (rect.top < 0) + OffsetRect(&rect, 0, -rect.top); + + itemHeight = rect.bottom - rect.top; + + + lines = dy / itemHeight; + if (0 != lines) + { + if (0 != (WS_VISIBLE & windowStyle)) + SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE); + + SendMessageW(hwnd, LVM_SCROLL, 0, lines); + + if (0 != (WS_VISIBLE & windowStyle)) + { + windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE); + windowStyle |= WS_VISIBLE; + SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle); + } + } + + if (0 != (WS_VISIBLE & windowStyle)) + { + if (ERROR == ListView_ScrollWindow(hwnd, -dy)) + InvalidateRect(hwnd, NULL, FALSE); + } + + return TRUE; +} + +// +// This function is called whenever the mouse is moved and +// we are dragging the scrollbar thumb about. +// +static void ThumbTrack(SCROLLBAR *sbar, HWND hwnd, POINTS pts, UINT scrollFlags) +{ + POINT pt; + RECT rc, winrect, rc2; + int thumbpos = nThumbPos; + //int thumbDelta; + int pos; + int siMaxMin = 0; + //UINT flatflag = (CSBS_FLATSB & sbar->fScrollFlags) ? BF_FLAT : 0; + + SCROLLINFO *si; + si = &sbar->scrollInfo; + + POINTSTOPOINT(pt, pts); + MapWindowPoints(hwnd, HWND_DESKTOP, &pt, 1); + + if (SB_VERT == sbar->nBarType) + { + LONG t; + t= pt.x; pt.x = pt.y; pt.y = t; + RotateRect(&rcThumbBounds); + } + + //draw the thumb at whatever position + rc = rcThumbBounds; + + SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST, + rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST); + + int cxH = GetScrollMetric(sbar, SM_CXHORZSB, scrollFlags); + + rc.left += cxH; + rc.right -= cxH; + + //if the mouse is not in a suitable distance of the scrollbar, + //then "snap" the thumb back to its initial position +#ifdef SNAP_THUMB_BACK + if (!PtInRect(&rc2, pt)) + { + thumbpos = nThumbPos0; + } + //otherwise, move the thumb to where the mouse is + else +#endif //SNAP_THUMB_BACK + { + //keep the thumb within the scrollbar limits + thumbpos = pt.x - nThumbMouseOffset; + if (thumbpos < rc.left) thumbpos = rc.left; + if (thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize; + } + + GetClientRect(hwnd, &winrect); + + MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&winrect, 2); + + RotateRect0(sbar, &winrect); + + OffsetRect(&rc, -winrect.left, -winrect.top); + thumbpos -= winrect.left; + + /*if (-1 == trackThumbPos) + thumbDelta = thumbpos - rc.left; + else + thumbDelta = thumbpos - trackThumbPos;*/ + + trackThumbPos = thumbpos; + + //post a SB_TRACKPOS message!!! + siMaxMin = si->nMax - si->nMin; + pos = (siMaxMin > 0) ? MulDiv(thumbpos - rc.left, siMaxMin - si->nPage + 1, rc.right - rc.left - nThumbSize) : (thumbpos - rc.left); + + if (si->nPage == 0) + pos = 0; // this supposed to protect from moving on empty scrollbar + + if (pos != nLastPos) + { + if (SWS_LISTVIEW & scrollFlags) // list view specific + { + // only for listviews + if (sbar->nBarType == SB_HORZ) + { + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_TRACKPOS; + if (GetScrollInfo(hwnd, SB_HORZ, &info)) + { + INT dx = pos - info.nTrackPos; + if (LVS_LIST == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + INT cw = (INT)(INT_PTR)SendMessageW(hwnd, LVM_GETCOLUMNWIDTH, 0, 0L); + dx = dx * cw; + } + SendMessageW(hwnd, LVM_SCROLL, dx, 0); + } + } + else if (sbar->nBarType == SB_VERT) + { + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_TRACKPOS; + if (GetScrollInfo(hwnd, SB_VERT, &info) && pos != info.nTrackPos) + { + INT dy = pos - info.nTrackPos; + if (LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + ListView_ScrollReportModeVert(hwnd, dy, (0 != (SWS_HIDEHSCROLL & scrollFlags))); + } + else + { + SendMessageW(hwnd, LVM_SCROLL, 0, dy); + } + } + } + } + else if ((SWS_TREEVIEW & scrollFlags) && + SB_VERT == sbar->nBarType && + ABS(nLastPos - pos) < 2) + { + INT i, cmd; + i = nLastPos - pos; + cmd = (i < 0) ? SB_LINEDOWN : SB_LINEUP; + if (i < 0) i = -i; + while (i--) + { + SendMessageW(hwnd, WM_VSCROLL, cmd, 0L); + } + } + else + { + si->nTrackPos = pos; + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_TRACKPOS|SIF_POS; + info.nTrackPos = pos; + info.nPos = pos; + + SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE); + SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos); + } + } + + nLastPos = pos; + + if (SB_VERT == sbar->nBarType) RotateRect(&rcThumbBounds); +} + +// +// remember to rotate the thumb bounds rectangle!! +// + +// +// Called when we have set the capture from the NCLButtonDown(...) +// +void SkinnedScrollWnd::OnMouseMove(UINT nFlags, POINTS pts) +{ + RECT rect; + //static UINT lastbutton = 0; + RECT winrect; + //UINT buttonIdx = 0; + SCROLLBAR *psb; + + if (nFlags) + { + if (MK_LBUTTON & nFlags) + { + UpdateScrollBars(TRUE); + } + } + psb = (uCurrentScrollbar == SB_VERT) ? psbVert : psbHorz; + if (CSBS_TRACKING & psb->fScrollFlags) + { + ThumbTrack(psb, hwnd, pts, scrollFlags); + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + return; + } + if (uCurrentScrollPortion == HTSCROLL_NONE) + { + __super::WindowProc(WM_MOUSEMOVE, (WPARAM)nFlags, *(LPARAM*)&pts); + return; + } + else + { + static UINT lastportion = 0; + POINT pt; + + POINTSTOPOINT(pt, pts); + + MapWindowPoints(hwnd, HWND_DESKTOP, &pt, 1); + + GetWindowRect(hwnd, &winrect); + + //get the total area of the normal scrollbar area + GetScrollRect(this, psb->nBarType, &rect); + + //see if we clicked in the inserted buttons / normal scrollbar + //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam)); + UINT thisportion = GetPortion(psb, hwnd, &rect, pt.x, pt.y, scrollFlags); + + //we need to do different things depending on if the + //user is activating the scrollbar itself, or one of + //the inserted buttons + switch (uCurrentScrollPortion) + { + //The scrollbar is active + case HTSCROLL_LEFT: + case HTSCROLL_RIGHT: + case HTSCROLL_THUMB: + case HTSCROLL_PAGELEFT: + case HTSCROLL_PAGERIGHT: + case HTSCROLL_NONE: + + //adjust the total scroll area to become where the scrollbar + //really is (take into account the inserted buttons) + GetRealScrollRect(psb, &rect, scrollFlags); + + OffsetRect(&rect, -winrect.left, -winrect.top); + + if (thisportion != uCurrentScrollPortion) + { + uScrollTimerPortion = HTSCROLL_NONE; + if (lastportion != thisportion) + { + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + } + } + //otherwise, draw the button in its depressed / clicked state + else + { + uScrollTimerPortion = uCurrentScrollPortion; + if (lastportion != thisportion) + { + InvalidateNC(InvalidateFlag_Normal, uCurrentScrollbar); + } + } + break; + } + + lastportion = thisportion; + //lastbutton = buttonIdx; + + //must return zero here, because we might get cursor anomilies + //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam); + + return; + } +} + +// +// We must allocate from in the non-client area for our scrollbars +// Call the default window procedure first, to get the borders (if any) +// allocated some space, then allocate the space for the scrollbars +// if they fit +// +INT SkinnedScrollWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp) +{ + RECT *prc; + INT hcy, vcx, result; + BOOL bSizingDown; + prc = &pncsp->rgrc[0]; + UINT updateBars = -1; + + hcy = GetScrollMetric(psbHorz, SM_CYHORZSB, scrollFlags); + vcx = GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags); + + + if (SWS_UPDATEFRAME & scrollFlags) + { + // need to reset style + DWORD style; + + scrollFlags &= ~SWS_UPDATEFRAME; + style = (DWORD)GetWindowLongPtrW(hwnd, GWL_STYLE); + if ((WS_HSCROLL | WS_VSCROLL) & style) SetWindowLongPtrW(hwnd, GWL_STYLE, style & ~(WS_HSCROLL | WS_VSCROLL)); + CallDefWndProc(WM_NCCALCSIZE, (WPARAM)bCalcValidRects, (LPARAM)pncsp); + if ((WS_HSCROLL | WS_VSCROLL) & style) SetWindowLongPtrW(hwnd, GWL_STYLE, style); + } + + result = __super::OnNcCalcSize(bCalcValidRects, pncsp); + bSizingDown = (bCalcValidRects && + ((pncsp->rgrc[0].right - pncsp->rgrc[0].left) < (pncsp->rgrc[1].right - pncsp->rgrc[1].left) || + (pncsp->rgrc[0].bottom - pncsp->rgrc[0].top) < (pncsp->rgrc[1].bottom - pncsp->rgrc[1].top))); + + + //if there is room, allocate some space for the horizontal scrollbar + //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the + //window before disappearing + if ((psbHorz->fScrollFlags & CSBS_VISIBLE) && (prc->bottom - prc->top) +#ifdef COOLSB_FILLWINDOW + >= +#else + > +#endif + hcy) + { + prc->bottom -= hcy; + if (TRUE != psbHorz->fScrollVisible) + { + psbHorz->fScrollVisible = TRUE; + updateBars = SB_HORZ; + } + } + else + { + if (FALSE != psbHorz->fScrollVisible) + { + psbHorz->fScrollVisible = FALSE; + updateBars = SB_HORZ; + } + } + + //if there is room, allocate some space for the vertical scrollbar + if ((psbVert->fScrollFlags & CSBS_VISIBLE) && (prc->right - prc->left) >= vcx) + { + if (SWS_LEFT & scrollFlags) prc->left += vcx; + else prc->right -= vcx; + if (TRUE != psbVert->fScrollVisible) + { + psbVert->fScrollVisible = TRUE; + updateBars = (SB_HORZ == updateBars) ? SB_BOTH : SB_VERT; + } + + } + else + { + if (FALSE != psbVert->fScrollVisible) + { + psbVert->fScrollVisible = FALSE; + updateBars = (SB_HORZ == updateBars) ? SB_BOTH : SB_VERT; + } + } + + if (-1 != updateBars) + { + if (SWS_COMBOLBOX & scrollFlags) + { + InvalidateNC(InvalidateFlag_RedrawNow, updateBars); + } + else if (bSizingDown) + { + PostMessageW(hwnd, WM_ML_IPC, TRUE, IPC_ML_SKINNEDSCROLLWND_UPDATEBARS); + } + + } + + return result; +} + +void SkinnedScrollWnd::OnNcMouseLeave() +{ + if (HTSCROLL_NONE != scrollPortionHover) + { + scrollPortionHover=HTSCROLL_NONE; + InvalidateNC(InvalidateFlag_Normal, SB_BOTH); + } +} +// +// used for hot-tracking over the scroll buttons +// +void SkinnedScrollWnd::OnNcMouseMove(UINT nHitTest, POINTS pts) +{ + if (!bDoHover) + { + __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts); + return; + } + SCROLLBAR *psb=0; + UINT scrollbar=0; + RECT rect; + + if (psbHorz) psbHorz->fScrollFlags &= ~CSBS_HOVERING; + if (psbVert) psbVert->fScrollFlags &= ~CSBS_HOVERING; + if (HTHSCROLL == nHitTest) + { + psb = psbHorz; + scrollbar = SB_HORZ; + //get the total area of the normal Horz scrollbar area + GetHScrollRect(this, &rect); + } + // + // VERTICAL SCROLLBAR PROCESSING + // + else if (HTVSCROLL== nHitTest) + { + psb = psbVert; + scrollbar = SB_VERT; + //get the total area of the normal Horz scrollbar area + GetVScrollRect(this, &rect); + } + // + // NORMAL PROCESSING + // + else + { + + scrollPortionHover=HTSCROLL_NONE; + __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts); + + return; + } + + if (NULL != psb) + { + psb->fScrollFlags |= CSBS_HOVERING; + UINT thisportion = GetPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags); + if (thisportion != scrollPortionHover) + { + TRACKMOUSEEVENT tracker; + tracker.cbSize = sizeof(tracker); + tracker.hwndTrack = hwnd; + tracker.dwHoverTime=0; + tracker.dwFlags = TME_LEAVE |TME_NONCLIENT; // benski> TME_NONCLIENT doesn't work on NT4.0, and we can work around it anyway + if (TrackMouseEvent(&tracker)) + { + scrollPortionHover=thisportion; + InvalidateNC(InvalidateFlag_Normal, scrollbar); + } + } + } + + __super::WindowProc(WM_NCMOUSEMOVE, nHitTest, *(LPARAM*)&pts); +} + +// +// Timer routine to generate scrollbar messages +// +void SkinnedScrollWnd::OnTimer(UINT_PTR idEvent, TIMERPROC fnTimer) +{ + //let all timer messages go past if we don't have a timer installed ourselves + if (uScrollTimerId != 0) + { + //if the first timer goes off, then we can start a more + //regular timer interval to auto-generate scroll messages + //this gives a slight pause between first pressing the scroll arrow, and the + //actual scroll starting + if (idEvent == COOLSB_TIMERID1) + { + KillTimer(hwnd, uScrollTimerId); + uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0); + return; + } + //send the scrollbar message repeatedly + else if (idEvent == COOLSB_TIMERID2) + { + //need to process a spoof WM_MOUSEMOVE, so that + //we know where the mouse is each time the scroll timer goes off. + //This is so we can stop sending scroll messages if the thumb moves + //under the mouse. + POINT pt; + GetCursorPos(&pt); + MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); + pt.x = POINTTOPOINTS(pt); + OnMouseMove(MK_LBUTTON, MAKEPOINTS(pt.x)); + if (uScrollTimerPortion != HTSCROLL_NONE) SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0); + UpdateScrollBars(TRUE); + return; + } + } + __super::WindowProc(WM_TIMER, (WPARAM)idEvent, (LPARAM)fnTimer); +} + +// +// We must intercept any calls to SetWindowLong, to check if +// left-scrollbars are taking effect or not +// + +static UINT curTool = -1; + +static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam) +{ + return SendMessageW(hwndTT, message, wParam, lParam); +} + +#ifdef COOLSB_TOOLTIPS +#define SendToolTipMessage SendToolTipMessage0 +#else +#define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0 +#endif + +void SkinnedScrollWnd::OnStyleChanged(INT styleType, STYLESTRUCT *pss) +{ + if (styleType == GWL_EXSTYLE) scrollFlags = (scrollFlags & ~SWS_LEFT) | ((WS_EX_LEFTSCROLLBAR & pss->styleNew) ? SWS_LEFT : 0); + __super::OnStyleChanged(styleType, pss); +} + +LRESULT SkinnedScrollWnd::OnEraseBackground(HDC hdc) +{ + if (0 == (CSBS_TRACKING & psbVert->fScrollFlags) && 0 == (CSBS_TRACKING & psbHorz->fScrollFlags) && uCurrentScrollPortion == HTSCROLL_NONE) + { + LRESULT result; + result = __super::WindowProc(WM_ERASEBKGND, (WPARAM)hdc, 0L); + UpdateScrollBars(TRUE); + return result; + } + return __super::WindowProc(WM_ERASEBKGND, (WPARAM)hdc, 0L); +} + + +void SkinnedScrollWnd::OnPrint(HDC hdc, UINT options) +{ + if ((PRF_NONCLIENT & options) && + (0 == (PRF_CHECKVISIBLE & options) || IsWindowVisible(hwnd))) + { + PaintNonClient(hdc); + if (PRF_CLIENT & options) + CallPrevWndProc(WM_PRINT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_CHECKVISIBLE) & options)); + } + else __super::OnPrint(hdc, options); +} + +LRESULT SkinnedScrollWnd::OnListViewScroll(INT dx, INT dy) +{ + if (0 != dy && + 0 != (SWS_LISTVIEW & scrollFlags) && + 0 != (SWS_HIDEHSCROLL & scrollFlags) && + (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax)) + { + DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + if (LVS_REPORT == (LVS_TYPEMASK & windowStyle)) + { + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo)) + { + if (0 == dy || + (scrollInfo.nPos == scrollInfo.nMin && dy < 0) || + (scrollInfo.nPos >= (scrollInfo.nMax - (INT)scrollInfo.nPage) && dy > 0)) + return TRUE; + + RECT rc; + rc.left = LVIR_BOUNDS; + if (SendMessageW(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rc)) + { + dy = dy / (rc.bottom - rc.top); + if (dy < 0) + { + if ((scrollInfo.nPos - dy) < scrollInfo.nMin) + dy = scrollInfo.nMin - scrollInfo.nPos; + } + else if (dy > 0) + { + if ((scrollInfo.nPos + dy) >= (scrollInfo.nMax - (INT)scrollInfo.nPage)) + dy = scrollInfo.nMax - (INT)scrollInfo.nPage - scrollInfo.nPos; + } + + dy = dy * (rc.bottom - rc.top); + + if (0 == dy) + return TRUE; + } + } + } + } + + LRESULT result = __super::WindowProc(LVM_SCROLL, (WPARAM)dx, (LPARAM)dy); + if (result) UpdateScrollBars(TRUE); + return result; +} + +void SkinnedScrollWnd::OnVertScroll(UINT code, UINT pos, HWND hwndSB) +{ + if (0 != (SWS_LISTVIEW & scrollFlags) && + 0 != (SWS_HIDEHSCROLL & scrollFlags) && + (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax)) + { + DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + if (LVS_REPORT == (LVS_TYPEMASK & windowStyle)) + { + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + + switch(code) + { + case SB_LINEDOWN: + scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) + && scrollInfo.nPos >= (scrollInfo.nMax - (INT)scrollInfo.nPage)) + return; + break; + } + } + } + __super::WindowProc(WM_VSCROLL, MAKEWPARAM(code, pos), (LPARAM)hwndSB); +} + + +void SkinnedScrollWnd::OnMouseWheel(INT delta, UINT vtKey, POINTS pts) +{ + if (0 == delta) + return; + + if (0 != (SWS_LISTVIEW & scrollFlags)) + { + DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + if (LVS_REPORT == (LVS_TYPEMASK & windowStyle)) + { + if (0 != (WS_VSCROLL & windowStyle)) + { + unsigned int wheelScroll; + int scrollLines, distance; + + if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheelScroll, 0)) + wheelScroll = 3; + + if (0 == wheelScroll) + return; + + if (WHEEL_PAGESCROLL == wheelScroll) + { + SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(((delta > 0) ? SB_PAGEUP : SB_PAGEDOWN), 0), 0L); + SendMessageW(hwnd, WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), 0L); + return; + } + + distance = delta + wheelCarryover; + scrollLines = distance * (INT)wheelScroll / WHEEL_DELTA; + + wheelCarryover = distance - scrollLines * WHEEL_DELTA / (INT)wheelScroll; + + if (ListView_ScrollReportModeVert(hwnd, -scrollLines, (0 != (SWS_HIDEHSCROLL & scrollFlags)))) + { + InvalidateNC(InvalidateFlag_RedrawNow, SB_VERT); + return; + } + } + else if (0 != (SWS_HIDEHSCROLL & scrollFlags)) + { + return; + } + } + + } + __super::WindowProc(WM_MOUSEWHEEL, MAKEWPARAM(vtKey, delta), *(LPARAM*)&pts); +} + +void SkinnedScrollWnd::UpdateFrame() +{ + if (SWS_UPDATEFRAME & scrollFlags) + { + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW); + } +} + +void SkinnedScrollWnd::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw) +{ + UINT newFlag = scrollFlags & ~SWS_USEFREEFORM; + if (UseFreeformScrollbars()) + newFlag |= SWS_USEFREEFORM; + + if (newFlag != scrollFlags) + { + RECT rcOld; + GetClientRect(hwnd, &rcOld); + + scrollFlags = newFlag; + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOREDRAW); + + } + __super::OnSkinChanged(bNotifyChildren, bRedraw); + + if (FALSE != bRedraw) + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE |RDW_ERASE | RDW_FRAME); +} + +LRESULT SkinnedScrollWnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + /*case SBM_GETSCROLLINFO: + { + SCROLLINFO *scrollInfo = (SCROLLINFO *)lParam; + int x=0; + x=0; + } + break;*/ + + case WM_NCMOUSEMOVE: OnNcMouseMove((UINT)wParam, MAKEPOINTS(lParam)); return 0; + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONUP: if (wParam == HTHSCROLL || wParam == HTVSCROLL) return 0; + break; + case WM_NCLBUTTONDBLCLK: if (wParam != HTHSCROLL && wParam != HTVSCROLL) break; // else fall to the nclbuttondown + case WM_NCLBUTTONDOWN: OnNcLButtonDown((UINT)wParam, MAKEPOINTS(lParam)); return 0; + case WM_NCMOUSELEAVE: + case WM_MOUSELEAVE: OnNcMouseLeave(); break; + case WM_LBUTTONUP: OnLButtonUp((UINT)wParam, MAKEPOINTS(lParam)); return 0; + case WM_MOUSEMOVE: OnMouseMove((UINT)wParam, MAKEPOINTS(lParam)); return 0; + case WM_TIMER: OnTimer((UINT_PTR)wParam, (TIMERPROC)lParam); return 0; + case WM_ERASEBKGND: return OnEraseBackground((HDC)wParam); + case WM_DISPLAYCHANGE: + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + break; + case WM_CAPTURECHANGED: + if (!ignoreCaptureChange) + { + LONG pts = GetMessagePos(); + POINT pt; + POINTSTOPOINT(pt, pts); + MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); + pts = POINTTOPOINTS(pt); + Emulate_LeftButtonUp((UINT)wParam, MAKEPOINTS(pts), FALSE); + } + break; + // sometimes update frame required when this messges arrive + case WM_ACTIVATE: + case WM_SETFOCUS: + case WM_HSCROLL: + { + LRESULT result = __super::WindowProc(uMsg, wParam, lParam); + UpdateFrame(); + return result; + } + break; + case WM_MOUSEWHEEL: + OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), MAKEPOINTS(lParam)); + UpdateFrame(); + return 0; + case WM_VSCROLL: + OnVertScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); + UpdateFrame(); + return 0; + case LVM_SCROLL: + if (SWS_LISTVIEW & scrollFlags) + return OnListViewScroll((INT)wParam, (INT)lParam); + break; + case WM_KEYDOWN: + if (0 != ((SWS_LISTVIEW | SWS_TREEVIEW ) & scrollFlags)) + { + LRESULT result = __super::WindowProc(uMsg, wParam, lParam); + switch(wParam) + { + case VK_PRIOR: + case VK_NEXT: + case VK_UP: + case VK_DOWN: + case VK_HOME: + case VK_END: + UpdateScrollBars(TRUE); + break; + } + return result; + } + break; + case WM_USER + 0x3443: + UpdateScrollBars(TRUE); + break; + } + return __super::WindowProc(uMsg, wParam, lParam); +} + +// +// return the default minimum size of a scrollbar thumb +// +static int WINAPI CoolSB_GetDefaultMinThumbSize(void) +{ + DWORD dwVersion = GetVersion(); + // set the minimum thumb size for a scrollbar. This + // differs between NT4 and 2000, so need to check to see + // which platform we are running under + return (dwVersion >= 0x80000000 && LOBYTE(LOWORD(dwVersion)) >= 5) ? MINTHUMBSIZE_2000 : MINTHUMBSIZE_NT4; +} + +BOOL SkinnedScrollWnd::ShowScrollBar(int wBar, BOOL fShow) +{ + DWORD styleOld, styleNew; + + styleOld = GetWindowLongPtrW(hwnd, GWL_STYLE); + styleNew = styleOld; + + if (wBar == SB_HORZ || wBar == SB_BOTH) + { + psbHorz->fScrollFlags = (psbHorz->fScrollFlags & ~CSBS_VISIBLE) | ((fShow) ? CSBS_VISIBLE : 0); + styleNew = (styleNew & ~WS_HSCROLL) | ((fShow) ? WS_HSCROLL :0); + } + + if (wBar == SB_VERT || wBar == SB_BOTH) + { + psbVert->fScrollFlags = (psbVert->fScrollFlags & ~CSBS_VISIBLE) | ((fShow) ? CSBS_VISIBLE : 0); + styleNew = (styleNew & ~WS_VSCROLL) | ((fShow) ? WS_VSCROLL :0); + } + + if (styleNew != styleOld) + { + SetWindowLongPtrW(hwnd, GWL_STYLE, styleNew); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOREDRAW); + } + + return TRUE; +} + +SkinnedScrollWnd::SkinnedScrollWnd(BOOL bIsDialog) + : SkinnedWnd(bIsDialog), psbHorz(0), psbVert(0), + scrollFlags(0), scrollPortionHover(0), wheelCarryover(0) +{ + if (-1 == bUseUpdateRgn) + { + OSVERSIONINFO osver = {0}; + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (::GetVersionEx(&osver)) + { + bUseUpdateRgn = + ((VER_PLATFORM_WIN32_NT != osver.dwPlatformId || + (osver.dwMajorVersion < 6 && osver.dwMinorVersion != 2))); + bDoHover = !(VER_PLATFORM_WIN32_NT == osver.dwPlatformId && osver.dwMajorVersion == 4); // can't use TrackMouseEvent with non-client areas on Windows NT 4.0 + } + } +} + +BOOL SkinnedScrollWnd::Attach(HWND hwndToSkin) +{ + DWORD style; + + if (!SkinnedWnd::Attach(hwndToSkin)) + return FALSE; + + SetType(SKINNEDWND_TYPE_SCROLLWND); + + psbHorz = (SCROLLBAR*)calloc(1, sizeof(SCROLLBAR)); + psbVert = (SCROLLBAR*)calloc(1, sizeof(SCROLLBAR)); + if (!psbHorz || !psbVert) return FALSE; + + scrollFlags = 0; + wheelCarryover = 0; + + psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO); + psbHorz->scrollInfo.fMask = SIF_ALL; + if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo)) + ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO)); + + psbVert->scrollInfo.cbSize = sizeof(SCROLLINFO); + psbVert->scrollInfo.fMask = SIF_ALL; + if (!GetScrollInfo(hwnd, SB_VERT, &psbVert->scrollInfo)) + ZeroMemory(&psbVert->scrollInfo, sizeof(SCROLLINFO)); + + scrollPortionHover = HTSCROLL_NONE; + + //check to see if the window has left-aligned scrollbars + if (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR) scrollFlags |= SWS_LEFT; + + style = GetWindowLongPtrW(hwnd, GWL_STYLE); + + if (WS_HSCROLL & style) psbHorz->fScrollFlags = CSBS_VISIBLE; + if (WS_VSCROLL & style) psbVert->fScrollFlags = CSBS_VISIBLE; + + psbHorz->nBarType = SB_HORZ; + psbVert->nBarType = SB_VERT; + + //set the default arrow sizes for the scrollbars + psbHorz->nMinThumbSize = CoolSB_GetDefaultMinThumbSize(); + psbVert->nMinThumbSize = psbHorz->nMinThumbSize; + + scrollFlags |= SWS_UPDATEFRAME; + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW); + InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_BOTH); + + return TRUE; +} + +SkinnedScrollWnd::~SkinnedScrollWnd(void) +{ + InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_BOTH); + if (psbHorz) free(psbHorz); + if (psbVert) free(psbVert); + if (hbrChecked) + { + DeleteObject(hbrChecked); + hbrChecked = NULL; + } +} + +void SkinnedScrollWnd::DisableNoScroll(BOOL bDisable) +{ + if (bDisable) scrollFlags |= SWS_DISABLENOSCROLL; + else scrollFlags &= ~SWS_DISABLENOSCROLL; +} +BOOL SkinnedScrollWnd::IsNoScrollDisabled() +{ + return (0 != (SWS_DISABLENOSCROLL & scrollFlags)); +} + +void SkinnedScrollWnd::InvalidateNC(InvalidateFlags invalidate, UINT bars) +{ + HRGN rgnH = NULL, rgnV = NULL; + RECT rc; + int scrollLength; + unsigned int flags; + long frameEdge, clientEdge; + + if (0 != (InvalidateFlag_Frame & invalidate)) + { + flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | + SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_NOREDRAW; + + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, flags); + } + + if (FALSE == GetClientRect(hwnd, &rc)) + return; + + if (SB_HORZ == bars || SB_BOTH == bars) + { + scrollLength = GetScrollMetric(psbHorz, SM_CYVERTSB, scrollFlags); + + clientEdge = rc.bottom; + if (0 != (InvalidateFlag_HorzBarRemoved & invalidate)) + clientEdge -= scrollLength; + + frameEdge = clientEdge + scrollLength; + + rgnH = CreateRectRgn(rc.left, clientEdge, rc.right, frameEdge); + } + else + rgnH = NULL; + + if (SB_VERT == bars || SB_BOTH == bars) + { + scrollLength = GetScrollMetric(psbVert, SM_CXVERTSB, scrollFlags); + + if (0 != (SWS_LEFT & scrollFlags)) + { + clientEdge = rc.left; + if (0 == (InvalidateFlag_VertBarRemoved & invalidate)) + clientEdge -= scrollLength; + } + else + { + clientEdge = rc.right; + if (0 != (InvalidateFlag_VertBarRemoved & invalidate)) + clientEdge -= scrollLength; + + frameEdge = clientEdge + scrollLength; + } + + rgnV = CreateRectRgn(clientEdge, rc.top, frameEdge, rc.bottom); + + if (NULL != rgnV && SB_BOTH == bars) + CombineRgn(rgnH, rgnH, rgnV, RGN_OR); + } + else + rgnV = NULL; + + flags = RDW_INVALIDATE | /*RDW_INTERNALPAINT | RDW_ERASE |*/ RDW_FRAME | RDW_NOCHILDREN; + if (0 != (InvalidateFlag_RedrawNow & invalidate)) + flags |= (RDW_UPDATENOW | RDW_ERASENOW); + + HRGN rgn = ((NULL != rgnH) ? rgnH : rgnV); + if (rgn) + RedrawWindow(hwnd, NULL, rgn, flags); + + if (rgnH) + DeleteRgn(rgnH); + + if (rgnV) + DeleteRgn(rgnV); +} + +void SkinnedScrollWnd::UpdateScrollBars(BOOL fInvalidate) +{ + UINT bars; + InvalidateFlags invalidateFlags; + + SCROLLINFO tsi; + tsi.cbSize = sizeof(SCROLLINFO); + tsi.fMask = SIF_ALL; + + bars = -1; + invalidateFlags = InvalidateFlag_Normal /*| InvalidateFlag_RedrawNow*/; + + if (0 == (SWS_HIDEHSCROLL & scrollFlags)) + { + if (GetScrollInfo(hwnd, SB_HORZ, &tsi) && + memcmp(&tsi, &psbHorz->scrollInfo, sizeof(SCROLLINFO))) + { + memcpy(&psbHorz->scrollInfo, &tsi, sizeof(SCROLLINFO)); + UpdateScrollBar(psbHorz, &invalidateFlags); + + psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO); + psbHorz->scrollInfo.fMask = SIF_ALL; + if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo)) + ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO)); + + bars = SB_HORZ; + } + } + else + { + psbHorz->scrollInfo.cbSize = sizeof(SCROLLINFO); + psbHorz->scrollInfo.fMask = SIF_ALL; + if (!GetScrollInfo(hwnd, SB_HORZ, &psbHorz->scrollInfo)) + ZeroMemory(&psbHorz->scrollInfo, sizeof(SCROLLINFO)); + } + + if (0 == (SWS_HIDEVSCROLL & scrollFlags)) + { + if (GetScrollInfo(hwnd, SB_VERT, &tsi)) + { + if (0 != (SWS_LISTVIEW & scrollFlags) && + LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + if (0 != (SWS_HIDEHSCROLL & scrollFlags)) + { + tsi.nMax = (int)SendMessageW(hwnd, LVM_GETITEMCOUNT, 0, 0L); + tsi.nPage = (unsigned int)SendMessageW(hwnd, LVM_GETCOUNTPERPAGE, 0, 0L); + if(tsi.nMax > 0) + tsi.nMax--; + + // if (psbHorz->scrollInfo.nPage <= (UINT)psbHorz->scrollInfo.nMax) + + } + } + + if (memcmp(&tsi, &psbVert->scrollInfo, sizeof(SCROLLINFO))) + { + memcpy(&psbVert->scrollInfo, &tsi, sizeof(SCROLLINFO)); + + UpdateScrollBar(psbVert, &invalidateFlags); + bars = (SB_HORZ == bars) ? SB_BOTH : SB_VERT; + } + } + } + else + { + psbVert->scrollInfo.cbSize = sizeof(SCROLLINFO); + psbVert->scrollInfo.fMask = SIF_ALL; + if (!GetScrollInfo(hwnd, SB_VERT, &psbVert->scrollInfo)) + ZeroMemory(&psbVert->scrollInfo, sizeof(SCROLLINFO)); + } + + if ((fInvalidate || 0 != (InvalidateFlag_Frame & invalidateFlags)) && + -1 != bars) + { + InvalidateNC(invalidateFlags, bars); + + if (0 != (InvalidateFlag_Frame & invalidateFlags) && + 0 != (SWS_LISTVIEW & scrollFlags) && + LVS_REPORT == (LVS_TYPEMASK & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + if (0 == (LVS_NOCOLUMNHEADER & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + HWND hHeader = (HWND)SendMessageW(hwnd, LVM_GETHEADER, 0, 0L); + if (NULL != hHeader) + { + RECT clientRect; + WINDOWPOS wp; + + GetClientRect(hwnd, &clientRect); + + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + if (0 != GetScrollInfo(hwnd, SB_HORZ, &si)) + clientRect.left -= si.nPos; + + HDLAYOUT layout; + layout.prc = &clientRect; + layout.pwpos = ℘ + if (FALSE != SendMessageW(hHeader, HDM_LAYOUT, 0, (LPARAM)&layout)) + { + if (FALSE == fInvalidate) + wp.flags |= SWP_NOREDRAW; + SetWindowPos(hHeader, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOZORDER | SWP_NOACTIVATE); + } + } + } + } + } +} + +void SkinnedScrollWnd::UpdateScrollBar(SCROLLBAR *psb, InvalidateFlags *invalidateFlags) +{ + SCROLLINFO *psi; + psi = &psb->scrollInfo; + + if ((psi->nPage > (UINT)psi->nMax || (psi->nPage == (UINT)psi->nMax && psi->nMax == 0) || psi->nMax <= psi->nMin)) + { + if (psb->fScrollVisible) + { + if (SWS_DISABLENOSCROLL & scrollFlags) + { + psb->fScrollFlags |= (ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT); + } + else + { + ShowScrollBar(psb->nBarType, FALSE); + *invalidateFlags |= InvalidateFlag_Frame; + if (SB_VERT == psb->nBarType) + *invalidateFlags |= InvalidateFlag_VertBarRemoved; + else + *invalidateFlags |= InvalidateFlag_HorzBarRemoved; + } + } + } + else + { + if ((!psb->fScrollVisible || ((ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT) & psb->fScrollFlags)) && psi->nPage > 0) + { + if ((SWS_DISABLENOSCROLL & scrollFlags) && ((ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT) & psb->fScrollFlags)) + { + psb->fScrollFlags &= ~(ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT); + } + + if (!psb->fScrollVisible) + { + if (SWS_LISTVIEW & scrollFlags) + { + DWORD ws = GetWindowLongPtrW(hwnd, GWL_STYLE); + if (LVS_ICON == (LVS_TYPEMASK & ws) || LVS_SMALLICON == (LVS_TYPEMASK & ws)) + { + switch(LVS_ALIGNMASK & ws) + { + case LVS_ALIGNLEFT: + if (SB_HORZ != psb->nBarType) psb->nBarType = ((SB_BOTH == psb->nBarType) ? SB_HORZ : -1); + break; + case LVS_ALIGNTOP: + if (SB_VERT != psb->nBarType) psb->nBarType = ((SB_BOTH == psb->nBarType) ? SB_VERT : -1); + break; + } + } + } + if (-1 != psb->nBarType) + { + ShowScrollBar(psb->nBarType, TRUE); + *invalidateFlags |= InvalidateFlag_Frame; + if (SB_VERT == psb->nBarType) + *invalidateFlags |= InvalidateFlag_VertBarAppeared; + else + *invalidateFlags |= InvalidateFlag_HorzBarAppeared; + } + } + } + else if (psb->fScrollVisible && 0 == psi->nPage) + { + if (SWS_DISABLENOSCROLL & scrollFlags) + { + psb->fScrollFlags |= (ESB_DISABLE_LEFT | ESB_DISABLE_RIGHT); + } + else + { + ShowScrollBar(psb->nBarType, FALSE); + *invalidateFlags |= InvalidateFlag_Frame; + if (SB_VERT == psb->nBarType) + *invalidateFlags |= InvalidateFlag_VertBarRemoved; + else + *invalidateFlags |= InvalidateFlag_HorzBarRemoved; + } + } + } +} + +void SkinnedScrollWnd::ShowHorzScroll(BOOL fEnable) +{ + scrollFlags = (scrollFlags & ~SWS_HIDEHSCROLL) | ((fEnable) ? 0 : SWS_HIDEHSCROLL); + psbHorz->fScrollFlags = 0; + InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_HORZ); +} + +BOOL SkinnedScrollWnd::IsHorzBarHidden() +{ + return (0 != (SWS_HIDEHSCROLL & scrollFlags)); +} + +BOOL SkinnedScrollWnd::IsVertBarHidden() +{ + return (0 != (SWS_HIDEVSCROLL & scrollFlags)); +} + +void SkinnedScrollWnd::ShowVertScroll(BOOL fEnable) +{ + scrollFlags = (scrollFlags & ~SWS_HIDEVSCROLL) | ((fEnable) ? 0 : SWS_HIDEVSCROLL); + psbVert->fScrollFlags = 0; + InvalidateNC(InvalidateFlag_Frame | InvalidateFlag_RedrawNow, SB_VERT); +} + +BOOL SkinnedScrollWnd::SetMode(UINT nMode) +{ + scrollFlags &= ~(SWS_LISTVIEW | SWS_TREEVIEW | SWS_COMBOLBOX); + switch (0xFF & nMode) + { + case SCROLLMODE_STANDARD_I: return TRUE; + case SCROLLMODE_LISTVIEW_I: scrollFlags |= SWS_LISTVIEW; return TRUE; + case SCROLLMODE_TREEVIEW_I: scrollFlags |= SWS_TREEVIEW; return TRUE; + case SCROLLMODE_COMBOLBOX_I: scrollFlags |= SWS_COMBOLBOX; return TRUE; + } + + return FALSE; +} + +UINT SkinnedScrollWnd::GetMode() +{ + if (0 != (SWS_LISTVIEW & scrollFlags)) + return SCROLLMODE_STANDARD_I; + + if (0 != (SWS_TREEVIEW & scrollFlags)) + return SCROLLMODE_TREEVIEW_I; + + if (0 != (SWS_COMBOLBOX & scrollFlags)) + return SCROLLMODE_COMBOLBOX_I; + + return SCROLLMODE_STANDARD_I; +} + +INT SkinnedScrollWnd::AdjustHover(UINT nHitTest, POINTS pts) +{ + SCROLLBAR *psb = NULL; + RECT rect; + + if (psbHorz) psbHorz->fScrollFlags &= ~CSBS_HOVERING; + if (psbVert) psbVert->fScrollFlags &= ~CSBS_HOVERING; + scrollPortionHover = HTSCROLL_NONE; + + if (HTHSCROLL == nHitTest) + { + psb = psbHorz; + GetHScrollRect(this, &rect); + } + else if (HTVSCROLL== nHitTest) + { + psb = psbVert; + GetVScrollRect(this, &rect); + } + + if (psb) + { + psb->fScrollFlags |= CSBS_HOVERING; + scrollPortionHover = GetPortion(psb, hwnd, &rect, pts.x, pts.y, scrollFlags); + } + return scrollPortionHover; +} + +BOOL SkinnedScrollWnd::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult) +{ + switch (msg) + { + case IPC_ML_SKINNEDSCROLLWND_UPDATEBARS: + UpdateScrollBars((BOOL)param); + *pResult = 1; + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_SHOWHORZBAR: + ShowHorzScroll((BOOL)param); + *pResult = 1; + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_SHOWVERTBAR: + ShowVertScroll((BOOL)param); + *pResult = 1; + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_SETMODE: + *pResult = SetMode((UINT)param); + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_DISABLENOSCROLL: + DisableNoScroll(0 != param); + *pResult = -1; + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_ADJUSTHOVER: + ((SBADJUSTHOVER*)param)->nResult = AdjustHover(((SBADJUSTHOVER*)param)->hitTest, ((SBADJUSTHOVER*)param)->ptMouse); + *pResult = TRUE; + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_GETHORZBARHIDDEN: + *pResult = IsHorzBarHidden(); + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_GETVERTBARHIDDEN: + *pResult = IsVertBarHidden(); + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_GETMODE: + *pResult = GetMode(); + return TRUE; + case IPC_ML_SKINNEDSCROLLWND_GETNOSCROLLDISABLED: + *pResult = IsNoScrollDisabled(); + return TRUE; + } + return __super::OnMediaLibraryIPC(msg, param, pResult); +}
\ No newline at end of file |