Subversion Repositories filter_foundry

Rev

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
}