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