先来个段子
十年生死两茫茫,喜羊羊,灰太狼。舒克贝塔,蓝猫话凄凉。纵使相逢应不识,圣斗士,美猴王。老夫聊发少年狂,治肾亏,不含糖。锦帽貂裘,千骑用康王。为报倾城随太守,三百年,九芝堂。夜来幽梦忽还乡,学外语,新东方。相顾无言,洗洗更健康。
Outlook风格在http://blog.csdn.net/wlsgzl/article/details/32083145中已经实现了,这里只搞一下多视图。
=======好羡慕出双入对的分割线========
先分析下VS2010给的示例代码OutlookMultiViews,看看相关的部分。
在COutlookMultiViewsApp的InitInstance中
将CSingleDocTemplate的构造函数的第4个参数改为自己的类
BOOL COutlookMultiViewsApp::InitInstance() { // Initialize OLE libraries if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. // Change the registry key under which our settings are stored. // TODO: You should modify this string to be something appropriate // such as the name of your company or organization. SetRegistryKey(_T("Microsoft\\MFC\\Samples")); LoadStdProfileSettings(); // Load standard INI file options (including MRU) SetRegistryBase (_T("Settings")); // Initialize all Managers for usage. They are automatically constructed // if not yet present InitContextMenuManager(); InitKeyboardManager(); // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views. CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(COutlookMultiViewsDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(/*COutlookMultiViewsView*/CFV1));//改为自己的视图类 AddDocTemplate(pDocTemplate); // 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 one and only window has been initialized, so show and update it. m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; }
主框架窗口类CMainFrame中的视图成员变量
// Array of views attached to single document CView * m_pViews[NUMVIEWS]; // Index to current view UINT m_nCurView;
在CMainFrame的InitViews中
void CMainFrame::InitViews () { m_nCurView = 0; // Save index of the currently active view class CView* pActiveView = GetActiveView(); m_pViews[0] = pActiveView;//这里MFC让默认的模板作为第一个视图数组成员 // m_pViews[1] = (CView*) new CView1; // m_pViews[2] = (CView*) new CView2; // m_pViews[3] = (CView*) new CView3; m_pViews[1] = (CView*) new CFV2;//改为自己的视图类,我这里是CFormView类型的 m_pViews[2] = (CView*) new CFV3;//改为自己的视图类,我这里是CFormView类型的 m_pViews[3] = (CView*) new CFV4;//改为自己的视图类,我这里是CFormView类型的 CDocument* pCurrentDoc = GetActiveDocument(); // Initialize a CCreateContext to point to the active document. // With this context, the new view is added to the document // when the view is created in CView::OnCreate(). CCreateContext newContext; newContext.m_pNewViewClass = NULL; newContext.m_pNewDocTemplate = NULL; newContext.m_pLastView = NULL; newContext.m_pCurrentFrame = NULL; newContext.m_pCurrentDoc = pCurrentDoc; CRect rect(0, 0, 0, 0); // gets resized later for (int nView = 1; nView < NUMVIEWS; nView++) { // Create the new view. In this example, the view persists for // the life of the application. The application automatically // deletes the view when the application is closed. m_pViews[nView]->Create(NULL, NULL, (AFX_WS_DEFAULT_VIEW & ~WS_VISIBLE), // views are created with the style of AFX_WS_DEFAULT_VIEW // In MFC 4.0, this is (WS_BORDER | WS_VISIBLE | WS_CHILD) rect, this, IDD_FORMVIEW1-1 + nView, &newContext);//这里面的ID是连续定义的(在resource.h中),便于循环处理。 // When a document template creates a view, the WM_INITIALUPDATE // message is sent automatically. However, this code must // explicitly send the message, as follows. //m_pViews [nView]->OnInitialUpdate();//这里要注意,如果是CFormView类型的视图,要注掉。 } }
然后再在COutlookMultiViewsApp的InitInstance中添加对InitViews的调用。
// Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE; ((CMainFrame*)m_pMainWnd)->InitViews ();//调用InitViews // The one and only window has been initialized, so show and update it. m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow();
在CMainFrame的消息映射宏中
感觉这个是手工添加的,因为Wizard添加不了ON_COMMAND_RANGE的宏,好像。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(ID_VIEW_CUSTOMIZE, OnViewCustomize) ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnToolbarReset) ON_REGISTERED_MESSAGE(AFX_WM_TOOLBARMENU, OnToolbarContextMenu) ON_COMMAND(ID_VIEW_OUTLOOKBAR, OnViewOutlookBar) ON_UPDATE_COMMAND_UI(ID_VIEW_OUTLOOKBAR, OnUpdateViewOutlookBar) ON_COMMAND_RANGE(ID_SHORTCUT_1, ID_SHORTCUT_4, OnOutlookBarShortcut)//就是这个,对这四个ID代表的按钮做处理 ON_UPDATE_COMMAND_UI_RANGE(ID_SHORTCUT_1, ID_SHORTCUT_4, OnUpdateOutlookBarShortcut) ON_COMMAND(ID_VIEW_CAPTIONBAR, OnViewCaptionBar) ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTIONBAR, OnUpdateViewCaptionBar) ON_COMMAND_RANGE(ID_VIEW_APPLOOK_2000, ID_VIEW_APPLOOK_2007_4, OnAppLook) ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_2000, ID_VIEW_APPLOOK_2007_4, OnUpdateAppLook) END_MESSAGE_MAP()
void CMainFrame::OnOutlookBarShortcut(UINT id) { const int nIndex = id - ID_SHORTCUT_1;//点击的是哪一个。连续ID定义的好处。 ASSERT( nIndex >=0 && nIndex < NUMVIEWS ); if ( nIndex < 0 || nIndex >= NUMVIEWS ) return; if (!m_pViews) return; CView* pNewView = m_pViews[nIndex]; if (!pNewView) return; CView* pActiveView =GetActiveView(); if ( !pActiveView ) // No currently active view return; if ( pNewView == pActiveView ) // Already there return; m_nCurView = nIndex; // Store the new current view's index // exchange view window ID's so RecalcLayout() works UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID); ::SetWindowLong(pActiveView->m_hWnd, GWL_ID,::GetWindowLong(pNewView->m_hWnd, GWL_ID)); ::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp); // Display and update the new current view - hide the old one pActiveView->ShowWindow(SW_HIDE); pNewView->ShowWindow(SW_SHOW); SetActiveView(pNewView); RecalcLayout(); pNewView->Invalidate(); //下面的这个是改变标题栏的内容,无关。 CString strCaption; strCaption.Format (_T("View %d"), nIndex + 1); m_wndCaptionBar.SetText (strCaption); m_wndCaptionBar.RedrawWindow (); }
大致就是这些。