12.2.3 框架窗口类
因为视图窗口是框架窗口的子窗口,位于框架窗口的客户区。视图窗口本身只是一个没有边框、没有标题条、更没有菜单条和控制条的矩形区域。视图窗口不能单独存在,必须依附于一个框架窗口,参见图12-11 a)。主框架窗口负责管理标题条、菜单条、控制条、加速键和视图窗口或文档子窗口,参见图12-11 b)。
a) 框架窗口与视图
b) MDI框架窗口与子窗口
图12-11 框架窗口
框架窗口(类)也是通过文档模板(类)与视图(类)及文档(类)联系在一起的。MFC中框架窗口类为从窗口类CWnd派生的类CFrameWnd,参见图12-12。
SDI应用程序的主框架窗口一般直接以CFrameWnd为基类,例如:
class CMainFrame : public CFrameWnd {
protected: // 仅从序列化创建 }
但MDI应用程序的主框架窗口则一般以其派生类CMDIFrameWnd为基类,例如:
图12-12 框架窗口类的层次结构
CMainFrame();
DECLARE_DYNCREATE(CMainFrame) ... ...
class CMainFrame : public CMDIFrameWnd {
DECLARE_DYNAMIC(CMainFrame)
public:
11
}
CMainFrame(); ... ...
而MDI中文档子窗口的框架窗口,则从另一个框架窗口类CMDIChildWnd派生。例如:
class CChildFrame : public CMDIChildWnd {
DECLARE_DYNCREATE(CChildFrame)
public: }
CChildFrame(); ... ...
12.2.4 视图类
视图是文档与用户的接口,为用户提供观察、选择、编辑文档数据的交互界面。MFC中的视图类为从CWnd派生的CView类及其派生类。
MFC应用程序的视图类的基类一般为CView,其他常用的视图基类有CScrollView、C[Rich]EditView、CFormView、CHtmlView、(MFC 8.0新加的)CWndFormsView和(MFC 9.0功能包新加的)CTabView,参见图12-13。
1.CView类
CView是用户视图类的默认基类,也是其他各种MFC视图类的基类。例如:
class CTestView : public CView { protected: // 仅从序列化创建
CTestView();
DECLARE_DYNCREATE(CTestView)
// 属性 public: ……
CTestDoc* GetDocument() const;
图12-13 视图类的层次结构
12
// 重写 public: ……
protected:
CDocument* m_pDocument;
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
// 生成的消息映射函数 protected: };
1)CView类的常用成员函数有:
CDocument* GetDocument( ) const; // 获得对应文档类对象的指针 virtual void OnInitialUpdate( ); // 初始化虚消息响应函数,可覆盖 virtual void OnActivateView( BOOL bActivate, CView* pActivateView,
CView* pDeactiveView ); // 当视图窗口被激活或非激活时被调用
virtual void OnDraw( CDC* pDC ) = 0; // 纯虚函数,必须覆盖 2)视图类从其基类CWnd继承的常用成员函数有:
CDC* GetDC( ); // 获得视图窗口的DC
int ReleaseDC( CDC* pDC ); // 释放视图窗口的DC
void GetClientRect( LPRECT lpRect ) const; // 获得客户区矩形 void GetWindowRect( LPRECT lpRect ) const; // 获得窗口矩形 // 获得需重绘的最小矩形
BOOL GetUpdateRect( LPRECT lpRect, BOOL bErase = FALSE ); // 改变窗口的位置和尺寸
void MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE ); void MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE ); CFrameWnd* GetParentFrame( ) const; // 获得父框架窗口的指针 CFrameWnd* GetTopLevelFrame( ) const; // 获得顶层框架窗口的指针 void Invalidate( BOOL bErase = TRUE ); // 使整个客户区矩形无效重画 void UpdateWindow( ); // 通过发送WM_PAINT消息来更新客户区
13
DECLARE_MESSAGE_MAP()
// 重绘窗口,相当于调用Invalidate和UpdateWindow
BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, CRgn* prgnUpdate = NULL,
UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
CWnd* SetCapture( ); // 设置鼠标捕获
:: BOOL ReleaseCapture(VOID); // 释放设置鼠标捕获
CWnd* GetDlgItem( int nID ) const; // 获得nID对应的控件窗口指针
UINT GetDlgItemInt( int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE ) const; // 获得/设置控件中显示的整数
void SetDlgItemInt( int nID, UINT nValue, BOOL bSigned = TRUE ); int GetDlgItemText( int nID, LPTSTR lpStr, int nMaxCount ) const; int GetDlgItemText( int nID, CString& rString ) const; // 获得/设置控件中显示的串
void SetDlgItemText( int nID, LPCTSTR lpszString );
2.GetDocument
默认情况下,MFC会自动在派生的视图类中覆盖其成员函数GetDocument,使其能够获得派生的文档类指针。应用程序中的GetDocument函数一般有两个版本:
? 在头文件中定义的正式版(内联函数):
#ifndef _DEBUG // TestView.cpp 中的非调试版本 inline CTestDoc* CTestView::GetDocument() const
{ return reinterpret_cast
? 在代码文件定义的测试版:
#ifdef _DEBUG ... ...
CTestDoc* CTestView::GetDocument() const // 调试版本是内联的 {
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc))); return (CTestDoc*)m_pDocument;
14
}
#endif //_DEBUG
在视图类中可以调用GetDocument函数来获得对应的文档对象,从而可显示、输出、编辑和修改文档数据。例如在OnDraw函数中MFC会自动加入的语句:
// CTestView 绘制
void CTestView::OnDraw(CDC* /*pDC*/) { }
CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
12.2.5 创建过程
MFC应用程序的文档-视图结构中各个对象的创建,完全由系统控制,对用户是透明(黑箱)的。但是,为了能正确使用窗口和文档对象,我们需要了解它们创建的顺序和过程,参见图12-14。
用户打开文档 创建应用程序对象 用户新建文档 调用文档类的Serialize函数 创建文档对象 文档数据可用 调用视图类的OnInitialUpdate函数 创建主框架窗口对象 调用视图类的OnDraw函数 创建视图对象 调用视图类的各种消息响应函数 调用视图类的OnSize函数 图12-14 创建SDI应用程序的主要过程
15