Rev 476 | Rev 478 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
439 | daniel-mar | 1 | /* |
2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
||
3 | Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au |
||
4 | Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft |
||
5 | |||
6 | This program is free software; you can redistribute it and/or modify |
||
7 | it under the terms of the GNU General Public License as published by |
||
8 | the Free Software Foundation; either version 2 of the License, or |
||
9 | (at your option) any later version. |
||
10 | |||
11 | This program 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 |
||
14 | GNU General Public License for more details. |
||
15 | |||
16 | You should have received a copy of the GNU General Public License |
||
17 | along with this program; if not, write to the Free Software |
||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
19 | */ |
||
20 | |||
21 | #include "ff.h" |
||
443 | daniel-mar | 22 | #include "slider_win.h" |
439 | daniel-mar | 23 | |
470 | daniel-mar | 24 | // More information about the PLUGIN.DLL sliders: |
25 | // https://misc.daniel-marschall.de/projects/filter_factory/sliders.html |
||
26 | |||
439 | daniel-mar | 27 | // PLUGIN.DLL Sliders: This method will register the "slider" class used in dialogs. |
477 | daniel-mar | 28 | #ifdef use_plugin_dll_sliders |
469 | daniel-mar | 29 | typedef BOOL(__cdecl* f_RegisterSlider)(HINSTANCE hInstanceDll, DWORD* MessageID); |
30 | BOOL RegisterSlider(HINSTANCE hInstanceDll, DWORD* MessageID) { |
||
439 | daniel-mar | 31 | f_RegisterSlider fRegisterSlider; |
470 | daniel-mar | 32 | BOOL res; |
439 | daniel-mar | 33 | |
477 | daniel-mar | 34 | if (!gdata->pluginDllSliderInfo.hLib) return false; |
35 | fRegisterSlider = (f_RegisterSlider)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "RegisterSlider"); |
||
470 | daniel-mar | 36 | res = (fRegisterSlider != 0) ? fRegisterSlider(hInstanceDll, MessageID) : false; |
37 | return res; |
||
439 | daniel-mar | 38 | } |
477 | daniel-mar | 39 | #endif |
439 | daniel-mar | 40 | |
41 | // PLUGIN.DLL Sliders: This method will unregister the "slider" class used in dialogs. |
||
477 | daniel-mar | 42 | #ifdef use_plugin_dll_sliders |
471 | daniel-mar | 43 | typedef BOOL(__cdecl* f_UnRegisterSlider)(HINSTANCE hInstanceDll); |
44 | BOOL UnRegisterSlider(HINSTANCE hInstanceDll) { |
||
45 | f_UnRegisterSlider fUnRegisterSlider; |
||
470 | daniel-mar | 46 | BOOL res; |
439 | daniel-mar | 47 | |
477 | daniel-mar | 48 | if (!gdata->pluginDllSliderInfo.hLib) return false; |
49 | fUnRegisterSlider = (f_UnRegisterSlider)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "UnRegisterSlider"); |
||
471 | daniel-mar | 50 | res = (fUnRegisterSlider != 0) ? fUnRegisterSlider(hInstanceDll) : false; |
470 | daniel-mar | 51 | return res; |
439 | daniel-mar | 52 | } |
477 | daniel-mar | 53 | #endif |
439 | daniel-mar | 54 | |
55 | // PLUGIN.DLL Sliders: Set slider range (min/max) |
||
477 | daniel-mar | 56 | #ifdef use_plugin_dll_sliders |
439 | daniel-mar | 57 | typedef int(__cdecl* f_SetSliderRange)(HWND hWnd, int nMin, int nMax); |
58 | int SetSliderRange(HWND hWnd, int nMin, int nMax) { |
||
59 | f_SetSliderRange fSetSliderRange; |
||
470 | daniel-mar | 60 | int res; |
439 | daniel-mar | 61 | |
477 | daniel-mar | 62 | if (!gdata->pluginDllSliderInfo.hLib) return 0; |
63 | fSetSliderRange = (f_SetSliderRange)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "SetSliderRange"); |
||
470 | daniel-mar | 64 | res = (fSetSliderRange != 0) ? fSetSliderRange(hWnd, nMin, nMax) : 0; |
65 | return res; |
||
439 | daniel-mar | 66 | } |
477 | daniel-mar | 67 | #endif |
439 | daniel-mar | 68 | |
69 | // PLUGIN.DLL Sliders : Sets slider position |
||
477 | daniel-mar | 70 | #ifdef use_plugin_dll_sliders |
439 | daniel-mar | 71 | typedef int(__cdecl* f_SetSliderPos)(HWND hWnd, int nPos, BOOL bRepaint); |
72 | int SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) { |
||
73 | f_SetSliderPos fSetSliderPos; |
||
470 | daniel-mar | 74 | int res; |
439 | daniel-mar | 75 | |
477 | daniel-mar | 76 | if (!gdata->pluginDllSliderInfo.hLib) return 0; |
77 | fSetSliderPos = (f_SetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "SetSliderPos"); |
||
470 | daniel-mar | 78 | res = (fSetSliderPos != 0) ? fSetSliderPos(hWnd, nPos, bRepaint) : 0; |
79 | return res; |
||
439 | daniel-mar | 80 | } |
477 | daniel-mar | 81 | #else |
82 | int SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) { |
||
83 | // This dummy is required, otherwise ui_compat.h won't compile |
||
84 | return 0; |
||
85 | } |
||
86 | #endif |
||
439 | daniel-mar | 87 | |
88 | // PLUGIN.DLL Sliders : Get slider position |
||
477 | daniel-mar | 89 | #ifdef use_plugin_dll_sliders |
439 | daniel-mar | 90 | typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition); |
91 | int GetSliderPos(HWND hWnd, BOOL bPixelPosition) { |
||
92 | f_GetSliderPos fGetSliderPos; |
||
470 | daniel-mar | 93 | int res; |
439 | daniel-mar | 94 | |
477 | daniel-mar | 95 | if (!gdata->pluginDllSliderInfo.hLib) return 0; |
96 | fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "GetSliderPos"); |
||
470 | daniel-mar | 97 | res = (fGetSliderPos != 0) ? fGetSliderPos(hWnd, bPixelPosition) : 0; |
98 | return res; |
||
439 | daniel-mar | 99 | } |
477 | daniel-mar | 100 | #else |
101 | int GetSliderPos(HWND hWnd, BOOL bPixelPosition) { |
||
102 | // This dummy is required, otherwise ui_compat.h won't compile |
||
103 | return 0; |
||
104 | } |
||
105 | #endif |
||
439 | daniel-mar | 106 | |
460 | daniel-mar | 107 | LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { |
108 | return DefWindowProc(hwnd, uMsg, wParam, lParam); |
||
109 | } |
||
110 | |||
461 | daniel-mar | 111 | void Win32sFixSuperclassing(HWND hDlg, int destItem, int sourceItem) { |
112 | // Win32s (Win3.11) compatibility fix: Since GetClassInfo(WC_BUTTON) and GetClassInfo(WC_STATIC) won't work, |
||
113 | // we had replaced the WndProc by a dummy. Now, we find out the real Button and Static WndProcs and give them |
||
114 | // to our classes, making them the intended superclasses. Messages which have been sent in between were lost, |
||
115 | // though... |
||
116 | |||
117 | WNDPROC wndProc; |
||
118 | #ifdef _WIN64 |
||
119 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC); |
||
120 | if (wndProc == DummyWndProc) { |
||
121 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWLP_WNDPROC); |
||
122 | SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC, (LONG_PTR)wndProc); |
||
123 | } |
||
124 | #else |
||
125 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC); |
||
126 | if (wndProc == DummyWndProc) { |
||
127 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWL_WNDPROC); |
||
128 | SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC, (LONG_PTR)wndProc); |
||
129 | } |
||
130 | #endif |
||
131 | } |
||
132 | |||
444 | daniel-mar | 133 | Boolean MakeSimpleSubclass(LPCTSTR targetClass, LPCTSTR sourceClass) { |
439 | daniel-mar | 134 | WNDCLASS clx; |
135 | |||
444 | daniel-mar | 136 | if (GetClassInfo(hDllInstance, sourceClass, &clx) != 0) { |
439 | daniel-mar | 137 | clx.lpszClassName = targetClass; |
138 | if (RegisterClass(&clx) == 0) { |
||
444 | daniel-mar | 139 | TCHAR s[0x300]; |
140 | xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); |
||
454 | daniel-mar | 141 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL); |
444 | daniel-mar | 142 | dbg(&s[0]); |
439 | daniel-mar | 143 | return false; |
144 | } |
||
145 | else { |
||
146 | return true; |
||
147 | } |
||
148 | } |
||
149 | else { |
||
460 | daniel-mar | 150 | if ((xstrcmp(sourceClass, WC_BUTTON) == 0) || (xstrcmp(sourceClass, WC_STATIC) == 0)) { |
151 | // GetClassInfo(WC_STATIC) and GetClassInfo(WC_BUTTON) fail on Win32s (Windows 3.11) |
||
152 | // So we create a fake-class now. It will be replaced with the real Button/Static WndProc later! |
||
153 | clx.style = 0; |
||
154 | clx.lpfnWndProc = DummyWndProc; |
||
155 | clx.cbClsExtra = 0; |
||
156 | clx.cbWndExtra = 0; |
||
157 | clx.hInstance = hDllInstance; |
||
158 | clx.hIcon = 0; |
||
159 | clx.hCursor = 0; |
||
160 | clx.hbrBackground = 0; |
||
161 | clx.lpszMenuName = 0; |
||
162 | clx.lpszClassName = targetClass; |
||
163 | |||
164 | if (RegisterClass(&clx) == 0) { |
||
165 | TCHAR s[0x300]; |
||
166 | xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); |
||
167 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL); |
||
168 | dbg(&s[0]); |
||
169 | return false; |
||
170 | } |
||
171 | else { |
||
172 | return true; |
||
173 | } |
||
174 | } |
||
175 | else { |
||
463 | daniel-mar | 176 | simplealert((TCHAR*)TEXT("GetClassInfo failed")); |
460 | daniel-mar | 177 | } |
439 | daniel-mar | 178 | return false; |
179 | } |
||
180 | } |
||
181 | |||
476 | daniel-mar | 182 | Boolean Slider_Init_PluginDll(LPCTSTR targetClass) { |
183 | |||
439 | daniel-mar | 184 | #ifndef use_plugin_dll_sliders |
476 | daniel-mar | 185 | return false; |
439 | daniel-mar | 186 | #else |
477 | daniel-mar | 187 | if (gdata->pluginDllSliderInfo.initialized) return true; |
476 | daniel-mar | 188 | |
477 | daniel-mar | 189 | if (!gdata->pluginDllSliderInfo.hLib) { |
476 | daniel-mar | 190 | // DM 16.04.2022 : It is important that PLUGIN.DLL stays loaded, otherwise |
191 | // DialogBoxParamA crashes. Can be reproduced if all 8BX modules are disabled in Photoshop 7 |
||
192 | // (they keep PLUGIN.DLL loaded). |
||
477 | daniel-mar | 193 | gdata->pluginDllSliderInfo.hLib = LoadLibrary(TEXT("Plugin.dll")); |
439 | daniel-mar | 194 | } |
476 | daniel-mar | 195 | |
477 | daniel-mar | 196 | if (gdata->pluginDllSliderInfo.hLib && RegisterSlider(hDllInstance, &gdata->pluginDllSliderInfo.messageId)) { |
476 | daniel-mar | 197 | // Make "FoundrySlider" a subclass of "slider" then |
477 | daniel-mar | 198 | if (MakeSimpleSubclass(targetClass, TEXT("slider"))) { |
199 | gdata->pluginDllSliderInfo.initialized = true; |
||
200 | return true; |
||
201 | } |
||
202 | else { |
||
203 | return false; |
||
204 | } |
||
476 | daniel-mar | 205 | } |
206 | else { |
||
207 | // This can happen if PLUGIN.DLL is not existing |
||
208 | // It will also happen if a previous uninitialization failed (or was forgotten) |
||
209 | return false; // Fall back to Windows sliders |
||
210 | } |
||
439 | daniel-mar | 211 | #endif |
212 | |||
213 | } |
||
214 | |||
476 | daniel-mar | 215 | void Slider_Uninit_PluginDll() { |
439 | daniel-mar | 216 | #ifndef use_plugin_dll_sliders |
476 | daniel-mar | 217 | return; |
439 | daniel-mar | 218 | #else |
477 | daniel-mar | 219 | if (!gdata->pluginDllSliderInfo.initialized) return; |
476 | daniel-mar | 220 | |
477 | daniel-mar | 221 | if (!UnRegisterSlider(hDllInstance)) { |
222 | simplealert((TCHAR*)TEXT("UnRegisterSlider failed")); |
||
223 | return; |
||
469 | daniel-mar | 224 | } |
477 | daniel-mar | 225 | |
226 | gdata->pluginDllSliderInfo.initialized = false; |
||
227 | |||
228 | if (gdata->pluginDllSliderInfo.hLib) { |
||
229 | FreeLibrary(gdata->pluginDllSliderInfo.hLib); |
||
230 | gdata->pluginDllSliderInfo.hLib = 0; |
||
231 | } |
||
439 | daniel-mar | 232 | #endif |
233 | } |
||
234 | |||
235 | typedef void(__stdcall* f_InitCommonControls)(); |
||
236 | typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce); |
||
444 | daniel-mar | 237 | Boolean Slider_Init_MsTrackbar(LPCTSTR targetClass) { |
439 | daniel-mar | 238 | f_InitCommonControls fInitCommonControls; |
239 | f_InitCommonControlsEx fInitCommonControlsEx; |
||
240 | |||
477 | daniel-mar | 241 | if (gdata->comctlSliderInfo.initialized) return true; |
242 | |||
439 | daniel-mar | 243 | // Make sure that Comctl32 is loaded |
477 | daniel-mar | 244 | if (!gdata->comctlSliderInfo.hLib) { |
245 | gdata->comctlSliderInfo.hLib = LoadLibrary(TEXT("Comctl32.dll")); |
||
476 | daniel-mar | 246 | } |
477 | daniel-mar | 247 | if (gdata->comctlSliderInfo.hLib) { |
248 | fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControlsEx"); |
||
439 | daniel-mar | 249 | if (fInitCommonControlsEx != 0) { |
250 | INITCOMMONCONTROLSEX icce; |
||
251 | icce.dwSize = sizeof(INITCOMMONCONTROLSEX); |
||
252 | icce.dwICC = ICC_BAR_CLASSES; |
||
253 | fInitCommonControlsEx(&icce); |
||
254 | } |
||
255 | else { |
||
477 | daniel-mar | 256 | fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControls"); |
439 | daniel-mar | 257 | if (fInitCommonControls != 0) { |
258 | fInitCommonControls(); |
||
259 | } |
||
260 | } |
||
476 | daniel-mar | 261 | |
262 | // Make "FoundrySlider" a subclass of "msctls_trackbar32" then |
||
477 | daniel-mar | 263 | if (MakeSimpleSubclass(targetClass, TEXT("msctls_trackbar32"))) { |
264 | gdata->comctlSliderInfo.initialized = true; |
||
265 | return true; |
||
266 | } |
||
267 | else { |
||
268 | return false; |
||
269 | } |
||
439 | daniel-mar | 270 | } |
476 | daniel-mar | 271 | else { |
272 | return false; |
||
273 | } |
||
274 | } |
||
439 | daniel-mar | 275 | |
476 | daniel-mar | 276 | void Slider_Uninit_MsTrackbar() { |
477 | daniel-mar | 277 | if (!gdata->comctlSliderInfo.initialized) return; |
278 | |||
279 | gdata->comctlSliderInfo.initialized = false; |
||
280 | |||
281 | if (gdata->comctlSliderInfo.hLib != 0) { |
||
282 | FreeLibrary(gdata->comctlSliderInfo.hLib); |
||
283 | gdata->comctlSliderInfo.hLib = 0; |
||
476 | daniel-mar | 284 | } |
439 | daniel-mar | 285 | } |
286 | |||
444 | daniel-mar | 287 | Boolean Slider_Init_None(LPCTSTR targetClass) { |
439 | daniel-mar | 288 | // Make "FoundrySlider" a subclass of "STATIC" (making it invisible) |
477 | daniel-mar | 289 | |
290 | if (gdata->noneSliderInfo.initialized) return true; |
||
291 | |||
292 | if (MakeSimpleSubclass(targetClass, WC_STATIC)) { |
||
293 | gdata->noneSliderInfo.initialized = true; |
||
294 | return true; |
||
295 | } |
||
296 | else { |
||
297 | return false; |
||
298 | } |
||
439 | daniel-mar | 299 | } |
476 | daniel-mar | 300 | |
301 | void Slider_Uninit_None() { |
||
477 | daniel-mar | 302 | if (!gdata->noneSliderInfo.initialized) return; |
303 | |||
476 | daniel-mar | 304 | // Nothing here |
305 | } |