From 253b9857e7b4317275b50795ddc53508e1cbd181 Mon Sep 17 00:00:00 2001 From: Jonas Kümmerlin Date: Fri, 12 Jun 2020 17:05:26 +0200 Subject: icon view and helper functions initial implementation, needs more testing --- alf/alf.h | 20 ++++++ alf/alfcompat.cpp | 20 ++++++ alf/alfcompat.h | 2 + alf/alficon.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 alf/alficon.cpp (limited to 'alf') diff --git a/alf/alf.h b/alf/alf.h index ad15ed7..db0481f 100644 --- a/alf/alf.h +++ b/alf/alf.h @@ -122,6 +122,9 @@ typedef struct { #define ALF_WM_TPLVL_SETDEFFONT (ALF_WM__BASE + 201) +#define ALF_WM_ICONVIEW_GETICON (ALF_WM__BASE + 201) +#define ALF_WM_ICONVIEW_SETICON (ALF_WM__BASE + 202) + #define ALF_WM_USER (ALF_WM__BASE + 300) typedef DWORD ALFColor; @@ -580,6 +583,23 @@ ALF_AddNativeCheckbox(HWND parent, WORD id, int x, int y, const TCHAR *text); HWND ALF_AddNativeRadioButton(HWND parent, WORD id, int x, int y, const TCHAR *text); +// icons and icon widget +HWND +ALF_AddIconView(HWND parent, WORD id, int x, int y, HICON icon); + +HICON +ALF_IconView_Icon(HWND control); + +HICON +ALF_IconView_SetIcon(HWND control, HICON icon); + +HICON +ALF_LoadIcon(HINSTANCE hinst, const TCHAR *name, int cx, int cy); + +SIZE +ALF_IconSize(HICON icon); + + #ifdef __cplusplus } // extern C #endif diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index df7f27d..7b30eac 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -476,6 +476,22 @@ ALF_Compat_fallbackGetThemeMargins(HTHEME hTheme, return E_NOTIMPL; } +static HRESULT WINAPI +ALF_Compat_fallbackLoadIconWithScaleDown(HINSTANCE hinst, + PCWSTR pszName, + int cx, + int cy, + HICON *phico) +{ + (void)hinst; + (void)pszName; + (void)cx; + (void)cy; + (void)phico; + + return E_NOTIMPL; +} + static BOOL CALLBACK ALF_Compat_DrawDisabledText_DrawStateProc(HDC hdc, @@ -612,6 +628,8 @@ void ALF_LoadCompatFunctions(void) LOAD_FUNC(uxtheme, GetThemeColor); LOAD_FUNC(uxtheme, GetThemeMargins); + LOAD_FUNC(comctl32, LoadIconWithScaleDown); + // initialize helper function for disabled text if (ALF_Compat_Is40()) { if (GetSystemMetrics(SM_SLOWMACHINE)) { @@ -704,6 +722,7 @@ void ALF_UnloadCompatFunctions(void) UNLOAD_FUNC(GetThemePartSize); UNLOAD_FUNC(GetThemeColor); UNLOAD_FUNC(GetThemeMargins); + UNLOAD_FUNC(LoadIconWithScaleDown); FreeLibrary(_alf_dll_uxtheme); FreeLibrary(_alf_dll_user32); @@ -741,3 +760,4 @@ BOOL (WINAPI *ALF_Compat_BufferedPaintRenderAnimation)(HWND,HDC) = NULL; HRESULT (WINAPI *ALF_Compat_GetThemeTransitionDuration)(HTHEME,int,int,int,int,DWORD*) = NULL; HRESULT (WINAPI *ALF_Compat_GetThemeColor)(HTHEME,int,int,int,COLORREF*) = NULL; HRESULT (WINAPI *ALF_Compat_GetThemeMargins)(HTHEME,HDC,int,int,int,const RECT *,MARGINS *) = NULL; +HRESULT (WINAPI *ALF_Compat_LoadIconWithScaleDown)(HINSTANCE,PCWSTR,int,int,HICON *) = NULL; diff --git a/alf/alfcompat.h b/alf/alfcompat.h index 5360d9d..e839df4 100644 --- a/alf/alfcompat.h +++ b/alf/alfcompat.h @@ -137,6 +137,8 @@ extern BOOL (WINAPI *ALF_Compat_BufferedPaintRenderAnimation)(HWND,HDC); extern HRESULT (WINAPI *ALF_Compat_GetThemeTransitionDuration)(HTHEME,int,int,int,int,DWORD*); extern HRESULT (WINAPI *ALF_Compat_GetThemeColor)(HTHEME,int,int,int,COLORREF*); extern HRESULT (WINAPI *ALF_Compat_GetThemeMargins)(HTHEME,HDC,int,int,int,const RECT *,MARGINS *); +extern HRESULT (WINAPI *ALF_Compat_LoadIconWithScaleDown)(HINSTANCE,PCWSTR,int,int,HICON *); + // compatibility bits diff --git a/alf/alficon.cpp b/alf/alficon.cpp new file mode 100644 index 0000000..eb83815 --- /dev/null +++ b/alf/alficon.cpp @@ -0,0 +1,206 @@ +#include "alfpriv.h" + +/* ICONS */ + +typedef struct { + ALFColor bgcolor; + HICON icon; + SIZE iconsize; +} ALFIconViewPriv; + +static void +ALF_IconView_Paint(HWND hwnd, ALFIconViewPriv *priv, HDC hdc, RECT *r) +{ + if (priv->bgcolor == ALF_COLOR_TRANSPARENT) { + ALF_Compat_DrawThemeParentBackground(hwnd, hdc, r); + SetBkMode(hdc, TRANSPARENT); + } else { + ALF_FillRect(hdc, r, priv->bgcolor); + SetBkMode(hdc, OPAQUE); + SetBkColor(hdc, ALF_ColorToGdi(priv->bgcolor)); + } + + if (priv->icon) { + RECT rcClient; + GetClientRect(hwnd, &rcClient); + int iconx = (rcClient.right - rcClient.left - priv->iconsize.cx) / 2; + int icony = (rcClient.bottom - rcClient.top - priv->iconsize.cy) / 2; + + DrawIconEx(hdc, iconx, icony, priv->icon, 0, 0, 0, NULL, DI_NORMAL); + } +} + +static LRESULT CALLBACK +ALF_IconView_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + ALFIconViewPriv *priv = (ALFIconViewPriv*)GetWindowLongPtr(hwnd, 0); + + if (uMsg == WM_CREATE && !priv) { + priv = ALF_New(ALFIconViewPriv, 1); + priv->bgcolor = ALF_COLOR_SYS(COLOR_BTNFACE); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv); + } + + if (!priv) + return DefWindowProc(hwnd, uMsg, wParam, lParam); + + if (uMsg == WM_GETDLGCODE) { + return DLGC_STATIC; + } else if (uMsg == WM_PAINT) { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + RECT rcClient; + GetClientRect(hwnd, &rcClient); + RECT rcPaint = { 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; + + HDC hdcBuffer = NULL; + ALF_Compat_HPAINTBUFFER hpb = ALF_Compat_BeginBufferedPaint(hdc, &rcPaint, 0, NULL, &hdcBuffer); + if (hpb) { + ALF_IconView_Paint(hwnd, priv, hdcBuffer, &ps.rcPaint); + ALF_Compat_EndBufferedPaint(hpb, TRUE); + } else { + ALF_IconView_Paint(hwnd, priv, hdc, &ps.rcPaint); + } + + EndPaint(hwnd, &ps); + + return TRUE; + } else if (uMsg == WM_PRINTCLIENT) { + RECT rcClient; + GetClientRect(hwnd, &rcClient); + RECT rcPaint = { 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; + + ALF_IconView_Paint(hwnd, priv, (HDC)wParam, &rcPaint); + } else if (uMsg == WM_NCHITTEST) { + return HTTRANSPARENT; + } else if (uMsg == ALF_WM_QUERYSIZE) { + *(SIZE*)lParam = priv->iconsize; + return TRUE; + } else if (uMsg == WM_WINDOWPOSCHANGED) { + WINDOWPOS *p = (WINDOWPOS *)lParam; + if (!(p->flags & SWP_NOSIZE)) { + InvalidateRect(hwnd, NULL, TRUE); + } + } else if (uMsg == ALF_WM_BACKGROUNDCHANGE) { + if (priv->bgcolor == ALF_COLOR_TRANSPARENT) { + InvalidateRect(hwnd, NULL, TRUE); + } + return TRUE; + } else if (uMsg == ALF_WM_SETBGCOLOR) { + ALFColor newcolor = (ALFColor)lParam; + if (priv->bgcolor == newcolor) + return TRUE; + + priv->bgcolor = newcolor; + InvalidateRect(hwnd, NULL, TRUE); + + return TRUE; + } else if (uMsg == ALF_WM_GETBGCOLOR) { + return (LRESULT)priv->bgcolor; + } else if (uMsg == ALF_WM_ICONVIEW_GETICON) { + return (LRESULT)priv->icon; + } else if (uMsg == ALF_WM_ICONVIEW_SETICON) { + HICON old = priv->icon; + SIZE oldsize = priv->iconsize; + + priv->icon = (HICON)lParam; + priv->iconsize = ALF_IconSize(priv->icon); + + InvalidateRect(hwnd, NULL, TRUE); + if (priv->iconsize.cx != oldsize.cx || priv->iconsize.cy != oldsize.cy) { + ALF_InvalidateLayout(GetParent(hwnd)); + } + + return (LRESULT)old; + } else if (uMsg == WM_DESTROY) { + ALF_Free(priv); + SetWindowLongPtr(hwnd, 0, 0); + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +HWND +ALF_AddIconView(HWND win, WORD id, int x, int y, HICON icon) +{ + HWND hwndIV = ALF_CreateControlWindow( 0, + TEXT(""), + WS_CHILD | WS_VISIBLE, + 0, 0, 100, 100, + win, + (HMENU)(ULONG_PTR)id, + ALF_IconView_WindowProc, + NULL); + + ALF_AddControl(win, x, y, hwndIV, 0, 0, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITBGCOLOR | ALF_LAYOUT_SENDBGCHANGE); + + ALF_IconView_SetIcon(hwndIV, icon); + + return hwndIV; +} + +HICON +ALF_IconView_Icon(HWND control) +{ + return (HICON)SendMessage(control, ALF_WM_ICONVIEW_GETICON, 0, 0); +} + +HICON +ALF_IconView_SetIcon(HWND control, HICON icon) +{ + return (HICON)SendMessage(control, ALF_WM_ICONVIEW_SETICON, 0, (LPARAM)icon); +} + +HICON +ALF_LoadIcon(HINSTANCE hinst, const TCHAR *name, int cx, int cy) +{ + HICON hi; + +#ifdef UNICODE + const WCHAR *namew = name; +#else + WCHAR namebuf[MAX_PATH] = {0}; + const WCHAR *namew; + + if (IS_INTRESOURCE(name)) { + namew = (WCHAR *)name; + } else { + MultiByteToWideChar(CP_ACP, 0, name, -1, namebuf, sizeof(namebuf)/sizeof(namebuf[0])-1); + namew = namebuf; + } +#endif + + if (SUCCEEDED(ALF_Compat_LoadIconWithScaleDown(hinst, namew, cx, cy, &hi))) { + return hi; + } else { + if (hinst == NULL) { + if (IS_INTRESOURCE(name)) { // standard icon + return CopyIcon(LoadIcon(hinst, name)); + } else { // .ico file + return (HICON)LoadImage(hinst, name, IMAGE_ICON, cx, cy, LR_LOADFROMFILE); + } + } else { + return (HICON)LoadImage(hinst, name, IMAGE_ICON, cx, cy, 0); + } + } +} + +SIZE +ALF_IconSize(HICON icon) +{ + ICONINFO ii; + SIZE s = { 0, 0 }; + if (GetIconInfo(icon, &ii)) { + BITMAP bm; + if (GetObject(ii.hbmMask, sizeof(bm), &bm) == sizeof(bm)) { + s.cx = bm.bmWidth; + s.cy = ii.hbmColor ? bm.bmHeight : bm.bmHeight / 2; + } + + if (ii.hbmMask) DeleteObject(ii.hbmMask); + if (ii.hbmColor) DeleteObject(ii.hbmColor); + } + + return s; +} -- cgit v1.2.3