Fix protocol test on winxp.
[wine] / dlls / comctl32 / theming.c
1 /*
2  * Theming - Initialization
3  *
4  * Copyright (c) 2005 by Frank Richter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "comctl32.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(theming);
32
33 typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM,
34     ULONG_PTR);
35
36 static const struct ThemingSubclass
37 {
38     const WCHAR* className;
39     THEMING_SUBCLASSPROC subclassProc;
40 } subclasses[] = {
41     /* Note: list must be sorted by class name */
42 };
43
44 #define NUM_SUBCLASSES        (sizeof(subclasses)/sizeof(subclasses[0]))
45
46 static WNDPROC originalProcs[NUM_SUBCLASSES];
47 static ATOM atRefDataProp;
48 static ATOM atSubclassProp;
49
50 /***********************************************************************
51  * THEMING_SubclassProc
52  *
53  * The window proc registered to the subclasses. Fetches the subclass
54  * proc and ref data and call the proc.
55  */
56 static LRESULT CALLBACK THEMING_SubclassProc (HWND wnd, UINT msg,
57                                               WPARAM wParam, LPARAM lParam)
58 {
59     int subclass = (int)GetPropW (wnd, MAKEINTATOMW (atSubclassProp));
60     LRESULT result;
61     ULONG_PTR refData;
62
63     refData = (ULONG_PTR)GetPropW (wnd, MAKEINTATOMW (atRefDataProp));
64
65     TRACE ("%d; (%p, %x, %x, %lx, %lx)", subclass, wnd, msg, wParam, lParam, 
66         refData);
67     result = subclasses[subclass].subclassProc (wnd, msg, wParam, lParam, refData);
68     TRACE (" = %lx\n", result);
69     return result;
70 }
71
72 /* Generate a number of subclass window procs.
73  * With a single proc alone, we can't really reliably find out the superclass,
74  * hence, the first time the subclass is called, these "stubs" are used which
75  * just save the internal ID of the subclass.
76  */
77 #define MAKE_SUBCLASS_STUB(N)                                               \
78 static LRESULT CALLBACK subclass_stub ## N (HWND wnd, UINT msg,             \
79                                             WPARAM wParam, LPARAM lParam)   \
80 {                                                                           \
81     SetPropW (wnd, MAKEINTATOMW (atSubclassProp), (HANDLE)N);               \
82     SetWindowLongPtrW (wnd, GWLP_WNDPROC, (LONG_PTR)THEMING_SubclassProc);  \
83     return THEMING_SubclassProc (wnd, msg, wParam, lParam);                 \
84 }
85
86 const static WNDPROC subclassStubs[NUM_SUBCLASSES] = {
87 };
88
89 /***********************************************************************
90  * THEMING_Initialize
91  *
92  * Register classes for standard controls that will shadow the system
93  * classes.
94  */
95 void THEMING_Initialize (void)
96 {
97     int i;
98     static const WCHAR subclassPropName[] = 
99         { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 };
100     static const WCHAR refDataPropName[] = 
101         { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
102
103     atSubclassProp = GlobalAddAtomW (subclassPropName);
104     atRefDataProp = GlobalAddAtomW (refDataPropName);
105
106     for (i = 0; i < NUM_SUBCLASSES; i++)
107     {
108         WNDCLASSEXW class;
109
110         class.cbSize = sizeof(class);
111         class.style |= CS_GLOBALCLASS;
112         GetClassInfoExW (NULL, subclasses[i].className, &class);
113         originalProcs[i] = class.lpfnWndProc;
114         class.lpfnWndProc = subclassStubs[i];
115         
116         if (!class.lpfnWndProc)
117         {
118             ERR("Missing stub for class %s\n", 
119                 debugstr_w (subclasses[i].className));
120             continue;
121         }
122
123         if (!RegisterClassExW (&class))
124         {
125             ERR("Could not re-register class %s: %lx\n", 
126                 debugstr_w (subclasses[i].className), GetLastError ());
127         }
128         else
129         {
130             TRACE("Re-registered class %s\n", 
131                 debugstr_w (subclasses[i].className));
132         }
133     }
134 }
135
136 /***********************************************************************
137  * THEMING_CallOriginalClass
138  *
139  * Determines the original window proc and calls it.
140  */
141 LRESULT THEMING_CallOriginalClass (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
142 {
143     int subclass = (int)GetPropW (wnd, MAKEINTATOMW (atSubclassProp));
144     WNDPROC oldProc = originalProcs[subclass];
145     return CallWindowProcW (oldProc, wnd, msg, wParam, lParam);
146 }
147
148 /***********************************************************************
149  * THEMING_SetSubclassData
150  *
151  * Update the "refData" value of the subclassed window.
152  */
153 void THEMING_SetSubclassData (HWND wnd, ULONG_PTR refData)
154 {
155     SetPropW (wnd, MAKEINTATOMW (atRefDataProp), (HANDLE)refData);
156 }