#include "osstyleXP.inl"
#include <core/heap.h>
#include <sewer/bmem.h>
#include <sewer/cassert.h>
#ifndef DTPB_WINDOWDC
#define DTPB_WINDOWDC 0x00000001
#endif
#ifndef DTPB_USECTLCOLORSTATIC
#define DTPB_USECTLCOLORSTATIC 0x00000002
#endif
typedef struct _osstyleXP_t OSStyleXP;
typedef BOOL(__stdcall *PFNISAPPTHEMED)(void);
typedef BOOL(__stdcall *PFNISTHEMEACTIVE)(void);
typedef HTHEME(__stdcall *PFNOPENTHEMEDATA)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT(__stdcall *PFNCLOSETHEMEDATA)(HTHEME hTheme);
typedef HRESULT(__stdcall *PFNGETTHEMEBACKGROUNDCONTENTRECT)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect);
typedef HRESULT(__stdcall *PFNDRAWTHEMEBACKGROUND)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect);
typedef BOOL(__stdcall *PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)(HTHEME hTheme, int iPartId, int iStateId);
typedef HRESULT(__stdcall *PFNDRAWTHEMEPARENTBACKGROUNDEX)(HWND hwnd, HDC hdc, DWORD dwFlags, const RECT *prc);
typedef HRESULT(__stdcall *PFNDRAWTHEMEEDGE)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, UINT uEdge, UINT uFlags, RECT *pContentRect);
typedef HRESULT(__stdcall *PFNGETTHEMEFONT)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, int iPropId, LOGFONT *pFont);
typedef HRESULT(__stdcall *PFNDRAWTHEMETEXT)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect);
struct _osstyleXP_t
{
HMODULE themeDll;
HTHEME theme;
PFNISAPPTHEMED IsAppThemed;
PFNISTHEMEACTIVE IsThemeActive;
PFNOPENTHEMEDATA OpenThemeData;
PFNCLOSETHEMEDATA CloseThemeData;
PFNGETTHEMEBACKGROUNDCONTENTRECT GetThemeBackgroundContentRect;
PFNDRAWTHEMEBACKGROUND DrawThemeBackground;
PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT IsThemeBackgroundPartiallyTransparent;
PFNDRAWTHEMEPARENTBACKGROUNDEX DrawThemeParentBackgroundEx;
PFNDRAWTHEMEEDGE DrawThemeEdge;
PFNGETTHEMEFONT GetThemeFont;
PFNDRAWTHEMETEXT DrawThemeText;
};
static OSStyleXP i_STYLEXP;
void _osstyleXP_init(void)
{
bmem_zero(&i_STYLEXP, OSStyleXP);
i_STYLEXP.themeDll = LoadLibrary(L"UxTheme.dll");
i_STYLEXP.IsAppThemed = cast_func(GetProcAddress(i_STYLEXP.themeDll, "IsAppThemed"), PFNISAPPTHEMED);
i_STYLEXP.IsThemeActive = cast_func(GetProcAddress(i_STYLEXP.themeDll, "IsThemeActive"), PFNISTHEMEACTIVE);
i_STYLEXP.OpenThemeData = cast_func(GetProcAddress(i_STYLEXP.themeDll, "OpenThemeData"), PFNOPENTHEMEDATA);
i_STYLEXP.CloseThemeData = cast_func(GetProcAddress(i_STYLEXP.themeDll, "CloseThemeData"), PFNCLOSETHEMEDATA);
i_STYLEXP.GetThemeBackgroundContentRect = cast_func(GetProcAddress(i_STYLEXP.themeDll, "GetThemeBackgroundContentRect"), PFNGETTHEMEBACKGROUNDCONTENTRECT);
i_STYLEXP.DrawThemeBackground = cast_func(GetProcAddress(i_STYLEXP.themeDll, "DrawThemeBackground"), PFNDRAWTHEMEBACKGROUND);
i_STYLEXP.IsThemeBackgroundPartiallyTransparent = cast_func(GetProcAddress(i_STYLEXP.themeDll, "IsThemeBackgroundPartiallyTransparent"), PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT);
i_STYLEXP.DrawThemeParentBackgroundEx = cast_func(GetProcAddress(i_STYLEXP.themeDll, "DrawThemeParentBackgroundEx"), PFNDRAWTHEMEPARENTBACKGROUNDEX);
i_STYLEXP.DrawThemeEdge = cast_func(GetProcAddress(i_STYLEXP.themeDll, "DrawThemeEdge"), PFNDRAWTHEMEEDGE);
i_STYLEXP.GetThemeFont = cast_func(GetProcAddress(i_STYLEXP.themeDll, "GetThemeFont"), PFNGETTHEMEFONT);
i_STYLEXP.DrawThemeText = cast_func(GetProcAddress(i_STYLEXP.themeDll, "DrawThemeText"), PFNDRAWTHEMETEXT);
}
void _osstyleXP_finish(void)
{
cassert(i_STYLEXP.themeDll != NULL);
FreeLibrary(i_STYLEXP.themeDll);
i_STYLEXP.themeDll = NULL;
}
static BOOL i_IsAppThemed(void)
{
return i_STYLEXP.IsAppThemed();
}
static BOOL i_IsThemeActive(void)
{
return i_STYLEXP.IsThemeActive();
}
HTHEME _osstyleXP_OpenTheme(HWND hwnd, LPCWSTR pszClassList)
{
HTHEME theme = NULL;
if (i_IsAppThemed() == TRUE && i_IsThemeActive() == TRUE)
theme = i_STYLEXP.OpenThemeData(hwnd, pszClassList);
return theme;
}
BOOL _osstyleXP_OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
{
cassert(i_STYLEXP.theme == NULL);
i_STYLEXP.theme = _osstyleXP_OpenTheme(hwnd, pszClassList);
return (i_STYLEXP.theme != NULL) ? TRUE : FALSE;
}
void _osstyleXP_CloseTheme(HTHEME theme)
{
HRESULT res = 0;
cassert_no_null(theme);
res = i_STYLEXP.CloseThemeData(theme);
cassert_unref(res == S_OK, res);
}
void _osstyleXP_CloseThemeData(void)
{
_osstyleXP_CloseTheme(i_STYLEXP.theme);
i_STYLEXP.theme = NULL;
}
void _osstyleXP_GetThemeBackgroundContentRect(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect)
{
HRESULT res = i_STYLEXP.GetThemeBackgroundContentRect(hTheme, hdc, iPartId, iStateId, pBoundingRect, pContentRect);
cassert_unref(res == S_OK, res);
}
void _osstyleXP_DrawThemeBackground2(HTHEME theme, int iPartId, int iStateId, HDC hdc, const RECT *rc)
{
HRESULT res = i_STYLEXP.DrawThemeBackground(theme, hdc, iPartId, iStateId, rc, NULL);
cassert_unref(res == S_OK, res);
}
void _osstyleXP_DrawThemeBackground(HWND hwnd, HDC hdc, int iPartId, int iStateId, const BOOL draw_parent_bg, const RECT *rc, RECT *border)
{
HRESULT res = 0;
cassert_no_null(i_STYLEXP.theme);
if (draw_parent_bg == TRUE)
{
if (i_STYLEXP.DrawThemeParentBackgroundEx != NULL)
{
if (i_STYLEXP.IsThemeBackgroundPartiallyTransparent(i_STYLEXP.theme, iPartId, iStateId) == TRUE)
i_STYLEXP.DrawThemeParentBackgroundEx(hwnd, hdc, DTPB_WINDOWDC | DTPB_USECTLCOLORSTATIC, cast(rc, RECT));
}
}
res = i_STYLEXP.DrawThemeBackground(i_STYLEXP.theme, hdc, iPartId, iStateId, rc, NULL);
cassert_unref(res == S_OK, res);
if (border != NULL)
{
res = i_STYLEXP.GetThemeBackgroundContentRect(i_STYLEXP.theme, hdc, iPartId, iStateId, rc, border);
cassert_unref(res == S_OK, res);
}
}
void _osstyleXP_DrawNonThemedButtonBackground(HWND hwnd, HDC hdc, BOOL has_focus, UINT state, const RECT *rc, RECT *border)
{
RECT rcback;
HBRUSH brush = NULL;
cassert_no_null(border);
{
HWND parent = GetParent(hwnd);
if (parent != NULL)
brush = (HBRUSH)SendMessage(parent, WM_CTLCOLORBTN, (WPARAM)hdc, (LPARAM)hwnd);
else
brush = (HBRUSH)GetStockObject(GRAY_BRUSH);
}
FillRect(hdc, rc, brush);
rcback = *border;
if (has_focus & ((state & DFCS_PUSHED) == 0))
InflateRect(&rcback, -1, -1);
DrawFrameControl(hdc, &rcback, DFC_BUTTON, state);
InflateRect(border, -4, -4);
}
void _osstyleXP_DrawThemeEdge(HDC hdc, int iPartId, int iStateId, const RECT *rc)
{
HRESULT res = 0;
cassert_no_null(i_STYLEXP.theme);
i_STYLEXP.DrawThemeEdge(i_STYLEXP.theme, hdc, iPartId, iStateId, rc, EDGE_BUMP, BF_TOP | BF_LEFT | BF_RIGHT | BF_BOTTOM, NULL);
cassert_unref(res == S_OK, res);
}
BOOL _osstyleXP_HasThemeFont(HDC hdc, int iPartId, int iStateId, int iPropId)
{
LOGFONTW font;
HRESULT res = 0;
cassert_no_null(i_STYLEXP.theme);
res = i_STYLEXP.GetThemeFont(i_STYLEXP.theme, hdc, iPartId, iStateId, iPropId, &font);
return (BOOL)(res == S_OK);
}
void _osstyleXP_DrawThemeText2(HTHEME theme, HDC hdc, int iPartId, int iStateId, const WCHAR *text, int num_chars, DWORD flags, const RECT *rc)
{
HRESULT res = 0;
cassert_no_null(theme);
res = i_STYLEXP.DrawThemeText(theme, hdc, iPartId, iStateId, text, (int)num_chars, flags, 0, rc);
cassert_unref(res == S_OK, res);
}
void _osstyleXP_DrawThemeText(HDC hdc, int iPartId, int iStateId, const WCHAR *text, uint32_t num_chars, DWORD flags, const RECT *rc)
{
HRESULT res = 0;
cassert_no_null(i_STYLEXP.theme);
res = i_STYLEXP.DrawThemeText(i_STYLEXP.theme, hdc, iPartId, iStateId, text, (int)num_chars, flags, 0, rc);
cassert_unref(res == S_OK, res);
}