MFC程序员WTL指南(8)分隔窗口
2008-01-19 20:26:47 来源:WEB开发网核心提示:现在运行我们的程序就可以看到分隔条,即使没有创建任何窗格窗口它仍具有基本的行为,MFC程序员WTL指南(8)分隔窗口(4),你可以拖动分隔条,用鼠标双击分隔条使其移到窗口的中间位置,不像MFC那样必须是CView的派生类,窗格窗口只要有WS_CHILD样式就行了,为了演示分隔窗口的不同使用方法,我将使用一个CListV
现在运行我们的程序就可以看到分隔条,即使没有创建任何窗格窗口它仍具有基本的行为。你可以拖动分隔条,用鼠标双击分隔条使其移到窗口的中间位置。
为了演示分隔窗口的不同使用方法,我将使用一个CListViewCtrl派生类和一个简单的CRichEditCtrl,下面是从CClipSpyListCtrl类摘录的代码,我们在左边的窗格使用这个类:
typedef CWinTraitsOR<LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER>
CListTraits;
class CClipSpyListCtrl :
public CWindowImpl<CClipSpyListCtrl, CListViewCtrl, CListTraits>,
public CCustomDraw<CClipSpyListCtrl>
{
public:
DECLARE_WND_SUPERCLASS(NULL, WC_LISTVIEW)
BEGIN_MSG_MAP(CClipSpyListCtrl)
MSG_WM_CHANGECBCHAIN(OnChangeCBChain)
MSG_WM_DRAWCLIPBOARD(OnDrawClipboard)
MSG_WM_DESTROY(OnDestroy)
CHAIN_MSG_MAP_ALT(CCustomDraw<CClipSpyListCtrl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
//...
};
如果你看过前面的几篇文章就会很容易读懂这个类的代码。它响应WM_CHANGECBCHAIN消息,这样就可以知道是否启动和关闭了其它剪贴板查看程序,它还响应WM_DRAWCLIPBOARD消息,这样就可以知道剪贴板的内容是否改变。
由于分隔窗口窗格内的子窗口在程序运行其间一直存在,我们也可以将它们设为CMainFrame类的成员:
class CMainFrame : public ...
{
//...
protected:
CSplitterWindow m_wndVertSplit;
CClipSpyListCtrl m_wndFormatList;
CRichEditCtrl m_wndDataViewer;
};
创建一个窗格内的窗口
既然已经有了分隔窗口和子窗口的成员变量,填充分隔窗口就是一件简单的事情了。先创建分隔窗口,然后创建两个子窗口,使用分隔窗口作为它们的父窗口:
LRESULT CMainFrame::OnCreate ( LPCREATESTRUCT lpcs )
{
//...
// Create the splitter window
const DWORD dwSplitStyle = WS_CHILD | WS_VISIBLE |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
dwSplitExStyle = WS_EX_CLIENTEDGE;
m_wndVertSplit.Create ( *this, rcDefault, NULL,
dwSplitStyle, dwSplitExStyle );
// Create the left pane (list of clip formats)
m_wndFormatList.Create ( m_wndVertSplit, rcDefault );
// Create the right pane (rich edit ctrl)
const DWORD dwRichEditStyle =
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE;
m_wndDataViewer.Create ( m_wndVertSplit, rcDefault,
NULL, dwRichEditStyle );
m_wndDataViewer.SetFont ( AtlGetStockFont(ANSI_FIXED_FONT) );
// Set the splitter as the client area window, and resize
// the splitter to match the frame size.
m_hWndClient = m_wndVertSplit;
UpdateLayout();
m_wndVertSplit.SetSplitterPos ( 200 );
return 0;
}
注意两个类的Create()函数都用m_wndVertSplit作为父窗口,RECT参数无关紧要,因为分隔窗口会重新调整它们的大小,所以可以使用CWindow::rcDefault。
最后就是将窗口的句柄传递给分隔窗口的窗格,这一步也需要在UpdateLayout()调用之前完成,这样最终所有的窗口都有正确的大小。
LRESULT CMainFrame::OnCreate ( LPCREATESTRUCT lpcs )
{
//...
m_wndDataViewer.SetFont ( AtlGetStockFont(ANSI_FIXED_FONT) );
// Set up the splitter panes
m_wndVertSplit.SetSplitterPanes ( m_wndFormatList, m_wndDataViewer );
// Set the splitter as the client area window, and resize
// the splitter to match the frame size.
m_hWndClient = m_wndVertSplit;
UpdateLayout();
m_wndVertSplit.SetSplitterPos ( 200 );
return 0;
}
现在,list控件上增加了几栏,结果看起来是这个样子:
需要注意的是分隔窗口对放进窗格的窗口类型没有限制,不像MFC那样必须是CView的派生类。窗格窗口只要有WS_CHILD样式就行了,没有任何其他限制。
更多精彩
赞助商链接