A Frame with a View
对于 MFC 程序员来说通常是把框架窗口的客户区作为一个分离的视图类子窗口来管理 . 主框架窗口负责 ” 装饰 ” 工作 , 如菜单条和工具条的安置 . 而视图类则仅仅负责呈现应用程序最重要的信息 . 这种抽象对处理 MDI 和分割窗口非常便利 , 稍后我们再详细讨论它们 .
视图类可以是具有窗口句柄 HWND 的任何东西 ( 在 MFC 中视图类必须是 CWnd 及其子类 ), 在主框架窗口 WM_CREATE 消息映射函数中把其成员变量 m_hWndClient 设置为 HWND 即可 . 例如可以把咱们的 SDI 程序位图绘制功能移植到视图类中完成 , 你可以如下定义一个视图类 :
class CBitmapView : public CWindowImpl<CBitmapView> {
public:
CBitmapView();
~CBitmapView();
BEGIN_MSG_MAP(CBitmapView)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&);
private:
HBITMAP m_hBmp;
};
如下使用此视图类:
LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&) {
…
// Create the View (m_view is of type CBitmapView)
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL,
WS_CHILD | WS_VISIBLE,
WS_EX_CLIENTEDGE);
return 0;
}
现在 , 当框架窗口大小发生变化时 , 视图类能自动调整其大小并与菜单栏 , 工具条 , 命令条和状态条紧密衔接充满整个框架窗口区域 .
ATL 和 WTL 的大部分窗口类都能作为视图类来工作 . 你可以使用所有窗口控件类和通用控件封装类作为视图类 . 例如 , 把 m_view 由 CBitmapView 类改为 CEdit 控件类 ( 定义在 atlctrls.h), 你就有了一个自己的文字编辑器 ( 见 Figure 6)
Figure 6: Simple Text Editor
如果你想继承自一个 ATL 窗口封装类并将其作为视图类 , 你可以用两种不同的继承方法来实现 : C++ 方法继承和窗口化方法 ---- 超类化 ( super-classing ), 这样就可以添加额外功能和消息处理 . 例如 , 继承自 CAxWindow , 你可以处理 HTML 网页 .
// Inherit the C++ way to inherit CAxWindow functionality
class CHtmlView : public CWindowImpl<CHtmlView, CAxWindow > {
public:
// Inherit the Windows way to pre-process Windows messages
DECLARE_WND_SUPERCLASS(NULL, CAxWindow::GetWndClassName())
BEGIN_MSG_MAP(CHtmlView)
…
END_MSG_MAP()
CHtmlView() {
// Init control hosting (defined in atlhost.h)
AtlAxWinInit();
}
};
我们可以用此视图类来处理网页浏览了 (Figure 7 显示了效果 )
LRESULT CMainFrame::OnCreate(UINT, WPARAM, LPARAM, BOOL&)
{
// Create the View (m_view is of type CHtmlView)
m_hWndClient = m_view.Create(m_hWnd, rcDefault,
"http://www.microsoft.com",
WS_CHILD | WS_VISIBLE,
WS_EX_CLIENTEDGE);
return 0;
}
Figure 7: Using the New View to Host a Web Page
Maintaining the MRU
To be continued···