Subversion Repositories filter_foundry

Rev

Rev 476 | Rev 478 | Go to most recent revision | 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.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"
  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 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 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 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 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. #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
  87.  
  88. // PLUGIN.DLL Sliders : Get slider position
  89. #ifdef use_plugin_dll_sliders
  90. typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition);
  91. int GetSliderPos(HWND hWnd, BOOL bPixelPosition) {
  92.         f_GetSliderPos fGetSliderPos;
  93.         int res;
  94.  
  95.         if (!gdata->pluginDllSliderInfo.hLib) return 0;
  96.         fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->pluginDllSliderInfo.hLib, "GetSliderPos");
  97.         res = (fGetSliderPos != 0) ? fGetSliderPos(hWnd, bPixelPosition) : 0;
  98.         return res;
  99. }
  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
  106.  
  107. LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  108.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  109. }
  110.  
  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.  
  133. Boolean MakeSimpleSubclass(LPCTSTR targetClass, LPCTSTR sourceClass) {
  134.         WNDCLASS clx;
  135.  
  136.         if (GetClassInfo(hDllInstance, sourceClass, &clx) != 0) {
  137.                 clx.lpszClassName = targetClass;
  138.                 if (RegisterClass(&clx) == 0) {
  139.                         TCHAR s[0x300];
  140.                         xstrcpy(s, (TCHAR*)TEXT("RegisterClass failed: "));
  141.                         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
  142.                         dbg(&s[0]);
  143.                         return false;
  144.                 }
  145.                 else {
  146.                         return true;
  147.                 }
  148.         }
  149.         else {
  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 {
  176.                         simplealert((TCHAR*)TEXT("GetClassInfo failed"));
  177.                 }
  178.                 return false;
  179.         }
  180. }
  181.  
  182. Boolean Slider_Init_PluginDll(LPCTSTR targetClass) {
  183.  
  184. #ifndef use_plugin_dll_sliders
  185.         return false;
  186. #else
  187.         if (gdata->pluginDllSliderInfo.initialized) return true;
  188.  
  189.         if (!gdata->pluginDllSliderInfo.hLib) {
  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).
  193.                 gdata->pluginDllSliderInfo.hLib = LoadLibrary(TEXT("Plugin.dll"));
  194.         }
  195.  
  196.         if (gdata->pluginDllSliderInfo.hLib && RegisterSlider(hDllInstance, &gdata->pluginDllSliderInfo.messageId)) {
  197.                 // Make "FoundrySlider" a subclass of "slider" then
  198.                 if (MakeSimpleSubclass(targetClass, TEXT("slider"))) {
  199.                         gdata->pluginDllSliderInfo.initialized = true;
  200.                         return true;
  201.                 }
  202.                 else {
  203.                         return false;
  204.                 }
  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.         }
  211. #endif
  212.  
  213. }
  214.  
  215. void Slider_Uninit_PluginDll() {
  216. #ifndef use_plugin_dll_sliders
  217.         return;
  218. #else
  219.         if (!gdata->pluginDllSliderInfo.initialized) return;
  220.  
  221.         if (!UnRegisterSlider(hDllInstance)) {
  222.                 simplealert((TCHAR*)TEXT("UnRegisterSlider failed"));
  223.                 return;
  224.         }
  225.  
  226.         gdata->pluginDllSliderInfo.initialized = false;
  227.  
  228.         if (gdata->pluginDllSliderInfo.hLib) {
  229.                 FreeLibrary(gdata->pluginDllSliderInfo.hLib);
  230.                 gdata->pluginDllSliderInfo.hLib = 0;
  231.         }
  232. #endif
  233. }
  234.  
  235. typedef void(__stdcall* f_InitCommonControls)();
  236. typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce);
  237. Boolean Slider_Init_MsTrackbar(LPCTSTR targetClass) {
  238.         f_InitCommonControls fInitCommonControls;
  239.         f_InitCommonControlsEx fInitCommonControlsEx;
  240.  
  241.         if (gdata->comctlSliderInfo.initialized) return true;
  242.  
  243.         // Make sure that Comctl32 is loaded
  244.         if (!gdata->comctlSliderInfo.hLib) {
  245.                 gdata->comctlSliderInfo.hLib = LoadLibrary(TEXT("Comctl32.dll"));
  246.         }
  247.         if (gdata->comctlSliderInfo.hLib) {
  248.                 fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControlsEx");
  249.                 if (fInitCommonControlsEx != 0) {
  250.                         INITCOMMONCONTROLSEX icce;
  251.                         icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
  252.                         icce.dwICC = ICC_BAR_CLASSES;
  253.                         fInitCommonControlsEx(&icce);
  254.                 }
  255.                 else {
  256.                         fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(gdata->comctlSliderInfo.hLib, "InitCommonControls");
  257.                         if (fInitCommonControls != 0) {
  258.                                 fInitCommonControls();
  259.                         }
  260.                 }
  261.  
  262.                 // Make "FoundrySlider" a subclass of "msctls_trackbar32" then
  263.                 if (MakeSimpleSubclass(targetClass, TEXT("msctls_trackbar32"))) {
  264.                         gdata->comctlSliderInfo.initialized = true;
  265.                         return true;
  266.                 }
  267.                 else {
  268.                         return false;
  269.                 }
  270.         }
  271.         else {
  272.                 return false;
  273.         }
  274. }
  275.  
  276. void Slider_Uninit_MsTrackbar() {
  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;
  284.         }
  285. }
  286.  
  287. Boolean Slider_Init_None(LPCTSTR targetClass) {
  288.         // Make "FoundrySlider" a subclass of "STATIC" (making it invisible)
  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.         }
  299. }
  300.  
  301. void Slider_Uninit_None() {
  302.         if (!gdata->noneSliderInfo.initialized) return;
  303.  
  304.         // Nothing here
  305. }