![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
Fast Track Visual C++ 6.0 Programming
How MDI Programs WorkIn the last chapter, the KeysSDI program supported the SDI interface and used the CSingleDocTemplate class to set up its document template. BOOL CKeysSDIApp::InitInstance() { . . . CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CKeysSDIDoc), ⇐ RUNTIME_CLASS(CMainFrame), // main SDI frame window ⇐ RUNTIME_CLASS(CKeysSDIView)); ⇐ AddDocTemplate(pDocTemplate); . . . Each time you open the program, a new window, document, and view are created. If you select New in the File menu, the document is erased and reusedyou can only have one document. Its different in our MDI program. Here, the document template is based on the CMultiDocTemplate class. In addition, the main window class is not the CMainFrame class that we used in SDI programming. In the MDI program, we use the MDI child window class, CChildFrame, as the documents window class. BOOL CMDIApp::InitInstance() { . . . CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDITYPE, RUNTIME_CLASS(CMDIDoc), ⇐ RUNTIME_CLASS(CChildFrame), // custom MDI child frame ⇐ RUNTIME_CLASS(CMDIView)); ⇐ AddDocTemplate(pDocTemplate); . . . In this program, every time we open a new document, a new document and view are created that are connected to an MDI child window, which then appears in the MDI main frame window. If you want to use a different view class, this is the place to do it. In fact, we do just that later in this chapter when we learn how to support multiple view classes in the same program. The rest of the InitInstance() function creates a new MDI frame window and displays it as shown in the following example (a default document already appears in its own child window in the new MDI frame window; later in this book, we open our own documents when the program first loads instead of default documents): BOOL CMDIApp::InitInstance() { . . . CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDITYPE, RUNTIME_CLASS(CMDIDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CMDIView)); AddDocTemplate(pDocTemplate); // create main MDI Frame window CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE; // The main window has been initialized, so show and update it. pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; }
Now that weve caught a glimpse behind the scenes in MDI programming, lets continue with our own MDI program. Handling Data in the MDI ProgramThis program, MDI, will let the user type into a document and enter multiple lines of text, so we need to write the code to support that process first. In this example, we make things easy for ourselves by storing each line of text in its own CString object, and we set aside those strings in an array of CString objects named text[]. In addition, we need to keep track of the current number of lines in the document so we know where to enter new text as the user types it; we can create an integer variable named number_lines for that. Here, we allow for a maximum of 1000 lines of text: const MAX_LINES = 1000; ⇐ class CMDIDoc : public CDocument { protected: // create from serialization only CMDIDoc(); DECLARE_DYNCREATE(CMDIDoc) // Attributes public: int number_lines; ⇐ CString text[MAX_LINES]; ⇐ In addition, we can initialize number_lines to 0 in the documents constructor. CString objects are initialized to the empty string, so we dont initialize the CString array in this case. CMDIDoc::CMDIDoc() { // TODO: add one-time construction code here number_lines = 0; ⇐ } Next, we read keys as theyre typed by the user. Reading Keys in MDIWe read keys by adding an OnChar() message handler with ClassWizard. void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default CView::OnChar(nChar, nRepCnt, nFlags); } We can add keys to the current string of text as we did in our KeysSDI program in the last chapter, but theres a difference because here were handling multiline text, which means we have to watch for the Enter key. If the user types the Enter key, we have to skip to the next line of text. We start by storing simple characters; we first make sure the typed character is not the Enter key. void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if(nChar != '\r'){ ⇐ . . . } ⇐ CView::OnChar(nChar, nRepCnt, nFlags); } Next, we store the character the user has typed in the current line of text and invalidate the view to redisplay it. void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CMDIDoc* pDoc = GetDocument(); ⇐ ASSERT_VALID(pDoc); ⇐ if(nChar != '\r'){ pDoc->text[pDoc->number_lines] += nChar; ⇐ Invalidate(); ⇐ } CView::OnChar(nChar, nRepCnt, nFlags); } If, on the other hand, the user did press the Enter key, we skip to the next line of text by incrementing number_lines. void CMDIView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CMDIDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(nChar != '\r'){ pDoc->text[pDoc->number_lines] += nChar; Invalidate(); } else{ pDoc->number_lines++; ⇐ } CView::OnChar(nChar, nRepCnt, nFlags); }
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement. |