MFC--CSplitterWnd

来源:互联网 发布:2017詹姆斯的数据 编辑:程序博客网 时间:2024/04/20 08:12

csplitterwnd 类
提供分离窗口的功能,是一个窗口包含多个方格。
CSplitterWnd
CObject
└CCmdTarget
└CWnd
└CSplitterWnd
CSplitterWnd类提供一个分隔器窗口的功能,分隔器窗口是一个包含有多个窗格的窗口。窗格通常是应用程序特定的由CView派生的对象,但它也可以是具有适当子窗口ID的任何CWnd对象。
一个CSplitterWnd对象通常被嵌入CFrameWnd或CMDIChildWnd父对象。你应按如下步骤创建一个CSplitterWnd对象:

1. 在父框架中嵌入一个CSplitterWnd成员变量。
2. 重载父框架的CFrameWnd::OnCreateClient成员函数。
3. 从重载的OnCreateClient函数中调用类CSplitterWnd的Create或CreateStatic成员函数。
        调用Create成员函数可以创建一个动态的分隔器窗口。动态的分隔器窗口通常用于创建和滚动同一文档的多个窗格或视。框架将自动为该分隔器创建一个起始窗格;然后,当用户操纵该分隔器窗口的控件时,框架创建,调整大小,并且排列其它的窗格。

Create()简介:       

       最大可创建2*2,当你调用Create时,应指定一个最小行高度和最小列宽度,这两个最小值被用来确定窗格什么时候太小以致于不能被完全显示。在调用了Create之后,你可以通过调用SetColumnInfo和SetRowInfo来调整这些最小值。你还可以使用SetColumnInfo和SetRowInfo成员函数来给一列设置一个“理想的”宽度,以及给一行设置一个“理想的”高度。当框架显示一个分隔器窗口时,首先显示父框架,然后才显示分隔器窗口。然后,框架从分隔器窗口的客户区左上角至右下角,根据窗格的理想尺寸以行或列来排放各个窗格。动态分隔器窗口中的所有窗格都必须是同一个类的窗格。读者熟悉的支持动态分隔器窗口的应用程序包括Microsoft Word和Microsoft Excel。         

CreateStatic()简介:       

        最大可创建16*16,使用CreateStatic成员函数可以创建一个静态分隔器窗口。用户只能修改静态分隔器窗口中的窗格的尺寸,但是不能改变其中的窗格序号和次序。
        在创建静态分隔器时必须专门创建该静态分隔器的所有窗格。你必须在父框架的OnCreateClient成员函数返回之前确保创建了所有窗格,否则,框架将不能正确显示该窗口。
        CreateStatic成员函数将使用为0的最小行高度和最小列宽度来自动初始化一个静态分隔器。在调用了Create之后,可以通过调用SetColumnInfo和SetRowInfo成员函数来调整这两个最小值。在调用CreateStatic之后,你也可以使用SetColumnInfo和SetRowInfo成员函数来指定你所希望的理想窗格值。
        静态分隔器中的窗格通常属于不同的类。给予静态分隔器窗口的示例,参见图形编辑器和Windows文件管理器。分隔器窗口支持特殊的滚动条(除窗格可能带有的滚动框之外)。这些滚动条是CSplitterWnd对象的子对象并且被窗格共享。
        当你创建这个分隔器窗口时,你创建了这些特殊的滚动条。例如,如果一个CSplitterWnd具有一行,两列,则WS_VSCROLL风格将显示两个窗格共享的垂直滚动条。当用户移动这个滚动条时,WM_VSCROLL消息将被发送给两个窗格。当窗格设置滚动条位置时,这个共享滚动条将被设置。
        有关动态分隔器窗口的更多信息,参见“Visual C++程序员指南”中的文章“多文档类型,视和框架窗口”中的“分隔器窗口”;和Visual C++联机文档中的“TN029:分隔器窗口”;以及CSplitterWnd类概述。有关如何创建动态分隔器窗口的更多信息,参见“Visual C++联机教程”中的“在增强视的Scribble中添加分隔器窗口”;和MFC常规示例VIEWEX。
#include
请参阅:CView, CWnd
类成员
 
CSplitterWnd类成员
构造 CSplitterWnd 构造一个CSplitterWnd对象
Create 创建一个动态的分隔器窗口并将它与一个CSplitterWnd对象连接
CreateStatic 创建一个静态的分隔器窗口并将它与一个CSplitterWnd对象连接
CreateView 在一个分隔器窗口中创建一个窗格

操作符 GetRowCount 返回当前窗格行的计数值
GetColumnCount 返回当前窗格列的计数值
GetRowInfo 返回指定行的信息
SetRowInfo 设置指定行的信息
GetColumnInfo 返回指定列的信息
SetColumnInfo 设置指定列的信息
GetPane 返回位于指定行和列处的窗格
IsChildPane 确定窗口是否是此分隔器窗口的当前子窗格
IdFromRowCol 返回位于指定行和列处的窗格的子窗口ID
RecalcLayout 在调整行或列尺寸后调用此函数来重新显示该分隔器窗口
GetScrollStyle 返回共享滚动条的风格
SetScrollStyle 为分隔器窗口的共享滚动条指定新的滚动条风格

可重载 OnDrawSplitter 绘制一个分隔器窗口的图像
OnInvertTracker 绘制一个分隔器窗口的图像,使它具有与框架窗口相同的大小和形状
CreateScrollBarCtrl 创建一个共享的滚动条控件
DeleteView 从分隔器窗口中删除一个视图
SplitRow 表明一个框架窗口是否是水平分隔的
SplitColumn 表明一个框架窗口是否是垂直分隔的
DeleteRow 从分隔器窗口中删除一行
DeleteColumn 从分隔器窗口中删除一列
GetActivePane 根据焦点或框架中的活动视来确定活动窗格
SetActivePane 在框架中设置一个活动窗格
CanActivateNext 检查Next Pane或Previous Pane命令当前是否有效
ActivateNext 执行Next Pane或Previous Pane命令
DoKeyboardSplit 执行键盘分隔命令,通常是“Window Split”
DoScroll 执行分隔窗口的同步滚动
DoScrollBy 将分隔窗口滚动给定的像素数

一、基本的CSplitterWnd的使用

1. 在CMainFrame中添加一个CSplitterWnd成员:
CSplitterWnd m_splitterwnd1;
2. 基于CView创建两个新的视图类,CViewLeft和CViewRight,一个用于在左边显示,一个用于在右边显示(如果是CFormView需设置为child属性)。
3. 重载CMainFrame的OnCreateClient函数,在并其中调用CSplitterWndr的CreateStatic函数创建该分割窗口,CreateView函数创建左右两个视图,SetColumnInfo设定分割窗口的

列的宽度:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// TODO: 在此添加专用代码和/或调用基类
m_mysplitter1.CreateStatic(this, 1, 2);//创建一个一行二列的分割窗口
m_mysplitter1.CreateView(0, 0, RUNTIME_CLASS(CViewLeft), CSize(0, 0),
pContext);//建立第0行第0列的视图
m_mysplitter1.CreateView(0, 1, RUNTIME_CLASS(CViewRight), CSize(0, 0),
pContext);//建立第0行第1列的视图
m_mysplitter1.SetColumnInfo(0, 250, 10);//设定某列的宽度,这里表示设定第0列的理想宽度为250像素,最小宽度为10像素(什么是最小宽度?没弄明白)
return TRUE;
//return CFrameWnd::OnCreateClient(lpcs, pContext);
}

运行后就可以看到生成了分割为左右两个视图的窗口。

二、为分割窗添加一些自己需要的功能

从系统的CSplitterWnd类派生一个新类。
在类视图中右键,选择“添加”->“类”,在弹出窗口中选择MFC类,输入新类的名字CMySplitter,基类选择为CWnd(这里基类的选项里面没有CSplitterWnd,所以要先选择Cwnd

)。然后把生成的MySplitter.h和MySplitter.cpp里面的三个地方的“Cwnd”改成“CSplitterWnd”。
MySplitter.h中:
class CMySplitter : public CSplitterWnd
Mysplitter.cpp中:
IMPLEMENT_DYNAMIC(CMySplitter, CSplitterWnd)
BEGIN_MESSAGE_MAP(CMySplitter, CSplitterWnd)

1. 双击分隔栏展开或者收起左边的一栏
重载OnLButtonDblClk函数:
void CMySplitterWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//CSplitterWnd::OnLButtonDblClk(nFlags, point);
int left, min;
GetColumnInfo(0, left, min);//得到第0栏(即左边的一栏)的宽度
if(left == 0 || left == min)//如果当前已经是收起的状态
{
SetColumnInfo(0, 250, 10);//重新设置左边一栏的宽度,这里设置为250,即展开
}
else
{
SetColumnInfo(0, 0, 10);//重新设置左边一栏的宽度,这里设置为0,即收起
}
RecalcLayout();//重新构建窗口布局
}

2. 设置分隔栏的宽度
在CMySplitter的构造函数中(这里是把宽度设为11像素):
m_cxSplitterGap = 11;
m_cxSplitter = 11;
几个相关变量的意义:
//int   m_cxSplitter,   m_cySplitter;              //   size   of   splitter   bar
//int   m_cxBorderShare,   m_cyBorderShare;        //   space   on   either   side   of   splitter
//int   m_cxSplitterGap,   m_cySplitterGap;        //   amount   of   space   between   panes
//int   m_cxBorder,   m_cyBorder;                  //   borders   in   client   area  
3. 禁止拖动分隔栏的位置
(1)重载OnLButtonDown函数,改成什么都不做:
void CMySplitter::OnLButtonDown(UINT nFlags, CPoint point)
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
  //CSplitterWnd::OnLButtonDown(nFlags, point);
}
(2)重载OnMouseMove函数,也改成什么都不做:
void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
  //CSplitterWnd::OnMouseMove(nFlags, point);
}
4. 在分隔栏上添加一个”按钮“
(1)在资源视图中导入两张位图资源,分另是一个向左的箭头和一个向右的箭头,图片大小为(6*31)像素:IDB_BITMAP_LEFT,IDB_BITMAP_RIGHT
(2)为CMySplitter类添加显示该“按钮”相关的成员:
CBitmap m_bitmapleft;    //左箭头位图
CBitmap m_bitmapright;   //右箭头位图
CDC m_dcMem;       //
CRect m_rectImgBtn;    //显示该“按钮”的矩形区域
(3)添加一个成员函数得到显示该“按钮”的矩形区域:
//这个函数用来得到显示该按钮的矩形区域
void CMySplitter::GetImgBtnRect(void)
{
  CRect r;
  int left, min;
  GetWindowRect(&r);
  GetColumnInfo(0, left, min);
  m_rectImgBtn.SetRect(left+2+2, r.Height()/2-16,
    left+2+8, r.Height()/2+15); //这里这么写是根据WindowsXP显示的分隔栏来确定的,要用绘图软件测一下
  if(left == 250)    //这里用到了正常显示下的左栏是250像素宽
  {
   if(m_dcMem != NULL)
   {
    m_dcMem.SelectObject(m_bitmapleft);    //这个DC选择左箭头的图片
   }
  }
  else
  {
   if(m_dcMem != NULL)
   {
    m_dcMem.SelectObject(m_bitmapright);    //这个DC选择右箭头的图片
   }
  }
}
(4)重载OnDrawSplitter函数,画出该按钮:
void CMySplitter::OnDrawSplitter(CDC* pDC, ESplitType nType,
         const CRect& rect)
{
  // TODO: 在此添加专用代码和/或调用基类
  CSplitterWnd::OnDrawSplitter(pDC, nType, rect);  //本来的画分隔栏
  if(pDC != NULL)
  {
   if(m_dcMem == NULL)
   {
    m_dcMem.CreateCompatibleDC(NULL);      //CreateCompatibleDC参数为NULL表示创建一个与当前显示器兼容的DC
   }
   GetImgBtnRect();
   pDC->BitBlt(m_rectImgBtn.left, m_rectImgBtn.top,
    m_rectImgBtn.Width(), m_rectImgBtn.Height(),
    &m_dcMem, 0, 0, SRCCOPY);        //从m_dcMem中把图片复制到pDC中并画出来(大概是这个意思)
   }
  }
}
(5)重载OnLButtonUp函数,使得点击该“按钮”时可以收起或者展开左栏
void CMySplitter::OnLButtonUp(UINT nFlags, CPoint point)
{
  // TODO: 在此添加消息处理程序代码和/或调用默认值
  GetImgBtnRect();
  if(m_rectImgBtn.PtInRect(point))   //如果鼠标当前是在“按钮”区域内
  {
   //这里判断一下左栏是否收起了,如果是,隐藏左栏;不是则显示左栏
   //通过GetColumnInfo和SetColumnInfo
  }
  else
  {
   CSplitterWnd::OnLButtonUp(nFlags, point);
  }
}
(6)重载OnMouseMove函数,当鼠标移动到“按钮”上时,把鼠标形状变成手形
void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
  GetImgBtnRect();
  if(m_rectImgBtn.PtInRect(point))
  {
   ::SetCursor(LoadCursor(NULL, IDC_HAND));
  }
  else
  {
   ::SetCursor(LoadCursor(NULL, IDC_ARROW));
  }
}

原创粉丝点击