Subversion Repositories filter_foundry

Rev

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
}