Subversion Repositories filter_foundry

Rev

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