8.1. Views

Microsoft Visual C++/Microsoft Foundation Classes


8.1. Views

8.1.1. How do I size a view?

Normally, you can change the size of a window by calling MoveWindow(). In an application developed with the Microsoft Foundation Class (MFC) Library, the view window is a child window of the frame window that surrounds the view. To change the size of the view window, retrieve a pointer to the frame window of the view by calling GetParentFrame(), then call MoveWindow() to change the size of the parent. When the parent frame window changes size, it automatically changes the size of the view window to fit in the parent frame.

MSVC Knowledge Base. 6/4/94

8.1.2. How do I size a CFormView?

See MS Knowledge Base article Q98598 for a very long answer. Basically, you need to override OnInitialUpdate() in a CFormView derived class. There's other details to deriving from CFormView that the article goes into.

MSVC Knowledge Base. 6/7/95

In the view ClikethisView declaration:

virtual void OnInitialUpdate();

In the ClikethisView code:

void ClikethisView::OnInitialUpdate()
{
    // make the window the size of the main dialog
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit( /*FALSE*/ );
}

[email protected], programmer.misc, 8/11/95

8.1.3. How do I use new views with a doc template?

In an application created with AppWizard, you have two options: change the derivation of the current view, or create a new view and use the new view in your MDI application along with the original view.

To create a new view, use ClassWizard to create a new class derived from CView. After the class has been created, the steps to use the new view or to modify the view provided by App Wizard are the same.

  1. Modify the header file for the view class to change all references to CView to the name of the desired view class.  In this example, the class is derived from CScrollView.   Usually, this step involves changing the class the view class is derived from as follows:
class CMyView : public CScrollView
  1. Modify the implementation file for the view class to change all references to CView to the name of the desired view class.  This involves changing the IMPLEMENT_DYNCREATE line as follows:
IMPLEMENT_DYNCREATE(CMyView, CScrollView)
 
changing the BEGIN_MESSAGE_MAP as follows:
 
BEGIN_MESSAGE_MAP(CMyView, CScrollView)
 
and changing any other references to CView to CScrollView.
  1. No further modifications are required if you are modifying a view created by App Wizard.   If you create a new view, find the AddDocTemplate() call in the CWinApp::InitInstance() function.  The third parameter to AddDocTemplate() is RUNTIME_CLASS(CSomeView).  To replace the current view with the new view class, change CSomeView to CMyView.  In an MDI application, you can use multiple view types by adding a second AddDocTemplate() call that changes RUNTIME_CLASS(CSomeView) to RUNTIME_CLASS(CMyView).

For more information, please see Knowledge Base article Q99562.

MSVC Knowledge Base 6/7/95

8.1.4. How do I change the background color of a view?

To change the background color for a CView, CFrameWnd, or CWnd object, process the WM_ERASEBKGND message. The following code shows how:

BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
{
    // Set brush to desired background color
    CBrush backBrush(RGB(255, 128, 128));
   
    // Save old brush
    CBrush* pOldBrush = pDC->SelectObject(&backBrush);
    CRect rect;
    pDC->GetClipBox(&rect);
   
    // Erase the area needed
    pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
    pDC->SelectObject(pOldBrush);
   
    return TRUE;
}

I solved the problem like this->

HBRUSH dlgtest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    switch (nCtlColor)
    {
        case CTLCOLOR_BTN:
        case CTLCOLOR_STATIC:
        {
            pDC->SetBkMode(TRANSPARENT);
        }
        case CTLCOLOR_DLG:
        {
            CBrush* back_brush;
            COLORREF color;
            color = (COLORREF) GetSysColor(COLOR_BTNFACE);
            back_brush = new CBrush(color);
            return (HBRUSH) (back_brush->m_hObject);
        }
    }
    return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor));
}

Tim, [email protected], email, 9/10/95

8.1.5. How do I get the current View?

The best thing to do is to pass the view along as a parameter. If this is impractical, you can get the view if you KNOW, that it is the currently active document and the currently active view. For details, see :

Microsoft KB, article Q108587, "Get Current CDocument or CView from Anywhere".

In brief, use

((CFrameWnd*) AfxGetApp()->m_pMainWnd))->GetActiveDocument()

and

((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->GetActiveView()

to get the document and the view. It might be a good idea to wrap them in static functions in your CMyDoc and CMyView and check that they are of the correct RUNTIME_CLASS.

If the view isn't the currently active view or if you can run OLE in-place, this won't work however.

[email protected], Niels Ull Jacobsen, programmer.misc, 6/8/95

8.1.6. How do I create multiple views on one document?

The CDocTemplate::CreateNewFrame() function creates additional views of a document in an MDI application written with MFC. To call this function, specify a pointer to a CDocument object (the document for which the function will create a view) and a pointer to a frame window that has the properties to duplicate. Typically, the second parameter of this function is NULL.

When an application calls CreateNewFrame(), the function creates a new frame window and a view in the frame window. The frame window type and view type depend on the document template (CDocTemplate) associated with the document specified in the CreateNewFrame() call.

The CHKBOOK MFC sample application that ships with Visual C++ also demonstrates creating additional frames and views for documents. Check out CHKBOOK.CPP, the CChkBookApp::OpenDocumentfile() function.

Another example of using CreateNewFrame() is the MULTVIEW sample application. Also, Dale Rogerson's article, "Multiple Views for a Single Document" located on the Microsoft Developer Network Development Library CD-ROM, which explains in detail how to add additional views to an existing document, is an excellent source of information.

CreateNewFrame() creates both a frame and a view; not only a view. If, for some reason, CreateNewFrame() does not quite address your situation, the source code for CreateNewFrame() is quite useful to demonstrate the steps required to create frames and views.

MS FAQ with mods, 6/25/95

8.1.7. How do I get all the views in an MDI app?

You need to use some functions which are undocumented:

  • CDocument::GetFirstViewPosition(); // DOCCORE.CPP
  • CDocument::GetNextView(); // DOCCORE.CPP
  • CMultiDocTemplate::GetFirstDocPosition(); // DOCMULTI.CPP
  • CMultiDocTemplate::GetNextDoc(); // DOCMULTI.CPP

You'll also need to mess with the m_templateList member of CWinApp.

[email protected], mfc-l, 7/11/95

Note: This has changed with MFC 4.0. There's now a class called CDocManager which can get to all of the views/docs for you. Check out MFC Internals for details.

[email protected]

8.1.8. How do I make a CScrollView "mouse scrollable"?

Download AUTOSV.LZH from the MSMFC library on CIS. This code shows you how to implement a secondary message loop taking care of the mouse activity. Hooks are provided to customize the code. Freeware.

Patrick Philippot, CIS email, 8/3/95

NEW!! 8.1.9. How do I limit the maximum and minimum sizing  of a view?

To limit the maximum and minimum size of a view, you need to do two things:

  1. Handle the WM_GETMINMAXINFO message in a CFrameWnd derived class.  This is because when the user resizes a view, they are actually grabbing the frame of the view.  The MINMAXINFO struct sets limits on the entire window, so remember to take into account toolbars, scroll bars, etc.
// Min and Mix size in pixels - values choosen are just examples
#define MINX  200
#define MINY  300
#define MAXX  300
#define MAXY  400
 
void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
    CRect rectWindow;
    GetWindowRect(&rectWindow);
 
    CRect rectClient;
    GetClientRect(&rectClient);
 
      // get offset of toolbars, scrollbars, etc.
    int nWidthOffset = rectWindow.Width() - rectClient.Width();
    int nHeightOffset = rectWindow.Height() - rectClient.Height();
 
    lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
    lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
    lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
    lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
}
  1. Also, be sure to remove the WS_MAXIMIZEBOX in your CFrameWnd derivative's PreCreateWindow function.   If you don't, when the view is maximized, the frame will not behave as you'd expect when maximized.  To understand what I'm getting at, try leaving the WM_MAXIMIZEBOX flag and see what happens when you maximize the view. 
BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.style &= ~WS_MAXIMIZEBOX;
    return CFrameWnd::PreCreateWindow(cs);
}