summaryrefslogtreecommitdiff
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
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.
-rw-r--r--Makefile.mingw7
-rw-r--r--Makefile.vc65
-rw-r--r--Makefile.vc6-ansi5
-rw-r--r--alf/alf.h4
-rw-r--r--alf/alfcheckbox.cpp118
-rw-r--r--alf/alflayout.cpp51
-rw-r--r--alf/alfwindow.cpp7
-rw-r--r--widgetfactory.cpp2
8 files changed, 193 insertions, 6 deletions
diff --git a/Makefile.mingw b/Makefile.mingw
index f3c52ed..8b5a3e2 100644
--- a/Makefile.mingw
+++ b/Makefile.mingw
@@ -8,12 +8,15 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static
all: out/widgetfactory.exe out/alf/alf.c out/widgetfactory-c.exe
-out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alflabel.o out/alflayout.o out/alfnotebook.o out/alfpanel.o out/alfwindow.o
+out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcheckbox.o out/alfcombobox.o out/alfcompat.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alflabel.o out/alflayout.o out/alfnotebook.o out/alfpanel.o out/alfwindow.o
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
out/alfbutton.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
+out/alfcheckbox.o: alf/alfcheckbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
out/alfcombobox.o: alf/alfcombobox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
@@ -47,7 +50,7 @@ out/alfwindow.o: alf/alfwindow.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h al
out/widgetfactory.o: widgetfactory.cpp alf/alf.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
-out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfwindow.cpp
+out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcheckbox.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfwindow.cpp
@mkdir -p out/alf
@printf "#include \"alf.h\"\\n" > $@
@cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@
diff --git a/Makefile.vc6 b/Makefile.vc6
index 3f09e24..9f34366 100644
--- a/Makefile.vc6
+++ b/Makefile.vc6
@@ -4,12 +4,15 @@ CXX = cl.exe
CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo
LDFLAGS = /link unicows.lib kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib
-out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alflabel.obj out/alflayout.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj
+out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcheckbox.obj out/alfcombobox.obj out/alfcompat.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alflabel.obj out/alflayout.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj
$(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS)
out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CFLAGS) -c -Fo$@ alf/alfbutton.cpp
+out/alfcheckbox.obj: alf/alfcheckbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
+ $(CXX) $(CFLAGS) -c -Fo$@ alf/alfcheckbox.cpp
+
out/alfcombobox.obj: alf/alfcombobox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CFLAGS) -c -Fo$@ alf/alfcombobox.cpp
diff --git a/Makefile.vc6-ansi b/Makefile.vc6-ansi
index fece0b8..feaade7 100644
--- a/Makefile.vc6-ansi
+++ b/Makefile.vc6-ansi
@@ -4,12 +4,15 @@ CXX = cl.exe
CFLAGS = -O2 -GA -W3 -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo
LDFLAGS = /link /entry:_entry /opt:nowin98 /fixed:no kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib
-out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alflabel.obj out/alflayout.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj
+out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcheckbox.obj out/alfcombobox.obj out/alfcompat.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alflabel.obj out/alflayout.obj out/alfnotebook.obj out/alfpanel.obj out/alfwindow.obj
$(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS)
out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CFLAGS) -c -Fo$@ alf/alfbutton.cpp
+out/alfcheckbox.obj: alf/alfcheckbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
+ $(CXX) $(CFLAGS) -c -Fo$@ alf/alfcheckbox.cpp
+
out/alfcombobox.obj: alf/alfcombobox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h
$(CXX) $(CFLAGS) -c -Fo$@ alf/alfcombobox.cpp
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)) {
diff --git a/widgetfactory.cpp b/widgetfactory.cpp
index 3320666..6e398b3 100644
--- a/widgetfactory.cpp
+++ b/widgetfactory.cpp
@@ -297,6 +297,8 @@ WinMain
ALF_SetBackgroundColor(hwndLbl6, ALF_COLOR_RGB(0, 0, 255));
ALF_SetTextColor(hwndLbl6, ALF_COLOR_RGB(255, 255, 255));
+ ALF_AddCheckbox(win, (WORD)-1, 1, 5, TEXT("Some Checkbox with a very very really very very long text"));
+
//ALF_AddWidgetLayoutFlag(win, ALF_WidgetHwndById(win, ID_LBL6), ALF_VEXPAND);
//ALF_AddWidgetLayoutFlag(win, ALF_WidgetHwndById(win, ID_B1), ALF_HEXPAND);