分享

C# WinForm控件美化扩展系列之实现点击收缩的SplitContainer控件

 木棉下的守望 2014-07-02

很多常用的软件中,我们都可以看到分隔栏(SplitSplitContainer)的使用,而且可以点击然后收缩其中的某个面板,例如QQ游戏大厅:

 

.NET也提供了分隔栏控件(SplitSplitContainer),但是却不能实现点击收缩的功能,不过我们可以在它的基础上实现点击收缩的功能。下面就来详细介绍怎样实现分隔栏控件点击收缩的功能。

 

首先来看看最终需要实现的效果:

 

    现在说明一下实现分隔栏控件点击收缩的功能的原理,原理很简单:

1.       确定点击按钮在分割栏的位置(实现的时候是取分隔栏的中间位置),然后在分隔栏上把按钮画出来。

2.       实现一个属性(CollapsePanel),以便选择使哪一个面板收缩,SplitContainer控件有两个面板,分别是Panel1Panel2

3.       提供一个点击按钮的事件(CollapseClick),当点击按钮的时候响应这个事件,以方便处理点击操作,默认的处理就是收缩和展开面板。

4.       重点,处理SplitContainer控件的鼠标事件(OnMouseMove、OnMouseDown、OnMouseUp、OnMouseLeave),以便处理按钮的点击、是否允许拖动分隔栏和改变控件的鼠标指针样式。

 

下面是SplitContainer控件扩展后的类视图:

 

    下面来看看中要的实现代码:

 

    CollapsePanel属性:

[DefaultValue(typeof(CollapsePanel), "1")]
public CollapsePanel CollapsePanel
{
get { return _collapsePanel; }
set
{
if (_collapsePanel != value)
{
Expand();
_collapsePanel = value;
}
}
}

    重写OnMouseMove方法:

protected override void OnMouseMove(MouseEventArgs e)
{
//如果鼠标的左键没有按下,重置HistTest
if (e.Button != MouseButtons.Left)
{
_histTest = HistTest.None;
}

Rectangle collapseRect = CollapseRect;
Point mousePoint = e.Location;

//鼠标在Button矩形里,并且不是在拖动
if (collapseRect.Contains(mousePoint) &&
_histTest != HistTest.Spliter)
{
base.Capture = false;
SetCursor(Cursors.Hand);
MouseState = ControlState.Hover;
return;
}//鼠标在分隔栏矩形里
else if (base.SplitterRectangle.Contains(mousePoint))
{
MouseState = ControlState.Normal;

//如果已经在按钮按下了鼠标或者已经收缩,就不允许拖动了
if (_histTest == HistTest.Button ||
(_collapsePanel != CollapsePanel.None &&
_spliterPanelState == SpliterPanelState.Collapsed))
{
base.Capture = false;
base.Cursor = Cursors.Default;
return;
}

//鼠标没有按下,设置Split光标
if (_histTest == HistTest.None &&
!base.IsSplitterFixed)
{
if (base.Orientation == Orientation.Horizontal)
{
SetCursor(Cursors.HSplit);
}
else
{
SetCursor(Cursors.VSplit);
}
return;
}
}

MouseState = ControlState.Normal;

//正在拖动分隔栏
if (_histTest == HistTest.Spliter &&
!base.IsSplitterFixed)
{
if (base.Orientation == Orientation.Horizontal)
{
SetCursor(Cursors.HSplit);
}
else
{
SetCursor(Cursors.VSplit);
}
base.OnMouseMove(e);
return;
}

base.Cursor = Cursors.Default;
base.OnMouseMove(e);
}

    重写OnMouseDown方法:

protected override void OnMouseDown(MouseEventArgs e)
{
Rectangle collapseRect = CollapseRect;
Point mousePoint = e.Location;

if (collapseRect.Contains(mousePoint) ||
(_collapsePanel != CollapsePanel.None &&
_spliterPanelState == SpliterPanelState.Collapsed))
{
_histTest = HistTest.Button;
return;
}

if (base.SplitterRectangle.Contains(mousePoint))
{
_histTest = HistTest.Spliter;
}

base.OnMouseDown(e);
}

    重写OnMouseUp方法:

protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
base.Invalidate(base.SplitterRectangle);

Rectangle collapseRect = CollapseRect;
Point mousePoint = e.Location;

if (_histTest == HistTest.Button &&
e.Button == MouseButtons.Left &&
collapseRect.Contains(mousePoint))
{
OnCollapseClick(EventArgs.Empty);
}
_histTest = HistTest.None;
}

重写OnMouseLeave方法:

protected override void OnMouseLeave(EventArgs e)
{
base.Cursor = Cursors.Default;
MouseState = ControlState.Normal;
base.OnMouseLeave(e);
}

以上介绍SplitContainer控件的扩展,希望能对你了解扩展SplitContainer控件有所帮助。
 

 

声明:

本文版权归作者和CS 程序员之窗所有,欢迎转载,转载必须保留以下版权信息,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多