分享
 
 
 

使用Visual C#制作可伸缩个性化窗体

王朝c#·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

使用Visual C#制作可伸缩个性化窗体

卢彦

引言:

谁都希望自己的应用程序能让人留下一个深刻的印象,让自己的程序窗体有一件与众不同的"外衣"是一个好办法。试想:在一大堆的普通窗口中突然跳出一个很酷的界面,一定能让人眼睛一亮进而产生兴趣的。

在VB,VC中如何定制可伸缩个性化窗口早就不是什么秘密了,已经有了大量相关的文章进行介绍,无非都是如何调用系统API之类的方法,但是在.Net中调用API却相对比较麻烦,所以使用.Net制作个性化窗体的文章也有一些,一般都是使用透明背景加图片的方式,所以不能移动或者不能任意放大缩小窗体。那有没有不需要调用系统API的方法来实现可伸缩的个性化窗体的办法呢?当然有,.Net Framework提供了一套非常强大的系统类库,我们下面就要做一个使用"纯".Net打造的可伸缩个性化窗体。

我们需要将窗体所有的"皮肤"全部换成我们自己定义的,包括标题栏,边框和系统按纽等,所以我们首先需要定做一套自己的皮肤图形文件。因为窗体是可伸缩的,所以我们不能简单的取一整幅图片来作为窗体皮肤,而是根据需要先将图片切割为不同的部分,一般来说,有以下图示几大部分(红线为切割线):

根据方位,将图片各部分命名为:Bottom_Left,Bottom_Middle,Bottom_Right,Middle_Left,Middle_Right,Top_Left,Top_Middle,Top_Right,SysButton_Min,SysButton_Max,SysButton_Close,SysButton_Restore等。注意,有些图片是可以伸缩的地方,比如Middle_Left,Bottom_Middle等处的图片可以只是一小块,以后需要进行重复贴图。而有些固定大小的图片,比如Bottom_Left,Top_Left等以后只用贴一次,实际应用的时候要注意区分。

采用以上原则,你便可以制作皮肤图片,图示如下:

然后可以将这些图片放到ImageList控件或资源文件中供程序调用。(关于如何制作资源文件请参考:Visual C#资源文件编程--创建资源文件

接下来,我们使用Visual Studio .Net新建一个Windows应用程序的项目,在窗体的属性设置中,将窗体的FormBorderStyle属性设置为None(无边框样式),如下图所示:

定义一个资源管理器:

private ResourceManager rm ;

然后使用以下的方法在Form的构造函数中将图片取出来(资源文件名为Skin.resources):

rm = new ResourceManager("SkinWindow.Skin", Assembly.GetExecutingAssembly());

Bottom_Left = (Bitmap)rm.GetObject("Bottom_Left");

…(其它的图片也按照此方法取)

重载Form的OnPaint事件:

Graphics g = e.Graphics;

//手工画窗体的各个部分

DrawMiddle_Left(e.Graphics);//画左边框

DrawBottom_Middle(e.Graphics);//画下边框

DrawMiddle_Right(e.Graphics);//画右边框

DrawBottom_Left(e.Graphics);//画左下角

DrawBottom_Right(e.Graphics);//画右下角

DrawTop_Left(e.Graphics);//画标题栏左边

DrawTop_Right(e.Graphics);//画标题栏右边

DrawTop_Middle(e.Graphics);//画标题栏中间

DrawSys_Button(e.Graphics);//画系统按纽

以下是上述画皮肤方法的具体实现部分,我只举一个画左边框的代码示例,其它的部分请读者举一返三:

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);

}

衣服穿上了,现在我们的程序就有了不同的外观:

看上去已经很酷了,不过只是花架子,因为边框,标题栏,系统按纽都是我们自己画上去的假的边框,标题栏和系统按纽,所以这个窗体既不能移动也不能自由的放大缩小,点关闭都没用。以前我们写程序从来都不需要关心这个的,这些都是窗体的基本功能呀?没有从来都没有想到这个竟然还会是个问题吧?

怎么办呢?答案就是我们自己来做,不过会比较麻烦,因为取消掉了边框,所以Windows不会帮你发出系统事件,你捕捉不到系统发生了什么事情的话,就没有办法写下响应代码,所以我们要自己检测鼠标的坐标,并根据鼠标的动作,自己来发出事件消息,然后进行响应。

首先我们先定义出一些响应事件的代码,我定义了一个抽象的基类MouseAction,用来表示所有的鼠标事件,它有一个抽象方法Action:

public abstract class MouseAction

{

public abstract void Action(int ScreenX, int ScreenY, System.Windows.Forms.Form form);

}

然后再来定义出它的各个派生类来表示出具体每个鼠标事件响应的代码。

下面是一个向右拉伸窗口事件的代码响应:

public class MouseSizeRight : MouseAction

{

private int lx;

public MouseSizeRight(int LocationX)

{

lx = LocationX;

}

public override void Action(int ScreenX, int ScreenY, System.Windows.Forms.Form form)

{

form.Width = ScreenX - lx;

form.Invalidate();

}

}

非常简单和容易理解,我就不再赘述,其它的各个事件也都一样简单,这里也不给出所有事件的实现代码,只是列举一下还需要实现的代码响应类:

MouseSizeLeft:拉伸左边框

MouseSizeBottom:拉伸下边框

MouseSizeTop:拉伸上边框

MouseSizeTopLeft:拉伸左上角

MouseSizeTopRight:拉伸右上角

MouseSizeBottomLeft:拉伸左下角

MouseSizeBottomRight:拉伸右下角

MouseDrag:鼠标拖动

鼠标拖动同样也很简单,不过却稍不同于窗口的缩放拉伸,这里举出它的实现代码:

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。

总结:

现在编译你的程序,运行试试,你的窗体已经拥有正常窗体所拥有的全部功能,并且还具有与众不同的外观,不明就里的人一下子还猜不出来你是怎么弄的,好了,乘别人还不知道,赶快拿出去炫耀一下吧 :)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有