Rev 471 | Rev 477 | 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. |
469 | daniel-mar | 28 | typedef BOOL(__cdecl* f_RegisterSlider)(HINSTANCE hInstanceDll, DWORD* MessageID); |
29 | BOOL RegisterSlider(HINSTANCE hInstanceDll, DWORD* MessageID) { |
||
439 | daniel-mar | 30 | f_RegisterSlider fRegisterSlider; |
470 | daniel-mar | 31 | BOOL res; |
439 | daniel-mar | 32 | |
476 | daniel-mar | 33 | if (!gdata->libPluginDll) return false; |
34 | fRegisterSlider = (f_RegisterSlider)(void*)GetProcAddress(gdata->libPluginDll, "RegisterSlider"); |
||
470 | daniel-mar | 35 | res = (fRegisterSlider != 0) ? fRegisterSlider(hInstanceDll, MessageID) : false; |
36 | return res; |
||
439 | daniel-mar | 37 | } |
38 | |||
39 | // PLUGIN.DLL Sliders: This method will unregister the "slider" class used in dialogs. |
||
471 | daniel-mar | 40 | typedef BOOL(__cdecl* f_UnRegisterSlider)(HINSTANCE hInstanceDll); |
41 | BOOL UnRegisterSlider(HINSTANCE hInstanceDll) { |
||
42 | f_UnRegisterSlider fUnRegisterSlider; |
||
470 | daniel-mar | 43 | BOOL res; |
439 | daniel-mar | 44 | |
476 | daniel-mar | 45 | if (!gdata->libPluginDll) return false; |
46 | fUnRegisterSlider = (f_UnRegisterSlider)(void*)GetProcAddress(gdata->libPluginDll, "UnRegisterSlider"); |
||
471 | daniel-mar | 47 | res = (fUnRegisterSlider != 0) ? fUnRegisterSlider(hInstanceDll) : false; |
470 | daniel-mar | 48 | return res; |
439 | daniel-mar | 49 | } |
50 | |||
51 | // PLUGIN.DLL Sliders: Set slider range (min/max) |
||
52 | typedef int(__cdecl* f_SetSliderRange)(HWND hWnd, int nMin, int nMax); |
||
53 | int SetSliderRange(HWND hWnd, int nMin, int nMax) { |
||
54 | f_SetSliderRange fSetSliderRange; |
||
470 | daniel-mar | 55 | int res; |
439 | daniel-mar | 56 | |
476 | daniel-mar | 57 | if (!gdata->libPluginDll) return 0; |
58 | fSetSliderRange = (f_SetSliderRange)(void*)GetProcAddress(gdata->libPluginDll, "SetSliderRange"); |
||
470 | daniel-mar | 59 | res = (fSetSliderRange != 0) ? fSetSliderRange(hWnd, nMin, nMax) : 0; |
60 | return res; |
||
439 | daniel-mar | 61 | } |
62 | |||
63 | // PLUGIN.DLL Sliders : Sets slider position |
||
64 | typedef int(__cdecl* f_SetSliderPos)(HWND hWnd, int nPos, BOOL bRepaint); |
||
65 | int SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) { |
||
66 | f_SetSliderPos fSetSliderPos; |
||
470 | daniel-mar | 67 | int res; |
439 | daniel-mar | 68 | |
476 | daniel-mar | 69 | if (!gdata->libPluginDll) return 0; |
70 | fSetSliderPos = (f_SetSliderPos)(void*)GetProcAddress(gdata->libPluginDll, "SetSliderPos"); |
||
470 | daniel-mar | 71 | res = (fSetSliderPos != 0) ? fSetSliderPos(hWnd, nPos, bRepaint) : 0; |
72 | return res; |
||
439 | daniel-mar | 73 | } |
74 | |||
75 | // PLUGIN.DLL Sliders : Get slider position |
||
76 | typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition); |
||
77 | int GetSliderPos(HWND hWnd, BOOL bPixelPosition) { |
||
78 | f_GetSliderPos fGetSliderPos; |
||
470 | daniel-mar | 79 | int res; |
439 | daniel-mar | 80 | |
476 | daniel-mar | 81 | if (!gdata->libPluginDll) return 0; |
82 | fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->libPluginDll, "GetSliderPos"); |
||
470 | daniel-mar | 83 | res = (fGetSliderPos != 0) ? fGetSliderPos(hWnd, bPixelPosition) : 0; |
84 | return res; |
||
439 | daniel-mar | 85 | } |
86 | |||
460 | daniel-mar | 87 | LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { |
88 | return DefWindowProc(hwnd, uMsg, wParam, lParam); |
||
89 | } |
||
90 | |||
461 | daniel-mar | 91 | void Win32sFixSuperclassing(HWND hDlg, int destItem, int sourceItem) { |
92 | // Win32s (Win3.11) compatibility fix: Since GetClassInfo(WC_BUTTON) and GetClassInfo(WC_STATIC) won't work, |
||
93 | // we had replaced the WndProc by a dummy. Now, we find out the real Button and Static WndProcs and give them |
||
94 | // to our classes, making them the intended superclasses. Messages which have been sent in between were lost, |
||
95 | // though... |
||
96 | |||
97 | WNDPROC wndProc; |
||
98 | #ifdef _WIN64 |
||
99 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC); |
||
100 | if (wndProc == DummyWndProc) { |
||
101 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWLP_WNDPROC); |
||
102 | SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC, (LONG_PTR)wndProc); |
||
103 | } |
||
104 | #else |
||
105 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC); |
||
106 | if (wndProc == DummyWndProc) { |
||
107 | wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWL_WNDPROC); |
||
108 | SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC, (LONG_PTR)wndProc); |
||
109 | } |
||
110 | #endif |
||
111 | } |
||
112 | |||
444 | daniel-mar | 113 | Boolean MakeSimpleSubclass(LPCTSTR targetClass, LPCTSTR sourceClass) { |
439 | daniel-mar | 114 | WNDCLASS clx; |
115 | |||
444 | daniel-mar | 116 | if (GetClassInfo(hDllInstance, sourceClass, &clx) != 0) { |
439 | daniel-mar | 117 | clx.lpszClassName = targetClass; |
118 | if (RegisterClass(&clx) == 0) { |
||
444 | daniel-mar | 119 | TCHAR s[0x300]; |
120 | xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); |
||
454 | daniel-mar | 121 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL); |
444 | daniel-mar | 122 | dbg(&s[0]); |
439 | daniel-mar | 123 | return false; |
124 | } |
||
125 | else { |
||
126 | return true; |
||
127 | } |
||
128 | } |
||
129 | else { |
||
460 | daniel-mar | 130 | if ((xstrcmp(sourceClass, WC_BUTTON) == 0) || (xstrcmp(sourceClass, WC_STATIC) == 0)) { |
131 | // GetClassInfo(WC_STATIC) and GetClassInfo(WC_BUTTON) fail on Win32s (Windows 3.11) |
||
132 | // So we create a fake-class now. It will be replaced with the real Button/Static WndProc later! |
||
133 | clx.style = 0; |
||
134 | clx.lpfnWndProc = DummyWndProc; |
||
135 | clx.cbClsExtra = 0; |
||
136 | clx.cbWndExtra = 0; |
||
137 | clx.hInstance = hDllInstance; |
||
138 | clx.hIcon = 0; |
||
139 | clx.hCursor = 0; |
||
140 | clx.hbrBackground = 0; |
||
141 | clx.lpszMenuName = 0; |
||
142 | clx.lpszClassName = targetClass; |
||
143 | |||
144 | if (RegisterClass(&clx) == 0) { |
||
145 | TCHAR s[0x300]; |
||
146 | xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); |
||
147 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL); |
||
148 | dbg(&s[0]); |
||
149 | return false; |
||
150 | } |
||
151 | else { |
||
152 | return true; |
||
153 | } |
||
154 | } |
||
155 | else { |
||
463 | daniel-mar | 156 | simplealert((TCHAR*)TEXT("GetClassInfo failed")); |
460 | daniel-mar | 157 | } |
439 | daniel-mar | 158 | return false; |
159 | } |
||
160 | } |
||
161 | |||
476 | daniel-mar | 162 | Boolean Slider_Init_PluginDll(LPCTSTR targetClass) { |
163 | |||
439 | daniel-mar | 164 | #ifndef use_plugin_dll_sliders |
476 | daniel-mar | 165 | return false; |
439 | daniel-mar | 166 | #else |
476 | daniel-mar | 167 | if (gdata->pluginDllSliderInitialized) return true; |
168 | |||
169 | if (!gdata->libPluginDll) { |
||
170 | // DM 16.04.2022 : It is important that PLUGIN.DLL stays loaded, otherwise |
||
171 | // DialogBoxParamA crashes. Can be reproduced if all 8BX modules are disabled in Photoshop 7 |
||
172 | // (they keep PLUGIN.DLL loaded). |
||
173 | gdata->libPluginDll = LoadLibrary(TEXT("Plugin.dll")); |
||
439 | daniel-mar | 174 | } |
476 | daniel-mar | 175 | |
176 | if (gdata->libPluginDll && RegisterSlider(hDllInstance, &gdata->pluginDllSliderMessageId)) { |
||
177 | gdata->pluginDllSliderInitialized = true; |
||
178 | |||
179 | // Make "FoundrySlider" a subclass of "slider" then |
||
180 | return MakeSimpleSubclass(targetClass, TEXT("slider")); |
||
181 | } |
||
182 | else { |
||
183 | // This can happen if PLUGIN.DLL is not existing |
||
184 | // It will also happen if a previous uninitialization failed (or was forgotten) |
||
185 | return false; // Fall back to Windows sliders |
||
186 | } |
||
439 | daniel-mar | 187 | #endif |
188 | |||
189 | } |
||
190 | |||
476 | daniel-mar | 191 | void Slider_Uninit_PluginDll() { |
439 | daniel-mar | 192 | #ifndef use_plugin_dll_sliders |
476 | daniel-mar | 193 | return; |
439 | daniel-mar | 194 | #else |
476 | daniel-mar | 195 | if (gdata->pluginDllSliderInitialized) { |
196 | if (UnRegisterSlider(hDllInstance)) { |
||
197 | gdata->pluginDllSliderInitialized = false; |
||
198 | |||
199 | if (gdata->libPluginDll) { |
||
200 | FreeLibrary(gdata->libPluginDll); |
||
201 | gdata->libPluginDll = 0; |
||
202 | } |
||
471 | daniel-mar | 203 | } |
204 | else { |
||
476 | daniel-mar | 205 | simplealert((TCHAR*)TEXT("UnRegisterSlider failed")); |
471 | daniel-mar | 206 | } |
469 | daniel-mar | 207 | } |
439 | daniel-mar | 208 | #endif |
209 | |||
210 | } |
||
211 | |||
212 | typedef void(__stdcall* f_InitCommonControls)(); |
||
213 | typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce); |
||
444 | daniel-mar | 214 | Boolean Slider_Init_MsTrackbar(LPCTSTR targetClass) { |
439 | daniel-mar | 215 | f_InitCommonControls fInitCommonControls; |
216 | f_InitCommonControlsEx fInitCommonControlsEx; |
||
217 | |||
218 | // Make sure that Comctl32 is loaded |
||
476 | daniel-mar | 219 | if (!gdata->libComctl32) { |
220 | gdata->libComctl32 = LoadLibrary(TEXT("Comctl32.dll")); |
||
221 | } |
||
222 | if (gdata->libComctl32) { |
||
223 | fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(gdata->libComctl32, "InitCommonControlsEx"); |
||
439 | daniel-mar | 224 | if (fInitCommonControlsEx != 0) { |
225 | INITCOMMONCONTROLSEX icce; |
||
226 | icce.dwSize = sizeof(INITCOMMONCONTROLSEX); |
||
227 | icce.dwICC = ICC_BAR_CLASSES; |
||
228 | fInitCommonControlsEx(&icce); |
||
229 | } |
||
230 | else { |
||
476 | daniel-mar | 231 | fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(gdata->libComctl32, "InitCommonControls"); |
439 | daniel-mar | 232 | if (fInitCommonControls != 0) { |
233 | fInitCommonControls(); |
||
234 | } |
||
235 | } |
||
476 | daniel-mar | 236 | |
237 | // Make "FoundrySlider" a subclass of "msctls_trackbar32" then |
||
238 | return MakeSimpleSubclass(targetClass, TEXT("msctls_trackbar32")); |
||
439 | daniel-mar | 239 | } |
476 | daniel-mar | 240 | else { |
241 | return false; |
||
242 | } |
||
243 | } |
||
439 | daniel-mar | 244 | |
476 | daniel-mar | 245 | void Slider_Uninit_MsTrackbar() { |
246 | if (gdata->libComctl32 != 0) { |
||
247 | FreeLibrary(gdata->libComctl32); |
||
248 | gdata->libComctl32 = 0; |
||
249 | } |
||
439 | daniel-mar | 250 | } |
251 | |||
444 | daniel-mar | 252 | Boolean Slider_Init_None(LPCTSTR targetClass) { |
439 | daniel-mar | 253 | // Make "FoundrySlider" a subclass of "STATIC" (making it invisible) |
460 | daniel-mar | 254 | return MakeSimpleSubclass(targetClass, WC_STATIC); |
439 | daniel-mar | 255 | } |
476 | daniel-mar | 256 | |
257 | void Slider_Uninit_None() { |
||
258 | // Nothing here |
||
259 | } |