Subversion Repositories filter_foundry

Rev

Rev 492 | Rev 495 | 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. #include "slider_win.h"
  32. #include "version.h"
  33.  
  34. HWND preview_hwnd;
  35. HCURSOR hCurHandOpen;
  36. HCURSOR hCurHandGrab;
  37.  
  38. HCURSOR hCurHandQuestion;
  39. HICON hIconCautionSign;
  40.  
  41. extern HINSTANCE hDllInstance;
  42.  
  43. void DoAbout(AboutRecordPtr pb){
  44.         PlatformData *p = (PlatformData*)pb->platformData;
  45.  
  46.         if (gdata && gdata->standalone) {
  47.                 TCHAR filters[3000];
  48.                 TCHAR* tmp1, * tmp2;
  49.  
  50.                 memset(&filters[0], 0, sizeof(filters));
  51.                 tmp1 = &filters[0];
  52.  
  53.                 //strcpy(gdata->parm.szTitle, "TestTitle");
  54.                 //strcpy(gdata->parm.szAuthor, "TestAuthor");
  55.                 //strcpy(gdata->parm.szCopyright, "TestCopyright");
  56.  
  57.                 tmp1 += mbstowcs(tmp1, gdata->parm.szTitle, 100);
  58.                 FF_GetMsg(tmp1, MSG_ABOUT_BY_ID); tmp1 += xstrlen(tmp1);
  59.                 tmp1 += mbstowcs(tmp1, gdata->parm.szAuthor, 100);
  60.                 tmp1 += mbstowcs(tmp1, "\n", 100);
  61.  
  62.                 tmp1 += mbstowcs(tmp1, gdata->parm.szCopyright, 100);
  63.                 tmp1 += mbstowcs(tmp1, "\n\n", 100);
  64.  
  65.                 FF_GetMsg(tmp1, MSG_ABOUT_BUILT_USING_ID); tmp1 += xstrlen(tmp1);
  66.                 tmp1 += mbstowcs(tmp1, VERSION_STR, 100);
  67.  
  68.                 #ifdef _WIN64
  69.                 tmp1 += mbstowcs(tmp1, " (64 bit)\n", 100);
  70.                 #else
  71.                 tmp1 += mbstowcs(tmp1, " (32 bit)\n", 100);
  72.                 #endif
  73.  
  74.                 tmp1 += mbstowcs(tmp1, "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n", 100);
  75.  
  76.                 FF_GetMsg(tmp1, MSG_ABOUT_LATEST_VERSION_FROM_ID); tmp1 += xstrlen(tmp1);
  77.                 tmp1 += mbstowcs(tmp1, "\n", 100);
  78.                 tmp1 += mbstowcs(tmp1, PROJECT_URL, 100);
  79.  
  80.                 showmessage(&filters[0]);
  81.         } else {
  82.                 TCHAR filters[3000];
  83.                 TCHAR* tmp1, * tmp2;
  84.  
  85.                 memset(&filters[0], 0, sizeof(filters));
  86.                 tmp1 = &filters[0];
  87.  
  88.                 tmp1 += mbstowcs(tmp1, "Filter Foundry " VERSION_STR, 100);
  89.                 #ifdef _WIN64
  90.                 tmp1 += mbstowcs(tmp1, " (64 bit)\n", 100);
  91.                 #else
  92.                 tmp1 += mbstowcs(tmp1, " (32 bit)\n", 100);
  93.                 #endif
  94.  
  95.                 tmp1 += mbstowcs(tmp1, "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n\n", 100);
  96.  
  97.                 FF_GetMsg(tmp1, MSG_ABOUT_LATEST_VERSION_FROM_ID); tmp1 += xstrlen(tmp1);
  98.                 tmp1 += mbstowcs(tmp1, "\n", 100);
  99.                 tmp1 += mbstowcs(tmp1, PROJECT_URL, 100);
  100.                 tmp1 += mbstowcs(tmp1, "\n\n", 100);
  101.  
  102.                 FF_GetMsg(tmp1, MSG_ABOUT_CONTACT_AUTHOR_ID); tmp1 += xstrlen(tmp1);
  103.  
  104.                 showmessage(&filters[0]);
  105.         }
  106. }
  107.  
  108. Boolean simplealert(TCHAR* s){
  109.         HWND hwnd;
  110.         TCHAR title[256] = { 0 };
  111.         if (gdata && gdata->standalone) {
  112.                 #ifdef UNICODE
  113.                 mbstowcs(&title[0], (const char*)gdata->parm.szTitle, 256);
  114.                 #else
  115.                 strcpy(&title[0], gdata->parm.szTitle);
  116.                 #endif
  117.         }
  118.         else {
  119.                 xstrcpy(&title[0], (TCHAR*)TEXT("Filter Foundry"));
  120.         }
  121.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  122.         return MessageBox(hwnd, s, title, MB_TASKMODAL|MB_ICONERROR|MB_OK) == IDOK;
  123. }
  124.  
  125. Boolean simplewarning(TCHAR* s) {
  126.         HWND hwnd;
  127.         TCHAR title[256] = { 0 };
  128.         if (gdata && gdata->standalone) {
  129.                 #ifdef UNICODE
  130.                 mbstowcs(&title[0], (const char*)gdata->parm.szTitle, 256);
  131.                 #else
  132.                 strcpy(&title[0], gdata->parm.szTitle);
  133.                 #endif
  134.         } else {
  135.                 xstrcpy(&title[0], (TCHAR*)TEXT("Filter Foundry"));
  136.         }
  137.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  138.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONEXCLAMATION|MB_OK) == IDOK;
  139. }
  140.  
  141. Boolean showmessage(TCHAR *s) {
  142.         HWND hwnd;
  143.         TCHAR title[256] = { 0 };
  144.         if (gdata && gdata->standalone) {
  145.                 #ifdef UNICODE
  146.                 mbstowcs(&title[0], (const char*)gdata->parm.szTitle, 256);
  147.                 #else
  148.                 strcpy(&title[0], gdata->parm.szTitle);
  149.                 #endif
  150.         }
  151.         else {
  152.                 xstrcpy(&title[0], (TCHAR*)TEXT("Filter Foundry"));
  153.         }
  154.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  155.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONINFORMATION|MB_OK) == IDOK;
  156. }
  157.  
  158. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  159.  
  160. // Description:
  161. //   Creates a tooltip for an item in a dialog box.
  162. // Parameters:
  163. //   idTool - identifier of an dialog box item.
  164. //   nDlg - window handle of the dialog box.
  165. //   pszText - string to use as the tooltip text.
  166. // Returns:
  167. //   The handle to the tooltip.
  168. //
  169. HWND CreateToolTip(int toolID, HWND hDlg, LPTSTR pszText) {
  170.         // Source: https://docs.microsoft.com/en-us/windows/win32/controls/create-a-tooltip-for-a-control (modified)
  171.  
  172.         HWND hwndTool, hwndTip;
  173.         TOOLINFO toolInfo;
  174.  
  175.         if (!toolID || !hDlg || !pszText) {
  176.                 return FALSE;
  177.         }
  178.         // Get the window of the tool.
  179.         hwndTool = GetDlgItem(hDlg, toolID);
  180.  
  181.         // Create the tooltip. g_hInst is the global instance handle.
  182.         hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
  183.                 WS_POPUP | TTS_ALWAYSTIP /* | TTS_BALLOON*/,
  184.                 CW_USEDEFAULT, CW_USEDEFAULT,
  185.                 CW_USEDEFAULT, CW_USEDEFAULT,
  186.                 hDlg, NULL,
  187.                 hDllInstance, NULL);
  188.  
  189.         if (!hwndTool || !hwndTip) {
  190.                 return (HWND)NULL;
  191.         }
  192.  
  193.         // Associate the tooltip with the tool.
  194.         memset(&toolInfo, 0, sizeof(TOOLINFO)); // toolInfo = { 0 };
  195.         toolInfo.cbSize = sizeof(toolInfo);
  196.         toolInfo.hwnd = hDlg;
  197.         toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  198.         toolInfo.uId = (UINT_PTR)hwndTool;
  199.         toolInfo.lpszText = pszText;
  200.         SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
  201.  
  202.         return hwndTip;
  203. }
  204.  
  205. #define IDT_TIMER_INITPREVIEW_DRAW 'tDRW'
  206.  
  207. WNDPROC lpControlEditWndProc[8];
  208.  
  209. LRESULT CALLBACK ControlTextWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  210.         extern Boolean doupdates;
  211.         int sliderNum;
  212.         for (sliderNum = 0; sliderNum < 8; sliderNum++) {
  213.                 if (hWnd == GetDlgItem(gdata->hWndMainDlg, FIRSTCTLTEXTITEM + sliderNum)) {
  214.                         if ((uMsg == WM_KEYDOWN) && (wParam == VK_UP) && doupdates)
  215.                         {
  216.                                 uint8_t sliderVal = slider[sliderNum] < 255 ? slider[sliderNum] + 1 : slider[sliderNum];
  217.                                 slider[sliderNum] = sliderVal;
  218.  
  219.                                 SETCTLTEXTINT(gdata->hWndMainDlg, FIRSTCTLTEXTITEM + sliderNum, sliderVal, false);
  220.                                 REPAINTCTL(gdata->hWndMainDlg, FIRSTCTLTEXTITEM + sliderNum);
  221.  
  222.                                 recalc_preview(gpb, gdata->hWndMainDlg);
  223.  
  224.                                 return 0;
  225.                         }
  226.                         if ((uMsg == WM_KEYDOWN) && (wParam == VK_DOWN) && doupdates)
  227.                         {
  228.                                 uint8_t sliderVal = slider[sliderNum] > 0 ? slider[sliderNum] - 1 : slider[sliderNum];
  229.                                 slider[sliderNum] = sliderVal;
  230.  
  231.                                 SETCTLTEXTINT(gdata->hWndMainDlg, FIRSTCTLTEXTITEM + sliderNum, sliderVal, false);
  232.                                 REPAINTCTL(gdata->hWndMainDlg, FIRSTCTLTEXTITEM + sliderNum);
  233.  
  234.                                 recalc_preview(gpb, gdata->hWndMainDlg);
  235.  
  236.                                 return 0;
  237.                         }
  238.                         return CallWindowProc(lpControlEditWndProc[sliderNum], hWnd, uMsg, wParam, lParam);
  239.                 }
  240.         }
  241.         return 0; // should not happen
  242. }
  243.  
  244. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam){
  245.         static POINT origpos;
  246.         static Point origscroll;
  247.         static Boolean panning = false;
  248.  
  249.         int item,i;
  250.         POINT newpos;
  251.         DRAWITEMSTRUCT *pdi;
  252.         Point newscroll = { 0, 0 };
  253.         HGDIOBJ hfnt;
  254.  
  255.         extern Boolean doupdates;
  256.         extern FFBuffer preview_handle;
  257.  
  258.         if ((gdata->pluginDllSliderInfo.initialized) && (wMsg == gdata->pluginDllSliderInfo.messageId)) {
  259.                 // This is for the PLUGIN.DLL sliders only
  260.                 if (doupdates) {
  261.                         int sliderNum = (int)wParam - FIRSTCTLITEM;
  262.                         int sliderVal = (lParam & 0xFFFF);
  263.                         if (sliderVal < 0) sliderVal = 0;
  264.                         else if (sliderVal > 255) sliderVal = 255;
  265.                         slider[sliderNum] = (uint8_t)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_TIMER:
  277.                 switch (wParam)
  278.                 {
  279.                 case IDT_TIMER_INITPREVIEW_DRAW:
  280.                         KillTimer(hDlg, IDT_TIMER_INITPREVIEW_DRAW);
  281.                         recalc_preview(gpb, hDlg);
  282.                         return 0;
  283.                 }
  284.                 break;
  285.         case WM_INITDIALOG:
  286.                 gdata->hWndMainDlg = hDlg;
  287.  
  288.                 if(gdata->standalone){
  289.                         SetWindowTextA(hDlg,gdata->parm.szTitle); // window title bar
  290.                 }
  291.                 centre_window(hDlg);
  292.  
  293.                 hfnt = GetStockObject(ANSI_FIXED_FONT);
  294.  
  295.                 hCurHandOpen = LoadCursorA(hDllInstance, "HAND_OPEN");
  296.                 hCurHandGrab = LoadCursorA(hDllInstance, "HAND_GRAB");
  297.                 hCurHandQuestion = LoadCursorA(hDllInstance, "HAND_QUESTION");
  298.  
  299.                 hIconCautionSign = LoadIconA(hDllInstance, "CAUTION_ICO");
  300.  
  301.                 // Note: The whole class "Preview" gets the mouse cursor, not just the single item!
  302.                 preview_hwnd = GetDlgItem(hDlg, PREVIEWITEM);
  303.                 GetClientRect(preview_hwnd, &preview_rect);
  304.                 SetClassLongPtr(preview_hwnd, GCLP_HCURSOR, (LONG_PTR)hCurHandOpen);
  305.  
  306.                 // Note: The whole class "Caution" gets the mouse cursor, not just the single item!
  307.                 SetClassLongPtr(GetDlgItem(hDlg, FIRSTICONITEM), GCLP_HCURSOR, (LONG_PTR)hCurHandQuestion);
  308.  
  309.                 for(i = 0; i < 4; ++i){
  310.                         TCHAR msg[0x100];
  311.                         LoadString(hDllInstance, MSG_ERROR_IN_EXPRESSION_CLICK_DETAILS_ID, &msg[0], 0x100);
  312.                         CreateToolTip(FIRSTICONITEM + i, hDlg, msg);
  313.                 }
  314.  
  315.                 {
  316.                         TCHAR msg[0x100];
  317.                         LoadString(hDllInstance, MSG_ZOOM_IN_ID, &msg[0], 0x100);
  318.                         CreateToolTip(ZOOMINITEM, hDlg, msg);
  319.                         LoadString(hDllInstance, MSG_ZOOM_OUT_ID, &msg[0], 0x100);
  320.                         CreateToolTip(ZOOMOUTITEM, hDlg, msg);
  321.                         LoadString(hDllInstance, MSG_FULLY_ZOOM_INOUT_ID, &msg[0], 0x100);
  322.                         CreateToolTip(ZOOMLEVELITEM, hDlg, msg);
  323.                 }
  324.  
  325.                 for(i = 0; i < 8; ++i){
  326.                         FF_SetSliderRange(hDlg, FIRSTCTLITEM+i, 0, 255);
  327.                         SendDlgItemMessage(hDlg,FIRSTCTLTEXTITEM+i,     EM_SETLIMITTEXT,3,0);
  328.                 }
  329.                 for(i = 0; i < 4; ++i){
  330.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        EM_SETLIMITTEXT,MAXEXPR-1,0); // we need 1 byte as NUL terminator, so our formula can be max 1023
  331.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        WM_SETFONT,(WPARAM)hfnt,false);
  332.                 }
  333.  
  334.                 // Implement "up" and "down" keys for the edit controls
  335.                 // TODO: Better use a spin-edit?
  336.                 for (i = 0; i < 8; ++i) {
  337.                         #ifdef _WIN64
  338.                         lpControlEditWndProc[i] = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg, FIRSTCTLTEXTITEM + i), GWLP_WNDPROC, (LONG_PTR)&ControlTextWndProc);
  339.                         #else
  340.                         lpControlEditWndProc[i] = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg, FIRSTCTLTEXTITEM + i), GWL_WNDPROC, (LONG_PTR)&ControlTextWndProc);
  341.                         #endif
  342.                 }
  343.  
  344.                 maindlginit(hDlg);
  345.  
  346.                 // Win32s (Windows 3.11) compatibility
  347.                 Win32sFixSuperclassing(hDlg, PREVIEWITEM, FIRSTCTLLABELITEM);
  348.                 for (i=0; i<4; i++) Win32sFixSuperclassing(hDlg, FIRSTICONITEM + i, OPENITEM);
  349.  
  350.                 // Some versions of Windows (NT 3.x) won't show the preview if it is calculated here.
  351.                 // So we need to put it in a timer.
  352.                 // Note that 1 millisecond is enough, even if the window needs longer than 1 millisecond to load.
  353.                 //recalc_preview(gpb, hDlg);
  354.                 SetTimer(hDlg, IDT_TIMER_INITPREVIEW_DRAW, 1, (TIMERPROC)NULL);
  355.  
  356.                 break;
  357.         case WM_DESTROY:
  358.                 gdata->hWndMainDlg = 0;
  359.                 DestroyCursor(hCurHandOpen);
  360.                 DestroyCursor(hCurHandGrab);
  361.                 DestroyCursor(hCurHandQuestion);
  362.                 DestroyIcon(hIconCautionSign);
  363.                 break;
  364.         case WM_DRAWITEM:
  365.                 pdi = (DRAWITEMSTRUCT*)lParam;
  366.                 if(pdi->itemAction == ODA_DRAWENTIRE){
  367.                         switch(pdi->CtlID){
  368.                         case PREVIEWITEM:
  369.                                 drawpreview(hDlg,pdi->hDC,lockBuffer(&preview_handle));
  370.                                 unlockBuffer(&preview_handle);
  371.                                 break;
  372.                         case FIRSTICONITEM:
  373.                         case FIRSTICONITEM + 1:
  374.                         case FIRSTICONITEM + 2:
  375.                         case FIRSTICONITEM + 3:
  376.                                 DrawIcon(pdi->hDC, 0, 0, hIconCautionSign);
  377.                                 break;
  378.                         default:
  379.                                 return false;
  380.                         }
  381.                 }else
  382.                         return false; // we couldn't handle the message
  383.                 break;
  384.         case WM_COMMAND:
  385.                 item = LOWORD(wParam);
  386.                 switch(HIWORD(wParam)){
  387.                 //case BN_CLICKED:
  388.                 case STN_CLICKED:
  389.                         // BN_CLICKED = Button clicked
  390.                         // STN_CLICKED = Static controls with SS_NOTIFY clicked
  391.                         // Both have the same ordinal number
  392.                         if(item==PREVIEWITEM && GetCursorPos(&origpos)){
  393.                                 panning = true;
  394.                                 origscroll = preview_scroll;
  395.                                 SetCursor(hCurHandGrab);
  396.                                 SetCapture(hDlg);
  397.                                 break;
  398.                         }
  399.                 /* ... falls through ... */
  400.                 case EN_CHANGE:
  401.                         if(doupdates && !maindlgitem(hDlg,item))
  402.                                 EndDialog(hDlg,item);
  403.                 }
  404.                 break;
  405. //      case WM_LBUTTONDOWN: break;
  406.         case WM_MOUSEMOVE:
  407.                 if(panning && GetCursorPos(&newpos)){
  408.                         newscroll.h = (int16)(origscroll.h - zoomfactor*((double)newpos.x - (double)origpos.x));
  409.                         newscroll.v = (int16)(origscroll.v - zoomfactor*((double)newpos.y - (double)origpos.y));
  410.                         if( newscroll.h != preview_scroll.h || newscroll.v != preview_scroll.v ){
  411.                                 preview_scroll = newscroll;
  412.                                 recalc_preview(gpb,hDlg);
  413.                         }
  414.                 }
  415.                 break;
  416.         case WM_LBUTTONUP:
  417.                 ReleaseCapture();
  418.                 panning = false;
  419.                 break;
  420.         case WM_HSCROLL:
  421.                 // Only for non-Plugin.dll-sliders
  422.                 item = GetDlgCtrlID((HWND)lParam);
  423.                 if(doupdates && !gdata->pluginDllSliderInfo.initialized && item>=FIRSTCTLITEM && item<=FIRSTCTLITEM+7)
  424.                         slidermoved(hDlg,item);
  425.                 break;
  426.         default:
  427.                 return false;
  428.         }
  429.  
  430.         return true;
  431. }
  432.  
  433. Boolean maindialog(FilterRecordPtr pb){
  434.         PlatformData *p;
  435.         INT_PTR res;
  436.  
  437.         // First try to use the sliders from PLUGIN.DLL (only Photoshop)
  438.         if (!Slider_Init_PluginDll(TEXT("FoundrySlider"))) {
  439.                 // If we couldn't get the sliders from PLUGIN.DLL (probably not running in Photoshop),
  440.                 // then try the Microsoft Trackbar Control instead
  441.                 if (!Slider_Init_MsTrackbar(TEXT("FoundrySlider"))) {
  442.                         // This will happen if we neither have PLUGIN.DLL, nor the Microsoft Trackbar Control (msctls_trackbar32).
  443.                         // "msctls_trackbar32" is not included in Windows NT 3.1, and since there is no OCX or RegSvr32.
  444.                         // It is included in Windows NT 3.5x.
  445.  
  446.                         //simplealert((TCHAR*)TEXT("This plugin requires Photoshop's PLUGIN.DLL or the Microsoft Trackbar Control (msctls_trackbar32) which was not found on your system."));
  447.                         //return false;
  448.  
  449.                         // We simply hide the sliders and let the user enter the numeric values in the edit-box.
  450.                         simplewarning_id(MSG_SLIDER_UNAVAILABLE_ID);
  451.                         Slider_Init_None(TEXT("FoundrySlider"));
  452.                 }
  453.         }
  454.  
  455.         // For the preview image and caution symbols, we register subclasses, so that we can assign a mouse cursor to this class.
  456.         MakeSimpleSubclass(TEXT("Preview"), WC_STATIC);
  457.         MakeSimpleSubclass(TEXT("Caution"), WC_BUTTON);
  458.  
  459.         // Now show the dialog
  460.         p = (PlatformData*)pb->platformData;
  461.  
  462.         // Note: "Invalid Cursor Handle" is the error when an unrecognized control class is detected
  463.         res = DialogBoxParam(hDllInstance,MAKEINTRESOURCE(gdata->standalone ? ID_PARAMDLG : ID_MAINDLG),
  464.                              (HWND)p->hwnd,maindlgproc,0);
  465.         if (res == 0) {
  466.                 simplealert((TCHAR*)TEXT("DialogBoxParam invalid parent window handle")); // TODO (Not so important): TRANSLATE
  467.         }
  468.         if (res == -1) {
  469.                 TCHAR s[0x300];
  470.                 xstrcpy(s, (TCHAR*)TEXT("DialogBoxParam failed: ")); // TODO (Not so important): TRANSLATE
  471.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
  472.                 simplealert(&s[0]);
  473.         }
  474.  
  475.         // Clean up after the dialog has been closed
  476.         UnregisterClass(TEXT("Preview"), hDllInstance);
  477.         UnregisterClass(TEXT("Caution"), hDllInstance);
  478.         UnregisterClass(TEXT("FoundrySlider"), hDllInstance);
  479.         Slider_Uninit_PluginDll();
  480.         Slider_Uninit_MsTrackbar();
  481.         Slider_Uninit_None();
  482.  
  483.         return res == IDOK;
  484. }
  485.