苦思冥想快2天的SplitContainer的Click事件控制SplitterDistance的问题,终于让我查出是什么问题!哈哈哈!
这个按说可以说是个微软的bug了,或者说是设计的时候没有考虑太多。有些东西他们设计也不是很精致亚,嘿嘿。
看张图可能你就明白了。

当鼠标按下的时候,splitContainer会响应自己的MouseDown事件,在这个事件里,他会生成一个新的层从而盖住了下面真正的Splitter。从而会影响到Click时间的执行情况,具体是啥情况就说不清楚了,我猜是:本来Click能好好的执行,可偏偏半路杀出一个MouseDown,这个MouseDown新产生的阴影层挡住了MouseUp的执行(不能算是一次Click操作)。从而使得界面闪了一下就又恢复原状了。
后来的实验也能证实,分别在MouseDown、MouseUp、MouseClick中实验。只有MouseDown可以完全正常执行。
解决方法:
其中一些思路来自于CollapsibleSplitter from codeproject
在Spliter中间画出一部分,点击这部分的时候进行快速切换操作,而点击其它部分的时候,就是控件默认调整
新建class继承自SplitContainer,然后覆盖OnPaint方法
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = this.SplitterRectangle;
g.FillRectangle(new SolidBrush(Color.Aqua), r);
if (Orientation == Orientation.Vertical)
{
rr = new Rectangle(r.X, (int)r.Y + ((r.Height - 115) / 2), 8, 115);
this.SplitterWidth = 8;
g.FillRectangle(new SolidBrush(hotColor), new Rectangle(rr.X + 1, rr.Y, 6, 115));
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y, rr.X + rr.Width - 2, rr.Y);
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y + rr.Height, rr.X + rr.Width - 2, rr.Y + rr.Height);
if (this.Enabled)
{
// draw the arrows for our control image
// the ArrowPointArray is a point array that defines an arrow shaped polygon
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + 3));
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + rr.Height - 9));
}
}
//do not Dispose,is it Ok???
//g.Dispose();
}
然后在MouseMove中进行判断当前鼠标是否在所画的区域即可,然后分别调用不同的事件处理。
private void OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
// check to see if the mouse cursor position is within the bounds of our control
System.Console.WriteLine(e.X.ToString() + " " + e.Y.ToString());
if (e.X >= rr.X && e.X <= rr.X + rr.Width && e.Y >= rr.Y && e.Y <= rr.Y + rr.Height)
{
if (!this.hot)
{
this.hot = true;
this.Cursor = Cursors.Hand;
this.Invalidate();
}
}
else
{
if (this.hot)
{
this.hot = false;
this.Invalidate(); ;
}
this.Cursor = Cursors.Default;
if (controlToHide != null)
{
if (!controlToHide.Visible)
this.Cursor = Cursors.Default;
else // Changed in v1.2 to support Horizontal Splitters
{
if (this.Orientation == Orientation.Vertical)
{
this.Cursor = Cursors.VSplit;
}
else
{
this.Cursor = Cursors.HSplit;
}
}
}
}
}
另外还要覆盖MouseDown事件。如果MouseDown的时候是在所画的区域则不调用base的MouseDown
protected override void OnMouseDown(MouseEventArgs e)
{
if (!this.hot)
base.OnMouseDown(e);
}
浙公网安备 33010602011771号