winamp/Src/Plugins/General/gen_ml/skinnedbutton.cpp
2024-09-24 14:54:57 +02:00

1343 lines
No EOL
39 KiB
C++

#include "main.h"
#include "./skinnedbutton.h"
#include "../winamp/wa_dlg.h"
#include "./skinning.h"
#include "./stockobjects.h"
#include "./colors.h"
#include "./ml_imagefilter.h"
#include "./ml_imagelist.h"
#include "./resource.h"
#include <math.h>
#include <strsafe.h>
#define MARGIN_TOP 2
#define MARGIN_BOTTOM 2
#define MARGIN_LEFT 6
#define MARGIN_RIGHT 6
#define IMAGE_SPACE 3
#define SPLITAREA_WIDTH 19
#define SPLITAREA_SPACE -5
#define SPLITAREA_SPACE_ALT -3
#define IMAGEFILTER_BLEND 0x00
#define IMAGEFILTER_BLENDPLUSCOLOR 0x01
// internaly used button styles
#define SWBS_SPLITSETMANUAL 0x10000000
#define SWBS_SPLITHOVER 0x20000000
#define SWBS_BUTTONHOVER 0x40000000
// additional colors
typedef struct _EXTENDEDCOLORTABLE
{
BOOL updateRequired;
COLORREF rgbTextBk;
BOOL bTextBkUnified;
COLORREF rgbTextBkDown;
BOOL bTextBkDownUnified;
COLORREF rgbTextDisabled;
COLORREF rgbTextDisabled2; // disabled based on WNDBG
COLORREF rgbText15;
COLORREF rgbText15Down;
COLORREF rgbText75;
COLORREF rgbText75Down;
COLORREF rgbToolBkHigh;
COLORREF rgbToolBkPressed;
} EXTENDEDCOLORTABLE;
typedef struct _IMAGEFILTERPARAM
{
BUTTONPAINTSTRUCT *pbps;
RECT *prcImage;
} IMAGEFILTERPARAM;
extern HMLIMGFLTRMNGR hmlifMngr; // default gen_ml fitler manager
static EXTENDEDCOLORTABLE extendedColors = { TRUE, 0, };
static HWND hoverHWND = NULL;
static BOOL hoverSplit = FALSE;
static HMLIMGLST hmlilSplitter = NULL;
static IMAGEFILTERPARAM imagefilterParam;
static HWND lButtonDownHWND = NULL;
static HMLIMGLST CreateSplitterImageList()
{
HMLIMGLST hmlil = MLImageListI_Create(6, 4, MLILC_COLOR32, 2, 1, 3, hmlifMngr);
if (hmlil)
{
MLIMAGESOURCE_I mlis = {0};
mlis.type = SRC_TYPE_PNG_I;
mlis.hInst = plugin.hDllInstance;
mlis.bpp = 32;
mlis.flags = ISF_FORCE_BPP_I;
mlis.lpszName = MAKEINTRESOURCEW(IDB_SPLITARROW);
MLImageListI_Add(hmlil, &mlis, MLIF_BUTTONBLENDPLUSCOLOR_UID, 0);
mlis.lpszName = MAKEINTRESOURCEW(IDB_SPLITARROW_PRESSED);
MLImageListI_Add(hmlil, &mlis, MLIF_BUTTONBLENDPLUSCOLOR_UID, 0);
}
return hmlil;
}
static void DrawButtonImage(HMLIMGLST hmlil, INT hmlilIndex, RECT *prcImage, BUTTONPAINTSTRUCT *pbps)
{
INT offset;
HIMAGELIST himl = MLImageListI_GetRealList(hmlil);
imagefilterParam.pbps = pbps;
imagefilterParam.prcImage = prcImage;
if (BST_PUSHED & pbps->buttonState)
offset = 10000;
else if (WS_DISABLED & pbps->windowStyle)
offset = 20000;
else if (SWBS_BUTTONHOVER & pbps->skinnedStyle)
offset = 30000;
else
offset = 0;
BOOL bUN;
if (SWBS_TOOLBAR & pbps->skinnedStyle)
{
bUN = TRUE;
offset += 40000;
if (offset == 40000 && (WS_BORDER & pbps->windowStyle))
{
offset = 40000 + 30000;
}
}
else
{
bUN = ((BST_PUSHED & pbps->buttonState) ?
extendedColors.bTextBkDownUnified :
extendedColors.bTextBkUnified);
}
COLORREF colorBk, colorFg;
colorFg = (COLORREF)(INT_PTR)WADlg_getBitmap();
colorBk = (COLORREF)MAKELONG(prcImage->bottom - prcImage->top, ((bUN) ? prcImage->top : 0) + offset);
INT index = MLImageListI_GetRealIndex(hmlil, hmlilIndex, colorBk, colorFg);
if (-1 != index)
ImageList_Draw(himl, index, pbps->hdc, prcImage->left, prcImage->top, ILD_NORMAL);
}
typedef struct _DIBDATA
{
BYTE *pData;
INT bpp;
INT cx;
INT cy;
INT step;
LONG pitch;
BOOL bFree;
} DIBDATA;
static BYTE* GetButtonDib(DIBDATA *pdd, BOOL bPressed)
{
BITMAPINFOHEADER bi;
HBITMAP hbmp;
if (!pdd) return NULL;
ZeroMemory(pdd, sizeof(DIBDATA));
hbmp = WADlg_getBitmap();
if (!hbmp) return NULL;
HDC hdc = (HDC)MlStockObjects_Get(CACHED_DC);
ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
bi.biSize = sizeof(BITMAPINFOHEADER);
if (GetDIBits(hdc, hbmp, 0, 0, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
{
bi.biCompression = BI_RGB;
pdd->bFree = TRUE;
pdd->step = (bi.biBitCount>>3);
pdd->pitch = bi.biWidth * pdd->step;
while (pdd->pitch%4) pdd->pitch++;
pdd->pData = (BYTE*)malloc(7 * pdd->pitch);
pdd->cx = bi.biWidth;
INT o = (bPressed) ? 15 : 0;
pdd->cy = GetDIBits(hdc, hbmp,
((bi.biHeight > 0) ? (bi.biHeight - (11 + o)) : (4 + o)), 7,
pdd->pData, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
if (!pdd->cy)
{
free(pdd->pData);
pdd->pData = NULL;
}
}
return pdd->pData;
}
COLORREF SkinnedButton::GetButtonBkColor(BOOL bPressed, BOOL *pbUnified)
{
DIBDATA dib;
BOOL bUnified = TRUE;
ULONG r(0), g(0), b(0);
int cy;
if (GetButtonDib(&dib, bPressed))
{
cy = dib.cy;
BYTE *line = dib.pData + (dib.step * 4);
DWORD p = *(DWORD*)line;
for (; cy-- != 0; line += dib.pitch)
{
r += line[2];
g += line[1];
b += line[0];
if (bUnified && p != *(DWORD*)line) bUnified = FALSE;
}
if (dib.bFree) free(dib.pData);
}
if (pbUnified) *pbUnified = bUnified;
cy = (dib.cy ? dib.cy : 1);
return RGB(r/cy, g/cy, b/cy);
}
static void UpdateExtendedColorTable()
{
COLORREF fg, bk;
float r;
extendedColors.updateRequired = FALSE;
extendedColors.rgbTextBk = SkinnedButton::GetButtonBkColor(FALSE, &extendedColors.bTextBkUnified);
extendedColors.rgbTextBkDown = SkinnedButton::GetButtonBkColor(TRUE, &extendedColors.bTextBkDownUnified);
extendedColors.rgbTextDisabled = WADlg_getColor(WADLG_BUTTONFG);
r = 77;
do
{
r -= 1;
fg = BlendColors(extendedColors.rgbTextDisabled, extendedColors.rgbTextBk, (COLORREF)r);
} while (GetColorDistance(fg, extendedColors.rgbTextBk) > 70);
extendedColors.rgbTextDisabled = fg;
extendedColors.rgbTextDisabled2 = WADlg_getColor(WADLG_WNDFG);
bk = WADlg_getColor(WADLG_WNDBG);
r = 77;
do
{
r -= 1;
fg = BlendColors(extendedColors.rgbTextDisabled2, bk, (COLORREF)r);
} while (GetColorDistance(fg, bk) > 70);
extendedColors.rgbTextDisabled2 = fg;
fg = WADlg_getColor(WADLG_BUTTONFG);
extendedColors.rgbText15 = BlendColors(fg, extendedColors.rgbTextBk, 40);
extendedColors.rgbText75 = BlendColors(fg, extendedColors.rgbTextBk, 191);
extendedColors.rgbText15Down = BlendColors(fg, extendedColors.rgbTextBkDown, 40);
extendedColors.rgbText75Down = BlendColors(fg, extendedColors.rgbTextBkDown, 191);
fg = WADlg_getColor(WADLG_HILITE);
extendedColors.rgbToolBkHigh = BlendColors(fg, bk, 64);
extendedColors.rgbToolBkPressed = BlendColors(fg, bk, 127);
}
SkinnedButton::SkinnedButton(void) : SkinnedWnd(FALSE)
{
ZeroMemory(&imagelist, sizeof(MLBUTTONIMAGELIST));
}
SkinnedButton::~SkinnedButton(void)
{
}
BOOL SkinnedButton::Attach(HWND hwndButton)
{
if(!SkinnedWnd::Attach(hwndButton)) return FALSE;
SetType(SKINNEDWND_TYPE_BUTTON);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
return TRUE;
}
void SkinnedButton::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw)
{
extendedColors.updateRequired = TRUE;
__super::OnSkinChanged(bNotifyChildren, bRedraw);
}
static void PushButton_DrawBackground(BUTTONPAINTSTRUCT *pbps)
{
if (SWBS_TOOLBAR & pbps->skinnedStyle)
{
SetBkColor(pbps->hdc, pbps->rgbTextBk);
ExtTextOutW(pbps->hdc, 0, 0, ETO_OPAQUE, &pbps->rcPaint, NULL, 0, NULL);
if (WS_BORDER & pbps->windowStyle) FrameRect(pbps->hdc, &pbps->rcClient, (HBRUSH)MlStockObjects_Get(HILITE_BRUSH));
}
else
{
HBITMAP hbmp = WADlg_getBitmap();
if (hbmp)
{
INT stretchModeOld;
INT yoffs = (BST_PUSHED & pbps->buttonState) ? 15 : 0;
HDC hdcSrc = (HDC)MlStockObjects_Get(CACHED_DC);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcSrc, hbmp);
SetBrushOrgEx(pbps->hdc, pbps->rcClient.left, pbps->rcClient.top, NULL);
stretchModeOld = SetStretchBltMode(pbps->hdc, COLORONCOLOR);
if (pbps->rcPaint.top <=4)
{
if (pbps->rcPaint.left <= 4)
BitBlt(pbps->hdc, pbps->rcPaint.left, pbps->rcPaint.top, 4 - pbps->rcPaint.left, 4 - pbps->rcPaint.top,
hdcSrc, pbps->rcPaint.left, pbps->rcPaint.top + yoffs, SRCCOPY); // top left
if (pbps->rcPaint.right > 4 && pbps->rcPaint.left < pbps->rcClient.right - 4)
StretchBlt(pbps->hdc, 4, pbps->rcClient.top, pbps->rcClient.right -4 -4, 4,
hdcSrc, 4, 0 + yoffs, 47-4-4, 4, SRCCOPY); // top center
if (pbps->rcPaint.right >= pbps->rcClient.right - 4)
BitBlt(pbps->hdc, pbps->rcClient.right - 4, pbps->rcPaint.top, 4, 4 - pbps->rcPaint.top,
hdcSrc, 47 - 4, pbps->rcPaint.top + yoffs, SRCCOPY); // top right
}
if (pbps->rcPaint.left <= 4)
StretchBlt(pbps->hdc, 0, 4, 4, pbps->rcClient.bottom - 4 -4, hdcSrc, 0, 4 + yoffs, 4, 15-4-4, SRCCOPY); // left edge
if (pbps->rcPaint.right >= pbps->rcClient.right - 4)
StretchBlt(pbps->hdc, pbps->rcClient.right - 4, pbps->rcClient.top + 4, 4, pbps->rcClient.bottom - 4 - 4, hdcSrc, 47-4,4+yoffs, 4, 15-4-4,SRCCOPY); // right edge
// center
if ((pbps->rcPaint.right > 4 && pbps->rcPaint.left < pbps->rcClient.right - 4) &&
(pbps->rcPaint.bottom > 4 && pbps->rcPaint.top < pbps->rcClient.bottom- 4))
StretchBlt(pbps->hdc, 4, 4, pbps->rcClient.right-4-4, pbps->rcClient.bottom -4 -4,
hdcSrc, 4,4+yoffs,47-4-4,15-4-4,SRCCOPY);
if (pbps->rcPaint.bottom >= pbps->rcClient.bottom - 4)
{
if (pbps->rcPaint.left <= 4)
BitBlt(pbps->hdc, 0, pbps->rcClient.bottom-4,4,4, hdcSrc, 0, 15-4+yoffs, SRCCOPY); // bottom left
if (pbps->rcPaint.right > 4 && pbps->rcPaint.left < pbps->rcClient.right - 4)
StretchBlt(pbps->hdc, 4, pbps->rcClient.bottom-4, pbps->rcClient.right-4-4,4, hdcSrc, 4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center
if (pbps->rcPaint.right >= pbps->rcClient.right - 4)
BitBlt(pbps->hdc, pbps->rcClient.right - 4, pbps->rcClient.bottom - 4, 4, 4, hdcSrc, 47-4, 15-4+yoffs, SRCCOPY); // bottom right
}
SelectObject(hdcSrc, hbmpOld);
if (COLORONCOLOR != stretchModeOld) SetStretchBltMode(pbps->hdc, stretchModeOld);
}
}
}
static void PushButton_CalulateRects(BUTTONPAINTSTRUCT *pbps, RECT *prcText, RECT *prcImage, INT imageWidth, INT imageHeight)
{
SetRect(prcText, 0, 0, 0, 0);
SetRect(prcImage, 0, 0, 0, 0);
if (!pbps->hImage && !pbps->cchText) return;
if (0 != (0x0F & pbps->textFormat))
{
INT l, t;
if (pbps->cchText)
{
if (FALSE == DrawTextW(pbps->hdc, pbps->szText, pbps->cchText, prcText,
(~0x0F & pbps->textFormat) | DT_CALCRECT))
{
SetRectEmpty(prcText);
}
if (imageWidth) prcText->right += (imageWidth + IMAGE_SPACE);
}
else SetRect(prcText, 0, 0, imageWidth, imageHeight);
if (DT_BOTTOM & pbps->textFormat) t = pbps->rcClient.bottom - prcText->bottom - MARGIN_BOTTOM;
else if (DT_VCENTER & pbps->textFormat) t = pbps->rcClient.top + ((pbps->rcClient.bottom - pbps->rcClient.top) - prcText->bottom)/2;
else t = pbps->rcClient.top + MARGIN_TOP;
if (DT_RIGHT & pbps->textFormat)
{
l = pbps->rcClient.right - prcText->right;
if (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)
l -= (SPLITAREA_WIDTH + SPLITAREA_SPACE);
if (SWBS_SPLITBUTTON & pbps->skinnedStyle)
l -= (SPLITAREA_WIDTH + SPLITAREA_SPACE_ALT);
else
l -= MARGIN_RIGHT;
}
else if (DT_CENTER & pbps->textFormat)
{
int w = pbps->rcClient.right - pbps->rcClient.left;
if (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)
{
w -= (SPLITAREA_WIDTH + SPLITAREA_SPACE);
}
else if (SWBS_SPLITBUTTON & pbps->skinnedStyle)
{
w -= (SPLITAREA_WIDTH + SPLITAREA_SPACE_ALT);
}
l = pbps->rcClient.left + (w - prcText->right)/2;
}
else
l = pbps->rcClient.left + MARGIN_LEFT;
if (BST_PUSHED & pbps->buttonState && (0 == (BS_PUSHLIKE & pbps->windowStyle)))
{
if (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle) t++;
else
{
l++;
if (SWBS_TOOLBAR & pbps->skinnedStyle) t++;
}
}
OffsetRect(prcText, l, t);
}
else
{
SetRect(prcText, MARGIN_LEFT , MARGIN_TOP,
pbps->rcClient.right - MARGIN_RIGHT, pbps->rcClient.bottom - MARGIN_BOTTOM);
if (0 != (BST_PUSHED & pbps->buttonState))
prcText +=1;
}
// Fit Text Rect
if (prcText->top < (pbps->rcClient.top + MARGIN_TOP))
{
LONG h = prcText->bottom - prcText->top;
prcText->top = pbps->rcClient.top + MARGIN_TOP;
if ((BST_PUSHED & pbps->buttonState) && (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)) prcText->top++;
prcText->bottom = prcText->top + h;
}
if (prcText->bottom > (pbps->rcClient.bottom - MARGIN_BOTTOM)) prcText->bottom = pbps->rcClient.bottom - MARGIN_BOTTOM;
if (prcText->left < (pbps->rcClient.left + MARGIN_LEFT))
{
LONG w = prcText->right - prcText->left;
prcText->left = pbps->rcClient.left + MARGIN_LEFT;
if ((BST_PUSHED & pbps->buttonState) && 0 == (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)) prcText->left++;
prcText->right = prcText->left + w - ((BST_PUSHED & pbps->buttonState) ? 1 : 0);
}
int lim = pbps->rcClient.right;
if (SWBS_SPLITBUTTON & pbps->skinnedStyle)
{
lim -= (SPLITAREA_WIDTH + SPLITAREA_SPACE_ALT);
if (BST_PUSHED & pbps->buttonState) lim++;
}
else if (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)
lim -= (SPLITAREA_WIDTH + SPLITAREA_SPACE);
else
lim -= MARGIN_RIGHT;
if (prcText->right > lim) prcText->right = lim;
if (imageHeight && imageWidth)
{
INT top;
if (prcText->left + imageWidth > prcText->right) imageWidth = prcText->right - prcText->left;
top = prcText->top;
if (prcText->top + imageHeight > prcText->bottom)
{
if ((DT_BOTTOM | DT_VCENTER) & pbps->textFormat)
{
if (DT_BOTTOM & pbps->textFormat) top = prcText->bottom -imageHeight;
else top += ((prcText->bottom - prcText->top) - imageHeight) / 2;
if (top < pbps->rcClient.top + MARGIN_TOP) top = pbps->rcClient.top + MARGIN_TOP;
}
if (top + imageHeight > (pbps->rcClient.bottom - MARGIN_BOTTOM)) imageHeight = pbps->rcClient.bottom - top - MARGIN_BOTTOM;
}
if ((DT_VCENTER & pbps->textFormat) && (prcText->bottom - top) > imageHeight)
top += ((prcText->bottom - top) - imageHeight)/2;
SetRect(prcImage, prcText->left, top, prcText->left + imageWidth, top + imageHeight);
prcText->left += (imageWidth + IMAGE_SPACE);
}
}
void SkinnedButton::DrawPushButton(BUTTONPAINTSTRUCT *pbps)
{
RECT rcText, rcImage;
SetRect(&rcText, 0, 0, 0, 0);
SetRect(&rcImage, 0, 0, 0, 0);
if (pbps->hImage)
{
if (-1 == pbps->imageIndex)
{
BITMAP bi;
if (GetObjectW(pbps->hImage, sizeof(BITMAP), &bi)) { rcImage.right = bi.bmWidth; rcImage.bottom = bi.bmHeight; }
}
else
{
MLImageListI_GetImageSize((HMLIMGLST)pbps->hImage, (INT*)&rcImage.right, (INT*)&rcImage.bottom);
}
}
PushButton_CalulateRects(pbps, &rcText, &rcImage, rcImage.right, rcImage.bottom);
PushButton_DrawBackground(pbps);
IntersectClipRect(pbps->hdc, pbps->rcClient.left + MARGIN_LEFT, pbps->rcClient.top + MARGIN_TOP,
pbps->rcClient.right - MARGIN_RIGHT, pbps->rcClient.bottom - MARGIN_BOTTOM);
if (rcImage.left != rcImage.right)
{
if (-1 == pbps->imageIndex)
{
HDC hdcSrc = (HDC)MlStockObjects_Get(CACHED_DC);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcSrc, pbps->hImage);
BitBlt(pbps->hdc, rcImage.left, rcImage.top, rcImage.right - rcImage.left, rcImage.bottom - rcImage.top, hdcSrc, 0, 0, SRCCOPY);
SelectObject(hdcSrc, hbmpOld);
}
else DrawButtonImage((HMLIMGLST)pbps->hImage, pbps->imageIndex, &rcImage, pbps);
}
if (0 != pbps->cchText) // draw text
{
INT bkModeOld = SetBkMode(pbps->hdc, TRANSPARENT);
DrawTextW(pbps->hdc, pbps->szText, pbps->cchText, &rcText, (~0x0F & pbps->textFormat) | DT_WORD_ELLIPSIS | DT_NOCLIP);
if (TRANSPARENT != bkModeOld) SetBkMode(pbps->hdc, bkModeOld);
}
if ((BST_FOCUS & pbps->buttonState) ||(SWBS_SPLITBUTTON & pbps->skinnedStyle))
{
HRGN rgn;
rgn = CreateRectRgnIndirect(&pbps->rcClient);
SelectClipRgn(pbps->hdc, rgn);
DeleteObject(rgn);
}
if ((SWBS_SPLITBUTTON | SWBS_DROPDOWNBUTTON) & pbps->skinnedStyle)
{
if (NULL == hmlilSplitter) hmlilSplitter = CreateSplitterImageList();
if (hmlilSplitter)
{
RECT rs;
INT left = pbps->rcClient.right - SPLITAREA_WIDTH;
if ((BST_PUSHED & pbps->buttonState) && 0 == (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)) left++;
SetRect(&rs, 0, 0, 0, 0);
MLImageListI_GetImageSize(hmlilSplitter, (INT*)&rs.right, (INT*)&rs.bottom);
OffsetRect(&rs, left + (SPLITAREA_WIDTH - rs.right)/2 - (SPLITAREA_WIDTH - rs.right)%2,
pbps->rcClient.top + (pbps->rcClient.bottom - pbps->rcClient.top - rs.bottom)/2 + 1 +
((SWBS_SPLITPRESSED & pbps->skinnedStyle) ? 1 : 0));
if (rs.left > (pbps->rcClient.left + 4) && rs.top > (pbps->rcClient.top + 2))
DrawButtonImage(hmlilSplitter, ((SWBS_SPLITPRESSED | SWBS_SPLITHOVER) & pbps->skinnedStyle) ? 1 : 0,
&rs, pbps);
if (SWBS_SPLITBUTTON & pbps->skinnedStyle)
{
HPEN pen = (HPEN)GetStockObject(DC_PEN);
HPEN penOld = (HPEN)SelectObject(pbps->hdc, pen);
SetDCPenColor(pbps->hdc, (BST_PUSHED & pbps->buttonState) ? extendedColors.rgbText75Down :
((WS_DISABLED & pbps->windowStyle)? extendedColors.rgbText15 : extendedColors.rgbText75));
MoveToEx(pbps->hdc, left, pbps->rcClient.top + (MARGIN_TOP + 1), NULL);
LineTo(pbps->hdc, left, pbps->rcClient.bottom - (MARGIN_BOTTOM + 1));
left++;
SetDCPenColor(pbps->hdc, (BST_PUSHED & pbps->buttonState) ? extendedColors.rgbText15Down : extendedColors.rgbText15);
MoveToEx(pbps->hdc, left, pbps->rcClient.top + (MARGIN_TOP + 1), NULL);
LineTo(pbps->hdc, left, pbps->rcClient.bottom - (MARGIN_BOTTOM + 1));
if (SWBS_SPLITPRESSED & pbps->skinnedStyle)
{
MoveToEx(pbps->hdc, left, pbps->rcClient.top + (MARGIN_TOP + 1), NULL);
LineTo(pbps->hdc, pbps->rcClient.right - 2, pbps->rcClient.top + (MARGIN_TOP + 1));
}
SelectObject(pbps->hdc, penOld);
}
}
}
if (BST_FOCUS & pbps->buttonState)
{
if (SWBS_TOOLBAR & pbps->skinnedStyle)
{
FrameRect(pbps->hdc, &pbps->rcClient, (HBRUSH)MlStockObjects_Get(HILITE_BRUSH));
}
else
{
COLORREF fg, bk;
RECT rf;
SetRect(&rf, pbps->rcClient.left + 2, pbps->rcClient.top + 2, pbps->rcClient.right - 2, pbps->rcClient.bottom - 2);
if (SWBS_SPLITBUTTON & pbps->skinnedStyle) rf.right = pbps->rcClient.right - SPLITAREA_WIDTH - 1;
fg = SetTextColor(pbps->hdc, GetSysColor(COLOR_WINDOWTEXT));
bk = SetBkColor(pbps->hdc, GetSysColor(COLOR_WINDOW));
DrawFocusRect(pbps->hdc, &rf);
SetTextColor(pbps->hdc, fg);
SetBkColor(pbps->hdc, bk);
}
}
}
void SkinnedButton::DrawGroupBox(BUTTONPAINTSTRUCT *pbps)
{
}
void SkinnedButton::DrawCheckBox(BUTTONPAINTSTRUCT *pbps)
{
ExtTextOutW(pbps->hdc, 0, 0, ETO_OPAQUE, &pbps->rcPaint, L"", 0, NULL);
if (pbps->cchText) DrawTextW(pbps->hdc, pbps->szText, pbps->cchText, &pbps->rcClient, pbps->textFormat);
}
void SkinnedButton::DrawRadioButton(BUTTONPAINTSTRUCT *pbps)
{
ExtTextOutW(pbps->hdc, 0, 0, ETO_OPAQUE, &pbps->rcPaint, L"", 0, NULL);
if (pbps->cchText) DrawTextW(pbps->hdc, pbps->szText, pbps->cchText, &pbps->rcClient, pbps->textFormat);
}
void SkinnedButton::DrawButton(BUTTONPAINTSTRUCT *pbps)
{
HFONT hfo(NULL);
COLORREF rgbTextOld, rgbTextBkOld;
if (pbps->hFont) hfo = (HFONT)SelectObject(pbps->hdc, pbps->hFont);
rgbTextOld = SetTextColor(pbps->hdc, pbps->rgbText);
rgbTextBkOld = SetBkColor(pbps->hdc, pbps->rgbTextBk);
INT type;
if (BS_PUSHLIKE & pbps->windowStyle) type = BS_PUSHBUTTON;
else type = (BS_TYPEMASK & pbps->windowStyle);
switch(type)
{
case BS_3STATE:
case BS_AUTO3STATE:
case BS_AUTOCHECKBOX:
case BS_CHECKBOX:
DrawCheckBox(pbps);
break;
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
DrawRadioButton(pbps);
break;
case BS_GROUPBOX:
DrawGroupBox(pbps);
break;
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON:
DrawPushButton(pbps);
break;
}
SetTextColor(pbps->hdc, rgbTextOld);
SetBkColor(pbps->hdc, rgbTextBkOld);
if (NULL != hfo) SelectObject(pbps->hdc, hfo);
}
void SkinnedButton::PrePaint(HWND hwnd, BUTTONPAINTSTRUCT *pbps, UINT skinStyle, UINT uiState)
{
GetClientRect(hwnd, &pbps->rcClient);
pbps->windowStyle = (UINT)GetWindowLongPtrW(hwnd, GWL_STYLE);
pbps->buttonState = (UINT)SendMessageW(hwnd, BM_GETSTATE, 0, 0L);
pbps->skinnedStyle = skinStyle;
if (hoverHWND == hwnd)
{
if (hoverSplit) pbps->skinnedStyle |= SWBS_SPLITHOVER;
else pbps->skinnedStyle |= SWBS_BUTTONHOVER;
}
if ((BST_FOCUS & pbps->buttonState) && (0x01/*UISF_HIDEFOCUS*/ & uiState))
{
pbps->buttonState &= ~BST_FOCUS;
}
if (SWBS_DROPDOWNBUTTON & pbps->skinnedStyle)
{
if (hoverHWND == hwnd) pbps->skinnedStyle |= SWBS_BUTTONHOVER;
if (SWBS_SPLITPRESSED & pbps->skinnedStyle) pbps->buttonState |= BST_PUSHED;
}
pbps->textFormat = 0;
pbps->cchText = (INT)SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0L);
if (!IsWindowEnabled(hwnd)) pbps->windowStyle |= WS_DISABLED;
if (extendedColors.updateRequired) UpdateExtendedColorTable();
if (BS_OWNERDRAW == (BS_TYPEMASK & pbps->windowStyle)) pbps->windowStyle = ((pbps->windowStyle & ~BS_OWNERDRAW) | BS_PUSHBUTTON);
INT type;
if (BS_PUSHLIKE & pbps->windowStyle) type = BS_PUSHBUTTON;
else type = (BS_TYPEMASK & pbps->windowStyle);
switch(type)
{
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON:
if (SWBS_TOOLBAR & pbps->skinnedStyle)
{
BOOL bChecked = (BS_PUSHLIKE & pbps->windowStyle) ? (BST_CHECKED == SendMessageW(hwnd, BM_GETCHECK, 0, 0L)) : FALSE;
if ((BST_PUSHED & pbps->buttonState) || hoverHWND == hwnd || bChecked) pbps->windowStyle |= WS_BORDER;
if (BST_PUSHED & pbps->buttonState)
pbps->rgbTextBk = extendedColors.rgbToolBkPressed;
else if (hoverHWND == hwnd || bChecked) pbps->rgbTextBk = extendedColors.rgbToolBkHigh;
else pbps->rgbTextBk = WADlg_getColor(WADLG_WNDBG);
pbps->rgbText = WADlg_getColor(WADLG_WNDFG);
}
else
{
pbps->rgbTextBk = (BST_PUSHED & pbps->buttonState) ? extendedColors.rgbTextBkDown : extendedColors.rgbTextBk;
pbps->rgbText = (WS_DISABLED & pbps->windowStyle) ? extendedColors.rgbTextDisabled : WADlg_getColor(WADLG_BUTTONFG);
}
break;
default:
pbps->rgbTextBk = WADlg_getColor(WADLG_WNDBG);
pbps->rgbText = (WS_DISABLED & pbps->windowStyle) ? extendedColors.rgbTextDisabled2 : WADlg_getColor(WADLG_WNDFG);
break;
}
if (pbps->cchText)
{
if (pbps->cchText > BUTTON_TEXT_MAX) pbps->cchText = BUTTON_TEXT_MAX;
SendMessageW(hwnd, WM_GETTEXT, (WPARAM)BUTTON_TEXT_MAX, (LPARAM)pbps->szText);
pbps->hFont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0L);
if (NULL == pbps->hFont) pbps->hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
if ( 0 == (BS_MULTILINE & pbps->windowStyle)) pbps->textFormat |= DT_SINGLELINE;
if (0x02/*UISF_HIDEACCEL*/ & uiState) pbps->textFormat |= 0x00100000 /*DT_HIDEPREFIX*/;
}
MLBUTTONIMAGELIST buttonIL;
if(MLSkinnedButton_GetImageList(hwnd, &buttonIL) && buttonIL.hmlil)
{
pbps->imageIndex = -1;
if (WS_DISABLED & pbps->windowStyle) pbps->imageIndex = buttonIL.disabledIndex;
else if (BST_PUSHED & pbps->buttonState) pbps->imageIndex = buttonIL.pressedIndex;
if (-1 == pbps->imageIndex)
pbps->imageIndex = ((SWBS_BUTTONHOVER & pbps->skinnedStyle) && -1 != buttonIL.hoverIndex) ? buttonIL.hoverIndex : buttonIL.normalIndex;
if (-1 != pbps->imageIndex) pbps->hImage = (HBITMAP)buttonIL.hmlil;
else pbps->hImage = NULL;
}
else
{
pbps->hImage = (HBITMAP)SendMessageW(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0L);
pbps->imageIndex = -1;
}
if (pbps->cchText || pbps->hImage)
{
switch((BS_CENTER & pbps->windowStyle))
{
case BS_LEFT: pbps->textFormat |= DT_LEFT; break;
case BS_RIGHT: pbps->textFormat |= DT_RIGHT; break;
case BS_CENTER: pbps->textFormat |= DT_CENTER; break;
case 0:
switch(BS_TYPEMASK & pbps->windowStyle)
{
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON: pbps->textFormat |= DT_CENTER; break;
default: pbps->textFormat |= DT_LEFT; break;
}
break;
}
switch((BS_VCENTER & pbps->windowStyle))
{
case BS_TOP: pbps->textFormat |= DT_TOP; break;
case BS_BOTTOM: pbps->textFormat |= DT_BOTTOM; break;
case 0:
case BS_VCENTER: pbps->textFormat |= DT_VCENTER; break;
}
}
}
void SkinnedButton::OnPaint()
{
PAINTSTRUCT ps;
BUTTONPAINTSTRUCT bps;
PrePaint(hwnd, &bps, style, uiState);
bps.hdc = BeginPaint(hwnd, &ps);
if (NULL == bps.hdc) return;
CopyRect(&bps.rcPaint, &ps.rcPaint);
DrawButton(&bps);
EndPaint(hwnd, &ps);
}
void SkinnedButton::OnPrintClient(HDC hdc, UINT options)
{
if ((PRF_CLIENT & options) && (0 == (PRF_CHECKVISIBLE & options) || IsWindowVisible(hwnd)))
{
BUTTONPAINTSTRUCT bps;
PrePaint(hwnd, &bps, style, uiState);
bps.hdc = hdc;
CopyRect(&bps.rcPaint, &bps.rcClient);
DrawButton(&bps);
}
}
void SkinnedButton::Emulate_LeftButtonDown(UINT flags, POINTS pts, BOOL forwardMessage)
{
if(SWBS_SPLITBUTTON & style)
{
POINT pt;
RECT rc;
UINT os = (style & ~SWBS_SPLITSETMANUAL);
POINTSTOPOINT(pt, pts);
GetClientRect(hwnd, &rc);
rc.left = rc.right - SPLITAREA_WIDTH;
style &= ~(SWBS_SPLITPRESSED | SWBS_SPLITSETMANUAL);
if (PtInRect(&rc, pt))
{
style |= SWBS_SPLITPRESSED;
if (0 == (SWBS_TOOLBAR & style) && hwnd != GetFocus()) SetFocus(hwnd);
}
if (style != os) InvalidateRect(hwnd, NULL, FALSE);
if (SWBS_SPLITPRESSED & style)
{
return;
}
}
else if (SWBS_DROPDOWNBUTTON & style)
{
UINT os = (style & ~SWBS_SPLITSETMANUAL);
style &= ~SWBS_SPLITSETMANUAL;
style |= SWBS_SPLITPRESSED;
if ( 0 == (SWBS_TOOLBAR & style) && hwnd != GetFocus()) SetFocus(hwnd);
if (style != os) InvalidateRect(hwnd, NULL, FALSE);
return;
}
if (SWBS_TOOLBAR & style)
{
if (lButtonDownHWND != hwnd)
{
lButtonDownHWND = hwnd;
SendMessageW(hwnd, BM_SETSTATE, TRUE, 0L);
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
return;
}
UINT s = (UINT)SendMessageW(hwnd, BM_GETSTATE, 0, 0L);
if (BST_PUSHED & s) return;
if (FALSE != forwardMessage)
{
DisableRedraw();
CallPrevWndProc(WM_LBUTTONDOWN, (WPARAM)flags, *((LONG*)&pts));
EnableRedraw(SWR_INVALIDATE | SWR_UPDATE);
}
}
void SkinnedButton::Emulate_LeftButtonUp(UINT flags, POINTS pts, BOOL forwardMessage)
{
if ((SWBS_DROPDOWNBUTTON | SWBS_SPLITBUTTON) & style)
{
if (SWBS_SPLITPRESSED & style)
{
SendMessageW(GetParent(hwnd), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwnd), MLBN_DROPDOWN), (LPARAM)hwnd);
if (0 == (SWBS_SPLITSETMANUAL &style))
{
style &= ~SWBS_SPLITPRESSED;
InvalidateRect(hwnd, NULL, FALSE);
return;
}
}
}
if (FALSE != forwardMessage)
{
__super::CallPrevWndProc(WM_LBUTTONUP, (WPARAM)flags, *((LONG*)&pts));
}
if (lButtonDownHWND)
{
lButtonDownHWND = FALSE;
HWND hParent = GetParent(hwnd);
SendMessageW(hwnd, BM_SETSTATE, FALSE, 0L);
DWORD ws = GetWindowLongPtrW(hwnd, GWL_STYLE);
INT type = (BS_TYPEMASK & ws);
switch(type)
{
case BS_AUTO3STATE:
case BS_AUTORADIOBUTTON:
case BS_AUTOCHECKBOX:
{
INT state = (INT)SendMessageW(hwnd, BM_GETCHECK, 0, 0L);
if (BS_AUTORADIOBUTTON == type && BST_CHECKED == state) break;
switch(state)
{
case BST_CHECKED:
state = (BS_AUTO3STATE == type) ? BST_INDETERMINATE : BST_UNCHECKED;
break;
case BST_INDETERMINATE:
case BST_UNCHECKED:
state = BST_CHECKED;
break;
}
if (BS_AUTORADIOBUTTON == type)
{
HWND h = hwnd;
wchar_t szClass[32] = {0};
DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
while (NULL != (h = GetWindow(h, GW_HWNDPREV)))
{
if (!GetClassNameW(h, szClass, sizeof(szClass)/sizeof(szClass[0])) ||
CSTR_EQUAL != CompareStringW(lcid, NORM_IGNORECASE, WC_BUTTONW, -1, szClass, -1)) break;
SendMessageW(h, BM_SETCHECK, BST_UNCHECKED, 0L);
if (WS_GROUP & GetWindowLongPtrW(h, GWL_STYLE)) break;
}
SendMessageW(hwnd, BM_SETCHECK, state, 0L);
h = hwnd;
while (NULL != (h = GetWindow(h, GW_HWNDNEXT)))
{
if (!GetClassNameW(h, szClass, sizeof(szClass)/sizeof(szClass[0])) ||
CSTR_EQUAL != CompareStringW(lcid, NORM_IGNORECASE, WC_BUTTONW, -1, szClass, -1)) break;
SendMessageW(h, BM_SETCHECK, BST_UNCHECKED, 0L);
if (WS_GROUP & GetWindowLongPtrW(h, GWL_STYLE)) break;
}
}
else SendMessageW(hwnd, BM_SETCHECK, state, 0L);
}
break;
}
if (hParent)
SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), BN_CLICKED), (LPARAM)hwnd);
}
UpdateWindow(hwnd);
}
void SkinnedButton::OnLButtonDown(UINT flags, POINTS pts)
{
Emulate_LeftButtonDown(flags, pts, TRUE);
}
void SkinnedButton::OnLButtonUp(UINT flags, POINTS pts)
{
Emulate_LeftButtonUp(flags, pts, TRUE);
}
void SkinnedButton::OnMouseMove(UINT flags, POINTS pts)
{
BOOL bInvalidate(FALSE);
if (hwnd != hoverHWND && (!lButtonDownHWND || lButtonDownHWND == hwnd) && (0 == (SWBS_TOOLBAR & style) || IsChild(GetActiveWindow(), hwnd)))
{
if (NULL != hoverHWND && hoverHWND != hwnd) SendMessageW(hoverHWND, WM_MOUSELEAVE, 0, 0L);
hoverHWND = hwnd;
if (lButtonDownHWND == hwnd) SendMessageW(hwnd, BM_SETSTATE, TRUE, 0L);
bInvalidate = TRUE;
hoverSplit = (SWBS_DROPDOWNBUTTON & style);
TRACKMOUSEEVENT track;
track.cbSize = sizeof(TRACKMOUSEEVENT);
track.dwFlags = TME_LEAVE;
track.hwndTrack = hwnd;
track.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&track);
}
if (SWBS_SPLITBUTTON == ((SWBS_SPLITPRESSED | SWBS_SPLITBUTTON) & style))
{
BOOL bSplit;
POINT pt;
RECT rc;
POINTSTOPOINT(pt, pts);
GetClientRect(hwnd, &rc);
rc.left = rc.right - SPLITAREA_WIDTH;
bSplit = PtInRect(&rc, pt);
if (hoverSplit != bSplit)
{
hoverSplit = bSplit;
bInvalidate = TRUE;
}
}
__super::CallPrevWndProc(WM_MOUSEMOVE, (WPARAM)flags, *((LONG*)&pts));
if (bInvalidate)
{
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
}
LRESULT SkinnedButton::GetIdealSize(LPCWSTR pszText)
{
INT cchText;
SIZE szButton;
szButton.cx = 0;
szButton.cy = 0;
cchText = (pszText) ? lstrlenW(pszText) : (INT)SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0L);
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE);
if (hdc)
{
wchar_t szText[BUTTON_TEXT_MAX] = {0};
if (NULL == pszText)
{
SendMessageW(hwnd, WM_GETTEXT, (WPARAM)BUTTON_TEXT_MAX, (LPARAM)szText);
pszText = szText;
}
HFONT hFont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0L);
if (NULL == hFont) hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
HFONT hfo = (NULL != hFont) ? (HFONT)SelectObject(hdc, hFont) : NULL;
if (0 != cchText)
{
RECT rt;
SetRect(&rt, 0, 0, 0, 0);
if (FALSE == DrawTextW(hdc, pszText, cchText, &rt, DT_CALCRECT | DT_SINGLELINE))
{
szButton.cx = 0;
szButton.cy = 0;
}
else
{
szButton.cx = rt.right - rt.left;
szButton.cy = rt.bottom - rt.top;
}
}
else
{
TEXTMETRIC metrics;
szButton.cx = 0;
if (FALSE == GetTextMetrics(hdc, &metrics))
szButton.cy = 0;
else
szButton.cy = metrics.tmHeight;
}
if (0 != szButton.cy)
szButton.cy += (MARGIN_TOP + MARGIN_BOTTOM);
if (0 != szButton.cx)
szButton.cx += (MARGIN_LEFT + MARGIN_RIGHT) + 2;
if (NULL != hfo)
SelectObject(hdc, hfo);
ReleaseDC(hwnd, hdc);
}
}
if (SWBS_DROPDOWNBUTTON & style) szButton.cx += (SPLITAREA_WIDTH + SPLITAREA_SPACE);
if (SWBS_SPLITBUTTON & style) szButton.cx += (SPLITAREA_WIDTH + SPLITAREA_SPACE_ALT);
MLBUTTONIMAGELIST buttonIL;
if(MLSkinnedButton_GetImageList(hwnd, &buttonIL) && buttonIL.hmlil)
{
INT imageCX, imageCY;
if (MLImageListI_GetImageSize(buttonIL.hmlil, &imageCX, &imageCY))
{
imageCY += (MARGIN_TOP + MARGIN_BOTTOM);
if (szButton.cy < imageCY) szButton.cy = imageCY;
szButton.cx += imageCX;
if (szButton.cx != imageCX) szButton.cx += IMAGE_SPACE;
else szButton.cx += (MARGIN_LEFT + MARGIN_RIGHT);
}
}
return MAKELPARAM(szButton.cx, szButton.cy);
}
BOOL SkinnedButton::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult)
{
switch(msg)
{
case ML_IPC_SKINNEDBUTTON_SETIMAGELIST:
ZeroMemory(&imagelist, sizeof(MLBUTTONIMAGELIST));
if (param) CopyMemory(&imagelist, (void*)param, sizeof(MLBUTTONIMAGELIST));
*pResult = TRUE;
InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
case ML_IPC_SKINNEDBUTTON_GETIMAGELIST:
if (!param) *pResult = FALSE;
else
{
CopyMemory((void*)param, &imagelist, sizeof(MLBUTTONIMAGELIST));
*pResult = TRUE;
}
return TRUE;
case ML_IPC_SKINNEDBUTTON_SETDROPDOWNSTATE:
{
UINT os = style;
style &= ~SWBS_SPLITPRESSED;
if (param) style |= SWBS_SPLITPRESSED;
style |= SWBS_SPLITSETMANUAL;
if (style != os) InvalidateRect(hwnd, NULL, FALSE);
}
return TRUE;
case ML_IPC_SKINNEDBUTTON_GETIDEALSIZE:
*pResult = GetIdealSize((LPCWSTR)param);
return TRUE;
}
return __super::OnMediaLibraryIPC(msg, param, pResult);
}
LRESULT SkinnedButton::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (SWS_USESKINCOLORS & style)
{
switch(uMsg)
{
case WM_PAINT: OnPaint(); return 0;
case WM_ERASEBKGND: return 0;
case WM_PRINTCLIENT: OnPrintClient((HDC)wParam, (UINT)lParam); return 0;
case WM_SETFOCUS:
case WM_KILLFOCUS:
case 0x0128/*WM_UPDATEUISTATE*/:
case WM_SETTEXT:
case WM_ENABLE:
{
DisableRedraw();
LRESULT r = __super::WindowProc(uMsg, wParam, lParam);
EnableRedraw(SWR_INVALIDATE | SWR_UPDATE);
return r;
}
case BM_SETSTATE:
if (GetUpdateRect(hwnd, NULL, FALSE)) UpdateWindow(hwnd);
{
LRESULT os = SendMessageW(hwnd, BM_GETSTATE, 0, 0L);
DisableRedraw();
__super::WindowProc(uMsg, wParam, lParam);
EnableRedraw(SWR_NONE);
if (os != SendMessageW(hwnd, BM_GETSTATE, 0, 0L))
{
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
}
break;
case BM_SETCHECK:
if (GetUpdateRect(hwnd, NULL, FALSE)) UpdateWindow(hwnd);
{
LRESULT os = SendMessageW(hwnd, BM_GETCHECK, 0, 0L);
DisableRedraw();
__super::WindowProc(uMsg, wParam, lParam);
EnableRedraw(SWR_NONE);
if (os != SendMessageW(hwnd, BM_GETCHECK, 0, 0L))
{
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
}
break;
case 0x0127/*WM_CHANGEUISTATE*/:
{
if (GetUpdateRect(hwnd, NULL, FALSE)) UpdateWindow(hwnd);
DisableRedraw();
LRESULT r = __super::WindowProc(uMsg, wParam, lParam);
EnableRedraw(SWR_NONE);
return r;
}
case WM_GETDLGCODE:
{
LRESULT r = __super::WindowProc(uMsg, wParam, lParam);
if ((SWBS_SPLITBUTTON | SWBS_DROPDOWNBUTTON) & style)
r |= DLGC_WANTARROWS;
return r;
}
case WM_KEYDOWN:
switch(wParam)
{
case VK_LEFT:
case VK_RIGHT:
if ((SWBS_SPLITBUTTON | SWBS_DROPDOWNBUTTON) & style)
{
HWND hwndParent = GetParent(hwnd);
if (hwndParent) SendMessageW(hwndParent, WM_NEXTDLGCTL, (VK_LEFT == wParam), 0L);
SendMessageW(hwnd, 0x127/*WM_CHANGEUISTATE*/, MAKELONG(2/*UIS_CLEAR*/, 1/*UISF_HIDEFOCUS*/), 0L);
return 0;
}
break;
case VK_DOWN:
case VK_UP:
case VK_SPACE:
if (((SWBS_SPLITBUTTON | SWBS_DROPDOWNBUTTON) & style) &&
1 == LOWORD(lParam) && 0 == (0x40000000 & lParam))
{
RECT rc;
GetClientRect(hwnd, &rc);
if (VK_SPACE != wParam) rc.left = rc.right - SPLITAREA_WIDTH;
OffsetRect(&rc, 1, 1);
LONG pts = POINTTOPOINTS(*(POINT*)&rc);
Emulate_LeftButtonDown(0, MAKEPOINTS(pts), FALSE);
SendMessageW(hwnd, 0x127/*WM_CHANGEUISTATE*/, MAKELONG(2/*UIS_CLEAR*/, 1/*UISF_HIDEFOCUS*/), 0L);
return 0;
}
break;
}
break;
case WM_KEYUP:
switch(wParam)
{
case VK_DOWN:
case VK_UP:
case VK_SPACE:
if (((SWBS_SPLITBUTTON | SWBS_DROPDOWNBUTTON) & style) &&
1 == LOWORD(lParam))
{
RECT rc;
GetClientRect(hwnd, &rc);
if (VK_SPACE != wParam) rc.left = rc.right - SPLITAREA_WIDTH;
OffsetRect(&rc, 1, 1);
LONG pts = POINTTOPOINTS(*(POINT*)&rc);
Emulate_LeftButtonUp(0, MAKEPOINTS(pts), FALSE);
return 0;
}
break;
}
break;
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN: OnLButtonDown((UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_MOUSEMOVE: OnMouseMove((UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_LBUTTONUP: OnLButtonUp((UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_MOUSELEAVE:
if (hwnd == hoverHWND ||
(SWBS_SPLITPRESSED | SWBS_SPLITBUTTON) == ((SWBS_SPLITPRESSED | SWBS_SPLITBUTTON | SWBS_SPLITSETMANUAL) & style))
{
hoverHWND = NULL;
hoverSplit = FALSE;
if (0 == (SWBS_SPLITSETMANUAL &style)) style &= ~SWBS_SPLITPRESSED;
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
if (lButtonDownHWND == hwnd) SendMessageW(hwnd, BM_SETSTATE, FALSE, 0L);
break;
}
}
return __super::WindowProc(uMsg, wParam, lParam);
}
static BOOL CALLBACK ImageFilter(LPBYTE pData, LONG cx, LONG cy, INT bpp, COLORREF rgbBk, COLORREF rgbFg, INT_PTR imageTag, LPARAM lParam)
{
LONG pitch, x, dibPitch;
LPBYTE dib, cursor, line;
HDC hdc, hdcSrc;
HBITMAP hbmp, hbmpOld;
IMAGEFILTERPARAM *param;
param = &imagefilterParam;
if (32 != bpp || !param)
return FALSE;
pitch = cx*4;
hdcSrc = param->pbps->hdc;
rgbFg = param->pbps->rgbText;
rgbBk = param->pbps->rgbTextBk;
BITMAPINFOHEADER bi;
ZeroMemory(&bi, sizeof(bi));
bi.biSize = sizeof(bi);
bi.biWidth = param->pbps->rcClient.right - param->pbps->rcClient.left;
bi.biHeight = -(param->pbps->rcClient.bottom - param->pbps->rcClient.top);
bi.biPlanes = 1;
bi.biBitCount = 32;
hdc = CreateCompatibleDC(NULL);
if (NULL == hdc)
return FALSE;
IntersectClipRect(hdc, param->prcImage->left, param->prcImage->top,
param->prcImage->right, param->prcImage->bottom);
hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (VOID**)&dib, NULL, NULL);
if (NULL == hbmp)
{
DeleteDC(hdc);
return FALSE;
}
hbmpOld = (HBITMAP)SelectObject(hdc, hbmp);
param->pbps->hdc = hdc;
RECT rcPaint;
CopyRect(&rcPaint, &param->pbps->rcPaint);
CopyRect(&param->pbps->rcPaint, param->prcImage);
PushButton_DrawBackground(param->pbps);
param->pbps->hdc = hdcSrc;
CopyRect(&param->pbps->rcPaint, &rcPaint);
SelectObject(hdc, hbmpOld);
DeleteDC(hdc);
dibPitch = 4*(bi.biWidth);
dib += 4*(param->prcImage->left) + param->prcImage->top*dibPitch;
cy = param->prcImage->bottom - param->prcImage->top;
for (line = pData; cy-- != 0; line += pitch, dib += dibPitch )
{
for (x = cx, cursor = line; x-- != 0; cursor += 4)
{
if (IMAGEFILTER_BLENDPLUSCOLOR == lParam)
{
BYTE luma;
luma = 255 - (BYTE)((cursor[2]*30 + cursor[1]*59 + cursor[0]*11)/100);
cursor[0] = GetBValue(rgbFg) - ((GetBValue(rgbFg) - GetBValue(rgbBk))*luma>>8);
cursor[1] = GetGValue(rgbFg) - ((GetGValue(rgbFg) - GetGValue(rgbBk))*luma>>8);
cursor[2] = GetRValue(rgbFg) - ((GetRValue(rgbFg) - GetRValue(rgbBk))*luma>>8);
}
if (0x00 == cursor[3])
{
cursor[0] = dib[0];
cursor[1] = dib[1];
cursor[2] = dib[2];
cursor[3] = 0xFF;
}
else if (cursor[3] != 0xFF)
{
cursor[0] = (cursor[0]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*dib[0] + 127)/255;
cursor[1] = (cursor[1]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*dib[1] + 127)/255;
cursor[2] = (cursor[2]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*dib[2] + 127)/255;
cursor[3] = 0xFF;
}
}
}
DeleteObject(hbmp); ///Last call
return TRUE;
}
BOOL SkinnedButton::RegisterImageFilter(HANDLE filterMananger)
{
BOOL result;
MLIMAGEFILTERINFO_I mlif;
ZeroMemory(&mlif, sizeof(MLIMAGEFILTERINFO_I));
mlif.mask = MLIFF_TITLE_I | MLIFF_FLAGS_I | MLIFF_PROC_I | MLIFF_PARAM_I;
mlif.uid = MLIF_BUTTONBLEND_UID;
mlif.fnProc = ImageFilter;
mlif.pszTitle = L"Button image filter (blend)";
mlif.lParam = IMAGEFILTER_BLEND;
mlif.fFlags = 0;
result = MLImageFilterI_Register((HMLIMGFLTRMNGR)filterMananger, &mlif);
mlif.mask = MLIFF_TITLE_I | MLIFF_FLAGS_I | MLIFF_PROC_I | MLIFF_PARAM_I;
mlif.uid = MLIF_BUTTONBLENDPLUSCOLOR_UID;
mlif.fnProc = ImageFilter;
mlif.pszTitle = L"Button image filter (blend plus color)";
mlif.lParam = IMAGEFILTER_BLENDPLUSCOLOR;
mlif.fFlags = 0;
if (!MLImageFilterI_Register((HMLIMGFLTRMNGR)filterMananger, &mlif)) result = FALSE;
return result;
}