使用CSplitterWnd类作窗口分割
使用平台:win7 64bit
使用环境:VS2012
1、CSplitterWnd介绍
上图是从MSDN中截取的类的继承图表,CSplitterWnd类继承自CWnd类。这个类主要就是提供窗口分割的功能。
2、使用CSplitterWnd类作窗口分割
建立单文档程序,选择不支持文档-视图框架。目的是为了使得程序结构更加的灵活,适合自己DIY。建立好的程序结构中就回存在有三个基础的类。
CXXXApp类 tips: (XXX)是建立工程的时候自己取得名字,代表的是这个工程的实例
CChildView类
CMainFrame类
窗口的分割要在CMainFrame类中进行完成。目前例子里面我们分割出如图所示的效果:
从上图中可以看到窗口分割成了5个部分,左边的白色部分和右边的四个黑色窗口部分。
在CMainFrame类中添加两个成员:
CSplitterWnd m_spliter1; //原版的CSplitterWnd
CMySplitterWndEx m_spliter2; //在CSplitterWnd上做修改之后
然后重载CMainFrame类的OnCreateClient()函数,在该函数中添加如下代码:
- BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
- {
- CRect rct;
- GetClientRect(&rct); //获取窗口大小
- int nRcWidth = rct.Width();
- int nRcHeight = rct.Height();
- //用第一个分隔条分割成1行2列
- if(m_spliter1.CreateStatic(this, 1, 2)==NULL) return FALSE;
- //分割的第一行第一列指定动态创建对象CLeftView
- //指定窗口宽度是1/4界面宽度,高度为整个界面高度
- m_spliter1.CreateView(0,0,RUNTIME_CLASS(CLeftView),CSize(nRcWidth / 4, nRcHeight), pContext);
- //对m_spliter1分割的第二个区域再使用m_spliter2进行分割,分割成2*2个区域
- if (m_spliter2.CreateStatic(&m_spliter1, 2, 2, WS_CHILD|WS_VISIBLE, m_spliter1.IdFromRowCol(0, 1)) == NULL) return FALSE;
- //和上述差不多,指定动态创建的对象为CLTView
- m_spliter2.CreateView(0, 0, RUNTIME_CLASS(CLTView), CSize(nRcWidth / 8 * 3, nRcHeight/2), pContext);
- m_spliter2.CreateView(0, 1, RUNTIME_CLASS(CLTView), CSize(nRcWidth / 8 * 3, nRcHeight/2), pContext);
- m_spliter2.CreateView(1, 0, RUNTIME_CLASS(CLTView), CSize(nRcWidth / 8 * 3, nRcHeight/2), pContext);
- m_spliter2.CreateView(1, 1, RUNTIME_CLASS(CLTView), CSize(nRcWidth / 8 * 3, nRcHeight/2), pContext);
- return CFrameWnd::OnCreateClient(lpcs, pContext);
- }
3、分割条的风格DIY
在上面的代码中两个风格条中有一个分割条是自己在原有的分割条上DIY后的,所有才有了黑底蓝色线条的分割,然而默认的分割风格是比较丑陋的。下面来DIY这个类。
向工程中添加一个MFC类,记住是MFC类,很关键!!!
选择其父类为CWnd,因为选择框里面并不能选择CSplitterWnd类,生成之后我们手动把他的继承类改成CSplitterWnd。添加鼠标左键按下的消息响应,并重载OnDrawSplittter函数。
类的定义就成了这个样子(名字可以随便取),为什么前面说的是要添加MFC类?因为MFC类里面才会给我们自动的添加上DECLARE_DYNAMIC(),DELARE_MESSAGE_MAP()这样的宏。也就才能有消息响应的发生。不然这里重载的OnDrawSplittter是无法生效的。
- class CMySplitterWndEx : public CSplitterWnd
- {
- DECLARE_DYNAMIC(CMySplitterWndEx)
- public:
- CMySplitterWndEx();
- virtual ~CMySplitterWndEx();
- protected:
- DECLARE_MESSAGE_MAP()
- public:
- afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnMouseMove(UINT nFlags, CPoint point);
- virtual void OnDrawSplitter(CDC* pDC, ESplitType nType, const CRect& rect);
- };
在类的构造函数里面就可以对分割条的Size进行调整了。
- CMySplitterWndEx::CMySplitterWndEx()
- {
- m_cxSplitterGap = 2;
- m_cxSplitter = 5;
- m_cySplitterGap = 2;
- m_cySplitter = 5;
- }
- void CMySplitterWndEx::OnDrawSplitter(CDC* pDC, ESplitType nType, const CRect& rect)
- {
- CSplitterWnd::OnDrawSplitter(pDC, nType, rect);
- if (pDC != NULL)
- {
- CBrush brush;
- brush.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
- pDC->FillRect(&rect,&brush);
- }
- }
鼠标左键的消息响应纯粹是为了不想让鼠标左键拖动风格窗条的。也就是在消息传递中截获该消息,不让它传向基类。
4、管理分割窗口
((CMainFrame*)AfxGetMainWnd())->你想访问的视图