Subversion Repositories filter_foundry

Rev

Rev 532 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.         This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.         Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
  4.         Copyright (C) 2018-2022 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"
  22. #include "slider_win.h"
  23.  
  24. // More information about the PLUGIN.DLL sliders:
  25. // https://misc.daniel-marschall.de/projects/filter_factory/sliders.html
  26.  
  27. // PLUGIN.DLL Sliders: This method will register the "slider" class used in dialogs.
  28. #ifdef use_plugin_dll_sliders
  29. typedef BOOL(__cdecl* f_RegisterSlider)(HINSTANCE hInstanceDll, DWORD* MessageID);
  30. BOOL PluginDll_RegisterSlider(HINSTANCE hInstanceDll, DWORD* MessageID) {
  31.         f_RegisterSlider fRegisterSlider;
  32.         BOOL res;
  33.  
  34.         if (!gdata->pluginDllSliderInfo.hLib) return false;
  35.         fRegisterSlider = (f_RegisterSlider)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "RegisterSlider");
  36.         res = (fRegisterSlider != 0) ? fRegisterSlider(hInstanceDll, MessageID) : false;
  37.         return res;
  38. }
  39. #endif
  40.  
  41. // PLUGIN.DLL Sliders: This method will unregister the "slider" class used in dialogs.
  42. #ifdef use_plugin_dll_sliders
  43. typedef BOOL(__cdecl* f_UnRegisterSlider)(HINSTANCE hInstanceDll);
  44. BOOL PluginDll_UnRegisterSlider(HINSTANCE hInstanceDll) {
  45.         f_UnRegisterSlider fUnRegisterSlider;
  46.         BOOL res;
  47.  
  48.         if (!gdata->pluginDllSliderInfo.hLib) return false;
  49.         fUnRegisterSlider = (f_UnRegisterSlider)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "UnRegisterSlider");
  50.         res = (fUnRegisterSlider != 0) ? fUnRegisterSlider(hInstanceDll) : false;
  51.         return res;
  52. }
  53. #endif
  54.  
  55. // PLUGIN.DLL Sliders: Set slider range (min/max)
  56. #ifdef use_plugin_dll_sliders
  57. typedef int(__cdecl* f_SetSliderRange)(HWND hWnd, int nMin, int nMax);
  58. int PluginDll_SetSliderRange(HWND hWnd, int nMin, int nMax) {
  59.         f_SetSliderRange fSetSliderRange;
  60.         int res;
  61.  
  62.         if (!gdata->pluginDllSliderInfo.hLib) return 0;
  63.         fSetSliderRange = (f_SetSliderRange)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "SetSliderRange");
  64.         res = (fSetSliderRange != 0) ? fSetSliderRange(hWnd, nMin, nMax) : 0;
  65.         return res;
  66. }
  67. #endif
  68.  
  69. // PLUGIN.DLL Sliders : Sets slider position
  70. #ifdef use_plugin_dll_sliders
  71. typedef int(__cdecl* f_SetSliderPos)(HWND hWnd, int nPos, BOOL bRepaint);
  72. int PluginDll_SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) {
  73.         f_SetSliderPos fSetSliderPos;
  74.         int res;
  75.  
  76.         if (!gdata->pluginDllSliderInfo.hLib) return 0;
  77.         fSetSliderPos = (f_SetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "SetSliderPos");
  78.         res = (fSetSliderPos != 0) ? fSetSliderPos(hWnd, nPos, bRepaint) : 0;
  79.         return res;
  80. }
  81. #endif
  82.  
  83. // PLUGIN.DLL Sliders : Get slider position
  84. #ifdef use_plugin_dll_sliders
  85. typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition);
  86. int PluginDll_GetSliderPos(HWND hWnd, BOOL bPixelPosition) {
  87.         f_GetSliderPos fGetSliderPos;
  88.         int res;
  89.  
  90.         if (!gdata->pluginDllSliderInfo.hLib) return 0;
  91.         fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "GetSliderPos");
  92.         res = (fGetSliderPos != 0) ? fGetSliderPos(hWnd, bPixelPosition) : 0;
  93.         return res;
  94. }
  95. #endif
  96.  
  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.  
  134. LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  135.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  136. }
  137.  
  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.  
  160. Boolean MakeSimpleSubclass(LPCTSTR targetClass, LPCTSTR sourceClass) {
  161.         WNDCLASS clx;
  162.  
  163.         if (GetClassInfo(hDllInstance, sourceClass, &clx) != 0) {
  164.                 clx.lpszClassName = targetClass;
  165.                 if (RegisterClass(&clx) == 0) {
  166.                         TCHAR s[0x300];
  167.                         xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); // TODO (Not so important): TRANSLATE
  168.                         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
  169.                         simplealert(&s[0]);
  170.                         return false;
  171.                 }
  172.                 else {
  173.                         return true;
  174.                 }
  175.         }
  176.         else {
  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];
  193.                                 xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: ")); // TODO (Not so important): TRANSLATE
  194.                                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
  195.                                 simplealert(&s[0]);
  196.                                 return false;
  197.                         }
  198.                         else {
  199.                                 return true;
  200.                         }
  201.                 }
  202.                 else {
  203.                         simplealert((TCHAR*)TEXT("GetClassInfo failed")); // TODO (Not so important): TRANSLATE
  204.                 }
  205.                 return false;
  206.         }
  207. }
  208.  
  209. Boolean Slider_Init_PluginDll(LPCTSTR targetClass) {
  210.  
  211. #ifndef use_plugin_dll_sliders
  212.         return false;
  213. #else
  214.         if (gdata->pluginDllSliderInfo.initialized) return true;
  215.  
  216.         if (!gdata->pluginDllSliderInfo.hLib) {
  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).
  220.                 gdata->pluginDllSliderInfo.hLib = LoadLibrary(TEXT("Plugin.dll"));
  221.         }
  222.  
  223.         if (gdata->pluginDllSliderInfo.hLib && PluginDll_RegisterSlider(hDllInstance, &gdata->pluginDllSliderInfo.messageId)) {
  224.                 // Make "FoundrySlider" a subclass of "slider" then
  225.                 if (MakeSimpleSubclass(targetClass, TEXT("slider"))) {
  226.                         gdata->pluginDllSliderInfo.initialized = true;
  227.                         return true;
  228.                 }
  229.                 else {
  230.                         return false;
  231.                 }
  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.         }
  238. #endif
  239.  
  240. }
  241.  
  242. void Slider_Uninit_PluginDll(void) {
  243. #ifndef use_plugin_dll_sliders
  244.         return;
  245. #else
  246.         if (!gdata->pluginDllSliderInfo.initialized) return;
  247.  
  248.         if (!PluginDll_UnRegisterSlider(hDllInstance)) {
  249.                 simplealert((TCHAR*)TEXT("UnRegisterSlider failed")); // TODO (Not so important): TRANSLATE
  250.                 return;
  251.         }
  252.  
  253.         gdata->pluginDllSliderInfo.initialized = false;
  254.  
  255.         if (gdata->pluginDllSliderInfo.hLib) {
  256.                 FreeLibrary(gdata->pluginDllSliderInfo.hLib);
  257.                 gdata->pluginDllSliderInfo.hLib = 0;
  258.         }
  259. #endif
  260. }
  261.  
  262. typedef void(__stdcall* f_InitCommonControls)();
  263. typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce);
  264. Boolean Slider_Init_MsTrackbar(LPCTSTR targetClass) {
  265.         f_InitCommonControls fInitCommonControls;
  266.         f_InitCommonControlsEx fInitCommonControlsEx;
  267.  
  268.         if (gdata->comctlSliderInfo.initialized) return true;
  269.  
  270.         // Make sure that Comctl32 is loaded
  271.         if (!gdata->comctlSliderInfo.hLib) {
  272.                 gdata->comctlSliderInfo.hLib = LoadLibrary(TEXT("Comctl32.dll"));
  273.         }
  274.         if (gdata->comctlSliderInfo.hLib) {
  275.                 fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControlsEx");
  276.                 if (fInitCommonControlsEx != 0) {
  277.                         INITCOMMONCONTROLSEX icce;
  278.                         icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
  279.                         icce.dwICC = ICC_BAR_CLASSES;
  280.                         fInitCommonControlsEx(&icce);
  281.                 }
  282.                 else {
  283.                         fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControls");
  284.                         if (fInitCommonControls != 0) {
  285.                                 fInitCommonControls();
  286.                         }
  287.                 }
  288.  
  289.                 // Make "FoundrySlider" a subclass of "msctls_trackbar32" then
  290.                 if (MakeSimpleSubclass(targetClass, TEXT("msctls_trackbar32"))) {
  291.                         gdata->comctlSliderInfo.initialized = true;
  292.                         return true;
  293.                 }
  294.                 else {
  295.                         return false;
  296.                 }
  297.         }
  298.         else {
  299.                 return false;
  300.         }
  301. }
  302.  
  303. void Slider_Uninit_MsTrackbar(void) {
  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;
  311.         }
  312. }
  313.  
  314. Boolean Slider_Init_None(LPCTSTR targetClass) {
  315.         // Make "FoundrySlider" a subclass of "STATIC" (making it invisible)
  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.         }
  326. }
  327.  
  328. void Slider_Uninit_None(void) {
  329.         if (!gdata->noneSliderInfo.initialized) return;
  330.  
  331.         // Nothing here
  332. }
  333.