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/alflabel.cpp | |
| parent | ecfb4b72fec0c25ef416038ef22db5d34d687ee4 (diff) | |
label reimplement
Diffstat (limited to 'alf/alflabel.cpp')
| -rw-r--r-- | alf/alflabel.cpp | 233 |
1 files changed, 196 insertions, 37 deletions
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); +} |
