diff options
| -rw-r--r-- | alf/alf.cpp | 18 | ||||
| -rw-r--r-- | alf/alf.h | 16 | ||||
| -rw-r--r-- | alf/alflabel.cpp | 2 | ||||
| -rw-r--r-- | alf/alflayout.cpp | 46 | ||||
| -rw-r--r-- | alf/alfnotebook.cpp | 18 | ||||
| -rw-r--r-- | alf/alfpanel.cpp | 14 | ||||
| -rw-r--r-- | alf/alfwindow.cpp | 20 | ||||
| -rw-r--r-- | widgetfactory.cpp | 126 |
8 files changed, 241 insertions, 19 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index 311c65b..3bf9ae7 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -439,3 +439,21 @@ ALF_ColorToGdi(ALFColor color) return (COLORREF)color; } } + +void +ALF_InvalidateBackground(HWND win) +{ + SendMessage(win, ALF_WM_BACKGROUNDCHANGE, 0, 0); +} + +void +ALF_SetBackgroundColor(HWND win, ALFColor color) +{ + SendMessage(win, ALF_WM_SETBGCOLOR, 0, (LPARAM)color); +} + +ALFColor +ALF_GetBackgroundColor(HWND win) +{ + return (ALFColor)SendMessage(win, ALF_WM_GETBGCOLOR, 0, 0); +} @@ -23,6 +23,7 @@ typedef struct { LRESULT (*notify)(void * /*closure*/, HWND /*window*/, WPARAM /*sourceid*/, NMHDR *); BOOL (*pretranslatemessage)(void * /*closure*/, HWND /*window*/, MSG * /*message*/); void (*paint)(void * /*closure*/, HWND, HDC, RECT *); + void (*windowposchanged)(void * /*closure*/, HWND, WINDOWPOS *); } ALFWindowVTable; typedef struct { @@ -45,6 +46,8 @@ typedef struct { #define ALF_LAYOUT_CUSTOMPOS 0x20 #define ALF_LAYOUT_SIZE_PX 0x40 #define ALF_LAYOUT_INHERITBGCOLOR 0x80 +#define ALF_LAYOUT_TRANSPARENTBG 0x100 +#define ALF_LAYOUT_SENDBGCHANGE 0x200 // label style flags @@ -72,6 +75,7 @@ typedef struct { #define ALF_WM_GETMODALRESULT (ALF_WM__BASE + 8) #define ALF_WM_CENTIPOINTTOPX (ALF_WM__BASE + 9) #define ALF_WM_SETFOCUS (ALF_WM__BASE + 10) +#define ALF_WM_BACKGROUNDCHANGE (ALF_WM__BASE + 11) #define ALF_WM_APPLYSIZE (ALF_WM__BASE + 12) #define ALF_WM_SETBGCOLOR (ALF_WM__BASE + 13) #define ALF_WM_GETBGCOLOR (ALF_WM__BASE + 14) @@ -190,6 +194,12 @@ ALF_WidgetHwndById(HWND win, WORD id); void ALF_InvalidateLayout(HWND win); +// Sends ALF_WM_BACKGROUNDCHANGE to notify the window of a changed background +// Only useful when you have overridden the window or panel pain() vfunc +// when you use solid background colors, ALF will handle this automatically +void +ALF_InvalidateBackground(HWND win); + // Recalculates the window's DPI and all fonts and applies them to child widgets. // ALF does this automatically on a DPI or settings change so you shouldn't have // to call ALF_UpdateFonts(). @@ -197,6 +207,12 @@ void ALF_UpdateFonts(HWND win); void +ALF_SetBackgroundColor(HWND win, ALFColor color); + +ALFColor +ALF_GetBackgroundColor(HWND win); + +void ALF_ResizeWindow(HWND win, int cptWidth, int cptHeight); void diff --git a/alf/alflabel.cpp b/alf/alflabel.cpp index f424486..8a878a0 100644 --- a/alf/alflabel.cpp +++ b/alf/alflabel.cpp @@ -240,7 +240,7 @@ ALF_AddLabel(HWND win, WORD id, int x, int y, const TCHAR *text) priv->style = ALF_LABEL_ALIGN_LEFT | ALF_LABEL_ALIGN_TOP_LIKE_EDIT; SetWindowLongPtr(hwndLabel, 0, (LONG_PTR)priv); - ALF_AddWidget(win, x, y, hwndLabel, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT); + ALF_AddWidget(win, x, y, hwndLabel, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_TRANSPARENTBG); return hwndLabel; } diff --git a/alf/alflayout.cpp b/alf/alflayout.cpp index ecd501c..228e5b3 100644 --- a/alf/alflayout.cpp +++ b/alf/alflayout.cpp @@ -63,6 +63,9 @@ ALF_Layout_GetRowFlags(ALFLayout *layout, HWND window, int rowno); static BOOL ALF_Layout_SetRowFlags(ALFLayout *layout, HWND window, int rowno, DWORD flags); +static void +ALF_Layout_HandleBackgroundChange(ALFLayout *layout, HWND window); + void ALF_Layout_Init(ALFLayout *layout) { @@ -123,6 +126,21 @@ ALF_Layout_ForwardBgColor(ALFLayout *layout, HWND window, WPARAM wparam, LPARAM } } +static void +ALF_Layout_HandleBackgroundChange(ALFLayout *layout, HWND window) +{ + (void)window; + + ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, i) { + if (i->flags & ALF_LAYOUT_TRANSPARENTBG) { + InvalidateRect(i->hwnd, NULL, TRUE); + } + if (i->flags & ALF_LAYOUT_SENDBGCHANGE) { + ALF_InvalidateBackground(i->hwnd); + } + } +} + void ALF_Layout_EnsureRowExists(ALFLayout *layout, int rowno) { @@ -377,13 +395,25 @@ ALF_Layout_Apply(ALFLayout* layout, HWND window) } else { UINT flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER; - if (bgcolor == ALF_COLOR_TRANSPARENT) - flags |= SWP_NOCOPYBITS; - // NT 3.51 and Win32s have so many invalidation bugs it's not even funny if (!ALF_Compat_IsMinWindowsVersion(4, 0)) flags |= SWP_NOCOPYBITS; + // transparent background: invalidate if widget moved + if (bgcolor == ALF_COLOR_TRANSPARENT) { + RECT oldR; + GetWindowRect(c->hwnd, &oldR); + + if (oldR.left != r.left || oldR.top != r.top) { + if (c->flags & ALF_LAYOUT_SENDBGCHANGE) { + ALF_InvalidateBackground(c->hwnd); + } + if (c->flags & ALF_LAYOUT_TRANSPARENTBG) { + flags |= SWP_NOCOPYBITS; + } + } + } + hdwp = DeferWindowPos(hdwp, c->hwnd, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, @@ -414,7 +444,7 @@ ALF_Layout_AddWidget(ALFLayout* layout, HWND window, const ALFAddWidgetParams* p ALF_Layout_ForwardFontToWidget(layout, window, w, (HFONT)SendMessage(window, WM_GETFONT, 0, 0), 0); } if (w->flags & ALF_LAYOUT_INHERITBGCOLOR) { - SendMessage(w->hwnd, ALF_WM_SETBGCOLOR, (WPARAM)SendMessage(window, ALF_WM_GETBGCOLOR, 0, 0), 0); + ALF_SetBackgroundColor(w->hwnd, ALF_GetBackgroundColor(window)); } ALF_ListInsert(layout->widgets.prev, &w->list); @@ -570,7 +600,7 @@ ALF_Layout_SetWidgetFlags(ALFLayout *layout, HWND window, HWND needle, DWORD fla if (flags & ALF_LAYOUT_INHERITFONT) ALF_Layout_ForwardFontToWidget(layout, window, w, (HFONT)SendMessage(window, WM_GETFONT, 0, 0), 0); if (flags & ALF_LAYOUT_INHERITBGCOLOR) - SendMessage(w->hwnd, ALF_WM_SETBGCOLOR, (WPARAM)SendMessage(window, ALF_WM_GETBGCOLOR, 0, 0), 0); + ALF_SetBackgroundColor(w->hwnd, ALF_GetBackgroundColor(window)); ALF_Layout_Invalidate(layout, window); @@ -752,6 +782,12 @@ ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam, if (msg == ALF_WM_SETBGCOLOR) { ALF_Layout_ForwardBgColor(layout, hwnd, wparam, lparam); + ALF_Layout_HandleBackgroundChange(layout, hwnd); + return TRUE; + } + + if (msg == ALF_WM_BACKGROUNDCHANGE) { + ALF_Layout_HandleBackgroundChange(layout, hwnd); return TRUE; } diff --git a/alf/alfnotebook.cpp b/alf/alfnotebook.cpp index 898c601..1db4011 100644 --- a/alf/alfnotebook.cpp +++ b/alf/alfnotebook.cpp @@ -96,9 +96,9 @@ ALF_Notebook_InternalHandleThemeChange(HWND hwndNotebook, ALFNotebookPriv *priv) HWND panel = ALF_Notebook_InternalTabPanel(hwndNotebook, priv->hwndTabCtrl, i); if (priv->hTheme) { - SendMessage(panel, ALF_WM_SETBGCOLOR, (WPARAM)ALF_COLOR_TRANSPARENT, 0); + ALF_SetBackgroundColor(panel, ALF_COLOR_TRANSPARENT); } else { - SendMessage(panel, ALF_WM_SETBGCOLOR, (WPARAM)ALF_COLOR_SYS(COLOR_BTNFACE), 0); + ALF_SetBackgroundColor(panel, ALF_COLOR_SYS(COLOR_BTNFACE)); } } } @@ -118,9 +118,9 @@ ALF_Notebook_InternalAddTab(HWND notebook, ALFNotebookPriv *priv, const TCHAR *t SendMessage(hwndPanel, WM_SETFONT, (WPARAM)SendMessage(priv->hwndTabCtrl, WM_GETFONT, 0, 0), 0); if (priv->hTheme) { - SendMessage(hwndPanel, ALF_WM_SETBGCOLOR, (WPARAM)ALF_COLOR_TRANSPARENT, 0); + ALF_SetBackgroundColor(hwndPanel, ALF_COLOR_TRANSPARENT); } else { - SendMessage(hwndPanel, ALF_WM_SETBGCOLOR, (WPARAM)ALF_COLOR_SYS(COLOR_BTNFACE), 0); + ALF_SetBackgroundColor(hwndPanel, ALF_COLOR_SYS(COLOR_BTNFACE)); } TCITEM tie; @@ -282,6 +282,9 @@ ALF__NotebookWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) GetClientRect(hwnd, &r); int n = ALF_Notebook_InternalTabCount(hwnd, priv->hwndTabCtrl); + RECT oldR; + GetWindowRect(priv->hwndTabCtrl, &oldR); + HDWP hdwp = BeginDeferWindowPos(n+1); // SWP_COPYBITS: NT 3.51 sadness, will not invalidate bottom edge properly on resize @@ -302,6 +305,13 @@ ALF__NotebookWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } EndDeferWindowPos(hdwp); + + if (priv->hTheme && ((oldR.bottom - oldR.top) != (r.bottom - r.top))) { + // only needed when height changes, since bg is tiled horizontally + HWND panel = ALF_NotebookSelectedPanel(hwnd); + if (panel != NULL) + ALF_InvalidateBackground(panel); + } } } else if (uMsg == ALF_NB_ADDTAB) { return (LRESULT)ALF_Notebook_InternalAddTab(hwnd, priv, (TCHAR *)lParam); diff --git a/alf/alfpanel.cpp b/alf/alfpanel.cpp index eb954ec..7e109bb 100644 --- a/alf/alfpanel.cpp +++ b/alf/alfpanel.cpp @@ -73,11 +73,12 @@ ALF_Panel_DefWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == ALF_WM_SETBGCOLOR) { - priv->bgcolor = (ALFColor)wparam; + priv->bgcolor = (ALFColor)lparam; InvalidateRect(window, NULL, TRUE); // fallthrough to layout, will propagate color to children + // and invalidate the background of transparent children } if (msg == WM_GETFONT) { @@ -121,6 +122,15 @@ ALF_Panel_DefWindowProc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) ALF_Layout_Apply(&priv->layout, window); } + if (msg == ALF_WM_BACKGROUNDCHANGE) { + if (priv->bgcolor != ALF_COLOR_TRANSPARENT) + return 0; // nothing to do here, background is our own solid color + + InvalidateRect(window, NULL, TRUE); + + // fallthrough to layout, will propagate to transparent children + } + LRESULT ret = 0; if (ALF_Layout_HandleMessage(&priv->layout, window, msg, wparam, lparam, &ret)) return ret; @@ -200,7 +210,7 @@ ALF_AddPanel(HWND parent, WORD id, int x, int y) { HWND hwndPanel = ALF_CreatePanelWindow(parent, id); - ALF_AddWidget(parent, x, y, hwndPanel, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_INHERITBGCOLOR); + ALF_AddWidget(parent, x, y, hwndPanel, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT | ALF_LAYOUT_INHERITBGCOLOR | ALF_LAYOUT_SENDBGCHANGE); return hwndPanel; } diff --git a/alf/alfwindow.cpp b/alf/alfwindow.cpp index 41d13e8..c11fede 100644 --- a/alf/alfwindow.cpp +++ b/alf/alfwindow.cpp @@ -197,11 +197,12 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) } if (msg == ALF_WM_SETBGCOLOR) { - priv->bgcolor = (ALFColor)wparam; + priv->bgcolor = (ALFColor)lparam; InvalidateRect(hwnd, NULL, TRUE); // fallthrough to layout, will propagate color to children + // and invalidate the background of transparent children } if (msg == ALF_WM_GETBGCOLOR) { @@ -374,6 +375,17 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) if (msg == WM_THEMECHANGED || msg == WM_SETTINGCHANGE) { ALF_UpdateFontsPriv(hwnd, priv); ALF_Layout_Invalidate(&priv->layout, hwnd); + ALF_InvalidateBackground(hwnd); + InvalidateRect(hwnd, NULL, TRUE); + } + + if (msg == ALF_WM_BACKGROUNDCHANGE) { + if (priv->bgcolor != ALF_COLOR_TRANSPARENT) + return 0; // nothing to do here, background is our own solid color + + InvalidateRect(hwnd, NULL, TRUE); + + // fallthrough to layout, will propagate to transparent children } if (msg == DM_GETDEFID) { @@ -399,6 +411,12 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return TRUE; } + if (msg == WM_WINDOWPOSCHANGED) { + if (priv->vtbl->windowposchanged) { + priv->vtbl->windowposchanged(priv->closure, hwnd, (WINDOWPOS *)lparam); + } + } + LRESULT ret = 0; if (ALF_Layout_HandleMessage(&priv->layout, hwnd, msg, wparam, lparam, &ret)) { // if the layout was changed, our current size might be too small diff --git a/widgetfactory.cpp b/widgetfactory.cpp index 53ba72d..3c8e35a 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -28,6 +28,8 @@ static HBRUSH green; static HBRUSH blue; static HBRUSH white; +BOOL (WINAPI *fnGradientFill)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG) = NULL; + LRESULT handleMessage(void *closure, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -77,6 +79,14 @@ handleCommand(void *closure, HWND window, WORD notificationcode, WORD sourceid, if (control != NULL && sourceid == ID_B2) { MessageBox(window, TEXT("Hello World!"), TEXT("Hello"), MB_ICONASTERISK|MB_OK); } + if (control != NULL && sourceid == ID_B3) { + ALFColor oldcolor = ALF_GetBackgroundColor(window); + if (oldcolor == ALF_COLOR_TRANSPARENT) { + ALF_SetBackgroundColor(window, ALF_COLOR_SYS(COLOR_BTNFACE)); + } else { + ALF_SetBackgroundColor(window, ALF_COLOR_TRANSPARENT); + } + } return 0; } @@ -85,10 +95,108 @@ static void handlePaint(void *closure, HWND window, HDC dc, RECT *rcPaint) { (void)closure; - (void)window; - SetBkColor(dc, RGB(255, 0, 0)); - ExtTextOut(dc, 0, 0, ETO_OPAQUE, rcPaint, TEXT(""), 0, NULL); + ALFColor color = ALF_GetBackgroundColor(window); + + if (color == ALF_COLOR_TRANSPARENT) { + RECT rcClient; + GetClientRect(window, &rcClient); + + if (fnGradientFill) { + TRIVERTEX vertex[6]; + vertex[0].x = rcClient.left; + vertex[0].y = rcClient.top; + vertex[0].Red = 0xff00; + vertex[0].Green = 0x8000; + vertex[0].Blue = 0x0000; + vertex[0].Alpha = 0x0000; + + vertex[1].x = rcClient.left; + vertex[1].y = rcClient.bottom; + vertex[1].Red = 0x9000; + vertex[1].Green = 0x0000; + vertex[1].Blue = 0x9000; + vertex[1].Alpha = 0x0000; + + vertex[2].x = rcClient.right; + vertex[2].y = rcClient.top; + vertex[2].Red = 0x9000; + vertex[2].Green = 0x0000; + vertex[2].Blue = 0x9000; + vertex[2].Alpha = 0x0000; + + vertex[3].x = rcClient.right; + vertex[3].y = rcClient.bottom; + vertex[3].Red = 0x0000; + vertex[3].Green = 0xd000; + vertex[3].Blue = 0xd000; + vertex[3].Alpha = 0x0000; + + vertex[4].x = rcClient.left; + vertex[4].y = rcClient.bottom; + vertex[4].Red = 0x9000; + vertex[4].Green = 0x0000; + vertex[4].Blue = 0x9000; + vertex[4].Alpha = 0x0000; + + vertex[5].x = rcClient.right; + vertex[5].y = rcClient.top; + vertex[5].Red = 0x9000; + vertex[5].Green = 0x0000; + vertex[5].Blue = 0x9000; + vertex[5].Alpha = 0x0000; + + GRADIENT_TRIANGLE gTriangle[2]; + gTriangle[0].Vertex1 = 0; + gTriangle[0].Vertex2 = 1; + gTriangle[0].Vertex3 = 2; + gTriangle[1].Vertex1 = 3; + gTriangle[1].Vertex2 = 4; + gTriangle[1].Vertex3 = 5; + + fnGradientFill(dc, vertex, 6, gTriangle, 2, GRADIENT_FILL_TRIANGLE); + } else { + HBRUSH white = (HBRUSH)GetStockObject(WHITE_BRUSH); + HBRUSH gray = (HBRUSH)GetStockObject(GRAY_BRUSH); + + int s = 10; + for (int y = rcClient.top; y < rcClient.bottom; y += 2*s) { + for (int x = rcClient.left; x < rcClient.right; x += 2*s) { + RECT a = { x, y, x + s, y + s }; + RECT b = { x + s, y, x + s + s, y + s }; + RECT c = { x, y + s, x + s, y + s + s }; + RECT d = { x + s, y + s, x + s + s, y + s + s }; + FillRect(dc, &a, white); + FillRect(dc, &b, gray); + FillRect(dc, &c, gray); + FillRect(dc, &d, white); + } + } + } + } else { + if (rcPaint) { + SetBkColor(dc, ALF_ColorToGdi(color)); + ExtTextOut(dc, 0, 0, ETO_OPAQUE, rcPaint, TEXT(""), 0, NULL); + } else { + RECT rcClient; + GetClientRect(window, &rcClient); + + SetBkColor(dc, ALF_ColorToGdi(color)); + ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rcClient, TEXT(""), 0, NULL); + } + } +} + +static void handleWindowPosChanged(void *closure, HWND window, WINDOWPOS *pos) +{ + (void)closure; + + if (!(pos->flags & SWP_NOSIZE)) { + ALFColor bgcolor = ALF_GetBackgroundColor(window); + + if (bgcolor == ALF_COLOR_TRANSPARENT) + ALF_InvalidateBackground(window); + } } int CALLBACK @@ -110,6 +218,13 @@ WinMain blue = CreateSolidBrush(RGB(0,0,255)); white = CreateSolidBrush(RGB(255,255,255)); + if (LOBYTE(LOWORD(GetVersion())) >= 4) { + HMODULE hMsimg32 = LoadLibraryA("msimg32.dll"); + if (hMsimg32) { + *((void**)&fnGradientFill) = (void*)GetProcAddress(hMsimg32, "GradientFill"); + } + } + ALFWindowClassParams cparams; ZeroMemory(&cparams, sizeof(cparams)); @@ -117,6 +232,7 @@ WinMain cparams.vtbl.message = handleMessage; cparams.vtbl.command = handleCommand; cparams.vtbl.paint = handlePaint; + cparams.vtbl.windowposchanged = handleWindowPosChanged; ALF_Initialize(); @@ -150,7 +266,7 @@ WinMain ALF_AddLabel(win, ID_LBL4, 0, 3, TEXT("&Editable Combo Box:")); HWND hwndCombo1 = ALF_AddEditableComboBox(win, ID_COMBO1, 1, 3, TEXT("Hello!")); - ALF_AddButton(win, ID_B3, 3, 3, TEXT("Ok")); + ALF_AddButton(win, ID_B3, 3, 3, TEXT("Change Background")); ALF_ComboBoxInsertString(hwndCombo1, 0, TEXT("Hello World!")); ALF_ComboBoxInsertString(hwndCombo1, -1, TEXT("Goodbye World!")); @@ -234,8 +350,6 @@ WinMain EnableWindow(ALF_WidgetHwndById(win, ID_LBL3), FALSE); - SendMessage(win, ALF_WM_SETBGCOLOR, (WPARAM)ALF_COLOR_TRANSPARENT, 0); - ALF_ResizeWindow(win, 1, 1); ALF_ShowModal(win); |
