Subversion Repositories filter_foundry

Rev

Rev 417 | Rev 420 | 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. 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.         char text[1000];
  45.         char title[200];
  46.         PlatformData *p = (PlatformData*)pb->platformData;
  47.  
  48.         if (gdata && gdata->standalone) {
  49.                 sprintf(title, "About %s", gdata->parm.szTitle);
  50.                 sprintf(text,  "%s by %s\n" /* {Title} by {Author} */
  51.                                "%s\n" /* {Copyright} */
  52.                                "\n"
  53.                                "This plugin was built using Filter Foundry " VERSION_STR
  54.                                 #ifdef _WIN64
  55.                                " (64 bit)\n"
  56.                                 #else
  57.                                " (32 bit)\n"
  58.                                 #endif
  59.                                "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n"
  60.                                "available from " PROJECT_URL,
  61.                                gdata->parm.szTitle,
  62.                                gdata->parm.szAuthor,
  63.                                gdata->parm.szCopyright);
  64.         } else {
  65.                 sprintf(title, "About Filter Foundry");
  66.                 sprintf(text,  "Filter Foundry " VERSION_STR
  67.                                 #ifdef _WIN64
  68.                                " (64 bit)\n"
  69.                                 #else
  70.                                " (32 bit)\n"
  71.                                 #endif
  72.                                "(C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall\n"
  73.                                "\n"
  74.                                "Latest version available from\n"
  75.                                PROJECT_URL "\n"
  76.                                "\nPlease contact the author with any bug reports,\n"
  77.                                "suggestions or comments.\n"
  78.                                "If you use this program and like it, please consider\n"
  79.                                "making a donation.");
  80.         }
  81.  
  82.         MessageBox((HWND)p->hwnd, text, title, MB_TASKMODAL|MB_ICONINFORMATION|MB_OK);
  83. }
  84.  
  85. Boolean simplealert(char *s){
  86.         HWND hwnd;
  87.         char* title;
  88.         if (gdata && gdata->standalone) {
  89.                 title = gdata->parm.szTitle;
  90.         } else {
  91.                 title = _strdup("Filter Foundry");
  92.         }
  93.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  94.         return MessageBox(hwnd, s, title, MB_TASKMODAL|MB_ICONERROR|MB_OK) == IDOK;
  95. }
  96.  
  97. Boolean simplewarning(char* s) {
  98.         HWND hwnd;
  99.         char* title;
  100.         if (gdata && gdata->standalone) {
  101.                 title = gdata->parm.szTitle;
  102.         } else {
  103.                 title = _strdup("Filter Foundry");
  104.         }
  105.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  106.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONEXCLAMATION|MB_OK) == IDOK;
  107. }
  108.  
  109. Boolean showmessage(char *s) {
  110.         HWND hwnd;
  111.         char* title;
  112.         if (gdata && gdata->standalone) {
  113.                 title = gdata->parm.szTitle;
  114.         } else {
  115.                 title = _strdup("Filter Foundry");
  116.         }
  117.         hwnd = gdata ? gdata->hWndMainDlg : NULL;
  118.         return MessageBox(hwnd,s,title,MB_TASKMODAL|MB_ICONINFORMATION|MB_OK) == IDOK;
  119. }
  120.  
  121. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  122.  
  123. // Description:
  124. //   Creates a tooltip for an item in a dialog box.
  125. // Parameters:
  126. //   idTool - identifier of an dialog box item.
  127. //   nDlg - window handle of the dialog box.
  128. //   pszText - string to use as the tooltip text.
  129. // Returns:
  130. //   The handle to the tooltip.
  131. //
  132. HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText) {
  133.         // Source: https://docs.microsoft.com/en-us/windows/win32/controls/create-a-tooltip-for-a-control (modified)
  134.  
  135.         HWND hwndTool, hwndTip;
  136.         TOOLINFO toolInfo;
  137.  
  138.         if (!toolID || !hDlg || !pszText) {
  139.                 return FALSE;
  140.         }
  141.         // Get the window of the tool.
  142.         hwndTool = GetDlgItem(hDlg, toolID);
  143.  
  144.         // Create the tooltip. g_hInst is the global instance handle.
  145.         hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
  146.                 WS_POPUP | TTS_ALWAYSTIP /* | TTS_BALLOON*/,
  147.                 CW_USEDEFAULT, CW_USEDEFAULT,
  148.                 CW_USEDEFAULT, CW_USEDEFAULT,
  149.                 hDlg, NULL,
  150.                 hDllInstance, NULL);
  151.  
  152.         if (!hwndTool || !hwndTip) {
  153.                 return (HWND)NULL;
  154.         }
  155.  
  156.         // Associate the tooltip with the tool.
  157.         memset(&toolInfo, 0, sizeof(TOOLINFO)); // toolInfo = { 0 };
  158.         toolInfo.cbSize = sizeof(toolInfo);
  159.         toolInfo.hwnd = hDlg;
  160.         toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  161.         toolInfo.uId = (UINT_PTR)hwndTool;
  162.         toolInfo.lpszText = pszText;
  163.         SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
  164.  
  165.         return hwndTip;
  166. }
  167.  
  168. #ifndef IDC_HAND
  169. #define IDC_HAND            MAKEINTRESOURCE(32649)
  170. #endif
  171.  
  172. INT_PTR CALLBACK maindlgproc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam){
  173.         static POINT origpos;
  174.         static Point origscroll;
  175.         static Boolean panning = false;
  176.  
  177.         int item,i;
  178.         POINT newpos;
  179.         DRAWITEMSTRUCT *pdi;
  180.         Point newscroll;
  181.         HGDIOBJ hfnt;
  182.  
  183.         extern Boolean doupdates;
  184.         extern Handle preview_handle;
  185.  
  186.         switch (wMsg) {
  187.         case WM_INITDIALOG:
  188.                 gdata->hWndMainDlg = hDlg;
  189.  
  190.                 if(gdata->standalone){
  191.                         SetWindowText(hDlg,gdata->parm.szTitle); // window title bar
  192.                 }
  193.                 centre_window(hDlg);
  194.  
  195.                 hfnt = GetStockObject(ANSI_FIXED_FONT);
  196.  
  197.                 hCurHandOpen = LoadCursor(hDllInstance, "HAND_OPEN");
  198.                 hCurHandGrab = LoadCursor(hDllInstance, "HAND_GRAB");
  199.                 hCurHandQuestion = LoadCursor(hDllInstance, "HAND_QUESTION");
  200.  
  201.                 hIconCautionSign = LoadIcon(hDllInstance, "CAUTION_ICO");
  202.  
  203.                 // Note: The whole class "Preview" gets the mouse cursor, not just the single item!
  204.                 preview_hwnd = GetDlgItem(hDlg, PREVIEWITEM);
  205.                 GetClientRect(preview_hwnd, &preview_rect);
  206.                 SetClassLongPtr(preview_hwnd, GCLP_HCURSOR, (LONG_PTR)hCurHandOpen);
  207.  
  208.                 // Note: The whole class "Caution" gets the mouse cursor, not just the single item!
  209.                 SetClassLongPtr(GetDlgItem(hDlg, FIRSTICONITEM), GCLP_HCURSOR, (LONG_PTR)hCurHandQuestion);
  210.  
  211.                 for(i = 0; i < 4; ++i){
  212.                         CreateToolTip(FIRSTICONITEM + i, hDlg, _strdup("Error in expression! Click to see details."));
  213.                 }
  214.  
  215.                 CreateToolTip(ZOOMINITEM, hDlg, _strdup("Zoom in"));
  216.                 CreateToolTip(ZOOMOUTITEM, hDlg, _strdup("Zoom out"));
  217.                 CreateToolTip(ZOOMLEVELITEM, hDlg, _strdup("Fully zoom in/out"));
  218.  
  219.                 for(i = 0; i < 8; ++i){
  220.                         SendDlgItemMessage(hDlg,FIRSTCTLITEM+i,         TBM_SETRANGE,TRUE,MAKELONG(0,255));
  221.                         SendDlgItemMessage(hDlg,FIRSTCTLITEM+i,         TBM_SETTICFREQ,SLIDERPAGE,0);
  222.                         SendDlgItemMessage(hDlg,FIRSTCTLITEM+i,         TBM_SETPAGESIZE,0,SLIDERPAGE);
  223.                         SendDlgItemMessage(hDlg,FIRSTCTLTEXTITEM+i,     EM_SETLIMITTEXT,3,0);
  224.                 }
  225.                 for(i = 0; i < 4; ++i){
  226.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        EM_SETLIMITTEXT,MAXEXPR-1,0); // we need 1 byte as NUL terminator, so our formula can be max 1023
  227.                         SendDlgItemMessage(hDlg,FIRSTEXPRITEM+i,        WM_SETFONT,(WPARAM)hfnt,false);
  228.                 }
  229.  
  230.                 maindlginit(hDlg);
  231.                 break;
  232.         case WM_DESTROY:
  233.                 gdata->hWndMainDlg = 0;
  234.                 DestroyCursor(hCurHandOpen);
  235.                 DestroyCursor(hCurHandGrab);
  236.                 DestroyCursor(hCurHandQuestion);
  237.                 DestroyIcon(hIconCautionSign);
  238.                 break;
  239.         case WM_DRAWITEM:
  240.                 pdi = (DRAWITEMSTRUCT*)lParam;
  241.                 if(pdi->itemAction == ODA_DRAWENTIRE){
  242.                         switch(pdi->CtlID){
  243.                         case PREVIEWITEM:
  244.                                 drawpreview(hDlg,pdi->hDC,PILOCKHANDLE(preview_handle,false));
  245.                                 PIUNLOCKHANDLE(preview_handle);
  246.                                 break;
  247.                         case FIRSTICONITEM:
  248.                         case FIRSTICONITEM + 1:
  249.                         case FIRSTICONITEM + 2:
  250.                         case FIRSTICONITEM + 3:
  251.                                 DrawIcon(pdi->hDC, 0, 0, hIconCautionSign);
  252.                                 break;
  253.                         default:
  254.                                 return false;
  255.                         }
  256.                 }else
  257.                         return false; // we couldn't handle the message
  258.                 break;
  259.         case WM_COMMAND:
  260.                 item = LOWORD(wParam);
  261.                 switch(HIWORD(wParam)){
  262.                 //case BN_CLICKED:
  263.                 case STN_CLICKED:
  264.                         // BN_CLICKED = Button clicked
  265.                         // STN_CLICKED = Static controls with SS_NOTIFY clicked
  266.                         // Both have the same ordinal number
  267.                         if(item==PREVIEWITEM && GetCursorPos(&origpos)){
  268.                                 panning = true;
  269.                                 origscroll = preview_scroll;
  270.                                 SetCursor(hCurHandGrab);
  271.                                 SetCapture(hDlg);
  272.                                 break;
  273.                         }
  274.                 /* ... falls through ... */
  275.                 case EN_CHANGE:
  276.                         if(doupdates && !maindlgitem(hDlg,item))
  277.                                 EndDialog(hDlg,item);
  278.                 }
  279.                 break;
  280. //      case WM_LBUTTONDOWN: break;
  281.         case WM_MOUSEMOVE:
  282.                 if(panning && GetCursorPos(&newpos)){
  283.                         newscroll.h = (int16)(origscroll.h - zoomfactor*((double)newpos.x - (double)origpos.x));
  284.                         newscroll.v = (int16)(origscroll.v - zoomfactor*((double)newpos.y - (double)origpos.y));
  285.                         if( newscroll.h != preview_scroll.h || newscroll.v != preview_scroll.v ){
  286.                                 preview_scroll = newscroll;
  287.                                 recalc_preview(gpb,hDlg);
  288.                         }
  289.                 }
  290.                 break;
  291.         case WM_LBUTTONUP:
  292.                 ReleaseCapture();
  293.                 panning = false;
  294.                 break;
  295.         case WM_HSCROLL:
  296.                 item = GetDlgCtrlID((HWND)lParam);
  297.                 if(doupdates && item>=FIRSTCTLITEM && item<=FIRSTCTLITEM+7)
  298.                         slidermoved(hDlg,item);
  299.                 break;
  300.         default:
  301.                 return false;
  302.         }
  303.  
  304.         return true;
  305. }
  306.  
  307. Boolean maindialog(FilterRecordPtr pb){
  308.         PlatformData *p;
  309.         WNDCLASS clx;
  310.         INT_PTR res;
  311.  
  312.         // ALL Versions of Windows show the confusing error message "Invalid Cursor Handle" when DialogBoxParamA
  313.         // tries to open a dialog with a control which class is unknown.
  314.         // "msctls_trackbar32" is not included in Windows NT 3.1, and since there is no OCX or RegSvr32,
  315.         // there seems no possibility to support this version of Windows at this point.
  316.         if (GetClassInfo(hDllInstance, "msctls_trackbar32", &clx) == 0) {
  317.                 //simplealert(_strdup("This plugin requires the Microsoft Trackbar Control (msctls_trackbar32) which was not found on your system."));
  318.                 //return false;
  319.  
  320.                 // We simply hide the sliders and let the user enter the numeric values in the edit-box.
  321.                 // At least the plugin runs on Windows NT 3.1 !
  322.                 simplewarning(_strdup("Visual sliders are not available because the Microsoft Trackbar Control (msctls_trackbar32) was not found on your system."));
  323.                 GetClassInfo(hDllInstance, "STATIC", &clx);
  324.                 clx.lpszClassName = "msctls_trackbar32";
  325.                 if (RegisterClass(&clx) == 0) {
  326.                         char s[100];
  327.                         strcpy(s, "RegisterClass failed: ");
  328.                         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  329.                         dbg(s);
  330.                 }
  331.         }
  332.  
  333.         // For the preview image and caution symbols, we register a class, so that we can assign a mouse cursor to this class.
  334.         GetClassInfo(hDllInstance, "STATIC", &clx);
  335.         clx.lpszClassName = "Preview";
  336.         if (RegisterClass(&clx) == 0) {
  337.                 char s[100];
  338.                 strcpy(s, "RegisterClass failed: ");
  339.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  340.                 dbg(s);
  341.         }
  342.         GetClassInfo(hDllInstance, "Button", &clx);
  343.         clx.lpszClassName = "Caution";
  344.         if (RegisterClass(&clx) == 0) {
  345.                 char s[100];
  346.                 strcpy(s, "RegisterClass failed: ");
  347.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  348.                 dbg(s);
  349.         }
  350.  
  351.         // Now show the dialog
  352.         p = (PlatformData*)pb->platformData;
  353.  
  354.         // Note: "Invalid Cursor Handle" is the error when an unrecognized control class is detected
  355.         res = DialogBoxParam(hDllInstance,MAKEINTRESOURCE(gdata->standalone ? ID_PARAMDLG : ID_MAINDLG),
  356.                              (HWND)p->hwnd,maindlgproc,0);
  357.         if (res == 0) {
  358.                 simplealert(_strdup("DialogBoxParam in valid parent window handle"));
  359.         }
  360.         if (res == -1) {
  361.                 char s[100];
  362.                 strcpy(s, "DialogBoxParam failed: ");
  363.                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + strlen(s), 0x100, NULL);
  364.                 dbg(s);
  365.         }
  366.  
  367.         // Clean up after the dialog has been closed
  368.         UnregisterClass("Preview", hDllInstance);
  369.         UnregisterClass("Caution", hDllInstance);
  370.  
  371.         return res == IDOK;
  372. }
  373.  
  374.