home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / bmviewer.zip / CanvasWindow.c < prev    next >
Text File  |  2000-07-01  |  10KB  |  323 lines

  1. #pragma strings(readonly)
  2.  
  3. #define INCL_WINWINDOWMGR
  4. #define INCL_WINFRAMEMGR
  5. #define INCL_WINMESSAGEMGR
  6. #define INCL_WINSTDFILE
  7. #define INCL_WINPOINTERS
  8. #define INCL_WININPUT
  9. #define INCL_WINRECTANGLES
  10. #define INCL_WINDIALOGS
  11. #define INCL_DOSPROCESS
  12.  
  13. #include <os2.h>
  14.  
  15. #include <memory.h>
  16. #include <malloc.h>
  17. #include <string.h>
  18.  
  19. #ifdef DEBUG_TERM
  20. #include <stdio.h>
  21. #endif
  22.  
  23. #include "CanvasWindow.h"
  24. #include "WorkerThread.h"
  25.  
  26. #include "resources.h"
  27.  
  28.  
  29. typedef struct _WINDOWDATA
  30. {
  31.    HAB hab;
  32.    HMQ hmqWorker;
  33.    RECTL rclCanvas;                      /* Area of window comtaining the bitmap */
  34.    RECTL rclPixelBuffer;                 /* Area of pixelbuffer in canvas        */
  35.    HPOINTER hptrCrosshair;               /* Handle of crosshair pointer          */
  36.    int tidWorker;
  37. }WINDOWDATA, *PWINDOWDATA;
  38.  
  39.  
  40. static MRESULT EXPENTRY WindowProcedure(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  41.  
  42.  
  43.  
  44. BOOL _Optlink registerCanvasClass(HAB hab)
  45. {
  46.    BOOL fSuccess = FALSE;
  47.    LONG lLength = 0;
  48.    char achClass[256] = "";
  49.  
  50.    /*
  51.     * Load class name from file's resources
  52.     */
  53.    lLength = WinLoadString(hab, (HMODULE)NULLHANDLE, IDS_CANVASCLASS, sizeof(achClass), achClass);
  54.    if(lLength != 0L)
  55.    {
  56.       fSuccess = WinRegisterClass(hab, achClass, WindowProcedure, CS_SIZEREDRAW, sizeof(PWINDOWDATA));
  57.    }
  58.    return fSuccess;
  59. }
  60.  
  61.  
  62. static MRESULT EXPENTRY WindowProcedure(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  63. {
  64.    MRESULT mReturn = 0;
  65.    BOOL fHandled = TRUE;
  66.    RECTL rect;
  67.    HPS hps;
  68.    PWINDOWDATA wd = (PWINDOWDATA)WinQueryWindowPtr(hwnd, 0);
  69.    FILEDLG fdlg;
  70.  
  71.    switch(msg)
  72.    {
  73.       case WM_CREATE:
  74.          wd = malloc(sizeof(WINDOWDATA));
  75.          if(wd)
  76.          {
  77.             /* Clear window data buffer */
  78.             memset(wd, 0, sizeof(WINDOWDATA));
  79.  
  80.             wd->hab = WinQueryAnchorBlock(hwnd);
  81.             wd->tidWorker = -1;
  82.  
  83.             /* Load the crosshair pointer */
  84.             wd->hptrCrosshair = WinLoadPointer(HWND_DESKTOP, (HMODULE)NULLHANDLE, PTR_CROSSHAIR);
  85.  
  86.             /* Last - but not leat - store the window buffer pointer in the window data area */
  87.             WinSetWindowPtr(hwnd, 0, wd);
  88.          }
  89.          break;
  90.  
  91.       case WM_PAINT:
  92.          hps = WinBeginPaint(hwnd, NULLHANDLE, &rect);
  93.          if(hps)
  94.          {
  95.             if(wd->hmqWorker)
  96.             {
  97.                /*
  98.                 * Post a paint message to the worker thread; pass paint rectangle through the mp1 and mp2 paramters.
  99.                 */
  100.                if(!WinPostQueueMsg(wd->hmqWorker, WM_PAINT, MPFROM2SHORT((SHORT)rect.xLeft, (SHORT)rect.yBottom), MPFROM2SHORT((SHORT)rect.xRight, (SHORT)rect.yTop)))
  101.                {
  102.                   #ifdef DEBUG_TERM
  103.                   puts("e WinPostQueue() for WM_PAINT failed.");
  104.                   #endif
  105.                }
  106.             }
  107.             else
  108.             {
  109.                /*
  110.                 * In the event that the worker thread hasn't been initialized
  111.                 * by the time this window recieves a paint request, just fill with pale gray.
  112.                 */
  113.                WinFillRect(hps, &rect, CLR_PALEGRAY);
  114.             }
  115.             WinEndPaint(hps);
  116.          }
  117.          break;
  118.  
  119.       case WM_SIZE:
  120.       case WM_HSCROLL:
  121.       case WM_VSCROLL:
  122.          if(wd->hmqWorker)
  123.          {
  124.             WinPostQueueMsg(wd->hmqWorker, msg, mp1, mp2);
  125.          }
  126.          break;
  127.  
  128.  
  129.       case WM_COMMAND:
  130.          /*
  131.           * Note: since all menuitems are disabled until worker thread is launched, no need to check
  132.           * if the worker thread has been initialized. If we get to any point which required the worker thread
  133.           * it should have been initialized.
  134.           */
  135.          switch(SHORT1FROMMP(mp1))
  136.          {
  137.             case IDM_FILE_LOAD:
  138.                memset(&fdlg, 0, sizeof(fdlg));
  139.                fdlg.cbSize = sizeof(fdlg);
  140.                fdlg.fl = FDS_CENTER | FDS_OPEN_DIALOG;
  141.                memcpy(fdlg.szFullFile, "*.bmp", 6);
  142.                if(WinFileDlg(HWND_DESKTOP, hwnd, &fdlg) != NULLHANDLE)
  143.                {
  144.                   if(fdlg.lReturn == DID_OK)
  145.                   {
  146.                      LONG len = strlen(fdlg.szFullFile)+1;
  147.                      char *tmp = malloc(len);
  148.                      memcpy(tmp, fdlg.szFullFile, len);
  149.                      WinPostQueueMsg(wd->hmqWorker, WTMSG_LOAD_BITMAP, (MPARAM)tmp, MPVOID);
  150.                   }
  151.                }
  152.                break;
  153.  
  154.             case IDM_OPT_ALIGN_HORZ_LEFT:
  155.             case IDM_OPT_ALIGN_HORZ_CENTER:
  156.             case IDM_OPT_ALIGN_HORZ_RIGHT:
  157.             case IDM_OPT_ALIGN_VERT_BOTTOM:
  158.             case IDM_OPT_ALIGN_VERT_CENTER:
  159.             case IDM_OPT_ALIGN_VERT_TOP:
  160.                WinPostQueueMsg(wd->hmqWorker, WM_COMMAND, mp1, mp2);
  161.                break;
  162.  
  163.  
  164.             default:
  165.                fHandled = FALSE;
  166.                break;
  167.          }
  168.          break;
  169.  
  170.       case WM_MOUSEMOVE:
  171.          if(wd->hmqWorker)
  172.          {
  173.             POINTL ptlMouse = { SHORT1FROMMP(mp1), SHORT2FROMMP(mp1) };
  174.  
  175.  
  176.             /*
  177.              * Check if the pointer is within the canvas area
  178.              */
  179.             if(WinPtInRect(wd->hab, &wd->rclCanvas, &ptlMouse))
  180.             {
  181.                /*
  182.                 * Pointer is within canvas area, set appropriate pointer
  183.                 */
  184.                WinSetPointer(HWND_DESKTOP, wd->hptrCrosshair);
  185.                if(wd->rclCanvas.xLeft || wd->rclCanvas.yBottom)
  186.                {
  187.                   mp1 = MPFROM2SHORT(SHORT1FROMMP(mp1)-wd->rclCanvas.xLeft, SHORT2FROMMP(mp1)-wd->rclCanvas.yBottom);
  188.                }
  189.                mp1 = MPFROM2SHORT(SHORT1FROMMP(mp1)+wd->rclPixelBuffer.xLeft, SHORT2FROMMP(mp1)+wd->rclPixelBuffer.yBottom);
  190.                if(!WinPostQueueMsg(wd->hmqWorker, WM_MOUSEMOVE, mp1, mp2))
  191.                {
  192.                   #ifdef DEBUG_TERM
  193.                   printf("e WinPostQueueMsg(%08x,%08x,%08x,%08x) failed in %s -> %s.\n", wd->hmqWorker, msg, mp1, mp2, __FILE__, __FUNCTION__);
  194.                   #endif
  195.                }
  196.             }
  197.             else
  198.             {
  199.                /*
  200.                 * Pointer is within window, but not within canvas area; call
  201.                 * default window procedure to get system default pointer.
  202.                 */
  203.                return WinDefWindowProc(hwnd, WM_MOUSEMOVE, mp1, mp2);
  204.             }
  205.          }
  206.          else
  207.          {
  208.             return WinDefWindowProc(hwnd, WM_MOUSEMOVE, mp1, mp2);
  209.          }
  210.          break;
  211.  
  212.  
  213.       case WM_CLOSE:
  214.          if(wd->hmqWorker)
  215.          {
  216.             /*
  217.              * Make the worker thread quit its message queue. When it does, it will clean up all it's data and
  218.              * then post a quit message to this thread, making this thread terminate.
  219.              */
  220.             while(!WinPostQueueMsg(wd->hmqWorker, WM_QUIT, MPVOID, MPVOID))
  221.             {
  222.                LONG lLength = 0;
  223.                char achTitle[40] = "";
  224.  
  225.                lLength = WinLoadString(wd->hab, (HMODULE)NULLHANDLE, IDS_POSTWRKRERRORTITLE, sizeof(achTitle), achTitle);
  226.                if(lLength != 0)
  227.                {
  228.                   char achMessage[256] = "";
  229.  
  230.                   lLength = WinLoadMessage(wd->hab, (HMODULE)NULLHANDLE, IDMSG_POSTQUITMSGFAILED, sizeof(achMessage), achMessage);
  231.                   if(lLength != 0)
  232.                   {
  233.                      ULONG usResponse = 0;
  234.                      usResponse = WinMessageBox(HWND_DESKTOP, hwnd, achMessage, achTitle, IDMSGBOX_POSTQUITERROR, MB_ABORTRETRYIGNORE | MB_ERROR | MB_DEFBUTTON2 | MB_APPLMODAL);
  235.                      if(usResponse == MBID_YES)
  236.                      {
  237.                         /* Kill thread */
  238.                         DosKillThread(wd->tidWorker);
  239.                         WinPostMsg(hwnd, WM_QUIT, MPVOID, MPVOID);
  240.                      }
  241.                      else if(usResponse == MBID_NO)
  242.                      {
  243.                         /* Break out of loop */
  244.                         break;
  245.                      }
  246.                      else
  247.                      {
  248.                         /* If forced termination wasn't requested and user ddoesn't wish to try
  249.                            again, break out of while loop */
  250.                         continue;
  251.                      }
  252.                   }
  253.                }
  254.             }
  255.          }
  256.          else
  257.          {
  258.             /*
  259.              * No worker thread has been initialized; just terminate this thread.
  260.              */
  261.             WinPostMsg(hwnd, WM_QUIT, MPVOID, MPVOID);
  262.          }
  263.          break;
  264.  
  265.       case WM_TRACKFRAME:
  266.          /*
  267.           * This message is sent here by the frame SubProc, it should just be redirected to the worker thread.
  268.           * TODO: Give the frame window the hmqWorker so it can do this by itself.
  269.           */
  270.          if(wd->hmqWorker)
  271.          {
  272.             WinPostQueueMsg(wd->hmqWorker, WM_TRACKFRAME, mp1, MPVOID);
  273.          }
  274.          break;
  275.  
  276.       case WM_DESTROY:
  277.          WinDestroyPointer(wd->hptrCrosshair);
  278.          /*
  279.           * Release window data buffer
  280.           */
  281.          free(wd);
  282.          break;
  283.  
  284.       case WMU_SET_CANVAS_RECT:
  285.          memcpy(&wd->rclCanvas, mp1, sizeof(RECTL));
  286.          break;
  287.  
  288.       case WMU_SET_PB_RECT:
  289.          memcpy(&wd->rclPixelBuffer, mp1, sizeof(RECTL));
  290.          break;
  291.  
  292.       case WMU_SET_VISIBILITY_RECTS:
  293.          memcpy(&wd->rclCanvas, mp1, sizeof(RECTL));
  294.          memcpy(&wd->rclPixelBuffer, mp2, sizeof(RECTL));
  295.          break;
  296.  
  297.       case WMU_CANVAS_NOTIFICATION:
  298.          switch(LONGFROMMP(mp1))
  299.          {
  300.             case WORKERTHREAD_TID:
  301.                wd->tidWorker = LONGFROMMP(mp2);
  302.                break;
  303.  
  304.             case WORKERTHREAD_HMQ:
  305.                wd->hmqWorker = LONGFROMMP(mp2);
  306.                #ifdef DEBUG_TERM
  307.                printf("i CanvasWindow got hmqWorker: %08x\n", wd->hmqWorker);
  308.                #endif
  309.                break;
  310.          }
  311.          break;
  312.  
  313.       default:
  314.          fHandled = FALSE;
  315.          break;
  316.    }
  317.    if(!fHandled)
  318.    {
  319.       mReturn = WinDefWindowProc(hwnd, msg, mp1, mp2);
  320.    }
  321.    return mReturn;
  322. }
  323.