mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 18:54:25 +00:00
[uxtheme]
- Properly disable themes when theme hooks are removed - Add WND_CONTEXT a per window struct that will hold several theme specific information. For now it contains only theme region related info. It will be stored as a window property - Implement destroying WND_CONTEXT for every window when theme hooks are removed or when the window is destroyed - Hook the messages that are sent to dialogs, like they are hooked for normal windows - Hook SetWindowRgn call from user32. When an application calls it, uxtheme will stop setting window region on its own region - Implement setting a custom window region for windows after receiving WM_WINDOWPOSCHANGED message using GetThemeBackgroundRegion svn path=/branches/GSoC_2011/ThemesSupport/; revision=53262
This commit is contained in:
parent
5ceabc031a
commit
10bed5b061
|
@ -1,4 +1,11 @@
|
|||
|
||||
typedef struct _WND_CONTEXT
|
||||
{
|
||||
BOOL HasAppDefinedRgn;
|
||||
BOOL HasThemeRgn;
|
||||
BOOL UpdatingRgn;
|
||||
} WND_CONTEXT, *PWND_CONTEXT;
|
||||
|
||||
typedef struct _DRAW_CONTEXT
|
||||
{
|
||||
HWND hWnd;
|
||||
|
@ -91,5 +98,9 @@ ThemeInitDrawContext(PDRAW_CONTEXT pcontext,
|
|||
void
|
||||
ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext);
|
||||
|
||||
PWND_CONTEXT
|
||||
ThemeGetWndContext(HWND hWnd);
|
||||
|
||||
extern ATOM atWindowTheme;
|
||||
extern ATOM atWndContrext;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "uxthemedll.h"
|
||||
#include "msstyles.h"
|
||||
#include "ncthm.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -64,6 +65,7 @@ static DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
|
|||
ATOM atWindowTheme;
|
||||
static ATOM atSubAppName;
|
||||
static ATOM atSubIdList;
|
||||
ATOM atWndContrext;
|
||||
|
||||
static BOOL bThemeActive = FALSE;
|
||||
static WCHAR szCurrentTheme[MAX_PATH];
|
||||
|
@ -148,7 +150,7 @@ static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue,
|
|||
*
|
||||
* Set the current active theme from the registry
|
||||
*/
|
||||
void UXTHEME_LoadTheme(void)
|
||||
void UXTHEME_LoadTheme(BOOL bLoad)
|
||||
{
|
||||
HKEY hKey;
|
||||
DWORD buffsize;
|
||||
|
@ -156,29 +158,36 @@ void UXTHEME_LoadTheme(void)
|
|||
WCHAR tmp[10];
|
||||
PTHEME_FILE pt;
|
||||
|
||||
/* Get current theme configuration */
|
||||
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
|
||||
TRACE("Loading theme config\n");
|
||||
buffsize = sizeof(tmp)/sizeof(tmp[0]);
|
||||
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
|
||||
bThemeActive = (tmp[0] != '0');
|
||||
if(bLoad == TRUE)
|
||||
{
|
||||
/* Get current theme configuration */
|
||||
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
|
||||
TRACE("Loading theme config\n");
|
||||
buffsize = sizeof(tmp)/sizeof(tmp[0]);
|
||||
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
|
||||
bThemeActive = (tmp[0] != '0');
|
||||
}
|
||||
else {
|
||||
bThemeActive = FALSE;
|
||||
TRACE("Failed to get ThemeActive: %d\n", GetLastError());
|
||||
}
|
||||
buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
|
||||
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
|
||||
szCurrentColor[0] = '\0';
|
||||
buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
|
||||
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
|
||||
szCurrentSize[0] = '\0';
|
||||
if (query_reg_path (hKey, szDllName, szCurrentTheme))
|
||||
szCurrentTheme[0] = '\0';
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
else {
|
||||
bThemeActive = FALSE;
|
||||
TRACE("Failed to get ThemeActive: %d\n", GetLastError());
|
||||
}
|
||||
buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
|
||||
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
|
||||
szCurrentColor[0] = '\0';
|
||||
buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
|
||||
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
|
||||
szCurrentSize[0] = '\0';
|
||||
if (query_reg_path (hKey, szDllName, szCurrentTheme))
|
||||
szCurrentTheme[0] = '\0';
|
||||
RegCloseKey(hKey);
|
||||
else
|
||||
TRACE("Failed to open theme registry key\n");
|
||||
}
|
||||
else
|
||||
TRACE("Failed to open theme registry key\n");
|
||||
{
|
||||
bThemeActive = FALSE;
|
||||
}
|
||||
|
||||
if(bThemeActive) {
|
||||
/* Make sure the theme requested is actually valid */
|
||||
|
@ -542,6 +551,7 @@ void UXTHEME_InitSystem(HINSTANCE hInst)
|
|||
atSubAppName = GlobalAddAtomW(szSubAppName);
|
||||
atSubIdList = GlobalAddAtomW(szSubIdList);
|
||||
atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
|
||||
atWndContrext = GlobalAddAtomW(L"ux_WndContext");
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include "vfwmsgs.h"
|
||||
#include "uxtheme.h"
|
||||
#include "uxthemedll.h"
|
||||
#include "ncthm.h"
|
||||
#include "tmschema.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
|
||||
|
@ -26,6 +29,163 @@ USERAPIHOOK user32ApiHook;
|
|||
BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
|
||||
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
|
||||
|
||||
|
||||
PWND_CONTEXT ThemeGetWndContext(HWND hWnd)
|
||||
{
|
||||
PWND_CONTEXT pcontext;
|
||||
|
||||
pcontext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
|
||||
if(pcontext == NULL)
|
||||
{
|
||||
pcontext = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(WND_CONTEXT));
|
||||
if(pcontext == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), pcontext);
|
||||
}
|
||||
|
||||
return pcontext;
|
||||
}
|
||||
|
||||
void ThemeDetroyWndContext(HWND hWnd)
|
||||
{
|
||||
PWND_CONTEXT pContext;
|
||||
DWORD ProcessId;
|
||||
|
||||
/*Do not destroy WND_CONTEXT of a window that belong to another process */
|
||||
GetWindowThreadProcessId(hWnd, &ProcessId);
|
||||
if(ProcessId != GetCurrentProcessId())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pContext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext));
|
||||
if(pContext == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(pContext->HasThemeRgn)
|
||||
{
|
||||
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, pContext);
|
||||
|
||||
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), NULL);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
|
||||
{
|
||||
ThemeDetroyWndContext(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
|
||||
{
|
||||
if (hWnd == NULL)
|
||||
{
|
||||
EnumWindows (ThemeCleanupWndContext, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThemeDetroyWndContext(hWnd);
|
||||
EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetThemeRegion(HWND hWnd, PWND_CONTEXT pcontext)
|
||||
{
|
||||
HTHEME hTheme;
|
||||
RECT rcWindow;
|
||||
HRGN hrgn, hrgn1;
|
||||
int CaptionHeight, iPart;
|
||||
WINDOWINFO wi;
|
||||
|
||||
if(!IsAppThemed())
|
||||
{
|
||||
if(pcontext->HasThemeRgn)
|
||||
{
|
||||
pcontext->HasThemeRgn = FALSE;
|
||||
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wi.cbSize = sizeof(wi);
|
||||
|
||||
GetWindowInfo(hWnd, &wi);
|
||||
|
||||
if((wi.dwStyle & WS_CAPTION)!=WS_CAPTION)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the caption part id */
|
||||
if (wi.dwExStyle & WS_EX_TOOLWINDOW)
|
||||
iPart = WP_SMALLCAPTION;
|
||||
else if (wi.dwStyle & WS_MAXIMIZE)
|
||||
iPart = WP_MAXCAPTION;
|
||||
else
|
||||
iPart = WP_CAPTION;
|
||||
|
||||
pcontext->HasThemeRgn = TRUE;
|
||||
|
||||
CaptionHeight = wi.cyWindowBorders;
|
||||
CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
|
||||
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
rcWindow.right -= rcWindow.left;
|
||||
rcWindow.bottom = CaptionHeight;
|
||||
rcWindow.top = 0;
|
||||
rcWindow.left = 0;
|
||||
|
||||
hTheme = OpenThemeData (hWnd, L"WINDOW");
|
||||
|
||||
GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
|
||||
|
||||
CloseThemeData(hTheme);
|
||||
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
rcWindow.right -= rcWindow.left;
|
||||
rcWindow.bottom -= rcWindow.top;
|
||||
rcWindow.top = CaptionHeight;
|
||||
rcWindow.left = 0;
|
||||
hrgn1 = CreateRectRgnIndirect(&rcWindow);
|
||||
|
||||
CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
|
||||
|
||||
DeleteObject(hrgn1);
|
||||
|
||||
user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
|
||||
}
|
||||
|
||||
int OnPostWinPosChanged(HWND hWnd)
|
||||
{
|
||||
PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
|
||||
|
||||
if(pcontext &&
|
||||
pcontext->HasAppDefinedRgn == FALSE &&
|
||||
pcontext->UpdatingRgn == FALSE)
|
||||
{
|
||||
pcontext->UpdatingRgn = TRUE;
|
||||
SetThemeRegion(hWnd, pcontext);
|
||||
pcontext = ThemeGetWndContext(hWnd);
|
||||
pcontext->UpdatingRgn = FALSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Hook Functions
|
||||
*/
|
||||
|
||||
static LRESULT CALLBACK
|
||||
ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -75,12 +235,50 @@ ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static LRESULT CALLBACK
|
||||
ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
|
||||
{
|
||||
switch(Msg)
|
||||
{
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
return OnPostWinPosChanged(hWnd);
|
||||
}
|
||||
case WM_DESTROY:
|
||||
{
|
||||
ThemeDetroyWndContext(hWnd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
|
||||
{
|
||||
PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
|
||||
if(pcontext)
|
||||
{
|
||||
pcontext->HasAppDefinedRgn = TRUE;
|
||||
pcontext->HasThemeRgn = FALSE;
|
||||
}
|
||||
|
||||
return user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Exports
|
||||
*/
|
||||
|
||||
BOOL CALLBACK
|
||||
ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
|
||||
{
|
||||
/* Sanity checks for the caller */
|
||||
if (!puah || State != uahLoadInit)
|
||||
{
|
||||
UXTHEME_LoadTheme(FALSE);
|
||||
ThemeCleanupWndContext(NULL, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -90,10 +288,17 @@ ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
|
|||
puah->DefWindowProcA = ThemeDefWindowProcA;
|
||||
puah->DefWindowProcW = ThemeDefWindowProcW;
|
||||
puah->PreWndProc = ThemePreWindowProc;
|
||||
puah->PostWndProc = ThemePostWindowProc;
|
||||
puah->PreDefDlgProc = ThemePreWindowProc;
|
||||
puah->PostDefDlgProc = ThemePostWindowProc;
|
||||
puah->DefWndProcArray.MsgBitArray = gabDWPmessages;
|
||||
puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
|
||||
puah->WndProcArray.MsgBitArray = gabMSGPmessages;
|
||||
puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
|
||||
puah->DlgProcArray.MsgBitArray = gabMSGPmessages;
|
||||
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
|
||||
|
||||
puah->SetWindowRgn = ThemeSetWindowRgn;
|
||||
|
||||
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
|
||||
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
|
||||
|
@ -130,7 +335,7 @@ ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
|
|||
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
|
||||
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
|
||||
|
||||
UXTHEME_LoadTheme();
|
||||
UXTHEME_LoadTheme(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -187,8 +392,7 @@ ThemeHooksRemove()
|
|||
|
||||
ret = UnregisterUserApiHook();
|
||||
|
||||
if(IsThemeActive())
|
||||
UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
|
||||
UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -95,7 +95,7 @@ HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
|
|||
ParseThemeIniFileProc callback, LPVOID lpData);
|
||||
|
||||
extern void UXTHEME_InitSystem(HINSTANCE hInst);
|
||||
extern void UXTHEME_LoadTheme(void);
|
||||
extern void UXTHEME_LoadTheme(BOOL bLoad);
|
||||
extern BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg);
|
||||
|
||||
/* No alpha blending */
|
||||
|
|
Loading…
Reference in a new issue