From 7ebda0eb50ad2972a93cc6f597b22c9d4473f304 Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Mon, 27 Apr 2020 17:09:25 +0200 Subject: button: make themed button always use unicode and do internal text handling --- alf/alf.cpp | 17 ++++++++ alf/alfbutton.cpp | 115 ++++++++++++++++++++++++++++++++++++------------------ alf/alfpriv.h | 3 ++ 3 files changed, 97 insertions(+), 38 deletions(-) (limited to 'alf') diff --git a/alf/alf.cpp b/alf/alf.cpp index 917008a..25dcd21 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -123,6 +123,23 @@ ALF_BuildUniqueName(TCHAR *buf, const TCHAR *prefix, ULONG_PTR uniquifier) buf[prefixlen + numlen] = 0; } +void +ALF_BuildUniqueNameW(WCHAR *buf, const WCHAR *prefix, ULONG_PTR uniquifier) +{ + int prefixlen = lstrlenW(prefix); + CopyMemory(buf, prefix, (SIZE_T)prefixlen * sizeof(*prefix)); + + int numlen = sizeof(LONG_PTR)*2; + int i = numlen - 1; + while (i >= 0) { + buf[prefixlen + i] = L"0123456789ABCDEF"[uniquifier & 0xf]; + uniquifier >>= 4; + i--; + } + + buf[prefixlen + numlen] = 0; +} + void ALF_DestroyWindow(HWND win) { diff --git a/alf/alfbutton.cpp b/alf/alfbutton.cpp index 2c7e918..dcf0898 100644 --- a/alf/alfbutton.cpp +++ b/alf/alfbutton.cpp @@ -30,6 +30,7 @@ typedef struct { DWORD uxDefaultAnimationDuration; int dpi; HFONT font; + WCHAR *text; } ALFNtButtonPriv; TCHAR *_alf_buttonClass = NULL; @@ -47,6 +48,17 @@ ALF_Button_DrawDisabledText_DrawStateProc(HDC hdc, return TRUE; } +static BOOL CALLBACK +ALF_Button_DrawDisabledTextW_DrawStateProc(HDC hdc, + LPARAM lData, + WPARAM wData, + int cx, + int cy) +{ + RECT rc = { 0, 0, cx, cy }; + DrawTextW(hdc, (const WCHAR *)lData, -1, &rc, (UINT)wData); + return TRUE; +} static int ALF_Button_DrawDisabledTextNt(HDC hdc, @@ -62,6 +74,20 @@ ALF_Button_DrawDisabledTextNt(HDC hdc, DST_COMPLEX | DSS_DISABLED); } +static int +ALF_Button_DrawDisabledTextNtW(HDC hdc, + LPCWSTR lpchText, + int cchText, + LPRECT lprc, + UINT format) +{ + (void)cchText; + return DrawStateW(hdc, NULL, ALF_Button_DrawDisabledTextW_DrawStateProc, + (LPARAM)lpchText, (WPARAM)format, + lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, + DST_COMPLEX | DSS_DISABLED); +} + static int ALF_Button_DrawDisabledText9x(HDC hdc, LPCTSTR lpchText, @@ -91,7 +117,7 @@ ALF_Button_DrawDisabledText31(HDC hdc, static ALFNtButtonPriv * -ALF_NtButton_InitializePriv(void) +ALF_NtButton_InitializePriv(CREATESTRUCTW *cs) { ALFNtButtonPriv *priv = ALF_New(ALFNtButtonPriv, 1); @@ -100,6 +126,10 @@ ALF_NtButton_InitializePriv(void) priv->uxStatePrev = -1; priv->dpi = 96; + SIZE_T l = (SIZE_T)lstrlenW(cs->lpszName); + priv->text = ALF_New(WCHAR, l + 1); + CopyMemory(priv->text, cs->lpszName, l * sizeof(WCHAR)); + return priv; } @@ -107,6 +137,7 @@ static void ALF_NtButton_FreePriv(ALFNtButtonPriv *priv) { ALF_Compat_CloseThemeData(priv->hTheme); + ALF_Free(priv->text); ALF_Free(priv); } @@ -128,7 +159,7 @@ ALF_NtButton_ModifyDrawFlags(HWND hwnd, ALFNtButtonPriv *priv, DWORD add, DWORD static void ALF_NtButton_HandleUIState(HWND hwnd, ALFNtButtonPriv *priv) { - LRESULT uiState = SendMessage(hwnd, WM_QUERYUISTATE, 0, 0); + LRESULT uiState = SendMessageW(hwnd, WM_QUERYUISTATE, 0, 0); DWORD add = 0; DWORD remove = 0; if (uiState & UISF_HIDEACCEL) { @@ -172,11 +203,7 @@ ALF_NtButton_CalculateSize(HWND hwnd, ALFNtButtonPriv *priv, SIZE *pSize) RECT r = { 0, 0, 0x7FFFFFFF, 100 }; - TCHAR *textbuf = ALF_Text(hwnd); - - DrawText(hdc, textbuf, -1, &r, format); - - ALF_Free(textbuf); + DrawTextW(hdc, priv->text, -1, &r, format); int xpadding = ALF_Compat_GetSystemMetricsForDpi(SM_CXEDGE, (UINT)priv->dpi) * 2 + 6; @@ -232,17 +259,13 @@ ALF_NtButton_RenderUxtheme(HWND hwnd, ALFNtButtonPriv *priv, int uxstate, DWORD if ((drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED) && !(drawFlags & ALF_NTBTN_FLAG_HIDEFOCUS)) DrawFocusRect(hDC, &content); - int textlen = GetWindowTextLengthW(hwnd); - WCHAR *textbuf = ALF_New(WCHAR, (SIZE_T)textlen + 1); - GetWindowTextW(hwnd, textbuf, textlen+1); - UINT style = DT_CENTER; if (drawFlags & ALF_NTBTN_FLAG_HIDEACCEL) style |= DT_HIDEPREFIX; RECT textbounds = content; - ALF_Compat_GetThemeTextExtent(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, textbuf, -1, style, &content, &textbounds); + ALF_Compat_GetThemeTextExtent(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, priv->text, -1, style, &content, &textbounds); RECT texttarget = content; texttarget.top += ((content.bottom - content.top) - (textbounds.bottom - textbounds.top)) / 2; @@ -250,9 +273,7 @@ ALF_NtButton_RenderUxtheme(HWND hwnd, ALFNtButtonPriv *priv, int uxstate, DWORD texttarget.right = texttarget.left + (textbounds.right - textbounds.left); texttarget.bottom = texttarget.top + (textbounds.bottom - textbounds.top); - ALF_Compat_DrawThemeText(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, textbuf, -1, style, 0, &texttarget); - - ALF_Free(textbuf); + ALF_Compat_DrawThemeText(priv->hTheme, hDC, BP_PUSHBUTTON, uxstate, priv->text, -1, style, 0, &texttarget); SelectFont(hDC, oldfont); } @@ -269,8 +290,6 @@ ALF_NtButton_RenderClassic(HWND hwnd, ALFNtButtonPriv *priv, HDC dc, RECT *rcPai RECT r = rcClient; - TCHAR *textbuf = ALF_Text(hwnd); - if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DEFAULT) { HBRUSH framecolor = GetSysColorBrush(COLOR_WINDOWFRAME); FrameRect(dc, &r, framecolor); @@ -287,14 +306,8 @@ ALF_NtButton_RenderClassic(HWND hwnd, ALFNtButtonPriv *priv, HDC dc, RECT *rcPai DrawFrameControl(dc, &r, DFC_BUTTON, dfcs); - if ((priv->drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED) && !(priv->drawFlags & ALF_NTBTN_FLAG_HIDEFOCUS)) { - RECT f = r; - InflateRect(&f, -1, -1); - DrawFocusRect(dc, &f); - } - RECT textbounds = rcClient; - DrawText(dc, textbuf, -1, &textbounds, DT_LEFT | DT_CALCRECT); + DrawTextW(dc, priv->text, -1, &textbounds, DT_LEFT | DT_CALCRECT); RECT texttarget = rcClient; texttarget.top += ((rcClient.bottom - rcClient.top) - (textbounds.bottom - textbounds.top)) / 2 - 1; @@ -316,14 +329,19 @@ ALF_NtButton_RenderClassic(HWND hwnd, ALFNtButtonPriv *priv, HDC dc, RECT *rcPai COLORREF oldBkColor = SetBkColor(dc, GetSysColor(COLOR_BTNFACE)); if (priv->drawFlags & ALF_NTBTN_FLAG_IS_DISABLED) { - ALF_Button_DrawDisabledText(dc, textbuf, -1, &texttarget, style); + ALF_Button_DrawDisabledTextNtW(dc, priv->text, -1, &texttarget, style); } else { - DrawText(dc, textbuf, -1, &texttarget, style); + DrawTextW(dc, priv->text, -1, &texttarget, style); } SetBkColor(dc, oldBkColor); + if ((priv->drawFlags & ALF_NTBTN_FLAG_IS_FOCUSED) && !(priv->drawFlags & ALF_NTBTN_FLAG_HIDEFOCUS)) { + RECT f = r; + InflateRect(&f, -1, -1); + DrawFocusRect(dc, &f); + } + SelectFont(dc, oldfont); - ALF_Free(textbuf); } static void @@ -436,7 +454,7 @@ 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); + SendMessageW(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetWindowLong(hwnd, GWL_ID), BN_CLICKED), (LPARAM)hwnd); } static LRESULT CALLBACK @@ -445,9 +463,9 @@ 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(); + priv = ALF_NtButton_InitializePriv((CREATESTRUCTW *)lParam); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv); + SetWindowLongPtrW(hwnd, 0, (LONG_PTR)priv); ALF_NtButton_HandleThemeChange(hwnd, priv); ALF_NtButton_HandleUIState(hwnd, priv); @@ -567,7 +585,28 @@ ALF_NtButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } else if (uMsg == WM_ERASEBKGND) { return TRUE; } else if (uMsg == WM_SETTEXT) { - ALF_InvalidateLayout(GetParent(hwnd)); + const WCHAR *newtext = (const WCHAR *)lParam; + if (newtext) { + SIZE_T len = (SIZE_T)lstrlenW(newtext); + ALF_Free(priv->text); + priv->text = ALF_New(WCHAR, len+1); + CopyMemory(priv->text, newtext, (len+1)*sizeof(WCHAR)); + ALF_InvalidateLayout(GetParent(hwnd)); + return TRUE; + } + return FALSE; + } else if (uMsg == WM_GETTEXTLENGTH) { + return (LRESULT)lstrlenW(priv->text); + } else if (uMsg == WM_GETTEXT) { + if (wParam < 1) + return 0; + + SIZE_T selflen = (SIZE_T)lstrlenW(priv->text); + SIZE_T buflen = (SIZE_T)wParam - 1; + SIZE_T tocopy = selflen < buflen ? selflen : buflen; + CopyMemory((WCHAR*)lParam, priv->text, tocopy * sizeof(WCHAR)); + ((WCHAR*)lParam)[tocopy] = 0; + return (LRESULT)tocopy; } else if (uMsg == WM_SETFONT) { priv->font = (HFONT)wParam; if (LOWORD(lParam) != 0) @@ -585,7 +624,7 @@ ALF_NtButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } else if (uMsg == WM_SIZE) { InvalidateRect(hwnd, NULL, TRUE); } else if (uMsg == WM_UPDATEUISTATE) { - LRESULT rv = DefWindowProc(hwnd, uMsg, wParam, lParam); + LRESULT rv = DefWindowProcW(hwnd, uMsg, wParam, lParam); ALF_NtButton_HandleUIState(hwnd, priv); @@ -599,10 +638,10 @@ ALF_NtButton_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } else if (uMsg == WM_DESTROY) { ALF_NtButton_FreePriv(priv); priv = NULL; - SetWindowLongPtr(hwnd, 0, 0); + SetWindowLongPtrW(hwnd, 0, 0); } - return DefWindowProc(hwnd, uMsg, wParam, lParam); + return DefWindowProcW(hwnd, uMsg, wParam, lParam); } void @@ -622,11 +661,11 @@ ALF_RegisterButtonClass(void) // Initialize custom themed button class on windows 2000 and newer // Win9x and NT3.51/NT4 are well served by the classic version if (ALF_Compat_IsMinWindowsVersion(5, 0)) { - WNDCLASS cls; + WNDCLASSW cls; ZeroMemory(&cls, sizeof(cls)); - TCHAR classNameBuf[256]; - ALF_BuildUniqueName(classNameBuf, TEXT("ALFNtButton."), (ULONG_PTR)&_alf_buttonClass); + WCHAR classNameBuf[256]; + ALF_BuildUniqueNameW(classNameBuf, L"ALFNtButton.", (ULONG_PTR)&_alf_buttonClass); cls.hInstance = ALF_HINSTANCE; cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); @@ -634,7 +673,7 @@ ALF_RegisterButtonClass(void) cls.cbWndExtra = sizeof(void*); cls.lpfnWndProc = ALF_NtButton_WndProc; - ATOM classatom = RegisterClass(&cls); + ATOM classatom = RegisterClassW(&cls); if (!classatom) MessageBox(NULL, TEXT("FATAL: Could not register button class"), NULL, MB_OK); diff --git a/alf/alfpriv.h b/alf/alfpriv.h index 77925e4..c2ab557 100644 --- a/alf/alfpriv.h +++ b/alf/alfpriv.h @@ -44,6 +44,9 @@ ALF_CreatePanelWindow(HWND parent, WORD id); void ALF_BuildUniqueName(TCHAR *buf, const TCHAR *prefix, ULONG_PTR uniquifier); +void +ALF_BuildUniqueNameW(WCHAR *buf, const WCHAR *prefix, ULONG_PTR uniquifier); + BOOL ALF_ShouldMessageBubble(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); -- cgit v1.2.3