summaryrefslogtreecommitdiff
path: root/alf
diff options
context:
space:
mode:
authorJonas Kümmerlin <jonas@kuemmerlin.eu>2020-04-28 10:57:22 +0200
committerJonas Kümmerlin <jonas@kuemmerlin.eu>2020-04-28 10:57:22 +0200
commit65d9985bdcaed63b52bfe8c35c61d8a4a43a8292 (patch)
tree4ee14cce7d4916b58b7f0683713a8c33066f374e /alf
parent7bc8d9583e0c088c42d5bbf0ecbada77c7cb8bd1 (diff)
first try at checkbox
The size calculation is really messy and the background stuff does not work with comctl v5. Probably need to go full owner-drawn, again.
Diffstat (limited to 'alf')
-rw-r--r--alf/alf.h4
-rw-r--r--alf/alfcheckbox.cpp118
-rw-r--r--alf/alflayout.cpp51
-rw-r--r--alf/alfwindow.cpp7
4 files changed, 178 insertions, 2 deletions
diff --git a/alf/alf.h b/alf/alf.h
index d300342..037f478 100644
--- a/alf/alf.h
+++ b/alf/alf.h
@@ -408,6 +408,10 @@ ALF_NotebookRemoveFlag(HWND notebook, DWORD flag) {
ALF_NotebookSetFlags(notebook, ALF_NotebookFlags(notebook) & ~flag);
}
+// checkbox
+HWND
+ALF_AddCheckbox(HWND parent, WORD id, int x, int y, const TCHAR *text);
+
#ifdef __cplusplus
} // extern C
#endif
diff --git a/alf/alfcheckbox.cpp b/alf/alfcheckbox.cpp
new file mode 100644
index 0000000..99a285f
--- /dev/null
+++ b/alf/alfcheckbox.cpp
@@ -0,0 +1,118 @@
+#include "alfpriv.h"
+
+typedef struct {
+ ALFColor bgcolor;
+ WNDPROC origWndProc;
+} ALFCheckboxPriv;
+
+static ALFCheckboxPriv *
+ALF_Checkbox_InitializePriv(void)
+{
+ return ALF_New(ALFCheckboxPriv, 1);
+}
+
+static void
+ALF_Checkbox_FreePriv(ALFCheckboxPriv *priv)
+{
+ ALF_Free(priv);
+}
+
+static BOOL
+ALF_Checkbox_IsTransparencySupported(void)
+{
+ // FIXME: for safety, check if the control is actually a v6 control
+ return ALF_Compat_IsAppThemed();
+}
+
+static LRESULT
+ALF_Checkbox_PaintBackground(HWND window, ALFCheckboxPriv *priv, HDC hDC)
+{
+ // FIXME: Drawing the (transparent) background in WM_CTLCOLORSTATIC is
+ // only supported in a themed V6 common control
+
+ SetTextColor(hDC, GetSysColor(COLOR_BTNTEXT));
+ if (ALF_Checkbox_IsTransparencySupported()) {
+ RECT r;
+ GetClientRect(window, &r);
+
+ if (priv->bgcolor == ALF_COLOR_TRANSPARENT) {
+ ALF_Compat_DrawThemeParentBackground(window, hDC, &r);
+ SetBkMode(hDC, TRANSPARENT);
+ } else {
+ ALF_FillRect(hDC, &r, priv->bgcolor);
+ SetBkMode(hDC, OPAQUE);
+ SetBkColor(hDC, ALF_ColorToGdi(priv->bgcolor));
+ }
+ return (LRESULT)GetStockObject(HOLLOW_BRUSH);
+ } else {
+ SetBkColor(hDC, GetSysColor(COLOR_BTNFACE));
+ SetBkMode(hDC, OPAQUE);
+ return (LRESULT)GetSysColorBrush(COLOR_BTNFACE);
+ }
+}
+
+static LRESULT CALLBACK
+ALF_Checkbox_WindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ ALFCheckboxPriv *priv = (ALFCheckboxPriv *)GetWindowLongPtr(window, GWLP_USERDATA);
+
+ if (!priv) // fuck
+ return DefWindowProc(window, msg, wparam, lparam);
+
+ if (msg == ALF_WM_SETBGCOLOR) {
+ ALFColor newColor = (ALFColor)lparam;
+ if (newColor != priv->bgcolor) {
+ priv->bgcolor = newColor;
+ if (ALF_Checkbox_IsTransparencySupported())
+ InvalidateRect(window, NULL, TRUE);
+ }
+ return TRUE;
+ }
+
+ if (msg == 0x2000 + WM_CTLCOLORSTATIC) {
+ return ALF_Checkbox_PaintBackground(window, priv, (HDC)wparam);
+ }
+
+ if (msg == ALF_WM_BACKGROUNDCHANGE) {
+ if (priv->bgcolor == ALF_COLOR_TRANSPARENT && ALF_Checkbox_IsTransparencySupported()) {
+ InvalidateRect(window, NULL, TRUE);
+ }
+ return TRUE;
+ }
+
+ if (msg == WM_THEMECHANGED) {
+ InvalidateRect(window, NULL, TRUE);
+ }
+
+ if (msg == WM_DESTROY) {
+ WNDPROC orig = priv->origWndProc;
+ SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)orig);
+ SetWindowLongPtr(window, GWLP_USERDATA, 0);
+ ALF_Checkbox_FreePriv(priv);
+ return CallWindowProc(orig, window, msg, wparam, lparam);
+ }
+
+ return CallWindowProc(priv->origWndProc, window, msg, wparam, lparam);
+}
+
+HWND
+ALF_AddCheckbox(HWND parent, WORD id, int x, int y, const TCHAR *text)
+{
+ HWND hwnd = CreateWindowEx(0,
+ TEXT("BUTTON"),
+ text,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX,
+ 0, 0, 100, 100,
+ parent,
+ (HMENU)(ULONG_PTR)id,
+ ALF_HINSTANCE,
+ NULL);
+
+ ALFCheckboxPriv *priv = ALF_Checkbox_InitializePriv();
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)priv);
+ priv->origWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ALF_Checkbox_WindowProc);
+
+ ALF_AddWidget(parent, x, y, hwnd, 0, 0, ALF_LAYOUT_SIZE_CHECKBOX | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_INHERITBGCOLOR | ALF_LAYOUT_SENDBGCHANGE);
+
+ return hwnd;
+}
diff --git a/alf/alflayout.cpp b/alf/alflayout.cpp
index 2e56886..6c5326d 100644
--- a/alf/alflayout.cpp
+++ b/alf/alflayout.cpp
@@ -101,8 +101,15 @@ ALF_Layout_ForwardFontToWidget(ALFLayout *layout, HWND window, ALFWidgetPriv *wi
if (widget->flags & ALF_LAYOUT_INHERITFONT) {
SendMessage(widget->hwnd, WM_SETFONT, (WPARAM)font, redraw);
- if (widget->flags & ALF_LAYOUT_SIZE_EDIT)
- ALF_Layout_Invalidate(layout, window);
+ switch (widget->flags & ALF_LAYOUT_SIZETYPE_MASK) {
+ case ALF_LAYOUT_SIZE_EDIT:
+ case ALF_LAYOUT_SIZE_CHECKBOX:
+ ALF_Layout_Invalidate(layout, window);
+ break;
+ default:
+ // do nothing
+ break;
+ }
}
}
@@ -206,6 +213,42 @@ ALF_Layout_CalcEditSize(HWND hwndWindow, ALFLayout *layout, HWND hwndEdit, SIZE
}
static void
+ALF_Layout_CalcCheckboxSize(HWND hwndWindow, ALFLayout *layout, HWND hwndCheckbox, SIZE *ps)
+{
+ (void)hwndWindow;
+
+ int checkwidth = 12 * layout->dpi / 96 + 1;
+
+ HDC hDC = GetDC(hwndCheckbox);
+ HFONT font = (HFONT)SendMessage(hwndCheckbox, WM_GETFONT, 0, 0);
+ HFONT oldfont = SelectFont(hDC, font);
+
+ RECT r = { 0, 0, 10, 10 };
+
+ TCHAR *textbuf = ALF_Text(hwndCheckbox);
+ DrawText(hDC, textbuf, -1, &r, DT_CALCRECT);
+ ALF_Free(textbuf);
+
+ if (!ps->cx) {
+ // lol
+ int cw = 0;
+ GetCharWidth(hDC, '0', '0', &cw);
+
+ ps->cx = checkwidth + r.right - r.left + cw;
+ }
+
+ if (!ps->cy) {
+ int height = r.bottom - r.top;
+ if (checkwidth > height)
+ height = checkwidth;
+ ps->cy = height;
+ }
+
+ SelectFont(hDC, oldfont);
+ ReleaseDC(hwndCheckbox, hDC);
+}
+
+static void
ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window, SIZE *s)
{
if (c->flags & ALF_LAYOUT_SIZE_PX) {
@@ -225,6 +268,10 @@ ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window, S
break;
case ALF_LAYOUT_SIZE_EDIT:
ALF_Layout_CalcEditSize(window, layout, c->hwnd, s);
+ break;
+ case ALF_LAYOUT_SIZE_CHECKBOX:
+ ALF_Layout_CalcCheckboxSize(window, layout, c->hwnd, s);
+ break;
default:
// FIXME! unimplemented
break;
diff --git a/alf/alfwindow.cpp b/alf/alfwindow.cpp
index 188f791..d3cbfcd 100644
--- a/alf/alfwindow.cpp
+++ b/alf/alfwindow.cpp
@@ -246,6 +246,13 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
return ret;
}
+ if (msg == WM_CTLCOLORSTATIC) {
+ LRESULT ret = SendMessage((HWND)lparam, 0x2000 + WM_CTLCOLORSTATIC, wparam, lparam);
+
+ if (ret)
+ return ret;
+ }
+
if (msg == WM_ACTIVATE) {
if (!HIWORD(wparam)) { // if !minimized
if (LOWORD(wparam)) {