I would like for someone to explain to me why the following use of a CScrollView derived object within a CDialog derived object works and whether this approach has hidden problems.
My concern is the casting of a CDialog to a CFrameWnd in order to use the CreateView()
method of the CFrameWnd class to create a Document/View pair for the CScrollView object in the CDialog object.
I am building an MFC DLL that will provide a series of GUI functions to display and allow the edit of some types of information in a legacy application which displays a page at a time.
One of the first pieces is to provide a way to display reports in a dialog that presents the report in a scrollable component allowing the user to view the entire report.
Looking into using a CSrollView derived control in a CDialog derived GUI object, I found this article, Creating a View in Dialog (An easy way), as I was running into a number of problems with exceptions on CDialog closing when using a CScrollView. I was also seeing a warning in the debug output window of "Warning: Creating a pane with no CDocument." which I am no longer seeing.
Using the basic concept from the article I have code which seems to be working fine with Visual Studio 2005 in Windows XP in the debugger.
The code I am using in the CDialog derived class for initializing in the OnInitDialog()
is as follows. I am creating the document first and putting lines of text into a memory area and the constructor of the CDialog derived object is given the address of the document, m_pDocument
, which is then used in the OnInitDialog()
function.
BOOL CScrollReportDialog::OnInitDialog ()
{
// Get the client area size of the dialog we are putting the
// CScrollView into and pull the right edge in sufficient to
// clear buttons on the right hand side of the dialog.
RECT rectSize;
GetClientRect (&rectSize);
rectSize.right -= 120;
// allocate and set up the view document context linking the view
// to a particular document, in our case a CScrollDocument.
CCreateContext pContext;
pContext.m_pCurrentDoc = m_pDocument;
pContext.m_pNewViewClass = RUNTIME_CLASS(CScrollReport);
// Cast the pointer to this dialog into a CFrameWnd pointer allowing
// us to access the CFrameWnd methods. Both CDialog and CFrameWnd are
// derived from CWnd so we can get away with this.
CFrameWnd* pFrameWnd = (CFrameWnd *) ((CWnd *)this);
CScrollReport *pView = (CScrollReport *)pFrameWnd->CreateView(&pContext);
ASSERT(pView);
// Set an initial scroll size for the CScrollView which will be
// modified in the OnDraw () later when presenting the actual view
// and we have the complete document and can calculate the document's
// scrollable size properly.
CSize sizeTotal;
sizeTotal.cx = rectSize.right;
sizeTotal.cy = 1 * rectSize.bottom;
pView->SetScrollSizes(MM_TEXT, sizeTotal);
pView->ShowWindow(SW_NORMAL);
/**
* After a view is created, resize window area of the view to fit into the
* dialog. Since this is a CScrollView, set an initial size for the
* size of the object being scrolled.
*/
pView->MoveWindow(&rectSize);
return TRUE;
}