- ·上一篇内容:视频服务器在监控中的作用
- ·下一篇内容:论C#变得越来越臃肿是不可避免的
C#个性化窗体界面的制作方法
以下是上述画皮肤方法的具体实现部分,我只举一个画左边框的代码示例,其它的部分请读者举一返三:
private void DrawMiddle_Left(Graphics g)
{
Brush brush = new TextureBrush(Middle_Left, new Rectangle(0, 0,
Middle_Left.Width, Middle_Left.Height));
g.FillRectangle(brush, 0, TITLE_WIDTH, Middle_Left.Width,
Height - Bottom_Middle.Height - TITLE_WIDTH);
}
衣服穿上了,现在我们的程序就有了不同的外观:
看上去已经很酷了,不过只是花架子,因为边框,标题栏,系统按纽都是我们自己画上去的假的边框,标题栏和系统按纽,所以这个窗体既不能移动也不能zi you的放大缩小,点关闭都没用。以前我们写程序从来都不需要关心这个的,这些都是窗体的基本功能呀?没有从来都没有想到这个竟然还会是个问题吧?
怎么办呢?答案就是我们自己来做,不过会比较麻烦,因为取消掉了边框,所以Windows不会帮你发出系统事件,你捕捉不到系统发生了什么事情的话,就没有办法写下响应代码,所以我们要自己检测鼠标的坐标,并根据鼠标的动作,自己来发出事件消息,然后进行响应。
首先我们先定义出一些响应事件的代码,我定义了一个抽象的基类MouseAction,用来表示所有的鼠标事件,它有一个抽象方法Action:
public abstract class MouseAction
{
public abstract void Action(int ScreenX, int ScreenY, System.Windows.Forms.Form form);
}
然后再来定义出它的各个派生类来表示出具体每个鼠标事件响应的代码。
下面是一个向右拉伸窗口事件的代码响应:
public class MouseDrag : MouseAction
{
private int x, y;
public MouseDrag(int hitX, int hitY)
{
x = hitX;
y = hitY;
}
public override void Action(int ScreenX, int ScreenY, System.Windows.Forms.Form form)
{
form.Location = new Point(ScreenX - x, ScreenY - y);
}
}
接下来我们开始编写发出事件的代码,先定义几个变量:
private int LEFT = 5, RIGHT = 5, BOTTOM = 5, TOP = 5, TITLE_WIDTH = 45;//边框和标题栏的大小
private int x = 0, y = 0;//保存鼠标的临时坐标
private MouseAction mouse;//鼠标的事件响应对象
然后在Form的MouseDown事件中记录下鼠标的当前坐标:
x = e.X;
y = e.Y;
附:e为System.Windows.Forms.MouseEventArgs
然后再根据鼠标的坐标定义出事件响应对象:
//鼠标点击左上边框
if((e.X <= LEFT + 10 && e.Y <= TOP) || (e.Y <= TOP + 10 && e.X <= LEFT))
...{
mouse = new MouseSizeTopLeft(Location.X, Location.Y, Width, Height);
return;
}
//当然有的事件也可以直接响应:
//鼠标点击系统关闭按纽
if(e.X > Width - 20 && e.Y > 6 && e.X < Width - 20 + SysButton_Min.Width && e.Y < 6 + SysButton_Min.Height)
...{
Close();
return;
}
//大部分的事件响应实际上是在MouseMove事件中完成的:
private void Form_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
...{
this.Parent.Cursor = CheckCursorType(e.X, e.Y);//改变鼠标的指针形状
if(mouse != null)
...{
mouse.Action(Control.MousePosition.X, Control.MousePosition.Y, this);//执行时间响应
//注意坐标是Control.MousePosition这个静态变量给出的,它的值为鼠标在桌面上的全局坐标
}
}
//给出每个不同部位的鼠标的指针形状:
private Cursor CheckCursorType(int X, int Y)
...{
if(((X <= LEFT + 10 && Y <= TOP) || (Y <= TOP + 10 && X <= LEFT))
|| ((X >= Width - RIGHT - 10 && Y >= Height - BOTTOM)
|| (Y >= Height - BOTTOM - 10 && X >= Width - RIGHT)))
...{
return Cursors.SizeNWSE;
}
else if(((Y <= TOP + 10 && X >= Width - RIGHT)
|| (Y <= TOP && X >= Width - RIGHT - 10))
|| ((X <= LEFT && Y >= Height - BOTTOM - 10)
|| (Y >= Height - BOTTOM && X <= LEFT + 10)))
...{
return Cursors.SizeNESW;
}
else if(X >= Width - RIGHT || X <= LEFT)
...{
return Cursors.SizeWE;
}
else if(Y >= Height - BOTTOM || Y <= TOP)
...{
return Cursors.SizeNS;
}
else
...{
return Cursors.Arrow;
}
}
//最后在MouseUp事件中将mouse变量释放掉:
private void Form_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
...{
mouse = null;
}
//为了更加逼真,还可以加上标题栏的双击最大化或者还原的事件:
private void Form_DoubleClick(object sender, System.EventArgs e)
...{
if(y > TOP && y < TITLE_WIDTH)
...{
if(WindowState == FormWindowState.Normal)
...{
WindowState = FormWindowState.Maximized;
SysButton = SysButton_Restore;
Invalidate();
}
else if(WindowState == FormWindowState.Maximized)
...{
WindowState = FormWindowState.Normal;
SysButton = SysButton_Max;
Invalidate();
}
}
}
防止窗体被缩小成一个点,最好给窗口的MinimumSize赋上一个适当的值,例如200,200。
总结:
现在编译你的程序,运行试试,你的窗体已经拥有正常窗体所拥有的全部功能,并且还具有与众不同的外观,不明就里的人一下子还猜不出来你是怎么弄的,好了,乘别人还不知道,赶快拿出去炫耀一下吧。
本文源自:翔宇亭——IT乐园(http://www.biye5u.com),转载请保留此信息!
微信搜索“优雅的代码”关注本站的公众号,或直接使用微信扫描下面二维码关注本站公众号,以获取最新内容。
个人成长离不开各位的关注,你的关注就是我继续前行的动力。