home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / primcuts.zip / FrameWindowTricks / ClientWindow.c next >
Text File  |  2000-07-19  |  20KB  |  660 lines

  1. #pragma strings(readonly)
  2.  
  3. #define INCL_WINWINDOWMGR
  4. #define INCL_WINFRAMEMGR
  5. #define INCL_WINTRACKRECT
  6. #define INCL_WINSYS
  7. #define INCL_WININPUT
  8. #define INCL_WINSCROLLBARS
  9. #define INCL_WINTIMER
  10. #define INCL_WINRECTANGLES
  11. #define INCL_WINPOINTERS
  12. #define INCL_GPILOGCOLORTABLE
  13.  
  14. #include <os2.h>
  15.  
  16. #include <malloc.h>
  17. #include <memory.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20.  
  21. #include "ClientWindow.h"
  22. #include "StatusbarWindow.h"
  23.  
  24.  
  25. #define MAPCX  25
  26. #define MAPCY  25
  27. #define SQCX   32
  28. #define SQCY   32
  29.  
  30.  
  31.  
  32.  
  33. typedef struct MAPCELL
  34. {
  35.    LONG lColor;
  36. }MAPCELL, *PMAPCELL;
  37.  
  38. typedef struct _WINDOWDATA
  39. {
  40.    HAB hab;
  41.    POINTL ptlCursor;
  42.    SIZEL sizlWindow;
  43.    MAPCELL map[MAPCY][MAPCX];
  44.    HWND hwndStatusbar;
  45.    LONG lHorzScroll;
  46.    LONG lVertScroll;
  47.    HWND hwndVertScroll;
  48.    HWND hwndHorzScroll;
  49.    BOOL fShowCursor;
  50.    USHORT fsLastFrameTrack;
  51. }WINDOWDATA, *PWINDOWDATA;
  52.  
  53.  
  54.  
  55. typedef struct _FRAMESUBPROCPARAMS
  56. {
  57.    PFNWP pfnOldProc;
  58.    ULONG ulMaxWidth;                     /* Maximum width of frame  */
  59.    ULONG ulMaxHeight;                    /* Maximum height of frame */
  60.    LONG cyStatusBar;
  61.    LONG cyScrollBar;
  62.    SIZEL sizlCell;                       /* Cell size            */
  63.    HWND hwndClient;                      /* Client window handle */
  64.    HWND hwndVertScroll;
  65.    HWND hwndHorzScroll;
  66. }FRAMESUBPROCPARAMS, *PFRAMESUBPROCPARAMS;
  67.  
  68.  
  69. #define TID_CHECK_CURSOR                 10
  70.  
  71.  
  72.  
  73. static MRESULT EXPENTRY WindowProcedure(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  74.  
  75. void _Inline invalidate_square(HWND hwnd, PWINDOWDATA wd, PPOINTL ptl);
  76.  
  77. static MRESULT EXPENTRY FrameSubProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  78.  
  79.  
  80.  
  81. #define WMU_MAX_CLIENT_SIZE              WM_USER+1
  82.  
  83.  
  84. BOOL _Optlink registerClientWindow(HAB hab)
  85. {
  86.    return WinRegisterClass(hab, WC_APPCLIENTCLASS, WindowProcedure, CS_CLIPCHILDREN | CS_SIZEREDRAW, sizeof(PWINDOWDATA));
  87. }
  88.  
  89.  
  90. static MRESULT EXPENTRY WindowProcedure(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  91. {
  92.    MRESULT mReturn = 0;
  93.    BOOL fHandled = TRUE;
  94.    PWINDOWDATA wd = (PWINDOWDATA)WinQueryWindowPtr(hwnd, 0);
  95.    HPS hps;
  96.    RECTL rect;
  97.    SHORT scxold;
  98.    SHORT scyold;
  99.    SHORT scxnew;
  100.    SHORT scynew;
  101.    POINTL ptl;
  102.    USHORT usidentifier;
  103.    SHORT sslider;
  104.    USHORT uscmd;
  105.  
  106.    switch(msg)
  107.    {
  108.       case WM_CREATE:
  109.          wd = (PWINDOWDATA)malloc(sizeof(WINDOWDATA));
  110.          if(wd)
  111.          {
  112.             HWND hwndFrame = WinQueryWindow(hwnd, QW_PARENT);
  113.             PFRAMESUBPROCPARAMS fspp = NULL;
  114.             POINTL p = { 0, 0 };
  115.             HAB hab = WinQueryAnchorBlock(hwnd);
  116.  
  117.             memset(wd, 0, sizeof(WINDOWDATA));
  118.  
  119.             wd->hab = hab;
  120.             wd->hwndStatusbar = WinWindowFromID(hwndFrame, FID_STATUSBAR);
  121.             wd->hwndHorzScroll = WinWindowFromID(hwndFrame, FID_HORZSCROLL);
  122.             wd->hwndVertScroll = WinWindowFromID(hwndFrame, FID_VERTSCROLL);
  123.  
  124.             /*
  125.              * Set up initial map
  126.              */
  127.             for(p.y = 0; p.y < MAPCY; p.y++)
  128.             {
  129.                for(p.x = 0; p.x < MAPCX; p.x++)
  130.                {
  131.                   wd->map[p.y][p.x].lColor = ((p.x*8)<<16)+(p.y*8);
  132.                }
  133.             }
  134.  
  135.             /*
  136.              * Calculate client window size from frame window
  137.              */
  138.             WinQueryWindowRect(hwnd, &rect);
  139.             wd->sizlWindow.cx = rect.xRight-rect.xLeft;
  140.             wd->sizlWindow.cy = rect.yTop-rect.yBottom;
  141.  
  142.             sslider = 0;
  143.             wd->lHorzScroll = sslider;
  144.             WinSendMsg(wd->hwndHorzScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(wd->sizlWindow.cx, MAPCX*SQCX), MPVOID);
  145.             WinSendMsg(wd->hwndHorzScroll, SBM_SETSCROLLBAR, MPFROMSHORT(sslider), MPFROM2SHORT(0, MAPCX*SQCX-wd->sizlWindow.cx));
  146.  
  147.             sslider = MAPCY*SQCY;
  148.             wd->lVertScroll = MAPCY*SQCY-sslider;
  149.             WinSendMsg(wd->hwndVertScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(wd->sizlWindow.cy, MAPCY*SQCY), MPVOID);
  150.             WinSendMsg(wd->hwndVertScroll, SBM_SETSCROLLBAR, MPFROMSHORT(sslider), MPFROM2SHORT(wd->sizlWindow.cy, MAPCY*SQCY));
  151.  
  152.             /*
  153.              * Sub allocate frame window
  154.              */
  155.             fspp = (PFRAMESUBPROCPARAMS)malloc(sizeof(FRAMESUBPROCPARAMS));
  156.             if(fspp)
  157.             {
  158.                memset(fspp, 0, sizeof(FRAMESUBPROCPARAMS));
  159.  
  160.                WinSetWindowULong(hwndFrame, QWL_USER, (ULONG)fspp);
  161.  
  162.                fspp->cyStatusBar = WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR);
  163.                fspp->cyScrollBar = WinQuerySysValue(HWND_DESKTOP, SV_CYHSCROLL);
  164.                fspp->pfnOldProc = WinSubclassWindow(hwndFrame, FrameSubProc);
  165.                fspp->sizlCell.cx = SQCX;
  166.                fspp->sizlCell.cy = SQCY;
  167.                fspp->hwndClient = hwnd;
  168.                if(fspp->pfnOldProc == 0L)
  169.                {
  170.                   free(fspp);
  171.                }
  172.                else
  173.                {
  174.                   /*
  175.                    * Maximum size of frame from max client size
  176.                    * This needs to be done _after_ subproc. is done since
  177.                    * the subproc. hadles the WM_CALCFRAMERECT message.
  178.                    */
  179.                   WinSendMsg(hwndFrame, WMU_MAX_CLIENT_SIZE, MPFROMLONG(MAPCX*SQCX), MPFROMLONG(MAPCY*SQCY));
  180.                }
  181.             }
  182.  
  183.             WinStartTimer(hab, hwnd, TID_CHECK_CURSOR, 100);
  184.  
  185.             WinSetWindowPtr(hwnd, 0, wd);
  186.  
  187.             mReturn = (MRESULT)FALSE;
  188.          }
  189.          break;
  190.  
  191.       case WM_PAINT:
  192.          hps = WinBeginPaint(hwnd, NULLHANDLE, &rect);
  193.          if(hps)
  194.          {
  195.             RECTL rclMap = { rect.xLeft+wd->lHorzScroll,
  196.                              rect.yBottom+wd->lVertScroll,
  197.                              rect.xRight+wd->lHorzScroll,
  198.                              rect.yTop+wd->lVertScroll };
  199.             LONG xSquareMin = rclMap.xLeft / SQCX;
  200.             LONG xSquareMax = rclMap.xRight / SQCX;
  201.             LONG ySquareMin = rclMap.yBottom / SQCY;
  202.             LONG ySquareMax = rclMap.yTop / SQCY;
  203.             POINTL p = { 0, 0 };
  204.  
  205.             GpiCreateLogColorTable(hps, LCOL_RESET, LCOLF_RGB, 0UL, 0UL, NULL);
  206.  
  207.             if(rclMap.xRight % SQCX)
  208.             {
  209.                xSquareMax++;
  210.             }
  211.             if(rclMap.yTop % SQCY)
  212.             {
  213.                ySquareMax++;
  214.             }
  215.  
  216.             for(p.y = ySquareMin; p.y < ySquareMax; p.y++)
  217.             {
  218.                for(p.x = xSquareMin; p.x < xSquareMax; p.x++)
  219.                {
  220.                   RECTL rclPaint = { p.x*SQCX-wd->lHorzScroll,
  221.                                      p.y*SQCY-wd->lVertScroll,
  222.                                      rclPaint.xLeft+SQCX,
  223.                                      rclPaint.yBottom+SQCY };
  224.  
  225.                   WinFillRect(hps, &rclPaint, wd->map[p.y][p.x].lColor);
  226.  
  227.                   if(p.x == wd->ptlCursor.x && p.y == wd->ptlCursor.y && wd->fShowCursor)
  228.                   {
  229.                      POINTL ptl = { rclPaint.xLeft, rclPaint.yBottom };
  230.  
  231.                      GpiSetColor(hps, 0x0011ffff);
  232.  
  233.                      GpiMove(hps, &ptl);
  234.                      ptl.x = rclPaint.xRight-1;
  235.                      ptl.y = rclPaint.yTop-1;
  236.                      GpiBox(hps, DRO_OUTLINE, &ptl, 20, 20);
  237.                   }
  238.                }
  239.             }
  240.             WinEndPaint(hps);
  241.          }
  242.          break;
  243.  
  244.       case WM_SIZE:
  245.          scxold = SHORT1FROMMP(mp1);
  246.          scyold = SHORT2FROMMP(mp1);
  247.          scxnew = SHORT1FROMMP(mp2);
  248.          scynew = SHORT2FROMMP(mp2);
  249.  
  250.          if(scxnew != scxold)
  251.          {
  252.             sslider = (SHORT)WinSendMsg(wd->hwndHorzScroll, SBM_QUERYPOS, MPVOID, MPVOID);
  253.  
  254.             wd->sizlWindow.cx = scxnew;
  255.  
  256.             /*
  257.              * Exclude any frame movements and make sure left frame border was tracked
  258.              */
  259.             if((wd->fsLastFrameTrack ^ TF_MOVE) && (wd->fsLastFrameTrack & TF_LEFT))
  260.             {
  261.                if(scxnew < scxold)
  262.                {
  263.                   /*
  264.                    * Window is shrinking horizontally
  265.                    */
  266.                   sslider += (scxold-scxnew);
  267.                }
  268.                else
  269.                {
  270.                   /*
  271.                    * Window is growing horizontally
  272.                    */
  273.                   sslider -= (scxnew-scxold);
  274.                }
  275.             }
  276.  
  277.             sslider = min((MAPCX*SQCX)-scxnew, sslider);
  278.             sslider = max(0, sslider);
  279.             wd->lHorzScroll = sslider;
  280.  
  281.             WinSendMsg(wd->hwndHorzScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(scxnew, MAPCX*SQCX), MPVOID);
  282.             WinSendMsg(wd->hwndHorzScroll, SBM_SETSCROLLBAR, (MPARAM)sslider, MPFROM2SHORT(0, MAPCX*SQCX-scxnew));
  283.          }
  284.  
  285.          if(scynew != scyold)
  286.          {
  287.             sslider = (SHORT)WinSendMsg(wd->hwndVertScroll, SBM_QUERYPOS, MPVOID, MPVOID);
  288.  
  289.             wd->sizlWindow.cy = scynew;
  290.  
  291.             if((wd->fsLastFrameTrack ^ TF_MOVE) && (wd->fsLastFrameTrack & TF_BOTTOM))
  292.             {
  293.                if(scynew < scyold)
  294.                {
  295.                   /*
  296.                    * Window is shrinking vertically
  297.                    */
  298.                   sslider -= (scyold-scynew);
  299.                }
  300.                else
  301.                {
  302.                   /*
  303.                    * Window is growing vertically
  304.                    */
  305.                   sslider += (scynew-scyold);
  306.                }
  307.             }
  308.  
  309.             /*
  310.              * Make sure no visible part of map is out of bound
  311.              */
  312.             sslider = min(MAPCY*SQCY, sslider);
  313.             sslider = max(scynew, sslider);
  314.             wd->lVertScroll = (MAPCY*SQCY)-sslider;
  315.  
  316.             WinSendMsg(wd->hwndVertScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(scynew, MAPCY*SQCY), MPVOID);
  317.             WinSendMsg(wd->hwndVertScroll, SBM_SETSCROLLBAR, (MPARAM)sslider, MPFROM2SHORT(scynew, MAPCY*SQCY));
  318.          }
  319.  
  320.          wd->fsLastFrameTrack  = 0;
  321.          break;
  322.  
  323.       case WM_HSCROLL:
  324.          usidentifier = SHORT1FROMMP(mp1);
  325.          sslider = SHORT1FROMMP(mp2);
  326.          uscmd = SHORT2FROMMP(mp2);
  327.  
  328.          switch(uscmd)
  329.          {
  330.             case SB_SLIDERTRACK:
  331.                wd->lHorzScroll = sslider;
  332.                WinSendMsg(wd->hwndHorzScroll, SBM_SETPOS, MPFROMSHORT(sslider), MPVOID);
  333.                WinInvalidateRect(hwnd, NULL, FALSE);
  334.                break;
  335.          }
  336.          break;
  337.  
  338.       case WM_VSCROLL:
  339.          usidentifier = SHORT1FROMMP(mp1);
  340.          sslider = SHORT1FROMMP(mp2);
  341.          uscmd = SHORT2FROMMP(mp2);
  342.  
  343.          switch(uscmd)
  344.          {
  345.             case SB_SLIDERTRACK:
  346.                wd->lVertScroll = (MAPCY*SQCY)-sslider;
  347.                WinSendMsg(wd->hwndVertScroll, SBM_SETPOS, MPFROMSHORT(sslider), MPVOID);
  348.                WinInvalidateRect(hwnd, NULL, FALSE);
  349.                break;
  350.          }
  351.          break;
  352.  
  353.       case WM_MOUSEMOVE:
  354.          ptl.x = (SHORT1FROMMP(mp1)+wd->lHorzScroll)/SQCX;
  355.          ptl.y = (SHORT2FROMMP(mp1)+wd->lVertScroll)/SQCY;
  356.          if(memcmp(&ptl, &wd->ptlCursor, sizeof(POINTL)) != 0)
  357.          {
  358.             char buf[256] = "";
  359.  
  360.             wd->fShowCursor = TRUE;
  361.  
  362.             invalidate_square(hwnd, wd, &wd->ptlCursor);
  363.  
  364.             memcpy(&wd->ptlCursor, &ptl, sizeof(POINTL));
  365.  
  366.             invalidate_square(hwnd, wd, &wd->ptlCursor);
  367.  
  368.             sprintf(buf, "New position (%d,%d)", ptl.x+1, ptl.y+1);
  369.             WinSetWindowText(wd->hwndStatusbar, buf);
  370.          }
  371.          fHandled = FALSE;
  372.          break;
  373.  
  374.       case WM_BUTTON1CLICK:
  375.          {
  376.             PPOINTS pts = (PPOINTS)&mp1; /* Not used here */
  377.             char buf[256] = "";
  378.  
  379.             wd->map[wd->ptlCursor.y][wd->ptlCursor.x].lColor = ((rand()%0xff)<<16) | ((rand()%0xff)<<8) | (rand()%0xff);
  380.  
  381.             invalidate_square(hwnd, wd, &wd->ptlCursor);
  382.  
  383.             sprintf(buf, "Color changed to 0x%08x at (%d,%d)", wd->map[wd->ptlCursor.y][wd->ptlCursor.x].lColor, wd->ptlCursor.x+1, wd->ptlCursor.y+1);
  384.             WinSetWindowText(wd->hwndStatusbar, buf);
  385.  
  386.             mReturn = (MRESULT)TRUE;
  387.          }
  388.          break;
  389.  
  390.       case WM_TIMER:
  391.          switch(SHORT1FROMMP(mp1))
  392.          {
  393.             case TID_CHECK_CURSOR:
  394.                WinQueryPointerPos(HWND_DESKTOP, &ptl);
  395.  
  396.                WinMapWindowPoints(HWND_DESKTOP, hwnd, &ptl, 1);
  397.  
  398.                WinQueryWindowRect(hwnd, &rect);
  399.                if(WinPtInRect(wd->hab, &rect, &ptl))
  400.                {
  401.                   if(wd->fShowCursor == FALSE)
  402.                   {
  403.                      wd->fShowCursor = TRUE;
  404.                      invalidate_square(hwnd, wd, &wd->ptlCursor);
  405.                   }
  406.                }
  407.                else
  408.                {
  409.                   if(wd->fShowCursor == TRUE)
  410.                   {
  411.                      wd->fShowCursor = FALSE;
  412.                      invalidate_square(hwnd, wd, &wd->ptlCursor);
  413.                   }
  414.                }
  415.                break;
  416.  
  417.             default:
  418.                fHandled = FALSE;
  419.                break;
  420.          }
  421.          break;
  422.  
  423.       case WM_TRACKFRAME:
  424.          /*
  425.           * Keep track of which part of the frame is being tracked; this way certain
  426.           * estetic adjustments can be made
  427.           */
  428.          #ifdef DEBUG_TERM
  429.          puts("i Client window WM_TRACKFRAME");
  430.          #endif
  431.          wd->fsLastFrameTrack = (SHORT1FROMMP(mp1) & TF_MOVE);
  432.          break;
  433.  
  434.       case WM_DESTROY:
  435.          WinStopTimer(wd->hab, hwnd, TID_CHECK_CURSOR);
  436.          free(wd);
  437.          break;
  438.  
  439.       default:
  440.          fHandled = FALSE;
  441.          break;
  442.    }
  443.    if(!fHandled)
  444.    {
  445.       mReturn = WinDefWindowProc(hwnd, msg, mp1, mp2);
  446.    }
  447.    return mReturn;
  448. }
  449.  
  450. void _Inline invalidate_square(HWND hwnd, PWINDOWDATA wd, PPOINTL ptl)
  451. {
  452.    RECTL r = { ptl->x*SQCX-wd->lHorzScroll, ptl->y*SQCY-wd->lVertScroll, r.xLeft+SQCX, r.yBottom+SQCY };
  453.  
  454.    WinInvalidateRect(hwnd, &r, FALSE);
  455. }
  456.  
  457.  
  458.  
  459.  
  460. static MRESULT EXPENTRY FrameSubProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  461. {
  462.    MRESULT mReturn = 0;
  463.    BOOL fHandled = TRUE;
  464.    PFRAMESUBPROCPARAMS wd = (PFRAMESUBPROCPARAMS)(ULONG)WinQueryWindowULong(hwnd, QWL_USER);
  465.    PTRACKINFO pti;
  466.    SHORT cControls;
  467.    PSWP pswp;
  468.    RECTL rect;
  469.  
  470.    switch(msg)
  471.    {
  472.       case WM_CALCFRAMERECT:
  473.          mReturn = (*wd->pfnOldProc)(hwnd, msg, mp1, mp2);
  474.          if(mReturn)
  475.          {
  476.             PRECTL pRect;
  477.  
  478.             if(SHORT1FROMMP(mp2))
  479.             {
  480.                pRect = (PRECTL)mp1;
  481.                pRect->yBottom += wd->cyStatusBar;
  482.                mReturn = (MRESULT)TRUE;
  483.             }
  484.             else
  485.             {
  486.                pRect = (PRECTL)mp1;
  487.                pRect->yBottom -= wd->cyStatusBar;
  488.                mReturn = (MRESULT)TRUE;
  489.             }
  490.          }
  491.          break;
  492.  
  493.       case WM_QUERYFRAMECTLCOUNT:
  494.          cControls = SHORT1FROMMR((*wd->pfnOldProc)(hwnd, msg, mp1, mp2));
  495.          return ((MRESULT)(cControls+1));
  496.  
  497.       case WM_FORMATFRAME:
  498.          {
  499.             USHORT iClient = 0;
  500.             USHORT iStatusBar = 0;
  501.             USHORT iHorzScroll = 0;
  502.             USHORT iVertScroll = 0;
  503.             PSWP swp = (PSWP)mp1;
  504.  
  505.             cControls = SHORT1FROMMR((*wd->pfnOldProc)(hwnd, WM_FORMATFRAME, mp1, mp2));
  506.  
  507.             iClient = cControls-1;
  508.  
  509.             while(swp[iHorzScroll].hwnd != WinWindowFromID(hwnd, FID_HORZSCROLL))
  510.             {
  511.                iHorzScroll++;
  512.             }
  513.  
  514.             while(swp[iVertScroll].hwnd != WinWindowFromID(hwnd, FID_VERTSCROLL))
  515.             {
  516.                iVertScroll++;
  517.             }
  518.  
  519.             iStatusBar = cControls;
  520.  
  521.             swp[iStatusBar].hwnd = WinWindowFromID(hwnd, FID_STATUSBAR);
  522.             swp[iStatusBar].x = swp[iClient].x;
  523.             swp[iStatusBar].cx = swp[iClient].cx + swp[iVertScroll].cx;
  524.             swp[iStatusBar].y = swp[iHorzScroll].y;
  525.             swp[iStatusBar].cy = wd->cyStatusBar;
  526.             swp[iStatusBar].fl = SWP_SHOW | SWP_MOVE | SWP_SIZE;
  527.  
  528.             swp[iHorzScroll].y += wd->cyStatusBar;
  529.  
  530.             swp[iVertScroll].y += wd->cyStatusBar;
  531.             swp[iVertScroll].cy -= wd->cyStatusBar;
  532.  
  533.             swp[iClient].y += wd->cyStatusBar;
  534.             swp[iClient].cy -= wd->cyStatusBar;
  535.  
  536.             mReturn = MRFROMSHORT(cControls+1);
  537.          }
  538.          break;
  539.  
  540.       case WM_QUERYTRACKINFO:
  541.          pti = (PTRACKINFO)mp2;
  542.          mReturn = (*wd->pfnOldProc)(hwnd, WM_QUERYTRACKINFO, mp1, mp2);
  543.  
  544.          /*
  545.           * Exclude move operations
  546.           *
  547.           * NOTE: Because of griding, window can not be set to maximum size(!)
  548.           *       FIX IT!
  549.           */
  550.          if((pti->fs & TF_MOVE) ^ TF_MOVE)
  551.          {
  552.             pti->fs |= TF_GRID;
  553.  
  554.             if(pti->fs & (TF_LEFT | TF_RIGHT))
  555.             {
  556.                pti->cxGrid = wd->sizlCell.cx;
  557.             }
  558.             if(pti->fs & (TF_TOP | TF_BOTTOM))
  559.             {
  560.                pti->cyGrid = wd->sizlCell.cy;
  561.             }
  562.          }
  563.  
  564.          if(wd->ulMaxWidth)
  565.          {
  566.             pti->ptlMaxTrackSize.x = wd->ulMaxWidth;
  567.          }
  568.          if(wd->ulMaxHeight)
  569.          {
  570.             pti->ptlMaxTrackSize.y = wd->ulMaxHeight;
  571.          }
  572.          break;
  573.  
  574.       case WM_MINMAXFRAME:
  575.          pswp = (PSWP)mp1;
  576.          if(pswp->fl & SWP_MAXIMIZE)
  577.          {
  578.             if(pswp->cx > wd->ulMaxWidth)
  579.             {
  580.                pswp->cx = wd->ulMaxWidth;
  581.                pswp->x = (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)/2)-(wd->ulMaxWidth/2);
  582.             }
  583.  
  584.             if(pswp->cy > wd->ulMaxHeight)
  585.             {
  586.                pswp->cy = wd->ulMaxHeight;
  587.                pswp->y = (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)/2)-(wd->ulMaxHeight/2);
  588.             }
  589.          }
  590.          break;
  591.  
  592.       case WM_DESTROY:
  593.          WinSubclassWindow(hwnd, wd->pfnOldProc);
  594.          free(wd);
  595.          break;
  596.  
  597.       case WMU_MAX_CLIENT_SIZE:
  598.          rect.xLeft = rect.yBottom = 0;
  599.          rect.xRight = LONGFROMMP(mp1);
  600.          rect.yTop = LONGFROMMP(mp2);
  601.          WinCalcFrameRect(hwnd, &rect, FALSE);
  602.          wd->ulMaxWidth = rect.xRight-rect.xLeft;
  603.          wd->ulMaxHeight = rect.yTop-rect.yBottom;
  604.          break;
  605.  
  606.       case WM_TRACKFRAME:
  607.          #ifdef DEBUG_TERM
  608.          puts("i FrameWindow: WM_TRACKFRAME");
  609.          #endif
  610.  
  611.          #ifdef DEBUG_TERM
  612.          printf("i Tracking:");
  613.          if(SHORT1FROMMP(mp1) & TF_MOVE)
  614.          {
  615.             if((SHORT1FROMMP(mp1) & TF_MOVE) ^ TF_MOVE)
  616.             {
  617.                if(SHORT1FROMMP(mp1) & TF_LEFT)
  618.                {
  619.                   printf(" Left");
  620.                }
  621.                if(SHORT1FROMMP(mp1) & TF_BOTTOM)
  622.                {
  623.                   printf(" Bottom");
  624.                }
  625.                if(SHORT1FROMMP(mp1) & TF_RIGHT)
  626.                {
  627.                   printf(" Right");
  628.                }
  629.                if(SHORT1FROMMP(mp1) & TF_TOP)
  630.                {
  631.                   printf(" Top");
  632.                }
  633.             }
  634.             else
  635.             {
  636.                printf(" Move");
  637.             }
  638.             puts("");
  639.          }
  640.          #endif
  641.  
  642.          /*
  643.           * Send tracking information to client
  644.           */
  645.          WinSendMsg(wd->hwndClient, WM_TRACKFRAME, mp1, mp2);
  646.          fHandled = FALSE;
  647.          break;
  648.  
  649.       default:
  650.          fHandled = FALSE;
  651.          break;
  652.    }
  653.    if(!fHandled)
  654.    {
  655.       mReturn = (*wd->pfnOldProc)(hwnd, msg, mp1, mp2);
  656.    }
  657.  
  658.    return mReturn;
  659. }
  660.