www.pudn.com > 单文档多视图.rar > Sdiframe.cpp
// SDIFrame.cpp : implementation of the CSDIFrameWnd class
//
#include "stdafx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSplitInfo class
CSplitInfo::CSplitInfo()
{
m_MaxRow = m_MaxCol = 0;
}
CSplitInfo &CSplitInfo::operator=(const CSplitInfo &SplitInfo)
{
// function only for CMap
return *this;
}
/////////////////////////////////////////////////////////////////////////////
// CSDIFrameWnd
IMPLEMENT_DYNCREATE(CSDIFrameWnd, CFrameWnd)
BEGIN_MESSAGE_MAP(CSDIFrameWnd, CFrameWnd)
//{{AFX_MSG_MAP(CSDIFrameWnd)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSDIFrameWnd construction/destruction
CSDIFrameWnd::CSDIFrameWnd()
{
}
CSDIFrameWnd::~CSDIFrameWnd()
{
}
BOOL CSDIFrameWnd::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
CView* pView;
CSDIWinApp* pApp = (CSDIWinApp*)AfxGetApp();
ASSERT_KINDOF(CSDIWinApp, pApp);
// hold informations from DocTemplates to create splitter
POSITION TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
CSDIDocTemplate* pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
ASSERT_KINDOF(CSDIDocTemplate, pTemplate);
if (pTemplate->m_nSplitterID != -1)//找到了一个Splitter,并将该Splitter的信息存储到Splitter信息结构中间
{
// find or create the splitter ID in the splitter map
int nID = pTemplate->m_nSplitterID;
m_SplitInfo[nID].m_MaxRow = max(m_SplitInfo[nID].m_MaxRow, pTemplate->m_nRow + 1);
m_SplitInfo[nID].m_MaxCol = max(m_SplitInfo[nID].m_MaxCol, pTemplate->m_nCol + 1);
}
}
// create the splitter and the views in the splitter
POSITION MapPos = m_SplitInfo.GetStartPosition();
while (MapPos)
{
int nID;
CSplitInfo SplitInfo;
m_SplitInfo.GetNextAssoc(MapPos, nID, SplitInfo);
if (m_SplitInfo[nID].m_MaxRow && m_SplitInfo[nID].m_MaxCol)//需要拆分
{
CRect rect;
GetClientRect(&rect);
int cx = rect.Width();
int cy = rect.Height();
// normaly always ToolBar & StatusBar
cy = cy - 56;
if (cy < 56) cy = 0;
if (m_SplitInfo[nID].m_MaxCol)
cx /= m_SplitInfo[nID].m_MaxCol;
if (m_SplitInfo[nID].m_MaxRow)
cy /= m_SplitInfo[nID].m_MaxRow;
CSize sizeDefault(cx, cy);
m_SplitInfo[nID].m_wndSplitter.CreateStatic(this, m_SplitInfo[nID].m_MaxRow, m_SplitInfo[nID].m_MaxCol);
// disable Splitter ID to use for next splitter
m_SplitInfo[nID].m_wndSplitter.SetDlgCtrlID(0);
//every view have a DocTemplate,so you should search the DocTepmplate Array to find the the view
TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
CSDIDocTemplate* pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
if (pTemplate->m_nSplitterID == nID)
{
// create view
int nRow = pTemplate->m_nRow, nCol = pTemplate->m_nCol;
pContext->m_pNewDocTemplate = pTemplate;
pContext->m_pNewViewClass = pTemplate->GetViewClass();
//Associate the view with the Splitter.
if (!m_SplitInfo[nID].m_wndSplitter.CreateView(nRow, nCol,
pContext->m_pNewViewClass, sizeDefault, pContext)) return FALSE;
pTemplate->m_pView =(CView*)m_SplitInfo[nID].m_wndSplitter.GetPane(nRow, nCol);
// disable view ID to use for next splitter view
pTemplate->m_pView->SetDlgCtrlID(0);
}
}
/*
TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
CSDIDocTemplate* pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
if (pTemplate->m_nSplitterID == nID)
pTemplate->m_pView->SetDlgCtrlID(0);
}
*/
}
}
// create the other views (no splitter)
TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
CSDIDocTemplate* pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
if (pTemplate->m_nSplitterID == -1)
{
pContext->m_pNewViewClass = pTemplate->GetViewClass();
pView = (CView*)CreateView(pContext, AFX_IDW_PANE_FIRST);
ASSERT(pView != NULL);
pTemplate->m_pView = pView;
// disable view ID to use for next view
pView->SetDlgCtrlID(0);
}
}
SetActiveView(NULL);
CSDIDocTemplate *pTemplate;
// litle problem ! if a CRichEditView is in the view list
// we must activate it first to update the layout correctly
pTemplate = pApp->GetTemplate(RUNTIME_CLASS(CRichEditView));
if (pTemplate) ActivateView(pTemplate->GetViewClass());
// activate the first doctemplate view
pTemplate = pApp->GetFirstTemplate();
ActivateView(pTemplate->GetViewClass());
return TRUE;
}
void CSDIFrameWnd::ActivateView(CRuntimeClass* pViewClass)
{
CSDIWinApp* pApp = (CSDIWinApp*)AfxGetApp();
CView* pActiveView = GetActiveView();
CSDIDocTemplate* pNewTemplate = pApp->GetTemplate(pViewClass);
CSDIDocTemplate* pActiveTemplate = pApp->GetTemplate(pActiveView);
// the view class doesn't exist
if (pNewTemplate == NULL) return;
// the new template is the active template, do nothing
if (pNewTemplate == pActiveTemplate) return;
CString str="hehhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
int i=2;
TRACE("%d",i);
//deal with the currently active view
if (pActiveTemplate != NULL)
{
// the active and new template are in the same splitter, change the active view
if (pActiveTemplate->m_nSplitterID != -1&&pActiveTemplate->m_nSplitterID == pNewTemplate->m_nSplitterID)
{
MessageBox("in the same splitter.");
UpdateResource(pNewTemplate);
SetActiveView(pNewTemplate->m_pView);
return;
}
// the active view is in another splitter, hide all views in the splitter and the splitter
if (pActiveTemplate->m_nSplitterID != -1&&pActiveTemplate->m_nSplitterID != pNewTemplate->m_nSplitterID)
{
POSITION TmpPos;
CSDIDocTemplate* pTemplate;
int nID = pActiveTemplate->m_nSplitterID;
TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
if (pTemplate->m_nSplitterID == nID)
{
pTemplate->m_pView->ShowWindow(SW_HIDE);
pTemplate->m_pView->SetDlgCtrlID(0);
}
}
// hide the splitter
m_SplitInfo[nID].m_wndSplitter.SetDlgCtrlID(0);
m_SplitInfo[nID].m_wndSplitter.ShowWindow(SW_HIDE);
}
// the currently active view is not in a splitter, hide the active view
else
{
pActiveTemplate->m_pView->SetDlgCtrlID(0);
pActiveTemplate->m_pView->ShowWindow(SW_HIDE);
}
}
//show the new view
// the new view is in a splitter, show all splitter views and the splitter
if (pNewTemplate->m_nSplitterID != -1)
{
POSITION TmpPos;
CSDIDocTemplate* pTemplate;
int nID = pNewTemplate->m_nSplitterID;
TmpPos = pApp->GetFirstDocTemplatePosition();
while (TmpPos)
{
pTemplate = (CSDIDocTemplate*)pApp->GetNextDocTemplate(TmpPos);
if (pTemplate->m_nSplitterID == nID)
{
int nRow = pTemplate->m_nRow;
int nCol = pTemplate->m_nCol;
int nDlgID = m_SplitInfo[nID].m_wndSplitter.IdFromRowCol(nRow, nCol);
pTemplate->m_pView->SetDlgCtrlID(nDlgID);
pTemplate->m_pView->ShowWindow(SW_SHOW);
}
}
// show the splitter
m_SplitInfo[nID].m_wndSplitter.SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_SplitInfo[nID].m_wndSplitter.ShowWindow(SW_SHOW);
}
// the new view is not in a splitter, active the new view
else
{
pNewTemplate->m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
pNewTemplate->m_pView->ShowWindow(SW_SHOW);
}
UpdateResource(pNewTemplate);
// display and update the new view
SetActiveView(pNewTemplate->m_pView);
RecalcLayout();
}
BOOL CSDIFrameWnd::IsViewActive(CRuntimeClass* pViewClass)
{
CView* pActiveView = GetActiveView();
if (pActiveView == NULL) return FALSE;
return (pActiveView->GetRuntimeClass() == pViewClass);
}
void CSDIFrameWnd::UpdateResource(CSDIDocTemplate *pNewTemplate)
{
CSDIWinApp* pApp = (CSDIWinApp*)AfxGetApp();
// support for view context menu, accelerator and help ID like MDI
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(pNewTemplate->GetResourceID()), RT_MENU);
// if menu is not the default menu, destroy it
HMENU hMenu = ::GetMenu(m_hWnd);
if (hMenu != m_hMenuDefault) ::DestroyMenu(hMenu);
// load menu from doctemplate
hMenu = ::LoadMenu(hInst, MAKEINTRESOURCE(pNewTemplate->GetResourceID()));
// if no menu, get default
if (hMenu == NULL) hMenu = m_hMenuDefault;
// load menu
::SetMenu(m_hWnd, hMenu);
// load new accelerator table
HACCEL hAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(pNewTemplate->GetResourceID()));
// if no table for this template, load default
if (hAccel == NULL) ::LoadAccelerators(hInst, MAKEINTRESOURCE(pApp->GetFirstTemplate()->GetResourceID()));
// chage help ID for this view
m_nIDHelp = pNewTemplate->GetResourceID();
// change the title of the document
pNewTemplate->GetDocString(m_strTitle, CDocTemplate::windowTitle);
OnUpdateFrameTitle(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// CSDIFrameWnd message handlers