m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSSplitView),
CSize(200, 400), pContext);
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CStretchView),
CSize(400, 400), pContext);
}
return TRUE; //CFrameWnd::OnCreateClient(lpcs, pContext);
(3)为SSplit项目添加基类为CView的视图类CStretchView,并为该视图类添加GetDocument成员函数(包括内联版和调试版),以返回对应的文档类对象:
? StretchView.h:
#pragma once
#include \// CStretchView 视图
class CStretchView : public CView {
…… public:
CSSplitDoc* GetDocument() const; …… };
#ifndef _DEBUG // StrechView.cpp 中的非调试版本
inline CSSplitDoc* CStretchView::GetDocument() const { return reinterpret_cast
……
#ifdef _DEBUG ……
CSSplitDoc* CStretchView::GetDocument() const {// 内联调试版本
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSSplitDoc))); return (CSSplitDoc*)m_pDocument;
31
}
#endif //_DEBUG
// CStretchView 消息处理程序 ……
(4)在文档类中定义CImage对象:
#pragma once
#include
class CSSplitDoc : public CDocument { …… // 属性 public: …… };
(5)在文档类的Serialize函数中装入图像:
void CSSplitDoc::Serialize(CArchive& ar) { }
(6)在CSSplitView类的OnDraw函数中绘制各向同性的图像:
void CSSplitView::OnDraw(CDC* pDC) {
CImage img;
if (ar.IsStoring()) { } else { }
// TODO: 在此添加加载代码
if (!img.IsNull()) img.Destroy();
HRESULT hr = img.Load(ar.GetFile()->GetFilePath()); ASSERT(SUCCEEDED(hr)); // TODO: 在此添加存储代码
CSSplitDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);
32
}
if (!pDoc) return;
// TODO: 在此处为本机数据添加绘制代码 if (!pDoc->img.IsNull()) { }
RECT rect;
GetClientRect(&rect);
if (pDoc->img.GetWidth() > rect.right) { }
else pDoc->img.Draw(pDC->m_hDC, 0, 0);
rect.bottom = (int)(((float)pDoc->img.GetHeight()
* rect.right) / pDoc->img.GetWidth() + 0.5);
pDC->SetStretchBltMode(HALFTONE); pDoc->img.Draw(pDC->m_hDC, rect);
(7)在CStretchView类的OnDraw函数中绘制各向异性的图像:
void CStretchView::OnDraw(CDC* pDC) { }
CSSplitDoc* pDoc = GetDocument(); // TODO: 在此添加绘制代码 if (!pDoc->img.IsNull()) { }
RECT rect;
GetClientRect(&rect);
pDC->SetStretchBltMode(HALFTONE); pDoc->img.StretchBlt(pDC->m_hDC, rect);
12.3.2 MDI程序不自动创建子窗口
为了MDI程序在开始运行时不自动创建一个新文档及其对应子窗口,可在应用程序类C*App的InitInstance函数的语句
33
与
// 分析标准外壳命令、DDE、打开文件操作的命令行 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo);
// 调度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,
则返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
之间,加上语句:
// 不让在启动时创建子框架窗口
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
12.3.2 自己创建文档窗口*
通常MFC只在响应ID_FILE_NEW和ID_FILE_OPEN消息时才创建文档窗口,若要在MDI应用程序的视图类中,在自己需要的时候创建同类的文档窗口,可以分如下三步进行。
1.获得文档模板
可先用文档类的成员函数GetDocTemplate来获得视图所对应的文档模板:
CDocTemplate* GetDocTemplate( ) const;
2.创建新子框架窗口
再调用文档模板类的成员函数CreateNewFrame来创建新子框架窗口:
virtual CFrameWnd* CreateNewFrame( CDocument* pDoc, CFrameWnd* pOther );
其中,pDoc为本视图类所对应的文档类对象的指针,pOther为MDI文档的子框架窗口的指针,可用视图类的基类CWnd的成员函数GetParentFrame来获得:
CFrameWnd* GetParentFrame( ) const;
34
3.初始化子框架窗口
然后再调用文档模板类的成员函数InitialUpdateFrame:
virtual void InitialUpdateFrame( CFrameWnd* pFrame, CDocument* pDoc,
BOOL bMakeVisible = TRUE );
来初始化并显示子框架窗口。
4.例子
在自己添加的菜单项ID_DOC_NEW的事件处理函数中自己来创建文档窗口:
void CTestView::OnDocNew() { }
CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);
CMDIChildWnd* pChild = (CMDIChildWnd*)GetParentFrame( ); CDocTemplate* pTem = pDoc->GetDocTemplate(); ASSERT_VALID(pTem);
CFrameWnd* pFWnd = pTem->CreateNewFrame(pDoc, pChild); pTem->InitialUpdateFrame(pFWnd, pDoc);
12.3.3 文件过滤器
文件过滤器用于指定打开和保存文件的扩展名,可以通过修改资源串、设置多文档模板、或添加自己的OnFileOpen消息响应函数(在其中,利用指定的过滤串,打开公用文件对话框)等方法,来为MFC应用程序设置文件过滤器。
1.资源串
通过资源串设置文件过滤器,可以在创建项目时进行,也可以在创建项目后再修改。 1) 创建时设置
在创建(非对话框类型的)项目时,在“MFC应用程序向导”对话框的“文档模板字符串”页中进行如下修改和设置(参见图12-25,结果如图12-26 所示):
35