#include "hdr/modern_commonheaders.h" #include "hdr/modern_commonprototypes.h" #include "m_api/m_xpTheme.h" //statical typedef struct _tagXPTObject { HANDLE hThemeHandle; HWND hOwnerWindow; LPCWSTR lpcwClassObject; } XPTObject; static SortedList * xptObjectList = NULL; static CRITICAL_SECTION xptCS; static BOOL xptModuleLoaded = FALSE; static HMODULE _xpt_ThemeAPIHandle = NULL; // handle to uxtheme.dll static HANDLE (WINAPI *_xpt_OpenThemeData)(HWND, LPCWSTR) = NULL; static HRESULT (WINAPI *_xpt_CloseThemeData)(HANDLE) = NULL; static BOOL (WINAPI *_xpt_IsThemeBackgroundPartiallyTransparent)(HANDLE, int,int) = NULL; static BOOL (WINAPI *_xpt_EnableThemeDialogTexture)(HANDLE, DWORD) = NULL; static HRESULT (WINAPI *_xpt_GetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, int eSize, SIZE *psz ) = NULL; static HRESULT (WINAPI *_xpt_DrawThemeParentBackground)(HWND, HDC, const RECT *) = NULL; static HRESULT (WINAPI *_xpt_DrawThemeBackground)(HANDLE, HDC, int, int,const RECT *, const RECT *) = NULL; static HRESULT (WINAPI *_xpt_DrawThemeText)(HANDLE, HDC, int, int, LPCWSTR, int,DWORD, DWORD, const RECT *) = NULL; #undef MGPROC #define MGPROC(x) GetProcAddress(_xpt_ThemeAPIHandle,x) #define xptcheck if ( !xptModuleLoaded) return #define xptlock() EnterCriticalSection(&xptCS) #define xptunlock() LeaveCriticalSection(&xptCS) static void _sttXptObjectDestructor (void * pt) { mir_free(pt); } static int _xpt_ThemeSupport() { if (IsWinVerXPPlus()) { if ( !_xpt_ThemeAPIHandle) { _xpt_ThemeAPIHandle = GetModuleHandleA("uxtheme"); if (_xpt_ThemeAPIHandle) { _xpt_OpenThemeData = (HANDLE(WINAPI *)(HWND, LPCWSTR))MGPROC("OpenThemeData"); _xpt_CloseThemeData = (HRESULT(WINAPI *)(HANDLE))MGPROC("CloseThemeData"); _xpt_IsThemeBackgroundPartiallyTransparent = (BOOL(WINAPI *)(HANDLE, int, int))MGPROC("IsThemeBackgroundPartiallyTransparent"); _xpt_DrawThemeParentBackground = (HRESULT(WINAPI *)(HWND, HDC, const RECT *))MGPROC("DrawThemeParentBackground"); _xpt_DrawThemeBackground = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, const RECT *, const RECT *))MGPROC("DrawThemeBackground"); _xpt_DrawThemeText = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, const RECT *))MGPROC("DrawThemeText"); _xpt_GetThemePartSize = (HRESULT(WINAPI *)(HTHEME , HDC , int , int , RECT *, int , SIZE * ))MGPROC("GetThemePartSize"); _xpt_EnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD)) MGPROC("EnableThemeDialogTexture"); } } // Make sure all of these methods are valid (i would hope either all or none work) if (_xpt_OpenThemeData && _xpt_CloseThemeData && _xpt_IsThemeBackgroundPartiallyTransparent && _xpt_DrawThemeParentBackground && _xpt_DrawThemeBackground && _xpt_DrawThemeText && _xpt_GetThemePartSize) { return 1; } } return 0; } static void _sttXptCloseThemeData(XPTObject * xptObject) { _xpt_CloseThemeData(xptObject->hThemeHandle); xptObject->hThemeHandle = NULL; } static void _sttXptReloadThemeData(XPTObject * xptObject) { _xpt_CloseThemeData(xptObject->hThemeHandle); xptObject->hThemeHandle = _xpt_OpenThemeData(xptObject->hOwnerWindow, xptObject->lpcwClassObject); } HRESULT XPThemesLoadModule() { if (_xpt_ThemeSupport()) { InitializeCriticalSection(&xptCS); xptObjectList = List_Create(0,1); xptModuleLoaded = TRUE; } return S_OK; } void XPThemesUnloadModule() { xptcheck; xptlock(); xptModuleLoaded = FALSE; xptunlock(); li_ListDestruct(xptObjectList,_sttXptObjectDestructor); DeleteCriticalSection(&xptCS); FreeLibrary(_xpt_ThemeAPIHandle); } BOOL xpt_IsThemed(XPTHANDLE xptHandle) { BOOL res = FALSE; xptcheck FALSE; if ( !xptHandle) return FALSE; xptlock(); { if (xpt_IsValidHandle(xptHandle) && ((XPTObject*) xptHandle)->hThemeHandle) res = TRUE; } xptunlock(); return res; } BOOL xpt_IsValidHandle(XPTHANDLE xptHandle) { BOOL res = FALSE; xptcheck FALSE; if ( !xptHandle) return FALSE; xptlock(); { if (List_IndexOf(xptObjectList, (void*)xptHandle) != -1) res = TRUE; } xptunlock(); return res; } XPTHANDLE xpt_AddThemeHandle(HWND hwnd, LPCWSTR className) { XPTHANDLE res = NULL; xptcheck NULL; xptlock(); { XPTObject* xptObject = (XPTObject*)mir_calloc(sizeof(XPTObject)); xptObject->lpcwClassObject = className; xptObject->hOwnerWindow = hwnd; _sttXptReloadThemeData(xptObject); List_InsertPtr(xptObjectList, (void*)xptObject); res = (XPTHANDLE)xptObject; } xptunlock(); return res; } void xpt_FreeThemeHandle(XPTHANDLE xptHandle) { xptcheck; xptlock(); if (xpt_IsValidHandle(xptHandle)) { XPTObject* xptObject = (XPTObject*)xptHandle; _sttXptCloseThemeData(xptObject); _sttXptObjectDestructor((void *) xptHandle); List_Remove(xptObjectList, List_IndexOf(xptObjectList,(void *) xptHandle)); } xptunlock(); } void xpt_FreeThemeForWindow(HWND hwnd) { xptcheck; xptlock(); { int i=0; while (i < xptObjectList->realCount) { XPTObject* xptObject = (XPTObject*)xptObjectList->items[i]; if (xptObject->hOwnerWindow == hwnd) { _sttXptCloseThemeData(xptObject); _sttXptObjectDestructor((void *) xptObject); List_Remove(xptObjectList, i); } else i++; } } xptunlock(); } void xpt_OnWM_THEMECHANGED() { xptcheck; xptlock(); { int i; for (i=0; i < xptObjectList->realCount; i++) _sttXptReloadThemeData((XPTObject*)xptObjectList->items[i]); } xptunlock(); } HRESULT xpt_DrawThemeBackground(XPTHANDLE xptHandle, HDC hdc, int type, int state, const RECT * sizeRect, const RECT * clipRect) { HRESULT res = S_FALSE; xptcheck S_FALSE; xptlock(); if (xpt_IsThemed(xptHandle)) res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect); xptunlock(); return res; } HRESULT xpt_DrawThemeParentBackground(HWND hWnd, HDC hdc, const RECT * sizeRect) { xptcheck S_FALSE; return xpt_DrawThemeParentBackground(hWnd, hdc, sizeRect); } BOOL xpt_IsThemeBackgroundPartiallyTransparent(XPTHANDLE xptHandle, int type, int state) { BOOL res = FALSE; xptcheck FALSE; xptlock(); if (xpt_IsThemed(xptHandle)) res = _xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state); xptunlock(); return res; } HRESULT xpt_DrawTheme(XPTHANDLE xptHandle, HWND hwnd, HDC hdc, int type, int state, const RECT *sizeRect, const RECT * clipRect) { HRESULT res = S_FALSE; xptcheck S_FALSE; xptlock(); if (xpt_IsThemed(xptHandle)) { if (_xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state)) res = _xpt_DrawThemeParentBackground(hwnd,hdc,sizeRect); res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect); } xptunlock(); return res; } HRESULT xpt_DrawThemeText(XPTHANDLE xptHandle, HDC hdc, int type, int state, LPCTSTR lpStr, int len, DWORD flag1, DWORD flag2, const RECT * textRect) { HRESULT res = S_FALSE; xptcheck S_FALSE; xptlock(); if (xpt_IsThemed(xptHandle)) _xpt_DrawThemeText(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, (LPCWSTR)lpStr, len, flag1, flag2, textRect); else ske_DrawText(hdc,lpStr,len, (RECT*)textRect, flag1); xptunlock(); return S_OK; } BOOL xpt_EnableThemeDialogTexture(HWND hwnd, DWORD flags) { BOOL res = FALSE; xptcheck res; xptlock(); res = _xpt_EnableThemeDialogTexture(hwnd, flags); xptunlock(); return res; } //usage outside // add theme data // in WM_DESTROY - release theme data // in paint xpt_DrawTheme