Subversion Repositories filter_foundry

Rev

Rev 532 | 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
536 daniel-mar 3
        Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
503 daniel-mar 4
        Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
439 daniel-mar 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);
478 daniel-mar 30
BOOL PluginDll_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);
478 daniel-mar 44
BOOL PluginDll_UnRegisterSlider(HINSTANCE hInstanceDll) {
471 daniel-mar 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);
478 daniel-mar 58
int PluginDll_SetSliderRange(HWND hWnd, int nMin, int nMax) {
439 daniel-mar 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);
478 daniel-mar 72
int PluginDll_SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) {
439 daniel-mar 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
#endif
439 daniel-mar 82
 
83
// PLUGIN.DLL Sliders : Get slider position
477 daniel-mar 84
#ifdef use_plugin_dll_sliders
439 daniel-mar 85
typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition);
478 daniel-mar 86
int PluginDll_GetSliderPos(HWND hWnd, BOOL bPixelPosition) {
439 daniel-mar 87
        f_GetSliderPos fGetSliderPos;
470 daniel-mar 88
        int res;
439 daniel-mar 89
 
477 daniel-mar 90
        if (!gdata->pluginDllSliderInfo.hLib) return 0;
91
        fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "GetSliderPos");
470 daniel-mar 92
        res = (fGetSliderPos != 0) ? fGetSliderPos(hWnd, bPixelPosition) : 0;
93
        return res;
439 daniel-mar 94
}
477 daniel-mar 95
#endif
439 daniel-mar 96
 
478 daniel-mar 97
void FF_SetSliderRange(HWND hDlg, int nIDDlgItem, int min, int max) {
98
        if (!gdata->pluginDllSliderInfo.initialized) {
99
                // Non PLUGIN.DLL sliders
100
                SetWindowLongPtr(GetDlgItem(hDlg, nIDDlgItem), GWL_STYLE, TBS_HORZ | TBS_AUTOTICKS | WS_CHILD | WS_VISIBLE);
101
                SendDlgItemMessage(hDlg, nIDDlgItem, TBM_SETRANGE, TRUE, MAKELONG(min, max));
102
                SendDlgItemMessage(hDlg, nIDDlgItem, TBM_SETTICFREQ, SLIDERPAGE, 0);
103
                SendDlgItemMessage(hDlg, nIDDlgItem, TBM_SETPAGESIZE, 0, SLIDERPAGE);
104
        }
105
        else {
106
                // PLUGIN.DLL sliders
107
                #ifdef use_plugin_dll_sliders
108
                PluginDll_SetSliderRange(GetDlgItem(hDlg, nIDDlgItem), min, max);
109
                #endif
110
        }
111
}
112
 
113
int FF_GetSliderPos(HWND hDlg, int nIDDlgItem) {
114
        if (gdata->pluginDllSliderInfo.initialized) {
115
                return PluginDll_GetSliderPos(GetDlgItem(hDlg, nIDDlgItem), false);
116
        }
117
        else if (gdata->comctlSliderInfo.initialized) {
118
                return (int)SendDlgItemMessage(hDlg, nIDDlgItem, TBM_GETPOS, 0, 0);
119
        }
120
        else {
121
                return 0;
122
        }
123
}
124
 
125
void FF_SetSliderPos(HWND hDlg, int nIDDlgItem, int pos) {
126
        if (gdata->pluginDllSliderInfo.initialized) {
127
                PluginDll_SetSliderPos(GetDlgItem(hDlg, nIDDlgItem), pos, true);
128
        }
129
        else if (gdata->comctlSliderInfo.initialized) {
130
                SendDlgItemMessage(hDlg, nIDDlgItem, TBM_SETPOS, TRUE, pos);
131
        }
132
}
133
 
460 daniel-mar 134
LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
135
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
136
}
137
 
461 daniel-mar 138
void Win32sFixSuperclassing(HWND hDlg, int destItem, int sourceItem) {
139
        // Win32s (Win3.11) compatibility fix: Since GetClassInfo(WC_BUTTON) and GetClassInfo(WC_STATIC) won't work,
140
        // we had replaced the WndProc by a dummy. Now, we find out the real Button and Static WndProcs and give them
141
        // to our classes, making them the intended superclasses. Messages which have been sent in between were lost,
142
        // though...
143
 
144
        WNDPROC wndProc;
145
#ifdef _WIN64
146
        wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC);
147
        if (wndProc == DummyWndProc) {
148
                wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWLP_WNDPROC);
149
                SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWLP_WNDPROC, (LONG_PTR)wndProc);
150
        }
151
#else
152
        wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC);
153
        if (wndProc == DummyWndProc) {
154
                wndProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(hDlg, sourceItem), GWL_WNDPROC);
155
                SetWindowLongPtr(GetDlgItem(hDlg, destItem), GWL_WNDPROC, (LONG_PTR)wndProc);
156
        }
157
#endif
158
}
159
 
444 daniel-mar 160
Boolean MakeSimpleSubclass(LPCTSTR targetClass, LPCTSTR sourceClass) {
439 daniel-mar 161
        WNDCLASS clx;
162
 
444 daniel-mar 163
        if (GetClassInfo(hDllInstance, sourceClass, &clx) != 0) {
439 daniel-mar 164
                clx.lpszClassName = targetClass;
165
                if (RegisterClass(&clx) == 0) {
444 daniel-mar 166
                        TCHAR s[0x300];
492 daniel-mar 167
                        xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); // TODO (Not so important): TRANSLATE
454 daniel-mar 168
                        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
482 daniel-mar 169
                        simplealert(&s[0]);
439 daniel-mar 170
                        return false;
171
                }
172
                else {
173
                        return true;
174
                }
175
        }
176
        else {
460 daniel-mar 177
                if ((xstrcmp(sourceClass, WC_BUTTON) == 0) || (xstrcmp(sourceClass, WC_STATIC) == 0)) {
178
                        // GetClassInfo(WC_STATIC) and GetClassInfo(WC_BUTTON) fail on Win32s (Windows 3.11)
179
                        // So we create a fake-class now. It will be replaced with the real Button/Static WndProc later!
180
                        clx.style = 0;
181
                        clx.lpfnWndProc = DummyWndProc;
182
                        clx.cbClsExtra = 0;
183
                        clx.cbWndExtra = 0;
184
                        clx.hInstance = hDllInstance;
185
                        clx.hIcon = 0;
186
                        clx.hCursor = 0;
187
                        clx.hbrBackground = 0;
188
                        clx.lpszMenuName = 0;
189
                        clx.lpszClassName = targetClass;
190
 
191
                        if (RegisterClass(&clx) == 0) {
192
                                TCHAR s[0x300];
492 daniel-mar 193
                                xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); // TODO (Not so important): TRANSLATE
460 daniel-mar 194
                                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
482 daniel-mar 195
                                simplealert(&s[0]);
460 daniel-mar 196
                                return false;
197
                        }
198
                        else {
199
                                return true;
200
                        }
201
                }
202
                else {
492 daniel-mar 203
                        simplealert((TCHAR*)TEXT("GetClassInfo failed")); // TODO (Not so important): TRANSLATE
460 daniel-mar 204
                }
439 daniel-mar 205
                return false;
206
        }
207
}
208
 
476 daniel-mar 209
Boolean Slider_Init_PluginDll(LPCTSTR targetClass) {
210
 
439 daniel-mar 211
#ifndef use_plugin_dll_sliders
476 daniel-mar 212
        return false;
439 daniel-mar 213
#else
477 daniel-mar 214
        if (gdata->pluginDllSliderInfo.initialized) return true;
476 daniel-mar 215
 
477 daniel-mar 216
        if (!gdata->pluginDllSliderInfo.hLib) {
476 daniel-mar 217
                // DM 16.04.2022 : It is important that PLUGIN.DLL stays loaded, otherwise
218
                // DialogBoxParamA crashes. Can be reproduced if all 8BX modules are disabled in Photoshop 7
219
                // (they keep PLUGIN.DLL loaded).
477 daniel-mar 220
                gdata->pluginDllSliderInfo.hLib = LoadLibrary(TEXT("Plugin.dll"));
439 daniel-mar 221
        }
476 daniel-mar 222
 
478 daniel-mar 223
        if (gdata->pluginDllSliderInfo.hLib && PluginDll_RegisterSlider(hDllInstance, &gdata->pluginDllSliderInfo.messageId)) {
476 daniel-mar 224
                // Make "FoundrySlider" a subclass of "slider" then
477 daniel-mar 225
                if (MakeSimpleSubclass(targetClass, TEXT("slider"))) {
226
                        gdata->pluginDllSliderInfo.initialized = true;
227
                        return true;
228
                }
229
                else {
230
                        return false;
231
                }
476 daniel-mar 232
        }
233
        else {
234
                // This can happen if PLUGIN.DLL is not existing
235
                // It will also happen if a previous uninitialization failed (or was forgotten)
236
                return false; // Fall back to Windows sliders
237
        }
439 daniel-mar 238
#endif
239
 
240
}
241
 
532 daniel-mar 242
void Slider_Uninit_PluginDll(void) {
439 daniel-mar 243
#ifndef use_plugin_dll_sliders
476 daniel-mar 244
        return;
439 daniel-mar 245
#else
477 daniel-mar 246
        if (!gdata->pluginDllSliderInfo.initialized) return;
476 daniel-mar 247
 
478 daniel-mar 248
        if (!PluginDll_UnRegisterSlider(hDllInstance)) {
492 daniel-mar 249
                simplealert((TCHAR*)TEXT("UnRegisterSlider failed")); // TODO (Not so important): TRANSLATE
477 daniel-mar 250
                return;
469 daniel-mar 251
        }
477 daniel-mar 252
 
253
        gdata->pluginDllSliderInfo.initialized = false;
254
 
255
        if (gdata->pluginDllSliderInfo.hLib) {
256
                FreeLibrary(gdata->pluginDllSliderInfo.hLib);
257
                gdata->pluginDllSliderInfo.hLib = 0;
258
        }
439 daniel-mar 259
#endif
260
}
261
 
262
typedef void(__stdcall* f_InitCommonControls)();
263
typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce);
444 daniel-mar 264
Boolean Slider_Init_MsTrackbar(LPCTSTR targetClass) {
439 daniel-mar 265
        f_InitCommonControls fInitCommonControls;
266
        f_InitCommonControlsEx fInitCommonControlsEx;
267
 
477 daniel-mar 268
        if (gdata->comctlSliderInfo.initialized) return true;
269
 
439 daniel-mar 270
        // Make sure that Comctl32 is loaded
477 daniel-mar 271
        if (!gdata->comctlSliderInfo.hLib) {
272
                gdata->comctlSliderInfo.hLib = LoadLibrary(TEXT("Comctl32.dll"));
476 daniel-mar 273
        }
477 daniel-mar 274
        if (gdata->comctlSliderInfo.hLib) {
275
                fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControlsEx");
439 daniel-mar 276
                if (fInitCommonControlsEx != 0) {
277
                        INITCOMMONCONTROLSEX icce;
278
                        icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
279
                        icce.dwICC = ICC_BAR_CLASSES;
280
                        fInitCommonControlsEx(&icce);
281
                }
282
                else {
477 daniel-mar 283
                        fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControls");
439 daniel-mar 284
                        if (fInitCommonControls != 0) {
285
                                fInitCommonControls();
286
                        }
287
                }
476 daniel-mar 288
 
289
                // Make "FoundrySlider" a subclass of "msctls_trackbar32" then
477 daniel-mar 290
                if (MakeSimpleSubclass(targetClass, TEXT("msctls_trackbar32"))) {
291
                        gdata->comctlSliderInfo.initialized = true;
292
                        return true;
293
                }
294
                else {
295
                        return false;
296
                }
439 daniel-mar 297
        }
476 daniel-mar 298
        else {
299
                return false;
300
        }
301
}
439 daniel-mar 302
 
532 daniel-mar 303
void Slider_Uninit_MsTrackbar(void) {
477 daniel-mar 304
        if (!gdata->comctlSliderInfo.initialized) return;
305
 
306
        gdata->comctlSliderInfo.initialized = false;
307
 
308
        if (gdata->comctlSliderInfo.hLib != 0) {
309
                FreeLibrary(gdata->comctlSliderInfo.hLib);
310
                gdata->comctlSliderInfo.hLib = 0;
476 daniel-mar 311
        }
439 daniel-mar 312
}
313
 
444 daniel-mar 314
Boolean Slider_Init_None(LPCTSTR targetClass) {
439 daniel-mar 315
        // Make "FoundrySlider" a subclass of "STATIC" (making it invisible)
477 daniel-mar 316
 
317
        if (gdata->noneSliderInfo.initialized) return true;
318
 
319
        if (MakeSimpleSubclass(targetClass, WC_STATIC)) {
320
                gdata->noneSliderInfo.initialized = true;
321
                return true;
322
        }
323
        else {
324
                return false;
325
        }
439 daniel-mar 326
}
476 daniel-mar 327
 
532 daniel-mar 328
void Slider_Uninit_None(void) {
477 daniel-mar 329
        if (!gdata->noneSliderInfo.initialized) return;
330
 
476 daniel-mar 331
        // Nothing here
503 daniel-mar 332
}