#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 #include #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, ¶m->pbps->rcPaint); CopyRect(¶m->pbps->rcPaint, param->prcImage); PushButton_DrawBackground(param->pbps); param->pbps->hdc = hdcSrc; CopyRect(¶m->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; }