How do I take control of frame sizing?

I want to "subclass" the Window Frame Class to allow me to control the size of my main window when it's resized by the mouse. I want to control the steps it take to resize too, (ie: by 8x8 steps).

--- CUT --- CUT ---- .H file --- CUT ---

HWND APIENTRY WinCreateMBWindow(

  HWND hwndParent,
  ULONG flStyle,
  PULONG pflCreateFlags,
  PSZ pszClientClass,
  PSZ pszTitle,
  ULONG styleClient,
  HMODULE hmod,
  USHORT idResources,
  PHWND phwndClient);


#define HMODFROMMP(mp) ((USHORT)(ULONG)(mp))

#define MB_CHILD_SIZE  WM_USER+204
          //Sent from child to frame indicating the new
          //requested size of the child area.  (high&width in MP1)
          //If ChildMax is shrinking below current size,
          // frame is redused, and evt scroll bars is hidden.
          //If Child is growing
          //   MP2=True -> grows frame to contain maximized child
          //   MP2=False-> enables scroll bars, keeps size.

#define MB_FIX_N       0x1 //Fix north border when sizing
#define MB_FIX_E       0x2 //Fix east  border when sizing

#define MB_FIX_NE       0x3 //Fix north east corner when sizing
#define MB_FIX_SE       0x2 //Fix south east corner when sizing
#define MB_FIX_NW       0x1 //Fix north west corner when sizing
#define MB_FIX_SW       0x0 //Fix south west corner when sizing

#define MB_QCHILD_SIZE_MAX     WM_USER+205
           //Sent from frame to child to queryw
           //max size of the child area.  (h&w in MR)
           //Used when sizing to determin if scroll bars are ness.

#define MB_QCHILD_GRID     WM_USER+206
           //Sent from frame to child before tracking
           //Child supposed to return x&y granularity in MR

#define MB_CREATE          WM_USER+207  //Internally shipped command.

typedef struct _FRM_DTA { /* Fram data */
    PFNWP    oldProc;
    SHORT    nTrkCnr,nYSclHor,nXSclVer,nTitle;
    SHORT    xMax,yMax;    //Max size of Client in PIX
    SHORT    ScrMaxX,ScrMaxY;
    POINTL   ptlBdr;
    HWND     hVert,hHori;
    SHORT    xCur,yCur;    //Current size of Client in PIX
    SHORT    nCorner;      //Which corner is to be stable
} FRM_DTA;
typedef FRM_DTA FAR * PFRM_DTA;

--- CUT --- CUT --- .C file --- CUT --- CUT ---

HWND	APIENTRY WinCreateMBWindow(HWND hParent, ULONG flStyle,
                                   PULONG pflCreate, PSZ pszClientClass,
                                   PSZ pszTitle, ULONG styleClient,
                                   HMODULE hmod,
                                   USHORT idResources, PHWND phClient)
{
  HWND         hFrame;
  PFRM_DTA     pFrm;

  hFrame = WinCreateStdWindow(hParent,flStyle,pflCreate,pszClientClass,
                              pszTitle,styleClient,hmod,idResources,phClient);

  //Allocate some storage for local parameters, and initialize it
  pFrm=malloc(sizeof( FRM_DTA));
  memset(pFrm,0,sizeof( FRM_DTA));

  WinSetWindowPtr(hFrame,QWL_USER,(PVOID) pFrm);

  pFrm->oldProc= WinSubclassWindow(hFrame,newFrameProc);

  //Now window is setup:

  WinSendMsg(hFrame,MB_CREATE,MP0,MP0);    //My own WM_CREATE

  WinShowWindow(hFrame,TRUE);

  WinUpdateWindow(hFrame);
  return hFrame;
}

VOID GetChildMax(HWND hFrame, PFRM_DTA	pFrm)
{ MRESULT mr;
  mr = WinSendMsg(WinWindowFromID(hFrame,FID_CLIENT),
                  MB_QCHILD_SIZE_MAX,MP0,MP0);
  pFrm->xMax=SHORT1FROMMR(mr);
  pFrm->yMax=SHORT2FROMMR(mr);
}

#define CLIENT_PROVIDED  FALSE
#define FRAME_PROVIDED	 TRUE

BOOL WinCalcFrameSWP(HWND hwnd, PSWP pSWP, BOOL bFrame)
{ //    TRUE       Frame rectangle provided
  //    FALSE      Client-area rectangle provided.
  RECTL rcl;
  BOOL bSuccess;

  rcl.xLeft   = pSWP->x;
  rcl.yBottom = pSWP->y;
  rcl.xRight  = pSWP->x+pSWP->cx;
  rcl.yTop    = pSWP->y+pSWP->cy;

  bSuccess = WinCalcFrameRect(hwnd, &rcl, bFrame );

  pSWP->x  =(SHORT) rcl.xLeft;
  pSWP->y  =(SHORT) rcl.yBottom;
  pSWP->cx =(SHORT) (rcl.xRight-rcl.xLeft);
  pSWP->cy =(SHORT) (rcl.yTop  -rcl.yBottom);

  return(bSuccess);
}


VOID SclBarEnable(HWND hwnd, PSWP pSWP, PFRM_DTA  pFrm)
{

  .....

Your routines to determine and en/disable scroll bars
  .....
/*    Part of my code */
  swpClient = *(pSWP);
  WinCalcFrameSWP(hwnd, &swpClient, FRAME_PROVIDED);
  if (swpClient.cx >= pFrm->xMax-1)
  { //Turn off horisontal scroll bar
    WinSetParent(pFrm->hHori,HWND_OBJECT ,FALSE);
    nUpdt = FCF_HORZSCROLL;
  }  /* code for enabling left out..... */

  if (nUpdt != 0)
  {
    WinSendMsg (hwnd, WM_UPDATEFRAME, MPFROMSHORT(nUpdt), MP0);
  }
*/
}

/***************** Start of frame subclass procedure *****************/

MRESULT  EXPENTRY newFrameProc( HWND hwnd, USHORT msg,
MPARAM mp1, MPARAM mp2 )

{ PSWP	    pSWP;
  PFNWP     oldProc;
  PFRM_DTA  pFrm;

  pFrm=(PFRM_DTA)WinQueryWindowPtr(hwnd,QWL_USER);
  oldProc=pFrm->oldProc;

  switch(msg)
  {
    case MB_CREATE:
      //Start hiding scroll bars
      pFrm->hVert  = WinWindowFromID(hwnd,FID_VERTSCROLL);
      WinSetParent(pFrm->hVert,HWND_OBJECT ,FALSE);
      pFrm->nYSclHor = 0;
    break;

    case WM_MINMAXFRAME:
    { SWP swpClient;
      pSWP=(PSWP) PVOIDFROMMP(mp1);
      pSWP->fs |= SWP_SIZE;

      GetChildMax(hwnd, pFrm);

      if (pSWP->fs & SWP_MAXIMIZE) //MaxiMizeing Operation
      {
        //tprintf("WM_MINMAXFRAME SWP_MAXIMIZE FS: %X ",pSWP->fs);
        if ((0!=pFrm->xMax) && (0!=pFrm->yMax))
        { //I have no data for all of screen, so act as Windowed OS/2

          memset(&swpClient,0,sizeof(swpClient));
          swpClient.cx=pFrm->xMax;
          swpClient.cy=pFrm->yMax;
          WinCalcFrameSWP(hwnd, &swpClient,CLIENT_PROVIDED);

          pSWP->cx = swpClient.cx;
          pSWP->cy = swpClient.cy;

          pSWP->y  = pFrm->ScrMaxY - swpClient.cy + (SHORT)pFrm->ptlBdr.y;


          SclBarEnable(hwnd, pSWP, pFrm);

          return MRFROMSHORT(FALSE);
        }
      }

      if (pSWP->fs & SWP_RESTORE) //MiniMizeing Operation

??? (restore i guess)

      {
        //tprintf("WM_MINMAXFRAME SWP_RESTORE FS: %X ",pSWP->fs);
        if ((0!=pFrm->xMax) && (0!=pFrm->yMax))  //Why do I need this?
        {
          return MRFROMSHORT(FALSE);
        }
      }
    }
    return (MRESULT)(*oldProc)(hwnd, msg, mp1, mp2);


    case WM_QUERYTRACKINFO:
    {
      PTRACKINFO pTI;
      LONG i;

      if (TF_MOVE <= SHORT1FROMMP(mp1))
      {
        pFrm->nTrkCnr= 0;
        return (MRESULT)(*oldProc)(hwnd, msg, mp1, mp2);
      }

      pTI = (PTRACKINFO) PVOIDFROMMP (mp2);  //Get structure pointer;
      //tprintf("@+WM_QUERYTRACKINFO FS: %X ",pTI->fs);
      if ((*oldProc)(hwnd, msg, mp1, mp2)==0) return MRFROMSHORT(FALSE);

      GetChildMax(hwnd, pFrm);
      if ((0!=pFrm->xMax) && (0!=pFrm->yMax))
      { //Setup track info structure
        pTI->ptlMaxTrackSize.x = (LONG) pFrm->xMax;
        pTI->ptlMaxTrackSize.y = (LONG) pFrm->yMax;

        WinCalcFrameRect(hwnd, &(pTI->rclTrack), FRAME_PROVIDED );

        { MRESULT mr;
          mr = WinSendMsg(WinWindowFromID(hwnd,FID_CLIENT),
                          MB_QCHILD_GRID,MP0,MP0);
          if (NULL!=mr)
          {
            pTI->cxGrid  = SHORT1FROMMR(mr);
            pTI->cyGrid  = SHORT2FROMMR(mr);

            //Setting height of client to integral cyGrid
            i = (pTI->rclTrack.yTop - pTI->rclTrack.yBottom)/pTI->cyGrid;
            pTI->rclTrack.yTop = i * pTI->cyGrid + pTI->rclTrack.yBottom;

            pTI->fs	|= TF_GRID;
            pFrm->nTrkCnr= WM_QUERYTRACKINFO;
            //Used in WM_ADJUSTWINODWPOS
          }
        }
      }
      return MRFROMSHORT(TRUE);
    }
    break;

    case WM_ADJUSTWINDOWPOS:
    { RECTL rcl;
      pSWP=(PSWP) PVOIDFROMMP(mp1);

      if (pSWP->fs & (SWP_SIZE | SWP_MOVE | SWP_MAXIMIZE))
      {
        GetChildMax(hwnd, pFrm);
        if (WM_QUERYTRACKINFO==pFrm->nTrkCnr)
          //As a result of tracking
        {
          //Go from client to frame values
          WinCalcFrameSWP(hwnd, pSWP, CLIENT_PROVIDED);
        }

        pFrm->nTrkCnr	 = 0;

        SclBarEnable(hwnd, pSWP, pFrm);
      }
      return (MRESULT)(*oldProc)(hwnd, msg, mp1, mp2);
    }
    break;

    case MB_CHILD_SIZE:      //xCur,yCur
    { SWP swp;

............. do your actions as responce to client resize request (Change of fontsize for instance)

      return (MRESULT)TRUE;
    }
    break;

    default:
    break;
  }
  return (MRESULT)(*oldProc)(hwnd, msg, mp1, mp2);
}

A lot is deleted (Som is very application specific), but i hope you get the general picture.

Credit: Henrik Wahlberg


[Back: How do I use the Font dialog (WinFontDlg)?]
[Next: How do I use the 16-bit EPM toolkit?]