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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 */ 21 22 #include "comctl32.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL(theming); 25 26 typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM, 27 ULONG_PTR); 28 29 #ifndef __REACTOS__ /* r73871 */ 30 extern LRESULT CALLBACK THEMING_ButtonSubclassProc (HWND, UINT, WPARAM, LPARAM, 31 ULONG_PTR) DECLSPEC_HIDDEN; 32 #endif 33 extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM, 34 ULONG_PTR) DECLSPEC_HIDDEN; 35 #ifndef __REACTOS__ /* r73803 */ 36 extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM, 37 ULONG_PTR) DECLSPEC_HIDDEN; 38 #endif 39 extern LRESULT CALLBACK THEMING_EditSubclassProc (HWND, UINT, WPARAM, LPARAM, 40 ULONG_PTR) DECLSPEC_HIDDEN; 41 extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM, 42 ULONG_PTR) DECLSPEC_HIDDEN; 43 extern LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND, UINT, WPARAM, LPARAM, 44 ULONG_PTR) DECLSPEC_HIDDEN; 45 46 #ifndef __REACTOS__ 47 static const WCHAR dialogClass[] = {'#','3','2','7','7','0',0}; 48 #endif 49 static const WCHAR comboLboxClass[] = {'C','o','m','b','o','L','b','o','x',0}; 50 51 static const struct ThemingSubclass 52 { 53 const WCHAR* className; 54 THEMING_SUBCLASSPROC subclassProc; 55 } subclasses[] = { 56 /* Note: list must be sorted by class name */ 57 #ifndef __REACTOS__ /* r73803 & r73871 */ 58 {dialogClass, THEMING_DialogSubclassProc}, 59 {WC_BUTTONW, THEMING_ButtonSubclassProc}, 60 #endif 61 {WC_COMBOBOXW, THEMING_ComboSubclassProc}, 62 {comboLboxClass, THEMING_ListBoxSubclassProc}, 63 {WC_EDITW, THEMING_EditSubclassProc}, 64 {WC_LISTBOXW, THEMING_ListBoxSubclassProc}, 65 {WC_SCROLLBARW, THEMING_ScrollbarSubclassProc} 66 }; 67 68 #define NUM_SUBCLASSES (sizeof(subclasses)/sizeof(subclasses[0])) 69 70 static WNDPROC originalProcs[NUM_SUBCLASSES]; 71 static ATOM atRefDataProp; 72 static ATOM atSubclassProp; 73 74 /* Generate a number of subclass window procs. 75 * With a single proc alone, we can't really reliably find out the superclass, 76 * so have one for each subclass. The subclass number is also stored in a prop 77 * since it's needed by THEMING_CallOriginalClass(). Then, the subclass 78 * proc and ref data are fetched and the proc called. 79 */ 80 #define MAKE_SUBCLASS_PROC(N) \ 81 static LRESULT CALLBACK subclass_proc ## N (HWND wnd, UINT msg, \ 82 WPARAM wParam, LPARAM lParam) \ 83 { \ 84 LRESULT result; \ 85 ULONG_PTR refData; \ 86 SetPropW (wnd, (LPCWSTR)MAKEINTATOM(atSubclassProp), (HANDLE)N); \ 87 refData = (ULONG_PTR)GetPropW (wnd, (LPCWSTR)MAKEINTATOM(atRefDataProp)); \ 88 TRACE ("%d; (%p, %x, %lx, %lx, %lx)\n", N, wnd, msg, wParam, lParam, \ 89 refData); \ 90 result = subclasses[N].subclassProc (wnd, msg, wParam, lParam, refData);\ 91 TRACE ("result = %lx\n", result); \ 92 return result; \ 93 } 94 95 MAKE_SUBCLASS_PROC(0) 96 MAKE_SUBCLASS_PROC(1) 97 MAKE_SUBCLASS_PROC(2) 98 MAKE_SUBCLASS_PROC(3) 99 MAKE_SUBCLASS_PROC(4) 100 #ifndef __REACTOS__ /* r73803 & r73871 */ 101 MAKE_SUBCLASS_PROC(5) 102 MAKE_SUBCLASS_PROC(6) 103 #endif 104 105 static const WNDPROC subclassProcs[NUM_SUBCLASSES] = { 106 subclass_proc0, 107 subclass_proc1, 108 subclass_proc2, 109 subclass_proc3, 110 #ifdef __REACTOS__ /* r73871 */ 111 subclass_proc4 112 #else 113 subclass_proc4, 114 subclass_proc5, 115 subclass_proc6 116 #endif 117 }; 118 119 /*********************************************************************** 120 * THEMING_Initialize 121 * 122 * Register classes for standard controls that will shadow the system 123 * classes. 124 */ 125 #ifdef __REACTOS__ /* r73803 */ 126 void THEMING_Initialize(HANDLE hActCtx5, HANDLE hActCtx6) 127 #else 128 void THEMING_Initialize (void) 129 #endif 130 { 131 unsigned int i; 132 static const WCHAR subclassPropName[] = 133 { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 }; 134 static const WCHAR refDataPropName[] = 135 { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 }; 136 #ifdef __REACTOS__ /* r73803 */ 137 ULONG_PTR ulCookie; 138 BOOL ret, bActivated; 139 #else 140 if (!IsThemeActive()) return; 141 #endif 142 143 atSubclassProp = GlobalAddAtomW (subclassPropName); 144 atRefDataProp = GlobalAddAtomW (refDataPropName); 145 146 for (i = 0; i < NUM_SUBCLASSES; i++) 147 { 148 WNDCLASSEXW class; 149 150 class.cbSize = sizeof(class); 151 152 #ifdef __REACTOS__ /* r73803 */ 153 bActivated = ActivateActCtx(hActCtx5, &ulCookie); 154 ret = GetClassInfoExW (NULL, subclasses[i].className, &class); 155 if (bActivated) 156 DeactivateActCtx(0, ulCookie); 157 158 if (!ret) 159 #else 160 if (!GetClassInfoExW (NULL, subclasses[i].className, &class)) 161 #endif 162 { 163 ERR("Could not retrieve information for class %s\n", 164 debugstr_w (subclasses[i].className)); 165 continue; 166 } 167 originalProcs[i] = class.lpfnWndProc; 168 class.lpfnWndProc = subclassProcs[i]; 169 #ifdef __REACTOS__ /* r73803 */ 170 class.style |= CS_GLOBALCLASS; 171 class.hInstance = COMCTL32_hModule; 172 #endif 173 174 if (!class.lpfnWndProc) 175 { 176 ERR("Missing proc for class %s\n", 177 debugstr_w (subclasses[i].className)); 178 continue; 179 } 180 181 #ifdef __REACTOS__ /* r73803 */ 182 bActivated = ActivateActCtx(hActCtx6, &ulCookie); 183 #endif 184 if (!RegisterClassExW (&class)) 185 { 186 #ifdef __REACTOS__ /* r73803 */ 187 WARN("Could not re-register class %s: %x\n", 188 #else 189 ERR("Could not re-register class %s: %x\n", 190 #endif 191 debugstr_w (subclasses[i].className), GetLastError ()); 192 } 193 else 194 { 195 TRACE("Re-registered class %s\n", 196 debugstr_w (subclasses[i].className)); 197 } 198 199 #ifdef __REACTOS__ /* r73803 */ 200 if (bActivated) 201 DeactivateActCtx(0, ulCookie); 202 #endif 203 } 204 } 205 206 /*********************************************************************** 207 * THEMING_Uninitialize 208 * 209 * Unregister shadow classes for standard controls. 210 */ 211 void THEMING_Uninitialize (void) 212 { 213 unsigned int i; 214 215 if (!atSubclassProp) return; /* not initialized */ 216 217 for (i = 0; i < NUM_SUBCLASSES; i++) 218 { 219 UnregisterClassW (subclasses[i].className, NULL); 220 } 221 } 222 223 /*********************************************************************** 224 * THEMING_CallOriginalClass 225 * 226 * Determines the original window proc and calls it. 227 */ 228 LRESULT THEMING_CallOriginalClass (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) 229 { 230 INT_PTR subclass = (INT_PTR)GetPropW (wnd, (LPCWSTR)MAKEINTATOM(atSubclassProp)); 231 WNDPROC oldProc = originalProcs[subclass]; 232 return CallWindowProcW (oldProc, wnd, msg, wParam, lParam); 233 } 234 235 /*********************************************************************** 236 * THEMING_SetSubclassData 237 * 238 * Update the "refData" value of the subclassed window. 239 */ 240 void THEMING_SetSubclassData (HWND wnd, ULONG_PTR refData) 241 { 242 SetPropW (wnd, (LPCWSTR)MAKEINTATOM(atRefDataProp), (HANDLE)refData); 243 } 244