Fixed pitch bending in the midi driver.
[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)) - 1;
60     LRESULT result;
61     ULONG_PTR refData;
62
63     if (subclass == -1)
64     {
65         /* Means this is the first time this proc is called for this window.
66          * Determine the index of the subclass */
67         WCHAR className[32];
68         int l = 0, r = NUM_SUBCLASSES;
69
70         GetClassNameW (wnd, className, sizeof(className)/sizeof(WCHAR));
71         while (l < r)
72         {
73             int d, m = (l+r) / 2;
74             d = lstrcmpiW (className, subclasses[m].className);
75             if (d == 0)
76             {
77                 subclass = m;
78                 break;
79             }
80             if (d < 0)
81                 r = m;
82             else
83                 l = m + 1;
84         }
85         if (subclass == -1)
86             ERR("Couldn't find subclass info for %s!\n", debugstr_w (className));
87         SetPropW (wnd, MAKEINTATOMW (atSubclassProp), (HANDLE)(subclass + 1));
88     }
89     refData = (ULONG_PTR)GetPropW (wnd, MAKEINTATOMW (atRefDataProp));
90
91     TRACE ("%d; (%p, %x, %x, %lx, %lx)", subclass, wnd, msg, wParam, lParam, 
92         refData);
93     result = subclasses[subclass].subclassProc (wnd, msg, wParam, lParam, refData);
94     TRACE (" = %lx\n", result);
95     return result;
96 }
97
98 /***********************************************************************
99  * THEMING_Initialize
100  *
101  * Register classes for standard controls that will shadow the system
102  * classes.
103  */
104 void THEMING_Initialize (void)
105 {
106     int i;
107     static const WCHAR subclassPropName[] = 
108         { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 };
109     static const WCHAR refDataPropName[] = 
110         { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
111
112     atSubclassProp = GlobalAddAtomW (subclassPropName);
113     atRefDataProp = GlobalAddAtomW (refDataPropName);
114
115     for (i = 0; i < NUM_SUBCLASSES; i++)
116     {
117         WNDCLASSEXW class;
118
119         class.cbSize = sizeof(class);
120         class.style |= CS_GLOBALCLASS;
121         GetClassInfoExW (NULL, subclasses[i].className, &class);
122         originalProcs[i] = class.lpfnWndProc;
123         class.lpfnWndProc = THEMING_SubclassProc;
124
125         if (!RegisterClassExW (&class))
126         {
127             ERR("Could not re-register class %s: %lx\n", 
128                 debugstr_w (subclasses[i].className), GetLastError ());
129         }
130         else
131         {
132             TRACE("Re-registered class %s\n", 
133                 debugstr_w (subclasses[i].className));
134         }
135     }
136 }
137
138 /***********************************************************************
139  * THEMING_CallOriginalClass
140  *
141  * Determines the original window proc and calls it.
142  */
143 LRESULT THEMING_CallOriginalClass (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
144 {
145     int subclass = (int)GetPropW (wnd, MAKEINTATOMW (atSubclassProp)) - 1;
146     WNDPROC oldProc = originalProcs[subclass];
147     return CallWindowProcW (oldProc, wnd, msg, wParam, lParam);
148 }
149
150 /***********************************************************************
151  * THEMING_SetSubclassData
152  *
153  * Update the "refData" value of the subclassed window.
154  */
155 void THEMING_SetSubclassData (HWND wnd, ULONG_PTR refData)
156 {
157     SetPropW (wnd, MAKEINTATOMW (atRefDataProp), (HANDLE)refData);
158 }