BOOKS i'm reading |
Control Client area minimum size (WM_GETMINMAXINFO) with MFC in C++Contents
IntroductionIsn't it strange that sometimes, even problems that seem easy at first are the ones causing the most troubles to find a solution to them? Trying to restrict a client view to a minimum size is one of those problems. I have tried many approaches before reaching a satisfactory solution. The final solution is still not perfect and I will explain why later. In this C++ Windows programming tutorial, I will give some background on the problem and describe the various difficulties that I have encountered on the road by presenting my first attempts to solve the problem. Then I will present the inner working of the final solution and give insights on why it has been designed like it is. I will then continue by presenting the demo program whose purpose is to show how to use the code in your own programs and finally, I will discuss the limitations and the possible enhancement to the current code.
BackgroundThe first nave attempt I tried was to handle the void CChildView::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { lpMMI->ptMinTrackSize.x = DEFAULTMINCLIENTSIZE; lpMMI->ptMinTrackSize.y = DEFAULTMINCLIENTSIZE; } If only it was that simple! It does not work at all because only resizable
top most windows receive the CMainFrame::CMainFrame() { minX = DEFAULTMINCLIENTSIZE; minY = DEFAULTMINCLIENTSIZE; } void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { CView *pView = GetActiveView(); if( pView ) { RECT viewRect; pView->GetClientRect(&viewRect); if( viewRect.right < DEFAULTMINCLIENTSIZE ) { minX += (DEFAULTMINCLIENTSIZE - viewRect.right); } if( viewRect.bottom < DEFAULTMINCLIENTSIZE ) { minY += (DEFAULTMINCLIENTSIZE - viewRect.bottom); } } lpMMI->ptMinTrackSize.x = minX; lpMMI->ptMinTrackSize.y = minY; } It gives a descent result but it is not very accurate. For instance, with an
application having a toolbar and a status bar, if you were to reduce the
vertical size of the frame, it would go a little below void CChildFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { // the minimum client rectangle (in that is lying the view window) CRect rc(0, 0, 200, 150); // compute the required size of the frame window rectangle // based on the desired client-rectangle size CalcWindowRect(rc); lpMMI->ptMinTrackSize.x = rc.Width(); lpMMI->ptMinTrackSize.y = rc.Height(); } It sounds good but it does not work neither. As I previously said, the frame client rectangle is shared among the status bar, the toolbars and the view. So if your frame client area only has a view, it will work otherwise it will not. Now with these different attempts, it should start to become clear that the only way to solve this problem is to put our hands in MFC guts to be able to exactly keep track of every client area components size and position. This is exactly what my code is doing and I will show you how in the next section.
|