VS2010 单文档+多视图+Outlook风格

先来个段子

十年生死两茫茫,喜羊羊,灰太狼。舒克贝塔,蓝猫话凄凉。纵使相逢应不识,圣斗士,美猴王。老夫聊发少年狂,治肾亏,不含糖。锦帽貂裘,千骑用康王。为报倾城随太守,三百年,九芝堂。夜来幽梦忽还乡,学外语,新东方。相顾无言,洗洗更健康。

------------------调皮的分割线-----------------------

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()

在CMainFrame的OnOutlookBarShortcut中

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 ();
}


大致就是这些。




你可能感兴趣的:(VS2010)