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