Added some generic code to allow subclassing (for the purpose of theming) of standard controls.
diff --git a/dlls/comctl32/Makefile.in b/dlls/comctl32/Makefile.in index f679073..b7f43ef 100644 --- a/dlls/comctl32/Makefile.in +++ b/dlls/comctl32/Makefile.in
@@ -35,6 +35,7 @@ status.c \ syslink.c \ tab.c \ + theming.c \ toolbar.c \ tooltips.c \ trackbar.c \
diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h index 1f7e0ad..10f1b8c 100644 --- a/dlls/comctl32/comctl32.h +++ b/dlls/comctl32/comctl32.h
@@ -249,4 +249,8 @@ 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 */
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index 4c1ea8a..697aabe 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c
@@ -144,6 +144,9 @@ TRACKBAR_Register (); TREEVIEW_Register (); UPDOWN_Register (); + + /* subclass user32 controls */ + THEMING_Initialize (); break; case DLL_PROCESS_DETACH:
diff --git a/dlls/comctl32/theming.c b/dlls/comctl32/theming.c new file mode 100644 index 0000000..ff3be61 --- /dev/null +++ b/dlls/comctl32/theming.c
@@ -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); +}