diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-06-30 12:48:57 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2019-06-30 12:48:57 +0200 |
| commit | fe078af239f3b73651c32bb1cdb158dcab39ad5c (patch) | |
| tree | c855620ab6970e658ea662d2c36b81cb68f50992 /alf | |
| parent | ecfb4b72fec0c25ef416038ef22db5d34d687ee4 (diff) | |
label reimplement
Diffstat (limited to 'alf')
| -rw-r--r-- | alf/alf.cpp | 2 | ||||
| -rw-r--r-- | alf/alf.h | 17 | ||||
| -rw-r--r-- | alf/alfcompat.cpp | 41 | ||||
| -rw-r--r-- | alf/alflabel.cpp | 233 | ||||
| -rw-r--r-- | alf/alfpriv.h | 4 |
5 files changed, 256 insertions, 41 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index 61ce4ee..932bd3b 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -364,6 +364,7 @@ ALF_Initialize(void) ALF_RegisterComboClass(); ALF_RegisterPanelClass(); ALF_RegisterSpacerClass(); + ALF_RegisterLabelClass(); ALF_Compat_BufferedPaintInit(); } @@ -387,6 +388,7 @@ ALF_UnInitialize(void) UnregisterClass(_alf_comboClass, ALF_HINSTANCE); UnregisterClass(_alf_panelClass, ALF_HINSTANCE); UnregisterClass(_alf_spacerClass, ALF_HINSTANCE); + UnregisterClass(_alf_labelClass, ALF_HINSTANCE); ALF_UnloadCompatFunctions(); } @@ -36,6 +36,19 @@ typedef struct { // sends a ALF_WM_APPLYFONTS message to the widget with ALFWindowFonts* lparam #define ALF_SENDAPPLYFONTS 0x80 +// label style flags +#define ALF_LABEL_ALIGN_LEFT 0 +#define ALF_LABEL_ALIGN_LEFT_LIKE_EDIT 1 +#define ALF_LABEL_ALIGN_HCENTER 2 +#define ALF_LABEL_ALIGN_RIGHT 3 +#define ALF_LABEL_HALIGN_MASK 3 +#define ALF_LABEL_ALIGN_TOP 0 +#define ALF_LABEL_ALIGN_TOP_LIKE_EDIT 4 +#define ALF_LABEL_ALIGN_VCENTER 8 +#define ALF_LABEL_ALIGN_BOTTOM 12 +#define ALF_LABEL_VALIGN_MASK 12 + + // messages #define ALF_WM__BASE 0x2800 #define ALF_WM_QUERYSIZE (ALF_WM__BASE + 1) @@ -55,6 +68,10 @@ typedef struct { #define ALF_WM_APPLYFONTS (ALF_WM__BASE + 16) #define ALF_WM_PRETRANSLATEMSG (ALF_WM__BASE + 17) +#define ALF_WM_LBL_GETSTYLE (ALF_WM__BASE + 201) +#define ALF_WM_LBL_SETSTYLE (ALF_WM__BASE + 202) + + typedef struct { const TCHAR *className; UINT classStyle; diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index 3895545..8672bb8 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -260,11 +260,44 @@ ALF_Compat_fallbackIsThemeBackgroundPartiallyTransparent(HTHEME hTheme, int iPar static HRESULT WINAPI ALF_Compat_fallbackDrawThemeParentBackground(HWND hwnd, HDC hdc, RECT *prc) { - (void)hwnd; - (void)hdc; - (void)prc; + HWND parent = GetParent(hwnd); + if (!parent) + return E_NOTIMPL; + + RECT rc; + if (prc) { + rc = *prc; + } else { + GetClientRect(hwnd, &rc); + } + MapWindowRect(hwnd, parent, &rc); - return E_NOTIMPL; + RECT childr; + GetClientRect(hwnd, &childr); + MapWindowRect(hwnd, parent, &childr); + + POINT o; + OffsetViewportOrgEx(hdc, -childr.left, -childr.top, &o); + + HRGN oldClipRgn = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(hdc, oldClipRgn)) { + DeleteObject(oldClipRgn); + oldClipRgn = NULL; + } + + IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); + + SendMessage(parent, WM_ERASEBKGND, (WPARAM)hdc, 0); + SendMessage(parent, WM_PRINTCLIENT, (WPARAM)hdc, (LPARAM)PRF_CLIENT); + + SelectClipRgn(hdc, oldClipRgn); + if (oldClipRgn) { + DeleteObject(oldClipRgn); + } + + SetViewportOrgEx(hdc, o.x, o.y, NULL); + + return S_OK; } static HRESULT WINAPI diff --git a/alf/alflabel.cpp b/alf/alflabel.cpp index e7550e4..208b033 100644 --- a/alf/alflabel.cpp +++ b/alf/alflabel.cpp @@ -2,8 +2,15 @@ /* LABEL */ -static -int ALF__LabelTopPadding(HWND hwnd) +typedef struct { + DWORD style; + HFONT font; +} ALFLabelPriv; + +TCHAR *_alf_labelClass; + +static int +ALF__LabelTopPadding(HWND hwnd) { // some pixels on top to align with the edit control // see also: alfedit.cpp @@ -12,28 +19,152 @@ int ALF__LabelTopPadding(HWND hwnd) + ((LOBYTE(LOWORD(GetVersion())) < 4) ? 2 : 1) /* internal padding in edit control */; } +static int +ALF__LabelLeftPadding(HWND hwnd, HDC hdc) +{ + // some pixels on the left to align with the edit control + // see also: alfedit.cpp + int p = ALF_Compat_GetSystemMetricsForDpi( + SM_CXEDGE, ALF_CentipointsToPixels(GetParent(hwnd), 7200)); + + p += 1; + + TEXTMETRIC tm; + ZeroMemory(&tm, sizeof(tm)); + if (GetTextMetrics(hdc, &tm)) { + if (tm.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE)) + p += ALF_GetAveCharWidth(hdc) / 2; + } + + return p; +} + +static BOOL CALLBACK +ALF__Label_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 }; + DrawText(hdc, (TCHAR*)lData, -1, &r, (UINT)wData); + + SetBkMode(hdc, oldBkMode); + + return TRUE; +} + static LRESULT CALLBACK -ALF__LabelSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +ALF__LabelWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - (void)uIdSubclass; - (void)dwRefData; + ALFLabelPriv *priv = (ALFLabelPriv*)GetWindowLongPtr(hwnd, 0); + if (!priv) + return DefWindowProc(hwnd, uMsg, wParam, lParam); + + if (uMsg == ALF_WM_LBL_GETSTYLE) { + return priv->style; + } else if (uMsg == ALF_WM_LBL_SETSTYLE) { + priv->style = (DWORD)lParam; + InvalidateRect(hwnd, NULL, TRUE); + return TRUE; + } else if (uMsg == WM_GETDLGCODE) { + return DLGC_STATIC; + } else if (uMsg == WM_SETFONT) { + priv->font = (HFONT)wParam; + if (LOWORD(lParam) != 0) + InvalidateRect(hwnd, NULL, TRUE); - if (uMsg == ALF_WM_QUERYSIZE) { + return 0; + } else if (uMsg == WM_GETFONT) { + return (LRESULT)priv->font; + } else if (uMsg == WM_UPDATEUISTATE) { + InvalidateRect(hwnd, NULL, TRUE); + } else if (uMsg == WM_PAINT) { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + ALF_Compat_DrawThemeParentBackground(hwnd, hdc, &ps.rcPaint); + + HFONT oldFont = NULL; + if (priv->font) + oldFont = SelectFont(hdc, priv->font); + + SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); + SetBkMode(hdc, TRANSPARENT); + + // calc drawtext style + UINT format = DT_EXPANDTABS; + + LRESULT uiState = SendMessage(hwnd, WM_QUERYUISTATE, 0, 0); + if (uiState & UISF_HIDEACCEL) + format |= DT_HIDEPREFIX; + + RECT rc; + GetClientRect(hwnd, &rc); + + switch (priv->style & ALF_LABEL_HALIGN_MASK) { + case ALF_LABEL_ALIGN_HCENTER: + format |= DT_CENTER; + break; + case ALF_LABEL_ALIGN_RIGHT: + format |= DT_RIGHT; + break; + } + switch (priv->style & ALF_LABEL_VALIGN_MASK) { + case ALF_LABEL_ALIGN_BOTTOM: + format |= DT_BOTTOM; + break; + case ALF_LABEL_ALIGN_VCENTER: + format |= DT_VCENTER; + break; + } + + if ((priv->style & ALF_LABEL_HALIGN_MASK) == ALF_LABEL_ALIGN_LEFT_LIKE_EDIT) + rc.left += ALF__LabelLeftPadding(hwnd, hdc); + if ((priv->style & ALF_LABEL_VALIGN_MASK) == ALF_LABEL_ALIGN_TOP_LIKE_EDIT) + rc.top += ALF__LabelTopPadding(hwnd); + + TCHAR *text = ALF_Text(hwnd); + + if (!IsWindowEnabled(hwnd)) { + if (GetVersion() >= 0x80000000) { + // Win9x just uses gray text. DSS_DISABLED is broken there, too, + // so we can't get the NT look even if we wanted to + SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + + DrawText(hdc, text, -1, &rc, format); + } else { + // FIXME! This doesn't look good when using uxtheme, even though windows does it the same way + // need to investigate whether drawing with disabled button style looks nicer + DrawState(hdc, NULL, + ALF__Label_Text_DrawStateProc, + (LPARAM)text, (WPARAM)format, + rc.left, + rc.top, + rc.right - rc.left, + rc.bottom - rc.top, + DST_COMPLEX | DSS_DISABLED); + } + } else { + DrawText(hdc, text, -1, &rc, format); + } + + ALF_Free(text); + + if (oldFont) + SelectFont(hdc, oldFont); + + EndPaint(hwnd, &ps); + + return TRUE; + } else if (uMsg == ALF_WM_QUERYSIZE) { HDC hdcLabel = GetDC(hwnd); - HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); HFONT oldFont = 0; - if (font) - oldFont = SelectFont(hdcLabel, font); + if (priv->font) + oldFont = SelectFont(hdcLabel, priv->font); // calc drawtext style - DWORD style = GetWindowLong(hwnd, GWL_STYLE); UINT format = DT_LEFT | DT_EXPANDTABS | DT_CALCRECT; - if (style & SS_NOPREFIX) - format |= DT_NOPREFIX; - if (style & SS_EDITCONTROL) - format |= DT_EDITCONTROL; - if (style & SS_ENDELLIPSIS || style & SS_PATHELLIPSIS || style & SS_WORDELLIPSIS) - format |= DT_SINGLELINE; RECT r = { 0, 0, 100, 100 }; @@ -46,45 +177,44 @@ ALF__LabelSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_ ALF_Free(textbuf); SIZE *pSize = (SIZE*)(void*)lParam; - if (pSize->cx == 0) + if (pSize->cx == 0) { pSize->cx = r.right - r.left; - if (pSize->cy == 0) - pSize->cy = r.bottom - r.top + ALF__LabelTopPadding(hwnd); + if ((priv->style & ALF_LABEL_HALIGN_MASK) == ALF_LABEL_ALIGN_LEFT_LIKE_EDIT) + pSize->cx += ALF__LabelLeftPadding(hwnd, hdcLabel); + } + if (pSize->cy == 0) { + pSize->cy = r.bottom - r.top; + if ((priv->style & ALF_LABEL_VALIGN_MASK) == ALF_LABEL_ALIGN_TOP_LIKE_EDIT) + pSize->cy += ALF__LabelTopPadding(hwnd); + } - if (font) + if (oldFont) SelectFont(hdcLabel, oldFont); ReleaseDC(hwnd, hdcLabel); - } else if (uMsg == ALF_WM_APPLYSIZE) { - RECT *p = (RECT *)lParam; - - int topPadding = ALF__LabelTopPadding(hwnd); - - return (LRESULT)DeferWindowPos((HDWP)wParam, - hwnd, NULL, - p->left, p->top + topPadding, - p->right - p->left, p->bottom - p->top - topPadding, - SWP_NOZORDER|SWP_NOACTIVATE); } else if (uMsg == WM_DESTROY) { - ALF_Compat_RemoveWindowSubclass(hwnd, ALF__LabelSubclassProc, 0); + ALF_Free(priv); + SetWindowLongPtr(hwnd, 0, 0); } - return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam); + return DefWindowProc(hwnd, uMsg, wParam, lParam); } HWND ALF_AddLabel(HWND win, WORD id, UINT x, UINT y, const TCHAR *text) { - HWND hwndLabel = CreateWindow(TEXT("STATIC"), + HWND hwndLabel = CreateWindow(_alf_labelClass, text, - WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP, + WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 0, 0, 100, 100, win, (HMENU)(int)id, - (HINSTANCE)GetWindowLongPtr(win, GWLP_HINSTANCE), + ALF_HINSTANCE, NULL); - ALF_Compat_SetWindowSubclass(hwndLabel, ALF__LabelSubclassProc, 0, 0); + ALFLabelPriv *priv = ALF_New(ALFLabelPriv, 1); + priv->style = ALF_LABEL_ALIGN_LEFT | ALF_LABEL_ALIGN_TOP_LIKE_EDIT; + SetWindowLongPtr(hwndLabel, 0, (LONG_PTR)priv); ALFWidgetLayoutParams p; ZeroMemory(&p, sizeof(p)); @@ -93,9 +223,38 @@ ALF_AddLabel(HWND win, WORD id, UINT x, UINT y, const TCHAR *text) p.y = y; p.width = 0; p.height = 0; - p.flags = ALF_QUERYSIZE | ALF_APPLYSIZE | ALF_MESSAGEFONT; + p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT; ALF_AddWidgetEx(win, &p); return hwndLabel; } + + +void +ALF_RegisterLabelClass(void) +{ + WNDCLASS cls; + ZeroMemory(&cls, sizeof(cls)); + + TCHAR classNameBuf[256]; + ALF_BuildUniqueName(classNameBuf, TEXT("ALFLabel."), (ULONG_PTR)&_alf_labelClass); + + cls.hInstance = ALF_HINSTANCE; + cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW); + if (LOBYTE(LOWORD(GetVersion())) >= 4) { + cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); + } else { + // NT 3.x has white dialog backgrounds + cls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + } + cls.lpszClassName = classNameBuf; + cls.cbWndExtra = sizeof(void*); + cls.lpfnWndProc = ALF__LabelWindowProc; + + ATOM classatom = RegisterClass(&cls); + if (!classatom) + MessageBox(NULL, TEXT("FATAL: Could not register label class"), NULL, MB_OK); + + _alf_labelClass = MAKEINTATOM(classatom); +} diff --git a/alf/alfpriv.h b/alf/alfpriv.h index aa0b39d..3d0f092 100644 --- a/alf/alfpriv.h +++ b/alf/alfpriv.h @@ -30,6 +30,7 @@ typedef struct { extern TCHAR *_alf_comboClass; extern TCHAR *_alf_panelClass; extern TCHAR *_alf_spacerClass; +extern TCHAR *_alf_labelClass; int ALF_CentipointsToPxPriv(ALFWindowPriv *priv, int cptValue); @@ -53,6 +54,9 @@ void ALF_RegisterSpacerClass(void); void +ALF_RegisterLabelClass(void); + +void ALF_BuildUniqueName(TCHAR *buf, const TCHAR *prefix, ULONG_PTR uniquifier); BOOL |
