1. 程式人生 > >VS2010 單文件+多檢視+Outlook風格

VS2010 單文件+多檢視+Outlook風格

先來個段子

十年生死兩茫茫,喜羊羊,灰太狼。舒克貝塔,藍貓話淒涼。縱使相逢應不識,聖鬥士,美猴王。老夫聊發少年狂,治腎虧,不含糖。錦帽貂裘,千騎用康王。為報傾城隨太守,三百年,九芝堂。夜來幽夢忽還鄉,學外語,新東方。相顧無言,洗洗更健康。

------------------調皮的分割線-----------------------

=======好羨慕出雙入對的分割線========

先分析下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 ();
}

大致就是這些。