#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=li.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 (li.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); li.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); li.List_Remove(xptObjectList, li.List_IndexOf(xptObjectList,(void *) xptHandle)); } xptunlock(); } void xpt_FreeThemeForWindow(HWND hwnd) { xptcheck; xptlock(); { int i=0; while (irealCount) { XPTObject* xptObject=(XPTObject*)xptObjectList->items[i]; if (xptObject->hOwnerWindow==hwnd) { _sttXptCloseThemeData(xptObject); _sttXptObjectDestructor((void *) xptObject); li.List_Remove(xptObjectList, i); } else i++; } } xptunlock(); } void xpt_OnWM_THEMECHANGED() { xptcheck; xptlock(); { int i; for (i=0; irealCount; 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