Added some generic code to allow subclassing (for the purpose of

theming) of standard controls.
This commit is contained in:
Frank Richter 2005-07-27 10:54:49 +00:00 committed by Alexandre Julliard
parent 7b416af6ea
commit 7d00bb387e
4 changed files with 166 additions and 0 deletions

View File

@ -35,6 +35,7 @@ C_SRCS = \
status.c \
syslink.c \
tab.c \
theming.c \
toolbar.c \
tooltips.c \
trackbar.c \

View File

@ -249,4 +249,8 @@ static inline void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
to->wMilliseconds = from->wMilliseconds;
}
extern void THEMING_Initialize(void);
extern LRESULT THEMING_CallOriginalClass(HWND, UINT, WPARAM, LPARAM);
extern void THEMING_SetSubclassData(HWND, ULONG_PTR);
#endif /* __WINE_COMCTL32_H */

View File

@ -144,6 +144,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
TRACKBAR_Register ();
TREEVIEW_Register ();
UPDOWN_Register ();
/* subclass user32 controls */
THEMING_Initialize ();
break;
case DLL_PROCESS_DETACH:

158
dlls/comctl32/theming.c Normal file
View File

@ -0,0 +1,158 @@
/*
* Theming - Initialization
*
* Copyright (c) 2005 by Frank Richter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "comctl32.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(theming);
typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM,
ULONG_PTR);
static const struct ThemingSubclass
{
const WCHAR* className;
THEMING_SUBCLASSPROC subclassProc;
} subclasses[] = {
/* Note: list must be sorted by class name */
};
#define NUM_SUBCLASSES (sizeof(subclasses)/sizeof(subclasses[0]))
static WNDPROC originalProcs[NUM_SUBCLASSES];
static ATOM atRefDataProp;
static ATOM atSubclassProp;
/***********************************************************************
* THEMING_SubclassProc
*
* The window proc registered to the subclasses. Fetches the subclass
* proc and ref data and call the proc.
*/
static LRESULT CALLBACK THEMING_SubclassProc (HWND wnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
int subclass = (int)GetPropW (wnd, MAKEINTATOMW (atSubclassProp)) - 1;
LRESULT result;
ULONG_PTR refData;
if (subclass == -1)
{
/* Means this is the first time this proc is called for this window.
* Determine the index of the subclass */
WCHAR className[32];
int l = 0, r = NUM_SUBCLASSES;
GetClassNameW (wnd, className, sizeof(className)/sizeof(WCHAR));
while (l < r)
{
int d, m = (l+r) / 2;
d = lstrcmpiW (className, subclasses[m].className);
if (d == 0)
{
subclass = m;
break;
}
if (d < 0)
r = m;
else
l = m + 1;
}
if (subclass == -1)
ERR("Couldn't find subclass info for %s!\n", debugstr_w (className));
SetPropW (wnd, MAKEINTATOMW (atSubclassProp), (HANDLE)(subclass + 1));
}
refData = (ULONG_PTR)GetPropW (wnd, MAKEINTATOMW (atRefDataProp));
TRACE ("%d; (%p, %x, %x, %lx, %lx)", subclass, wnd, msg, wParam, lParam,
refData);
result = subclasses[subclass].subclassProc (wnd, msg, wParam, lParam, refData);
TRACE (" = %lx\n", result);
return result;
}
/***********************************************************************
* THEMING_Initialize
*
* Register classes for standard controls that will shadow the system
* classes.
*/
void THEMING_Initialize (void)
{
int i;
static const WCHAR subclassPropName[] =
{ 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 };
static const WCHAR refDataPropName[] =
{ 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
atSubclassProp = GlobalAddAtomW (subclassPropName);
atRefDataProp = GlobalAddAtomW (refDataPropName);
for (i = 0; i < NUM_SUBCLASSES; i++)
{
WNDCLASSEXW class;
class.cbSize = sizeof(class);
class.style |= CS_GLOBALCLASS;
GetClassInfoExW (NULL, subclasses[i].className, &class);
originalProcs[i] = class.lpfnWndProc;
class.lpfnWndProc = THEMING_SubclassProc;
if (!RegisterClassExW (&class))
{
ERR("Could not re-register class %s: %lx\n",
debugstr_w (subclasses[i].className), GetLastError ());
}
else
{
TRACE("Re-registered class %s\n",
debugstr_w (subclasses[i].className));
}
}
}
/***********************************************************************
* THEMING_CallOriginalClass
*
* Determines the original window proc and calls it.
*/
LRESULT THEMING_CallOriginalClass (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int subclass = (int)GetPropW (wnd, MAKEINTATOMW (atSubclassProp)) - 1;
WNDPROC oldProc = originalProcs[subclass];
return CallWindowProcW (oldProc, wnd, msg, wParam, lParam);
}
/***********************************************************************
* THEMING_SetSubclassData
*
* Update the "refData" value of the subclassed window.
*/
void THEMING_SetSubclassData (HWND wnd, ULONG_PTR refData)
{
SetPropW (wnd, MAKEINTATOMW (atRefDataProp), (HANDLE)refData);
}