Subversion Repositories filter_foundry

Rev

Rev 432 | Rev 435 | 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. /* Win32 user interface routines */
  22.  
  23. #include "world.h"
  24.  
  25. #include "PIAbout.h"
  26.  
  27. #include <windows.h>
  28. #include <commctrl.h>
  29.  
  30. #include "ff.h"
  31.  
  32. #include "version.h"
  33.  
  34. #define use_plugin_dll_sliders
  35.  
  36. HWND preview_hwnd;
  37. HCURSOR hCurHandOpen;
  38. HCURSOR hCurHandGrab;
  39.  
  40. HCURSOR hCurHandQuestion;
  41. HICON hIconCautionSign;
  42.  
  43. // PLUGIN.DLL Sliders: This method will register the "slider" class used in dialogs.
  44. typedef int(__cdecl* f_RegisterSlider)(HINSTANCE hInstanceDll, DWORD* MessageID);
  45. int RegisterSlider(HINSTANCE hInstanceDll, DWORD* MessageID) {
  46.         f_RegisterSlider fRegisterSlider;
  47.  
  48.         if (!gdata->pluginDllModule) return 0;
  49.         fRegisterSlider = (f_RegisterSlider)(void*)GetProcAddress(gdata->pluginDllModule, "RegisterSlider");
  50.         if (fRegisterSlider != 0) {
  51.                 return fRegisterSlider(hInstanceDll, MessageID);
  52.         }
  53.         else {
  54.                 return 0;
  55.         }
  56. }
  57.  
  58. // PLUGIN.DLL Sliders: This method will unregister the "slider" class used in dialogs.
  59. typedef int(__cdecl* f_UnregisterSlider)(HINSTANCE hInstanceDll);
  60. int UnregisterSlider(HINSTANCE hInstanceDll) {
  61.         f_UnregisterSlider fUnregisterSlider;
  62.  
  63.         if (!gdata->pluginDllModule) return 0;
  64.         fUnregisterSlider = (f_UnregisterSlider)(void*)GetProcAddress(gdata->pluginDllModule, "UnregisterSlider");
  65.         if (fUnregisterSlider != 0) {
  66.                 return fUnregisterSlider(hInstanceDll);
  67.         }
  68.         else {
  69.                 return 0;
  70.         }
  71. }
  72.  
  73. // PLUGIN.DLL Sliders: Set slider range (min/max)
  74. typedef int(__cdecl* f_SetSliderRange)(HWND hWnd, int nMin, int nMax);
  75. int SetSliderRange(HWND hWnd, int nMin, int nMax) {
  76.         f_SetSliderRange fSetSliderRange;
  77.  
  78.         if (!gdata->pluginDllModule) return 0;
  79.         fSetSliderRange = (f_SetSliderRange)(void*)GetProcAddress(gdata->pluginDllModule, "SetSliderRange");
  80.         if (fSetSliderRange != 0) {
  81.                 return fSetSliderRange(hWnd, nMin, nMax);
  82.         }
  83.         else {
  84.                 return 0;
  85.         }
  86. }
  87.  
  88. // PLUGIN.DLL Sliders : Sets slider position
  89. typedef int(__cdecl* f_SetSliderPos)(HWND hWnd, int nPos, BOOL bRepaint);
  90. int SetSliderPos(HWND hWnd, int nPos, BOOL bRepaint) {
  91.         f_SetSliderPos fSetSliderPos;
  92.  
  93.         if (!gdata->pluginDllModule) return 0;
  94.         fSetSliderPos = (f_SetSliderPos)(void*)GetProcAddress(gdata->pluginDllModule, "SetSliderPos");
  95.         if (fSetSliderPos != 0) {
  96.                 return fSetSliderPos(hWnd, nPos, bRepaint);
  97.         }
  98.         else {
  99.                 return 0;
  100.         }
  101. }
  102.  
  103. // PLUGIN.DLL Sliders : Get slider position
  104. typedef int(__cdecl* f_GetSliderPos)(HWND hWnd, BOOL bPixelPosition);
  105. int GetSliderPos(HWND hWnd, BOOL bPixelPosition) {
  106.         f_GetSliderPos fGetSliderPos;
  107.  
  108.         if (!gdata->pluginDllModule) return 0;
  109.         fGetSliderPos = (f_GetSliderPos)(void*)GetProcAddress(gdata->pluginDllModule, "GetSliderPos");
  110.         if (fGetSliderPos != 0) {
  111.                 int res = fGetSliderPos(hWnd, bPixelPosition);
  112.                 return res;
  113.         }
  114.         else {
  115.                 return 0;
  116.         }
  117. }
  118.  
  119. extern HINSTANCE hDllInstance;
  120.  
  121. void DoAbout(AboutRecordPtr pb){
  122.         char text[1000];
  123.         char title[200];
  124.         PlatformData *p = (PlatformData*)pb->platformData;
  125.  
  126.         if (gdata && gdata->standalone) {
  127.                 sprintf(title, "About %s", gdata->parm.szTitle);
  128.                 sprintf(text,  "%s by %s\n" /* {Title} by {Author} */
  129.                                "%s\n" /* {Copyright} */
  130.                                "\n"
  131.                                "This plugin was built using Filter Foundry " VERSION_STR
  132.                                 #ifdef _WIN64
  133.                                " (64 bit)\n"
  134.                                 #else
  135.                                " (32 bit)\n"
  136.                                 #endif
  137.                                "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n"
  138.                                "available from " PROJECT_URL,
  139.                                gdata->parm.szTitle,
  140.                                gdata->parm.szAuthor,
  141.                                gdata->parm.szCopyright);
  142.         } else {
  143.                 sprintf(title, "About Filter Foundry");
  144.                 sprintf(text,  "Filter Foundry " VERSION_STR
  145.                                 #ifdef _WIN64
  146.                                " (64 bit)\n"
  147.                                 #else
  148.                                " (32 bit)\n"
  149.                                 #endif
  150.                                "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n"
  151.                                "\n"
  152.                                "Latest version available from\n"
  153.                                PROJECT_URL "\n"
  154.                                "\nPlease contact the author with any bug reports,\n"
  155.                                "suggestions or comments.\n"
  156.                                "If you use this program and like it, please consider\n"
  157.                                "making a donation.");
  158.         }
  159.  
  160.         MessageBox((HWND)p->hwnd, text, title, MB_TASKMODAL|MB_ICONINFORMATION|MB_OK);
  161. }
  162.  
  163. Boolean simplealert(char *s){
  164.         HWND hwnd;
  165.         char* title;
  166.         if (gdata && gdata->standalone) {
  167.                 title = gdata->parm.szTitle;
  168.         } else {
  169.                 title = _strdup("Filter Foundry");
  170.         }
  171.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  172.         return MessageBox(hwnd, s, title, MB_TASKMODAL|MB_ICONERROR|MB_OK) == IDOK;
  173. }
  174.  
  175. Boolean simplewarning(char* s) {
  176.         HWND hwnd;
  177.         char* title;
  178.         if (gdata && gdata->standalone) {
  179.                 title = gdata->parm.szTitle;
  180.         } else {
  181.                 title = _strdup("Filter Foundry");
  182.         }
  183.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  184.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONEXCLAMATION|MB_OK) == IDOK;
  185. }
  186.  
  187. Boolean showmessage(char *s) {
  188.         HWND hwnd;
  189.         char* title;
  190.         if (gdata && gdata->standalone) {
  191.                 title = gdata->parm.szTitle;
  192.         } else {
  193.                 title = _strdup("Filter Foundry");
  194.         }
  195.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  196.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONINFORMATION|MB_OK) == IDOK;
  197. }
  198.  
  199. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  200.  
  201. // Description:
  202. //   Creates a tooltip for an item in a dialog box.
  203. // Parameters:
  204. //   idTool - identifier of an dialog box item.
  205. //   nDlg - window handle of the dialog box.
  206. //   pszText - string to use as the tooltip text.
  207. // Returns:
  208. //   The handle to the tooltip.
  209. //
  210. HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText) {
  211.         // Source: https://docs.microsoft.com/en-us/windows/win32/controls/create-a-tooltip-for-a-control (modified)
  212.  
  213.         HWND hwndTool, hwndTip;
  214.         TOOLINFO toolInfo;
  215.  
  216.         if (!toolID || !hDlg || !pszText) {
  217.                 return FALSE;
  218.         }
  219.         // Get the window of the tool.
  220.         hwndTool = GetDlgItem(hDlg, toolID);
  221.  
  222.         // Create the tooltip. g_hInst is the global instance handle.
  223.         hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
  224.                 WS_POPUP | TTS_ALWAYSTIP /* | TTS_BALLOON*/,
  225.                 CW_USEDEFAULT, CW_USEDEFAULT,
  226.                 CW_USEDEFAULT, CW_USEDEFAULT,
  227.                 hDlg, NULL,
  228.                 hDllInstance, NULL);
  229.  
  230.         if (!hwndTool || !hwndTip) {
  231.                 return (HWND)NULL;
  232.         }
  233.  
  234.         // Associate the tooltip with the tool.
  235.         memset(&toolInfo, 0, sizeof(TOOLINFO)); // toolInfo = { 0 };
  236.         toolInfo.cbSize = sizeof(toolInfo);
  237.         toolInfo.hwnd = hDlg;
  238.         toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  239.         toolInfo.uId = (UINT_PTR)hwndTool;
  240.         toolInfo.lpszText = pszText;
  241.         SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
  242.  
  243.         return hwndTip;
  244. }
  245.  
  246. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam){
  247.         static POINT origpos;
  248.         static Point origscroll;
  249.         static Boolean panning = false;
  250.  
  251.         int item,i;
  252.         POINT newpos;
  253.         DRAWITEMSTRUCT *pdi;
  254.         Point newscroll;
  255.         HGDIOBJ hfnt;
  256.  
  257.         extern Boolean doupdates;
  258.         extern Handle preview_handle;
  259.  
  260.         if ((gdata->pluginDllSliderMessageId != 0) && (wMsg == gdata->pluginDllSliderMessageId)) {
  261.                 // This is for the PLUGIN.DLL sliders only
  262.                 if (doupdates) {
  263.                         int sliderNum = wParam - FIRSTCTLITEM;
  264.                         uint8_t sliderVal = (uint8_t)(lParam & 0xFFFF);
  265.                         slider[sliderNum] = sliderVal;
  266.  
  267.                         SETCTLTEXTINT(hDlg, FIRSTCTLTEXTITEM + sliderNum, sliderVal, false);
  268.                         REPAINTCTL(hDlg, FIRSTCTLTEXTITEM + sliderNum);
  269.  
  270.                         recalc_preview(gpb, hDlg);
  271.                 }
  272.                 return true;
  273.         }
  274.  
  275.         switch (wMsg) {
  276.         case WM_INITDIALOG:
  277.                 gdata->hWndMainDlg = hDlg;
  278.  
  279.                 if(gdata->standalone){
  280.                         SetWindowText(hDlg,gdata->parm.szTitle); // window title bar
  281.                 }
  282.                 centre_window(hDlg);
  283.  
  284.                 hfnt = GetStockObject(ANSI_FIXED_FONT);
  285.  
  286.                 hCurHandOpen = LoadCursor(hDllInstance, "HAND_OPEN");
  287.                 hCurHandGrab = LoadCursor(hDllInstance, "HAND_GRAB");
  288.                 hCurHandQuestion = LoadCursor(hDllInstance, "HAND_QUESTION");
  289.  
  290.                 hIconCautionSign = LoadIcon(hDllInstance, "CAUTION_ICO");
  291.  
  292.                 // Note: The whole class "Preview" gets the mouse cursor, not just the single item!
  293.                 preview_hwnd = GetDlgItem(hDlg, PREVIEWITEM);
  294.                 GetClientRect(preview_hwnd, &preview_rect);
  295.                 SetClassLongPtr(preview_hwnd, GCLP_HCURSOR, (LONG_PTR)hCurHandOpen);
  296.  
  297.                 // Note: The whole class "Caution" gets the mouse cursor, not just the single item!
  298.                 SetClassLongPtr(GetDlgItem(hDlg, FIRSTICONITEM), GCLP_HCURSOR, (LONG_PTR)hCurHandQuestion);
  299.  
  300.                 for(i = 0; i < 4; ++i){
  301.                         CreateToolTip(FIRSTICONITEM + i, hDlg, _strdup("Error in expression! Click to see details."));
  302.                 }
  303.  
  304.                 CreateToolTip(ZOOMINITEM, hDlg, _strdup("Zoom in"));
  305.                 CreateToolTip(ZOOMOUTITEM, hDlg, _strdup("Zoom out"));
  306.                 CreateToolTip(ZOOMLEVELITEM, hDlg, _strdup("Fully zoom in/out"));
  307.  
  308.                 for(i = 0; i < 8; ++i){
  309.                         if (gdata->pluginDllSliderMessageId == 0) {
  310.                                 // Non PLUGIN.DLL sliders
  311.                                 SetWindowLongPtr(GetDlgItem(hDlg, FIRSTCTLITEM + i), GWL_STYLE, TBS_HORZ | TBS_AUTOTICKS | WS_CHILD | WS_VISIBLE);
  312.                                 SendDlgItemMessage(hDlg, FIRSTCTLITEM + i, TBM_SETRANGE, TRUE, MAKELONG(0, 255));
  313.                                 SendDlgItemMessage(hDlg, FIRSTCTLITEM + i, TBM_SETTICFREQ, SLIDERPAGE, 0);
  314.                                 SendDlgItemMessage(hDlg, FIRSTCTLITEM + i, TBM_SETPAGESIZE, 0, SLIDERPAGE);
  315.                         }
  316.                         else {
  317.                                 // PLUGIN.DLL sliders
  318.                                 SetSliderRange(GetDlgItem(hDlg, FIRSTCTLITEM + i), 0, 255);
  319.                         }
  320.                         SendDlgItemMessage(hDlg,FIRSTCTLTEXTITEM+i,     EM_SETLIMITTEXT,3,0);
  321.                 }
  322.                 for(i = 0; i < 4; ++i){
  323.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        EM_SETLIMITTEXT,MAXEXPR-1,0); // we need 1 byte as NUL terminator, so our formula can be max 1023
  324.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        WM_SETFONT,(WPARAM)hfnt,false);
  325.                 }
  326.  
  327.                 maindlginit(hDlg);
  328.                 break;
  329.         case WM_DESTROY:
  330.                 gdata->hWndMainDlg = 0;
  331.                 DestroyCursor(hCurHandOpen);
  332.                 DestroyCursor(hCurHandGrab);
  333.                 DestroyCursor(hCurHandQuestion);
  334.                 DestroyIcon(hIconCautionSign);
  335.                 break;
  336.         case WM_DRAWITEM:
  337.                 pdi = (DRAWITEMSTRUCT*)lParam;
  338.                 if(pdi->itemAction == ODA_DRAWENTIRE){
  339.                         switch(pdi->CtlID){
  340.                         case PREVIEWITEM:
  341.                                 drawpreview(hDlg,pdi->hDC,PILOCKHANDLE(preview_handle,false));
  342.                                 PIUNLOCKHANDLE(preview_handle);
  343.                                 break;
  344.                         case FIRSTICONITEM:
  345.                         case FIRSTICONITEM + 1:
  346.                         case FIRSTICONITEM + 2:
  347.                         case FIRSTICONITEM + 3:
  348.                                 DrawIcon(pdi->hDC, 0, 0, hIconCautionSign);
  349.                                 break;
  350.                         default:
  351.                                 return false;
  352.                         }
  353.                 }else
  354.                         return false; // we couldn't handle the message
  355.                 break;
  356.         case WM_COMMAND:
  357.                 item = LOWORD(wParam);
  358.                 switch(HIWORD(wParam)){
  359.                 //case BN_CLICKED:
  360.                 case STN_CLICKED:
  361.                         // BN_CLICKED = Button clicked
  362.                         // STN_CLICKED = Static controls with SS_NOTIFY clicked
  363.                         // Both have the same ordinal number
  364.                         if(item==PREVIEWITEM && GetCursorPos(&origpos)){
  365.                                 panning = true;
  366.                                 origscroll = preview_scroll;
  367.                                 SetCursor(hCurHandGrab);
  368.                                 SetCapture(hDlg);
  369.                                 break;
  370.                         }
  371.                 /* ... falls through ... */
  372.                 case EN_CHANGE:
  373.                         if(doupdates && !maindlgitem(hDlg,item))
  374.                                 EndDialog(hDlg,item);
  375.                 }
  376.                 break;
  377. //      case WM_LBUTTONDOWN: break;
  378.         case WM_MOUSEMOVE:
  379.                 if(panning && GetCursorPos(&newpos)){
  380.                         newscroll.h = (int16)(origscroll.h - zoomfactor*((double)newpos.x - (double)origpos.x));
  381.                         newscroll.v = (int16)(origscroll.v - zoomfactor*((double)newpos.y - (double)origpos.y));
  382.                         if( newscroll.h != preview_scroll.h || newscroll.v != preview_scroll.v ){
  383.                                 preview_scroll = newscroll;
  384.                                 recalc_preview(gpb,hDlg);
  385.                         }
  386.                 }
  387.                 break;
  388.         case WM_LBUTTONUP:
  389.                 ReleaseCapture();
  390.                 panning = false;
  391.                 break;
  392.         case WM_HSCROLL:
  393.                 // Only for non-Plugin.dll-sliders
  394.                 item = GetDlgCtrlID((HWND)lParam);
  395.                 if(doupdates && gdata->pluginDllSliderMessageId == 0 && item>=FIRSTCTLITEM && item<=FIRSTCTLITEM+7)
  396.                         slidermoved(hDlg,item);
  397.                 break;
  398.         default:
  399.                 return false;
  400.         }
  401.  
  402.         return true;
  403. }
  404.  
  405. Boolean MakeSimpleSubclass(LPCSTR targetClass, LPCSTR sourceClass) {
  406.         WNDCLASS clx;
  407.  
  408.         if (GetClassInfoA(hDllInstance, sourceClass, &clx) != 0) {
  409.                 clx.lpszClassName = targetClass;
  410.                 if (RegisterClass(&clx) == 0) {
  411.                         char s[100];
  412.                         strcpy(s, "RegisterClass failed: ");
  413.                         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  414.                         dbg(s);
  415.                         return false;
  416.                 }
  417.                 else {
  418.                         return true;
  419.                 }
  420.         }
  421.         else {
  422.                 return false;
  423.         }
  424. }
  425.  
  426. void Slider_Uninit_PluginDll() {
  427.         WNDCLASS clx;
  428.  
  429.         #ifndef use_plugin_dll_sliders
  430.         return false;
  431.         #endif
  432.  
  433.         if (GetClassInfo(hDllInstance, "slider", &clx) != 0) {
  434.                 UnregisterSlider(hDllInstance);
  435.         }
  436.         if (gdata->pluginDllModule) {
  437.                 FreeLibrary(gdata->pluginDllModule);
  438.                 gdata->pluginDllModule = 0;
  439.         }
  440. }
  441.  
  442. Boolean Slider_Init_PluginDll(LPCSTR targetClass) {
  443.         DWORD sliderMsgId;
  444.  
  445.         #ifndef use_plugin_dll_sliders
  446.         return false;
  447.         #endif
  448.  
  449.         // Try loading PLUGIN.DLL (only Photoshop) in order to register the class "slider"
  450.         gdata->pluginDllModule = LoadLibraryA("PLUGIN.DLL");
  451.         if (!gdata->pluginDllModule) return false;
  452.         sliderMsgId = 0; // important
  453.         RegisterSlider(hDllInstance, &sliderMsgId);
  454.         if (sliderMsgId != 0) {
  455.                 // RegisterSlider will "remember" if it gave you a message ID before,
  456.                 // and it will NOT give it to you again! (instead, the output variable stays untouched).
  457.                 // The problem: PLUGIN.DLL stays loaded the whole time, so it keeps remembering, while Filter Foundry
  458.                 // loses its internal state every time the window is closed.
  459.                 // So, we keep the message ID in the global (persistant) data, so we remember it.
  460.                 gdata->pluginDllSliderMessageId = sliderMsgId;
  461.         }
  462.  
  463.         // Make "FoundrySlider" a subclass of "slider" then
  464.         return MakeSimpleSubclass(targetClass, "slider");
  465. }
  466.  
  467. typedef void(__stdcall* f_InitCommonControls)();
  468. typedef BOOL(__stdcall* f_InitCommonControlsEx)(const INITCOMMONCONTROLSEX* picce);
  469. Boolean Slider_Init_MsTrackbar(LPCSTR targetClass) {
  470.         f_InitCommonControls fInitCommonControls;
  471.         f_InitCommonControlsEx fInitCommonControlsEx;
  472.         HMODULE libComctl32;
  473.  
  474.         // Make sure that Comctl32 is loaded
  475.         libComctl32 = LoadLibraryA("Comctl32.dll");
  476.         if (libComctl32) {
  477.                 fInitCommonControlsEx = (f_InitCommonControlsEx)(void*)GetProcAddress(libComctl32, "InitCommonControlsEx");
  478.                 if (fInitCommonControlsEx != 0) {
  479.                         INITCOMMONCONTROLSEX icce;
  480.                         icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
  481.                         icce.dwICC = ICC_BAR_CLASSES;
  482.                         fInitCommonControlsEx(&icce);
  483.                 }
  484.                 else {
  485.                         fInitCommonControls = (f_InitCommonControls)(void*)GetProcAddress(libComctl32, "InitCommonControls");
  486.                         if (fInitCommonControls != 0) {
  487.                                 fInitCommonControls();
  488.                         }
  489.                 }
  490.                 FreeLibrary(libComctl32);
  491.         }
  492.  
  493.         // Make "FoundrySlider" a subclass of "msctls_trackbar32" then
  494.         return MakeSimpleSubclass(targetClass, "msctls_trackbar32");
  495. }
  496.  
  497. Boolean Slider_Init_None(LPCSTR targetClass) {
  498.         // Make "FoundrySlider" a subclass of "STATIC" (making it invisible)
  499.         return MakeSimpleSubclass(targetClass, "STATIC");
  500. }
  501.  
  502. Boolean maindialog(FilterRecordPtr pb){
  503.         PlatformData *p;
  504.         INT_PTR res;
  505.  
  506.         // First try to use the sliders from PLUGIN.DLL (only Photoshop)
  507.         if (!Slider_Init_PluginDll("FoundrySlider")) {
  508.                 // If we couldn't get the sliders from PLUGIN.DLL (probably not running in Photoshop),
  509.                 // then try the Microsoft Trackbar Control instead
  510.                 if (!Slider_Init_MsTrackbar("FoundrySlider")) {
  511.                         // This will happen if we neither have PLUGIN.DLL, nor the Microsoft Trackbar Control (msctls_trackbar32).
  512.                         // "msctls_trackbar32" is not included in Windows NT 3.1, and since there is no OCX or RegSvr32.
  513.                         // It is included in Windows NT 3.5x.
  514.  
  515.                         //simplealert(_strdup("This plugin requires Photoshop's PLUGIN.DLL or the Microsoft Trackbar Control (msctls_trackbar32) which was not found on your system."));
  516.                         //return false;
  517.  
  518.                         // We simply hide the sliders and let the user enter the numeric values in the edit-box.
  519.                         simplewarning(_strdup("Visual sliders are not available because neither PLUGIN.DLL, nor the Microsoft Trackbar Control (msctls_trackbar32) was found on your system."));
  520.                         Slider_Init_None("FoundrySlider");
  521.                 }
  522.         }
  523.  
  524.         // For the preview image and caution symbols, we register subclasses, so that we can assign a mouse cursor to this class.
  525.         MakeSimpleSubclass("Preview", "STATIC");
  526.         MakeSimpleSubclass("Caution", "Button");
  527.  
  528.         // Now show the dialog
  529.         p = (PlatformData*)pb->platformData;
  530.  
  531.         // Note: "Invalid Cursor Handle" is the error when an unrecognized control class is detected
  532.         res = DialogBoxParam(hDllInstance,MAKEINTRESOURCE(gdata->standalone ? ID_PARAMDLG : ID_MAINDLG),
  533.                              (HWND)p->hwnd,maindlgproc,0);
  534.         if (res == 0) {
  535.                 simplealert(_strdup("DialogBoxParam in valid parent window handle"));
  536.         }
  537.         if (res == -1) {
  538.                 char s[100];
  539.                 strcpy(s, "DialogBoxParam failed: ");
  540.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  541.                 dbg(s);
  542.         }
  543.  
  544.         // Clean up after the dialog has been closed
  545.         UnregisterClass("Preview", hDllInstance);
  546.         UnregisterClass("Caution", hDllInstance);
  547.         UnregisterClass("FoundrySlider", hDllInstance);
  548.         Slider_Uninit_PluginDll();
  549.  
  550.         return res == IDOK;
  551. }
  552.