summaryrefslogtreecommitdiff
path: root/alf/alfbutton.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alfbutton.cpp')
-rw-r--r--alf/alfbutton.cpp946
1 files changed, 630 insertions, 316 deletions
diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp
index 579fdce..667287a 100644
--- a/alf/alfbutton.cpp
+++ b/alf/alfbutton.cpp
@@ -1,5 +1,7 @@
#include "alfpriv.h"
+/* Themed "NT" Button for Win2k and up */
+
#define BP_PUSHBUTTON 1
#define PBS_NORMAL 1
#define PBS_HOT 2
@@ -8,36 +10,155 @@
#define PBS_DEFAULTED 5
#define PBS_DEFAULTED_ANIMATING 6
+#define ALF_NTBTN_FLAG_UXTHEME 1
+#define ALF_NTBTN_FLAG_IS_DISABLED 2
+#define ALF_NTBTN_FLAG_IS_DEFAULT 4
+#define ALF_NTBTN_FLAG_IS_HOT 8
+#define ALF_NTBTN_FLAG_IS_FOCUSED 16
+#define ALF_NTBTN_FLAG_IS_PRESSED 32
+#define ALF_NTBTN_FLAG_HIDEFOCUS 64
+#define ALF_NTBTN_FLAG_HIDEACCEL 128
+#define ALF_NTBTN_FLAG_DEFAULT_ANIMATING 256
typedef struct {
- BOOL isDefault;
- BOOL isHot;
+ DWORD drawFlags;
HTHEME hTheme;
int uxStatePrev;
int uxStateCurrent;
- UINT itemStatePrev;
- UINT itemStateCurrent;
+ DWORD uxDrawFlagsCurrent;
+ DWORD uxDrawFlagsPrev;
DWORD uxDefaultAnimationDuration;
- BOOL uxIsDefaultAnimating;
int dpi;
-} ALFButtonPriv;
+ HFONT font;
+} ALFNtButtonPriv;
+
+TCHAR *_alf_buttonClass = NULL;
+
+static ALFNtButtonPriv *
+ALF_NtButton_InitializePriv(void)
+{
+ ALFNtButtonPriv *priv = ALF_New(ALFNtButtonPriv, 1);
+
+ priv->drawFlags = ALF_NTBTN_FLAG_UXTHEME;
+ priv->uxStateCurrent = -1;
+ priv->uxStatePrev = -1;
+ priv->dpi = 96;
+
+ return priv;
+}
+
+static void
+ALF_NtButton_FreePriv(ALFNtButtonPriv *priv)
+{
+ ALF_Compat_CloseThemeData(priv->hTheme);
+ ALF_Free(priv);
+}
+
+static void
+ALF_NtButton_ModifyDrawFlags(HWND hwnd, ALFNtButtonPriv *priv, DWORD add, DWORD remove, BOOL redraw)
+{
+ DWORD newFlags = priv->drawFlags;
+ newFlags |= add;
+ newFlags &= ~remove;
+
+ if (newFlags != priv->drawFlags) {
+ priv->drawFlags = newFlags;
+ if (redraw) {
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ }
+}
+
+static void
+ALF_NtButton_HandleUIState(HWND hwnd, ALFNtButtonPriv *priv)
+{
+ LRESULT uiState = SendMessage(hwnd, WM_QUERYUISTATE, 0, 0);
+ DWORD add = 0;
+ DWORD remove = 0;
+ if (uiState & UISF_HIDEACCEL) {
+ add |= ALF_NTBTN_FLAG_HIDEACCEL;
+ } else {
+ remove |= ALF_NTBTN_FLAG_HIDEACCEL;
+ }
+ if (uiState & UISF_HIDEFOCUS) {
+ add |= ALF_NTBTN_FLAG_HIDEFOCUS;
+ } else {
+ remove |= ALF_NTBTN_FLAG_HIDEFOCUS;
+ }
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, add, remove, TRUE);
+}
+
+static void
+ALF_NtButton_HandleThemeChange(HWND hwnd, ALFNtButtonPriv *priv)
+{
+ ALF_Compat_CloseThemeData(priv->hTheme);
+ priv->hTheme = NULL;
+ if (ALF_Compat_IsAppThemed())
+ priv->hTheme = ALF_Compat_OpenThemeData(hwnd, L"Button");
+ priv->uxDefaultAnimationDuration = 0;
+ ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
+ BP_PUSHBUTTON,
+ PBS_DEFAULTED,
+ PBS_DEFAULTED_ANIMATING,
+ TMT_TRANSITIONDURATION,
+ &priv->uxDefaultAnimationDuration);
+ InvalidateRect(hwnd, NULL, TRUE);
+}
+
+static void
+ALF_NtButton_CalculateSize(HWND hwnd, ALFNtButtonPriv *priv, SIZE *pSize)
+{
+ HDC hdc = GetDC(hwnd);
+ HFONT oldFont = SelectFont(hdc, priv->font);
+
+ // calc drawtext style
+ UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT;
+
+ RECT r = { 0, 0, 0x7FFFFFFF, 100 };
+
+ TCHAR *textbuf = ALF_Text(hwnd);
+
+ DrawText(hdc, textbuf, -1, &r, format);
+
+ ALF_Free(textbuf);
+
+ int xpadding = ALF_Compat_GetSystemMetricsForDpi(SM_CXEDGE,
+ (UINT)priv->dpi) * 2 + 6;
+ int ypadding = ALF_Compat_GetSystemMetricsForDpi(SM_CYEDGE,
+ (UINT)priv->dpi) * 2 + 4;
+
+ if (pSize->cx < r.right - r.left + xpadding) {
+ pSize->cx = r.right - r.left + xpadding;
+ }
+ if (pSize->cy < r.bottom - r.top + ypadding) {
+ pSize->cy = r.bottom - r.top + ypadding;
+ }
+ if (pSize->cx < pSize->cy) {
+ pSize->cx = pSize->cy;
+ }
+
+ SelectFont(hdc, oldFont);
+
+ ReleaseDC(hwnd, hdc);
+}
static void CALLBACK
-ALF__Button_DefaultAnimatingTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+ALF_NtButton_DefaultAnimatingTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
(void)uMsg;
(void)dwTime;
- ALFButtonPriv *priv = (ALFButtonPriv *)idEvent;
+ ALFNtButtonPriv *priv = (ALFNtButtonPriv *)idEvent;
- priv->uxIsDefaultAnimating = !priv->uxIsDefaultAnimating;
- InvalidateRect(hwnd, NULL, FALSE);
+ if (priv->drawFlags & ALF_NTBTN_FLAG_DEFAULT_ANIMATING) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_DEFAULT_ANIMATING, TRUE);
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_DEFAULT_ANIMATING, 0, TRUE);
+ }
}
static BOOL CALLBACK
-ALF__Button_Text_DrawStateProc(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy)
+ALF_NtButton_Text_DrawStateProc(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy)
{
- (void)wData;
-
int oldBkMode = SetBkMode(hdc, TRANSPARENT);
RECT r = { 0, 0, cx, cy };
@@ -49,21 +170,23 @@ ALF__Button_Text_DrawStateProc(HDC hdc, LPARAM lData, WPARAM wData, int cx, int
}
static void
-ALF__Button_RenderUxtheme(HWND hwnd, ALFButtonPriv *priv, int uxstate, UINT itemState, HDC hDC, LPRECT pRcItem)
+ALF_NtButton_RenderUxtheme(HWND hwnd, ALFNtButtonPriv *priv, int uxstate, DWORD drawFlags, HDC hDC, RECT *rcPaint)
{
+ HFONT oldfont = SelectFont(hDC, priv->font);
+
if (ALF_Compat_IsThemeBackgroundPartiallyTransparent(priv->hTheme, BP_PUSHBUTTON, uxstate)) {
- ALF_Compat_DrawThemeParentBackground(hwnd, hDC, pRcItem);
+ ALF_Compat_DrawThemeParentBackground(hwnd, hDC, rcPaint);
}
- RECT r = *pRcItem;
- InflateRect(&r, 1, 1); // HACK! get rid of 1px transparent border
+ RECT r;
+ GetClientRect(hwnd, &r);
- ALF_Compat_DrawThemeBackground(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, &r, pRcItem);
+ ALF_Compat_DrawThemeBackground(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, &r, rcPaint);
RECT content = r;
ALF_Compat_GetThemeBackgroundContentRect(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, &r, &content);
- if ((itemState & ODS_FOCUS) && !(itemState & ODS_NOFOCUSRECT))
+ if ((drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED) && !(drawFlags & ALF_NTBTN_FLAG_HIDEFOCUS))
DrawFocusRect(hDC, &content);
int textlen = GetWindowTextLengthW(hwnd);
@@ -72,7 +195,7 @@ ALF__Button_RenderUxtheme(HWND hwnd, ALFButtonPriv *priv, int uxstate, UINT item
UINT style = DT_CENTER;
- if (itemState & ODS_NOACCEL)
+ if (drawFlags & ALF_NTBTN_FLAG_HIDEACCEL)
style |= DT_HIDEPREFIX;
RECT textbounds = content;
@@ -87,47 +210,56 @@ ALF__Button_RenderUxtheme(HWND hwnd, ALFButtonPriv *priv, int uxstate, UINT item
ALF_Compat_DrawThemeText(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, textbuf, -1, style, 0, &texttarget);
ALF_Free(textbuf);
+
+ SelectFont(hDC, oldfont);
}
static void
-ALF__Button_Render95(HWND hwnd, ALFButtonPriv *priv, LPDRAWITEMSTRUCT dis)
+ALF_NtButton_RenderClassic(HWND hwnd, ALFNtButtonPriv *priv, HDC dc, RECT *rcPaint)
{
- RECT r = dis->rcItem;
+ (void)rcPaint;
+
+ RECT rcClient;
+ GetClientRect(hwnd, &rcClient);
+
+ HFONT oldfont = SelectFont(dc, priv->font);
+
+ RECT r = rcClient;
TCHAR *textbuf = ALF_Text(hwnd);
- if (priv->isDefault) {
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DEFAULT) {
HBRUSH framecolor = GetSysColorBrush(COLOR_WINDOWFRAME);
- FrameRect(dis->hDC, &r, framecolor);
+ FrameRect(dc, &r, framecolor);
InflateRect(&r, -1, -1);
}
UINT dfcs = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
- if (dis->itemState & ODS_SELECTED)
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_PRESSED)
dfcs |= DFCS_FLAT;
- if (dis->itemState & ODS_DISABLED)
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DISABLED)
dfcs |= DFCS_INACTIVE;
- if (dis->itemState & ODS_HOTLIGHT)
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_HOT)
dfcs |= DFCS_HOT;
- DrawFrameControl(dis->hDC, &r, DFC_BUTTON, dfcs);
+ DrawFrameControl(dc, &r, DFC_BUTTON, dfcs);
- if ((dis->itemState & ODS_FOCUS) && !(dis->itemState & ODS_NOFOCUSRECT)) {
+ if ((priv->drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED) && !(priv->drawFlags & ALF_NTBTN_FLAG_HIDEFOCUS)) {
RECT f = r;
InflateRect(&f, -1, -1);
- DrawFocusRect(dis->hDC, &f);
+ DrawFocusRect(dc, &f);
}
- RECT textbounds = dis->rcItem;
- DrawText(dis->hDC, textbuf, -1, &textbounds, DT_LEFT | DT_CALCRECT);
+ RECT textbounds = rcClient;
+ DrawText(dc, textbuf, -1, &textbounds, DT_LEFT | DT_CALCRECT);
- RECT texttarget = dis->rcItem;
- texttarget.top += ((dis->rcItem.bottom - dis->rcItem.top) - (textbounds.bottom - textbounds.top)) / 2 - 1;
- texttarget.left += ((dis->rcItem.right - dis->rcItem.left) - (textbounds.right - textbounds.left)) / 2;
+ RECT texttarget = rcClient;
+ texttarget.top += ((rcClient.bottom - rcClient.top) - (textbounds.bottom - textbounds.top)) / 2 - 1;
+ texttarget.left += ((rcClient.right - rcClient.left) - (textbounds.right - textbounds.left)) / 2;
texttarget.right = texttarget.left + (textbounds.right - textbounds.left);
texttarget.bottom = texttarget.top + (textbounds.bottom - textbounds.top);
- if (dis->itemState & ODS_SELECTED) {
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_PRESSED) {
texttarget.top += 1;
texttarget.left += 1;
texttarget.right += 1;
@@ -136,101 +268,447 @@ ALF__Button_Render95(HWND hwnd, ALFButtonPriv *priv, LPDRAWITEMSTRUCT dis)
UINT style = DT_CENTER;
- if (dis->itemState & ODS_NOACCEL)
+ if (priv->drawFlags & ALF_NTBTN_FLAG_HIDEACCEL)
style |= DT_HIDEPREFIX;
- if (dis->itemState & ODS_DISABLED) {
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DISABLED) {
if (ALF_Compat_IsWin9x()) {
// Win9x just uses gray text. DSS_DISABLED is broken there, too,
// so we can't get the NT look even if we wanted to
- COLORREF oldTextColor = SetTextColor(dis->hDC, GetSysColor(COLOR_GRAYTEXT));
+ COLORREF oldTextColor = SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
POINT oldorg = { 0, 0 };
- SetViewportOrgEx(dis->hDC, texttarget.left, texttarget.top, &oldorg);
- ALF__Button_Text_DrawStateProc(dis->hDC, (LPARAM)textbuf, (WPARAM)style,
+ SetViewportOrgEx(dc, texttarget.left, texttarget.top, &oldorg);
+ ALF_NtButton_Text_DrawStateProc(dc, (LPARAM)textbuf, (WPARAM)style,
texttarget.right - texttarget.left, texttarget.bottom - texttarget.top);
- SetViewportOrgEx(dis->hDC, oldorg.x, oldorg.y, NULL);
+ SetViewportOrgEx(dc, oldorg.x, oldorg.y, NULL);
- SetTextColor(dis->hDC, oldTextColor);
+ SetTextColor(dc, oldTextColor);
} else {
- DrawState(dis->hDC, NULL, ALF__Button_Text_DrawStateProc,
- (LPARAM)textbuf, (WPARAM)style,
- texttarget.left, texttarget.top,
- texttarget.right - texttarget.left, texttarget.bottom - texttarget.top,
- DST_COMPLEX | DSS_DISABLED);
+ DrawState(dc, NULL, ALF_NtButton_Text_DrawStateProc,
+ (LPARAM)textbuf, (WPARAM)style,
+ texttarget.left, texttarget.top,
+ texttarget.right - texttarget.left, texttarget.bottom - texttarget.top,
+ DST_COMPLEX | DSS_DISABLED);
}
} else {
POINT oldorg = { 0, 0 };
- SetViewportOrgEx(dis->hDC, texttarget.left, texttarget.top, &oldorg);
- ALF__Button_Text_DrawStateProc(dis->hDC, (LPARAM)textbuf, (WPARAM)style,
- texttarget.right - texttarget.left, texttarget.bottom - texttarget.top);
- SetViewportOrgEx(dis->hDC, oldorg.x, oldorg.y, NULL);
+ SetViewportOrgEx(dc, texttarget.left, texttarget.top, &oldorg);
+ ALF_NtButton_Text_DrawStateProc(dc, (LPARAM)textbuf, (WPARAM)style,
+ texttarget.right - texttarget.left, texttarget.bottom - texttarget.top);
+ SetViewportOrgEx(dc, oldorg.x, oldorg.y, NULL);
}
+ SelectFont(dc, oldfont);
ALF_Free(textbuf);
}
static void
-ALF__Button_Render3x(HWND hwnd, ALFButtonPriv *priv, LPDRAWITEMSTRUCT dis)
+ALF_NtButton_Paint(HWND hwnd, ALFNtButtonPriv *priv, HDC dc, RECT *r)
{
- RECT r = dis->rcItem;
+ if (!ALF_Compat_BufferedPaintRenderAnimation(hwnd, dc)) {
+ if ((priv->drawFlags & ALF_NTBTN_FLAG_UXTHEME) && priv->hTheme) {
+ // Draw XP style themed button
+ int stateid = PBS_NORMAL;
+
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DEFAULT)
+ stateid = (priv->drawFlags & ALF_NTBTN_FLAG_DEFAULT_ANIMATING) ? PBS_DEFAULTED_ANIMATING : PBS_DEFAULTED;
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_HOT)
+ stateid = PBS_HOT;
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_PRESSED)
+ stateid = PBS_PRESSED;
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DISABLED)
+ stateid = PBS_DISABLED;
+
+ if (priv->uxStatePrev == -1) {
+ // initial draw
+ priv->uxStateCurrent = stateid;
+ priv->uxDrawFlagsCurrent = priv->drawFlags;
+
+ if (priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)
+ priv->uxStateCurrent = PBS_NORMAL;
+ }
+
+ priv->uxStatePrev = priv->uxStateCurrent;
+ priv->uxStateCurrent = stateid;
+ priv->uxDrawFlagsPrev = priv->uxDrawFlagsCurrent;
+ priv->uxDrawFlagsCurrent = priv->drawFlags;
+
+ ALF_Compat_BP_ANIMATIONPARAMS animParams;
+ ZeroMemory(&animParams, sizeof(animParams));
+ animParams.cbSize = sizeof(animParams);
+ animParams.style = ALF_Compat_BPAS_LINEAR;
+
+ if (priv->uxStateCurrent != priv->uxStatePrev) {
+ if ((priv->uxStateCurrent == PBS_DEFAULTED && priv->uxStatePrev == PBS_DEFAULTED_ANIMATING) ||
+ (priv->uxStatePrev == PBS_DEFAULTED && priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)) {
+ animParams.dwDuration = priv->uxDefaultAnimationDuration;
+ } else if (priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING) {
+ // Win7 misses these transition times, use the one for PBS_DEFAULTED
+ ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
+ BP_PUSHBUTTON,
+ priv->uxStatePrev,
+ PBS_DEFAULTED,
+ TMT_TRANSITIONDURATION,
+ &animParams.dwDuration);
+ } else if (priv->uxStatePrev == PBS_DEFAULTED_ANIMATING) {
+ // Win7 misses these transition times, use the one for PBS_DEFAULTED
+ ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
+ BP_PUSHBUTTON,
+ PBS_DEFAULTED,
+ priv->uxStateCurrent,
+ TMT_TRANSITIONDURATION,
+ &animParams.dwDuration);
+ } else {
+ ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
+ BP_PUSHBUTTON,
+ priv->uxStatePrev,
+ priv->uxStateCurrent,
+ TMT_TRANSITIONDURATION,
+ &animParams.dwDuration);
+ }
+
+ if ((priv->uxStatePrev == PBS_DEFAULTED || priv->uxStatePrev == PBS_DEFAULTED_ANIMATING)
+ && !(priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)) {
+ KillTimer(hwnd, (UINT_PTR)priv);
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_DEFAULT_ANIMATING, FALSE);
+ }
+
+ if (!(priv->uxStatePrev == PBS_DEFAULTED || priv->uxStatePrev == PBS_DEFAULTED_ANIMATING)
+ && (priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)
+ && priv->uxDefaultAnimationDuration) {
+ SetTimer(hwnd, (UINT_PTR)priv, priv->uxDefaultAnimationDuration, ALF_NtButton_DefaultAnimatingTimerProc);
+ }
+ }
+
+ HDC hdcFrom = NULL, hdcTo = NULL;
+ ALF_Compat_HANIMATIONBUFFER hbpAnimation;
+
+ hbpAnimation = ALF_Compat_BeginBufferedAnimation(hwnd, dc, r, 0, NULL, &animParams, &hdcFrom, &hdcTo);
+ if (hbpAnimation) {
+ HFONT font = (HFONT)GetCurrentObject(dc, OBJ_FONT);
+
+ if (hdcFrom) {
+ SelectFont(hdcFrom, font);
+ ALF_NtButton_RenderUxtheme(hwnd, priv, priv->uxStatePrev, priv->uxDrawFlagsPrev, hdcFrom, r);
+ }
+
+ if (hdcTo) {
+ SelectFont(hdcTo, font);
+ ALF_NtButton_RenderUxtheme(hwnd, priv, priv->uxStateCurrent, priv->uxDrawFlagsCurrent, hdcTo, r);
+ }
+
+ ALF_Compat_EndBufferedAnimation(hbpAnimation, TRUE);
+ } else {
+ ALF_NtButton_RenderUxtheme(hwnd, priv, stateid, priv->uxDrawFlagsCurrent, dc, r);
+ }
+ } else {
+ // Draw classic unthemed button
+ ALF_NtButton_RenderClassic(hwnd, priv, dc, r);
+ }
+ }
+}
+
+static void
+ALF_NtButton_Clicked(HWND hwnd, ALFNtButtonPriv *priv)
+{
+ (void)priv;
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID), BN_CLICKED), (LPARAM)hwnd);
+}
+
+static LRESULT CALLBACK
+ALF_NtButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ ALFNtButtonPriv *priv = (ALFNtButtonPriv *)GetWindowLongPtr(hwnd, 0);
+
+ if (uMsg == WM_CREATE) {
+ priv = ALF_NtButton_InitializePriv();
+
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv);
+
+ ALF_NtButton_HandleThemeChange(hwnd, priv);
+ ALF_NtButton_HandleUIState(hwnd, priv);
+ } else if (uMsg == ALF_WM_QUERYSIZE) {
+ ALF_NtButton_CalculateSize(hwnd, priv, (SIZE*)lParam);;
+ return TRUE;
+ } else if (uMsg == WM_PAINT) {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+
+ ALF_NtButton_Paint(hwnd, priv, hdc, &ps.rcPaint);
+
+ EndPaint(hwnd, &ps);
+
+ return TRUE;
+ } else if (uMsg == WM_PRINTCLIENT) {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+
+ ALF_NtButton_Paint(hwnd, priv, (HDC)wParam, &rc);
+ } else if (uMsg == WM_GETDLGCODE) {
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DEFAULT) {
+ return DLGC_DEFPUSHBUTTON | DLGC_BUTTON;
+ } else {
+ return DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON;
+ }
+ } else if (uMsg == BM_SETSTYLE) {
+ BOOL newDefault = (wParam & BS_DEFPUSHBUTTON) ? 1 : 0;
+
+ if (newDefault) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_DEFAULT, 0, TRUE);
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_DEFAULT, TRUE);
+ }
+ } else if (uMsg == WM_STYLECHANGED) {
+ BOOL newDefault = (GetWindowLong(hwnd, GWL_STYLE) & BS_DEFPUSHBUTTON) ? 1 : 0;
+
+ if (newDefault) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_DEFAULT, 0, TRUE);
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_DEFAULT, TRUE);
+ }
+ } else if (uMsg == WM_THEMECHANGED) {
+ ALF_NtButton_HandleThemeChange(hwnd, priv);
+ } else if (uMsg == WM_MOUSEMOVE) {
+ if (!(priv->drawFlags & ALF_NTBTN_FLAG_IS_HOT)) {
+ TRACKMOUSEEVENT tme;
+ ZeroMemory(&tme, sizeof(tme));
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ if (ALF_Compat_TrackMouseEvent(&tme)) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_HOT, 0, TRUE);
+ }
+ }
+
+ RECT rcWindow;
+ GetWindowRect(hwnd, &rcWindow);
+
+ DWORD pos = GetMessagePos();
+
+ if (GET_X_LPARAM(pos) >= rcWindow.left && GET_X_LPARAM(pos) < rcWindow.right
+ && GET_Y_LPARAM(pos) >= rcWindow.top && GET_Y_LPARAM(pos) < rcWindow.bottom) {
+ if (wParam & MK_LBUTTON) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_PRESSED, 0, TRUE);
+ }
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+ }
+ } else if (uMsg == WM_MOUSELEAVE) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_HOT, TRUE);
+ } else if (uMsg == WM_SETFOCUS) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_FOCUSED, 0, TRUE);
+ } else if (uMsg == WM_KILLFOCUS) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_FOCUSED | ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+ } else if (uMsg == WM_LBUTTONDOWN) {
+ if (IsWindowEnabled(hwnd)) {
+ if (!(priv->drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED)) {
+ SetFocus(hwnd);
+ }
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_PRESSED, 0, TRUE);
+ SetCapture(hwnd);
+ }
+ return 0;
+ } else if (uMsg == WM_LBUTTONUP) {
+ ReleaseCapture();
+
+ if (IsWindowEnabled(hwnd)) {
+ RECT rcClient;
+ GetClientRect(hwnd, &rcClient);
+
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+
+ if (GET_X_LPARAM(lParam) >= rcClient.left && GET_X_LPARAM(lParam) < rcClient.right
+ && GET_Y_LPARAM(lParam) >= rcClient.top && GET_Y_LPARAM(lParam) < rcClient.bottom) {
+ ALF_NtButton_Clicked(hwnd, priv);
+ }
+ }
+ return 0;
+ } else if (uMsg == WM_KEYDOWN) {
+ if (GetCapture() != hwnd && IsWindowEnabled(hwnd)) {
+ if (wParam == VK_SPACE && LOWORD(lParam) == 1) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_PRESSED, 0, TRUE);
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+ }
+ }
+ } else if (uMsg == WM_KEYUP) {
+ if (GetCapture() != hwnd && IsWindowEnabled(hwnd)) {
+ if (wParam == VK_SPACE) {
+ if (priv->drawFlags & ALF_NTBTN_FLAG_IS_PRESSED) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+ ALF_NtButton_Clicked(hwnd, priv);
+ }
+ }
+ }
+ } else if (uMsg == WM_ERASEBKGND) {
+ return TRUE;
+ } else if (uMsg == WM_SETTEXT) {
+ ALF_InvalidateLayout(GetParent(hwnd));
+ } else if (uMsg == WM_SETFONT) {
+ priv->font = (HFONT)wParam;
+ if (LOWORD(lParam) != 0)
+ InvalidateRect(hwnd, NULL, TRUE);
+
+ ALF_InvalidateLayout(GetParent(hwnd));
+
+ return 0;
+ } else if (uMsg == WM_GETFONT) {
+ return (LRESULT)priv->font;
+ } else if (uMsg == ALF_WM_DPICHANGE) {
+ priv->dpi = (int)lParam;
+ ALF_InvalidateLayout(GetParent(hwnd));
+ return TRUE;
+ } else if (uMsg == WM_SIZE) {
+ InvalidateRect(hwnd, NULL, TRUE);
+ } else if (uMsg == WM_UPDATEUISTATE) {
+ LRESULT rv = DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+ ALF_NtButton_HandleUIState(hwnd, priv);
+
+ return rv;
+ } else if (uMsg == WM_ENABLE) {
+ if (wParam) {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, 0, ALF_NTBTN_FLAG_IS_DISABLED, TRUE);
+ } else {
+ ALF_NtButton_ModifyDrawFlags(hwnd, priv, ALF_NTBTN_FLAG_IS_DISABLED, ALF_NTBTN_FLAG_IS_PRESSED, TRUE);
+ }
+ } else if (uMsg == WM_DESTROY) {
+ ALF_NtButton_FreePriv(priv);
+ priv = NULL;
+ SetWindowLongPtr(hwnd, 0, 0);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+void
+ALF_RegisterButtonClass(void)
+{
+ if (ALF_Compat_IsWin9x() || !ALF_Compat_IsMinWindowsVersion(4, 0))
+ return; // use classic button on Win9x and NT 3.51
+
+ WNDCLASS cls;
+ ZeroMemory(&cls, sizeof(cls));
+
+ TCHAR classNameBuf[256];
+ ALF_BuildUniqueName(classNameBuf, TEXT("ALFNtButton."), (ULONG_PTR)&_alf_buttonClass);
+
+ cls.hInstance = ALF_HINSTANCE;
+ cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW);
+ cls.lpszClassName = classNameBuf;
+ cls.cbWndExtra = sizeof(void*);
+ cls.lpfnWndProc = ALF_NtButton_WndProc;
+
+ ATOM classatom = RegisterClass(&cls);
+ if (!classatom)
+ MessageBox(NULL, TEXT("FATAL: Could not register button class"), NULL, MB_OK);
+
+ _alf_buttonClass = MAKEINTATOM(classatom);
+}
+
+static HWND
+ALF_NtButton_Create(HWND win, WORD id, int x, int y, const TCHAR *text)
+{
+ HWND hwndButton = CreateWindowEx(0,
+ _alf_buttonClass,
+ text,
+ WS_CHILD | WS_TABSTOP | WS_VISIBLE,
+ 0, 0, 100, 100,
+ win,
+ (HMENU)(int)id,
+ ALF_HINSTANCE,
+ NULL);
+
+ ALF_AddWidget(win, x, y, hwndButton, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_SENDDPICHANGE | ALF_LAYOUT_TRANSPARENTBG);
+
+ return hwndButton;
+}
+
+
+/* Classic Button for Win9x and NT3.51 */
+// Win9x/Win32s absolutely needs a real button window, otherwise the dialog manager will get confused
+
+typedef struct {
+ WNDPROC origWndProc;
+ BOOL isDefault;
+} ALFClassicButtonPriv;
+
+static ALFClassicButtonPriv *
+ALF_ClassicButton_InitializePriv(void)
+{
+ return ALF_New(ALFClassicButtonPriv, 1);
+}
+
+static void
+ALF_ClassicButton_FreePriv(ALFClassicButtonPriv *priv)
+{
+ ALF_Free(priv);
+}
+
+static void
+ALF_ClassicButton_CalculateSize(HWND hwnd, SIZE *pSize)
+{
+ HDC hdc = GetDC(hwnd);
+ HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
+ HFONT oldFont = SelectFont(hdc, font);
- ALF_Compat_DrawThemeParentBackground(hwnd, dis->hDC, &r);
+ // calc drawtext style
+ UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT;
+
+ RECT r = { 0, 0, 0x7FFFFFFF, 100 };
TCHAR *textbuf = ALF_Text(hwnd);
- HBRUSH framecolor = GetSysColorBrush(COLOR_WINDOWFRAME);
- HBRUSH facecolor = GetSysColorBrush(COLOR_BTNFACE);
+ DrawText(hdc, textbuf, -1, &r, format);
- // black frame
- if (priv->isDefault) {
- RECT rt = { r.left + 1, r.top, r.right - 1, r.top + 2 };
- RECT rl = { r.left, r.top + 1, r.left + 2, r.bottom - 1 };
- RECT rr = { r.right - 2, r.top + 1, r.right, r.bottom - 1 };
- RECT rb = { r.left + 1, r.bottom - 2, r.right - 1, r.bottom };
- FillRect(dis->hDC, &rt, framecolor);
- FillRect(dis->hDC, &rl, framecolor);
- FillRect(dis->hDC, &rr, framecolor);
- FillRect(dis->hDC, &rb, framecolor);
- InflateRect(&r, -2, -2);
- } else {
- RECT rt = { r.left + 1, r.top, r.right - 1, r.top + 1 };
- RECT rl = { r.left, r.top + 1, r.left + 1, r.bottom - 1 };
- RECT rr = { r.right - 1, r.top + 1, r.right, r.bottom - 1 };
- RECT rb = { r.left + 1, r.bottom - 1, r.right - 1, r.bottom };
- FillRect(dis->hDC, &rt, framecolor);
- FillRect(dis->hDC, &rl, framecolor);
- FillRect(dis->hDC, &rr, framecolor);
- FillRect(dis->hDC, &rb, framecolor);
- InflateRect(&r, -1, -1);
+ ALF_Free(textbuf);
+
+ int xpadding = GetSystemMetrics(SM_CXEDGE) * 2 + 6;
+ int ypadding = GetSystemMetrics(SM_CYEDGE) * 2 + 4;
+
+ if (pSize->cx < r.right - r.left + xpadding) {
+ pSize->cx = r.right - r.left + xpadding;
+ }
+ if (pSize->cy < r.bottom - r.top + ypadding) {
+ pSize->cy = r.bottom - r.top + ypadding;
+ }
+ if (pSize->cx < pSize->cy) {
+ pSize->cx = pSize->cy;
}
- // 3d button
- if (dis->itemState & ODS_SELECTED) {
- DrawEdge(dis->hDC, &r, BDR_SUNKENOUTER, BF_TOPLEFT);
+ SelectFont(hdc, oldFont);
- RECT f = r;
- f.left++;
- f.top++;
+ ReleaseDC(hwnd, hdc);
+}
- FillRect(dis->hDC, &f, facecolor);
+static void
+ALF_ClassicButton_Paint(HWND hwnd, ALFClassicButtonPriv *priv, DRAWITEMSTRUCT *dis)
+{
+ RECT r = dis->rcItem;
- InflateRect(&r, -2, -2);
- } else {
- DrawEdge(dis->hDC, &r, BDR_RAISEDINNER, BF_RECT);
- InflateRect(&r, -1, -1);
- DrawEdge(dis->hDC, &r, BDR_RAISEDINNER, BF_RECT);
- InflateRect(&r, -1, -1);
+ TCHAR *textbuf = ALF_Text(hwnd);
- FillRect(dis->hDC, &r, facecolor);
+ if (priv->isDefault) {
+ HBRUSH framecolor = GetSysColorBrush(COLOR_WINDOWFRAME);
+ FrameRect(dis->hDC, &r, framecolor);
+ InflateRect(&r, -1, -1);
}
+ UINT dfcs = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
+ if (dis->itemState & ODS_SELECTED)
+ dfcs |= DFCS_FLAT;
+ if (dis->itemState & ODS_DISABLED)
+ dfcs |= DFCS_INACTIVE;
+
+ DrawFrameControl(dis->hDC, &r, DFC_BUTTON, dfcs);
+
RECT textbounds = dis->rcItem;
DrawText(dis->hDC, textbuf, -1, &textbounds, DT_LEFT | DT_CALCRECT);
RECT texttarget = dis->rcItem;
- texttarget.top += ((dis->rcItem.bottom - dis->rcItem.top) - (textbounds.bottom - textbounds.top)) / 2;
+ texttarget.top += ((dis->rcItem.bottom - dis->rcItem.top) - (textbounds.bottom - textbounds.top)) / 2 - 1;
texttarget.left += ((dis->rcItem.right - dis->rcItem.left) - (textbounds.right - textbounds.left)) / 2;
texttarget.right = texttarget.left + (textbounds.right - textbounds.left);
texttarget.bottom = texttarget.top + (textbounds.bottom - textbounds.top);
@@ -242,274 +720,110 @@ ALF__Button_Render3x(HWND hwnd, ALFButtonPriv *priv, LPDRAWITEMSTRUCT dis)
texttarget.bottom += 1;
}
- if (dis->itemState & ODS_FOCUS) {
- DrawFocusRect(dis->hDC, &texttarget);
- }
-
- int oldBkMode = SetBkMode(dis->hDC, TRANSPARENT);
+ UINT style = DT_CENTER;
+ COLORREF oldBkColor = SetBkColor(dis->hDC, GetSysColor(COLOR_BTNFACE));
if (dis->itemState & ODS_DISABLED) {
- // FIXME! This is how NT 3.51 does it, but Win 3.1 is different
- COLORREF oldTextColor = SetTextColor(dis->hDC, GetSysColor(COLOR_BTNSHADOW));
+ // Win9x just uses gray text. DSS_DISABLED is broken there, too,
+ // so we can't get the NT look even if we wanted to
+ COLORREF disabledColor = ALF_Compat_IsMinWindowsVersion(4, 0) ? GetSysColor(COLOR_GRAYTEXT) : GetSysColor(COLOR_BTNSHADOW);
+ COLORREF oldTextColor = SetTextColor(dis->hDC, disabledColor);
- DrawText(dis->hDC, textbuf, -1, &texttarget, DT_CENTER);
+ DrawText(dis->hDC, textbuf, -1, &texttarget, style);
SetTextColor(dis->hDC, oldTextColor);
} else {
- DrawText(dis->hDC, textbuf, -1, &texttarget, DT_CENTER);
+ COLORREF oldTextColor = SetTextColor(dis->hDC, GetSysColor(COLOR_BTNTEXT));
+
+ DrawText(dis->hDC, textbuf, -1, &texttarget, style);
+
+ SetTextColor(dis->hDC, oldTextColor);
}
+ SetBkColor(dis->hDC, oldBkColor);
- SetBkMode(dis->hDC, oldBkMode);
+ if (dis->itemState & ODS_FOCUS) {
+ RECT f = r;
+ InflateRect(&f, -1, -1);
+ DrawFocusRect(dis->hDC, &f);
+ }
ALF_Free(textbuf);
}
-/* BUTTON */
static LRESULT CALLBACK
-ALF__ButtonSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+ALF_ClassicButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- (void)uIdSubclass;
- (void)dwRefData;
-
- ALFButtonPriv *priv = (ALFButtonPriv *)dwRefData;
+ ALFClassicButtonPriv *priv = (ALFClassicButtonPriv *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (!priv)
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
if (uMsg == ALF_WM_QUERYSIZE) {
- HDC hdc = GetDC(hwnd);
- HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
- HFONT oldFont = 0;
- if (font)
- oldFont = SelectFont(hdc, font);
-
- // calc drawtext style
- LONG style = GetWindowLong(hwnd, GWL_STYLE);
- UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT;
- if ((style & BS_MULTILINE) == 0)
- format |= DT_SINGLELINE;
-
- RECT r = { 0, 0, 0x7FFFFFFF, 100 };
-
- TCHAR *textbuf = ALF_Text(hwnd);
-
- DrawText(hdc, textbuf, -1, &r, format);
-
- ALF_Free(textbuf);
-
- int xpadding = ALF_Compat_GetSystemMetricsForDpi(SM_CXEDGE,
- (UINT)priv->dpi) * 2 + 6;
- int ypadding = ALF_Compat_GetSystemMetricsForDpi(SM_CYEDGE,
- (UINT)priv->dpi) * 2 + 4;
-
- SIZE *pSize = (SIZE*)(void*)lParam;
- if (pSize->cx < r.right - r.left + xpadding) {
- pSize->cx = r.right - r.left + xpadding;
- }
- if (pSize->cy < r.bottom - r.top + ypadding) {
- pSize->cy = r.bottom - r.top + ypadding;
- }
- if (pSize->cx < pSize->cy) {
- pSize->cx = pSize->cy;
- }
-
- if (font)
- SelectFont(hdc, oldFont);
-
- ReleaseDC(hwnd, hdc);
+ ALF_ClassicButton_CalculateSize(hwnd, (SIZE*)lParam);;
+ return TRUE;
} else if (uMsg == 0x2000 + WM_DRAWITEM) {
LPDRAWITEMSTRUCT dis = (DRAWITEMSTRUCT *)lParam;
- if (!ALF_Compat_BufferedPaintRenderAnimation(hwnd, dis->hDC)) {
- if (priv->hTheme) {
- // Draw XP style themed button
- int stateid = PBS_NORMAL;
-
- if (priv->isDefault && IsChild(GetForegroundWindow(), hwnd))
- stateid = priv->uxIsDefaultAnimating ? PBS_DEFAULTED_ANIMATING : PBS_DEFAULTED;
- if (priv->isHot)
- stateid = PBS_HOT;
- if (dis->itemState & ODS_SELECTED)
- stateid = PBS_PRESSED;
- if (dis->itemState & ODS_DISABLED)
- stateid = PBS_DISABLED;
-
- if (priv->uxStatePrev == -1) {
- // initial draw
- priv->uxStateCurrent = stateid;
- priv->itemStateCurrent = dis->itemState;
-
- if (priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)
- priv->uxStateCurrent = PBS_NORMAL;
- }
-
- priv->uxStatePrev = priv->uxStateCurrent;
- priv->uxStateCurrent = stateid;
- priv->itemStatePrev = priv->itemStateCurrent;
- priv->itemStateCurrent = dis->itemState;
-
- ALF_Compat_BP_ANIMATIONPARAMS animParams;
- ZeroMemory(&animParams, sizeof(animParams));
- animParams.cbSize = sizeof(animParams);
- animParams.style = ALF_Compat_BPAS_LINEAR;
-
- if (priv->uxStateCurrent != priv->uxStatePrev) {
- if ((priv->uxStateCurrent == PBS_DEFAULTED && priv->uxStatePrev == PBS_DEFAULTED_ANIMATING) ||
- (priv->uxStatePrev == PBS_DEFAULTED && priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)) {
- animParams.dwDuration = priv->uxDefaultAnimationDuration;
- } else if (priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING) {
- // Win7 misses these transition times, use the one for PBS_DEFAULTED
- ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
- BP_PUSHBUTTON,
- priv->uxStatePrev,
- PBS_DEFAULTED,
- TMT_TRANSITIONDURATION,
- &animParams.dwDuration);
- } else if (priv->uxStatePrev == PBS_DEFAULTED_ANIMATING) {
- // Win7 misses these transition times, use the one for PBS_DEFAULTED
- ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
- BP_PUSHBUTTON,
- PBS_DEFAULTED,
- priv->uxStateCurrent,
- TMT_TRANSITIONDURATION,
- &animParams.dwDuration);
- } else {
- ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
- BP_PUSHBUTTON,
- priv->uxStatePrev,
- priv->uxStateCurrent,
- TMT_TRANSITIONDURATION,
- &animParams.dwDuration);
- }
-
- if ((priv->uxStatePrev == PBS_DEFAULTED || priv->uxStatePrev == PBS_DEFAULTED_ANIMATING)
- && !(priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)) {
- KillTimer(hwnd, (UINT_PTR)priv);
- priv->uxIsDefaultAnimating = FALSE;
- }
-
- if (!(priv->uxStatePrev == PBS_DEFAULTED || priv->uxStatePrev == PBS_DEFAULTED_ANIMATING)
- && (priv->uxStateCurrent == PBS_DEFAULTED || priv->uxStateCurrent == PBS_DEFAULTED_ANIMATING)
- && priv->uxDefaultAnimationDuration) {
- SetTimer(hwnd, (UINT_PTR)priv, priv->uxDefaultAnimationDuration, ALF__Button_DefaultAnimatingTimerProc);
- }
- }
-
- HDC hdcFrom = NULL, hdcTo = NULL;
- ALF_Compat_HANIMATIONBUFFER hbpAnimation;
-
- hbpAnimation = ALF_Compat_BeginBufferedAnimation(hwnd, dis->hDC, &dis->rcItem, 0, NULL, &animParams, &hdcFrom, &hdcTo);
- if (hbpAnimation) {
- HFONT font = (HFONT)GetCurrentObject(dis->hDC, OBJ_FONT);
-
- if (hdcFrom) {
- SelectFont(hdcFrom, font);
- ALF__Button_RenderUxtheme(hwnd, priv, priv->uxStatePrev, priv->itemStatePrev, hdcFrom, &dis->rcItem);
- }
-
- if (hdcTo) {
- SelectFont(hdcTo, font);
- ALF__Button_RenderUxtheme(hwnd, priv, priv->uxStateCurrent, priv->itemStateCurrent, hdcTo, &dis->rcItem);
- }
-
- ALF_Compat_EndBufferedAnimation(hbpAnimation, TRUE);
- } else {
- ALF__Button_RenderUxtheme(hwnd, priv, stateid, dis->itemState, dis->hDC, &dis->rcItem);
- }
- } else if (ALF_Compat_IsMinWindowsVersion(4, 0)) {
- // Draw 95 style button
- ALF__Button_Render95(hwnd, priv, dis);
- } else {
- // Draw pre-95 style button
- ALF__Button_Render3x(hwnd, priv, dis);
- }
- }
+ ALF_ClassicButton_Paint(hwnd, priv, dis);
return TRUE;
+ } else if (uMsg == WM_ERASEBKGND) {
+ return TRUE;
+ } else if (uMsg == BM_SETSTYLE) {
+ priv->isDefault = (wParam & BS_DEFPUSHBUTTON);
+ wParam = BS_OWNERDRAW;
} else if (uMsg == WM_GETDLGCODE) {
if (priv->isDefault) {
- return DLGC_DEFPUSHBUTTON | DLGC_BUTTON;
+ return (LRESULT)DLGC_DEFPUSHBUTTON;
} else {
- return DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON;
+ return (LRESULT)DLGC_UNDEFPUSHBUTTON;
}
- } else if (uMsg == BM_SETSTYLE) {
- // HACK! stop windows from resetting the owner draw flag
- priv->isDefault = (wParam & BS_DEFPUSHBUTTON) ? 1 : 0;
-
- return ALF_Compat_DefSubclassProc(hwnd, BM_SETSTYLE, (wParam & 0xFFFFFFF0) | BS_OWNERDRAW, lParam);
- } else if (uMsg == WM_THEMECHANGED) {
- ALF_Compat_CloseThemeData(priv->hTheme);
- priv->hTheme = NULL;
- if (ALF_Compat_IsAppThemed())
- priv->hTheme = ALF_Compat_OpenThemeData(hwnd, L"Button");
- priv->uxDefaultAnimationDuration = 0;
- ALF_Compat_GetThemeTransitionDuration(priv->hTheme,
- BP_PUSHBUTTON,
- PBS_DEFAULTED,
- PBS_DEFAULTED_ANIMATING,
- TMT_TRANSITIONDURATION,
- &priv->uxDefaultAnimationDuration);
- InvalidateRect(hwnd, NULL, TRUE);
- } else if (uMsg == WM_MOUSEMOVE) {
- if (!priv->isHot) {
- TRACKMOUSEEVENT tme;
- ZeroMemory(&tme, sizeof(tme));
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = hwnd;
- if (ALF_Compat_TrackMouseEvent(&tme)) {
- priv->isHot = TRUE;
- InvalidateRect(hwnd, NULL, FALSE);
- }
- }
- } else if (uMsg == WM_MOUSELEAVE) {
- if (priv->isHot) {
- priv->isHot = FALSE;
- InvalidateRect(hwnd, NULL, FALSE);
- }
- } else if (uMsg == WM_DESTROY) {
- ALF_Compat_CloseThemeData(priv->hTheme);
- ALF_Free(priv);
- ALF_Compat_RemoveWindowSubclass(hwnd, ALF__ButtonSubclassProc, 0);
- } else if (uMsg == WM_ERASEBKGND) {
- return TRUE;
- } else if (uMsg == WM_SETTEXT) {
- ALF_InvalidateLayout(GetParent(hwnd));
} else if (uMsg == WM_SETFONT) {
ALF_InvalidateLayout(GetParent(hwnd));
- } else if (uMsg == ALF_WM_DPICHANGE) {
- priv->dpi = (int)lParam;
- ALF_InvalidateLayout(GetParent(hwnd));
- return TRUE;
+ InvalidateRect(hwnd, NULL, TRUE);
+ } else if (uMsg == WM_DESTROY) {
+ WNDPROC o = priv->origWndProc;
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)o);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ ALF_ClassicButton_FreePriv(priv);
+ return CallWindowProc(o, hwnd, uMsg, wParam, lParam);
}
- return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam);
+ return CallWindowProc(priv->origWndProc, hwnd, uMsg, wParam, lParam);
}
-HWND
-ALF_AddButton(HWND win, WORD id, int x, int y, const TCHAR *text)
+static HWND
+ALF_ClassicButton_Create(HWND win, WORD id, int x, int y, const TCHAR *text)
{
HWND hwndButton = CreateWindowEx(0,
TEXT("BUTTON"),
text,
- WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_PUSHBUTTON | BS_MULTILINE | BS_OWNERDRAW,
+ WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_OWNERDRAW,
0, 0, 100, 100,
win,
(HMENU)(int)id,
- (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE),
+ ALF_HINSTANCE,
NULL);
- ALFButtonPriv *priv = ALF_New(ALFButtonPriv, 1);
- priv->uxStateCurrent = -1;
- priv->uxStatePrev = -1;
- priv->dpi = 96;
-
- ALF_Compat_SetWindowSubclass(hwndButton, ALF__ButtonSubclassProc, 0, (DWORD_PTR)priv);
-
- SendMessage(hwndButton, WM_THEMECHANGED, 0, 0);
+ ALFClassicButtonPriv *priv = ALF_ClassicButton_InitializePriv();
+ SetWindowLongPtr(hwndButton, GWLP_USERDATA, (LONG_PTR)priv);
+ priv->origWndProc = (WNDPROC)SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)ALF_ClassicButton_WndProc);
- ALF_AddWidget(win, x, y, hwndButton, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_SENDDPICHANGE);
+ ALF_AddWidget(win, x, y, hwndButton, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT);
return hwndButton;
}
+/* Factory and helper functions for both button types */
+
+HWND
+ALF_AddButton(HWND win, WORD id, int x, int y, const TCHAR *text)
+{
+ if (_alf_buttonClass) {
+ return ALF_NtButton_Create(win, id, x, y, text);
+ } else {
+ return ALF_ClassicButton_Create(win, id, x, y, text);
+ }
+}
void
ALF_SetDefaultButton(HWND win, WORD id)