用C#制作 个性化窗体 win 界面.doc_第1页
用C#制作 个性化窗体 win 界面.doc_第2页
用C#制作 个性化窗体 win 界面.doc_第3页
用C#制作 个性化窗体 win 界面.doc_第4页
用C#制作 个性化窗体 win 界面.doc_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

引言:谁都希望自己的应用程序能让人留下一个深刻的印象,让自己的程序窗体有一件与众不同的外衣是一个好办法。试想:在一大堆的普通窗口中突然跳出一个很酷的界面,一定能让人眼睛一亮进而产生兴趣的。在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 MouseActionpublic abstract void Action(int ScreenX, int ScreenY, System.Windows.Forms.Form form);然后再来定义出它的各个派生类来表示出具体每个鼠标事件响应的代码。下面是一个向右拉伸窗口事件的代码响应:/china/community/Column/60.mspxpublic 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 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 = Width - RIGHT - 10 & Y = Height - BOTTOM) | (Y = Height - BOTTOM - 10 & X = Width - RIGHT) . return Cursors.SizeNWSE; else if(Y = Width - RIGHT) | (Y = Width - RIGHT - 10) | (X = Height - BOTTOM - 10) | (Y = Height - BOTTOM & X = Width - RIGHT | X = Height - BOTTOM | 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。总结:现在编译你的程序,运行试试,你的窗体已经拥有正常窗体所拥有的全部功能,并且还具有与众不同的外观,不明就里的人一下子还猜不出来你是怎么弄的,好了,乘别人还不知道,赶快拿出去炫耀一下吧 :)。我原本打算这样做,可是在实施过程中,好歹也需要绘制改变大小的虚框,随着mouseMove不断更新虚框,我是用controlPaint在屏幕上绘制的,但是更新的时候也有一定闪烁,可是看一般的文件夹,根本就没有闪烁,可否告知这是为什么 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐:搜索后的关键字高亮显示(急)100分 hbxtlhx (平民百姓) 等级: 更多勋章#6楼 得分:0回复于:2008-03-27 13:55:48对你的窗体在构造函数中添加如下的语句就不会闪动了:this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true);但这时需要你对窗体进行绘制。 对我有用0 丢个板砖0 引用 举报 管理 TOP hbxtlhx (平民百姓) 等级: 更多勋章#7楼 得分:0回复于:2008-03-27 14:04:25参考一下下面的代码,这是一个无边的窗体且在上面有绘制:C# code public partial class NoBorder : Form internal static int WM_NCHITTEST = 0x84; /移动鼠标,按住或释放鼠标时发生的系统消息 internal static IntPtr HTCLIENT = (IntPtr)0x1;/工作区 internal static IntPtr HTSYSMENU = (IntPtr)3;/系统菜单 internal static IntPtr HTCAPTION = (IntPtr)0x2; /标题栏 private int m_BorderWidth = 2; private int m_CaptionHeight = 22; public NoBorder() this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true); InitializeComponent(); this.Padding = new Padding(this.m_BorderWidth, this.m_BorderWidth + this.m_CaptionHeight, this.m_BorderWidth, this.m_BorderWidth); protected override CreateParams CreateParams get int WS_SYSMENU = 0x00080000; int WS_MAXIMIZEBOX = 0x10000; int WS_MINIMIZEBOX = 0x20000; int WS_THICKFRAME = 0x40000; CreateParams cp = base.CreateParams; cp.Style |= WS_SYSMENU | 0x20000 | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; return cp; / / 重写以处理模拟鼠标系统处理 / / protected override void WndProc(ref Message m) if (m.Msg = WM_NCHITTEST) base.WndProc(ref m); if (DesignMode) return; if (m.Result = HTCLIENT) m.HWnd = this.Handle; Rectangle rect = this.Bounds; Point cp = Cursor.Position; if (cp.Y rect.Top + m_BorderWidth & cp.Y rect.Left + m_BorderWidth & cp.X rect.Right - m_BorderWidth) if (cp.X = rect.Left + m_BorderWidth + m_CaptionHeight) m.Result = HTSYSMENU;/模拟系统菜单,双击可以关闭窗体 else m.Result = HTCAPTION;/模拟标题栏,移动或双击可以最大或最小化窗体 return; base.WndProc(ref m); / / 绘制窗体 / / protected override void OnPaint(PaintEventArgs e) base.OnPaint(e); Rectangle captionRect = Rectangle.FromLTRB(this.m_BorderWidth, this.m_BorderWidth, this.ClientRectangle.Right - this.m_BorderWidth, this.m_CaptionHeight); Rectangle clientRect = Rectangle.FromLTRB(this.m_BorderWidth, this.m_BorderWidth + this.m_CaptionHeight, this.ClientRectangle.Right - this.m_BorderWidth, this.ClientRectangle.Bottom - this.m_BorderWidth); /绘制整个窗体 e.Graphics.FillRectangle(SystemBrushes.InactiveBorder, this.ClientRectangle); /绘制标题栏 e.Graphics.FillRectangle(SystemBrushes.ActiveCaption, captionRect); /绘制窗体的图标 if (this.Icon != null) e.Graphics.DrawIcon(this.Icon, Rectangle.FromLTRB(this.m_BorderWidth, this.m_BorderWidth, this.m_CaptionHeight, this.m_CaptionHeight); /绘制窗体客户区 e.Graphics.FillRectangle(SystemBrushes.Window, clientRect); string strHello = 欢迎访问我的CSDN博客:n/hbxtlhx; TextRenderer.DrawText(e.Graphics, strHello, this.Font, clientRect, Color.Red, Color.White, TextFormatFlags.VerticalCenter); / / 重写以处理鼠标按钮准备调整窗体大小 / / protected override void OnMouseDown(MouseEventArgs e) base.OnMouseDown(e); MState.SetData(this.Bounds, Cursor.Position); / / 重写以处理鼠标抬起事件重置状态 / / protected override void OnMouseUp(MouseEventArgs e) base.OnMouseUp(e); MState.ResetState(); / / 重写以处理鼠标移动调整窗体大小位置 / / protected override void OnMouseMove(MouseEventArgs e) base.OnMouseMove(e); if (!this.Capture) MState.SetState(this.setMouse(e.Location); return; int dx = 0; int dy = 0; int dr = 0; int db = 0; Point cp = Cursor.Position; if (MState.LastState = MouseAction.Left)/左 dx = cp.X - MState.LastX; else if (MState.LastState = MouseAction.Right)/右 dr = cp.X - MState.LastX; else if (MState.LastState = MouseAction.Top)/上 dy = cp.Y - MState.LastY; else if (MState.LastState = MouseAction.Bottom)/下 db = cp.Y - MState.LastY; else if (MState.LastState = MouseAction.LeftTop) dx = cp.X - MState.LastX; dy = cp.Y - MState.LastY; else if (MState.LastState = MouseAction.RightTop) dr = cp.X - MState.LastX; dy = cp.Y - MState.LastY; else if (MState.LastState = MouseAction.LeftBottom) dx = cp.X - MState.LastX; db = cp.Y - MState.LastY; else if (MState.LastState = MouseAction.RightBottom) dr = cp.X - MState.LastX; db = cp.Y - MState.LastY; this.Bounds = Rectangle.FromLTRB(MState.Left + dx, MState.Top + dy, MState.Right + dr, MState.Bottom + db); this.Invalidate(); / / 重写以处理重置鼠标光标信息 / / protected override void OnMouseLeave(EventArgs e) base.OnMouseLeave(e); if (this.Bounds.Contains(Cursor.Position) this.Cursor = Cursors.Default; protected override void OnMouseClick(MouseEventArgs e) base.OnMouseClick(e); / / 由指定点设置鼠标动作 / / / private MouseAction setMouse(Point point) Rectangle rect = this.ClientRectangle; if (point.X = rect.Left + m_BorderWidth) & (point.Y = rect.Left + rect.Width - m_BorderWidth) & (point.Y = rect.Top + m_BorderWidth) /右上 this.Cursor = Cursors.SizeNESW; return MouseAction.RightTop; else if (point.X = rect.Top + rect.Height - m_BorderWidth) /左下 this.Cursor = Cursors.SizeNESW; return MouseAction.LeftBottom; else if (point.X = rect.Left + rect.Width - m_BorderWidth) & (point.Y = rect.Top + rect.Height - m_BorderWidth) /右下 this.Cursor = Cursors.SizeNWSE; return MouseAction.RightBottom; else if (point.X = rect.Left + rect.Width - m_BorderWidth) /右 this.Cursor = Cursors.SizeWE; return MouseAction.Right; else if (point.Y = rect.Top + rect.Height - m_BorderWidth) /下 this.Cursor = Cursors.SizeNS; return MouseAction.Bottom; this.Cursor = Cursors.Default; return MouseAction.None; / / 关闭窗体 / / / private void button1_Click(object sender, EventArgs e) this.Close(); 对我有用0 丢个板砖0 引用 举报 管理 TOP hbxtlhx (平民百姓) 等级: 更多勋章#8楼 得分:0回复于:2008-03-27 14:05:01上面代码中用到的类可以参考下面的代码:C# code / / 表示鼠标按下并调整大小位置时的数据状态 / internal static class MState private static int m_Left; private static int m_Top; private static int m_Right; private static int m_Bottom; private static int m_LastX; private static int m_LastY; private static MouseAction m_State; private static MouseAction m_LastState; / / 窗体的左坐标 / public static int Left get return MState.m_Left; / / 窗体的上坐标 / public static int Top get return MState.m_Top; / / 窗体的右坐标 / public static int Right get return MState.m_Right; / / 窗体的下坐标 / public static int Bottom get return MState.m_Bottom; / / 当前的鼠标状态 / public static MouseAction State get return MState.m_State; / / 鼠标按下时的Y坐标 / public static int LastX get return MState.m_LastX; / / 鼠标按下时的X坐标 / public static int LastY get return MState.m_LastY; / / 鼠标按下时的状态 / public static MouseAction LastState get return MState.m_LastState; / / 设置数据值 / / 窗体的大小位置 / 鼠标的位置 public static void SetData(Rectangle bounds, Point point) m_Left = bounds.Left; m_Top = bounds.Top; m_Right = bounds.Right; m_Bottom = bounds.Bottom; m_LastX = point.X; m_LastY = point.Y; m_LastState = m_State; / / 设置状态 / / 要设置的状态值 public static void SetState(MouseAction state) m_State = state; / / 重置状态 / public static void ResetState() m_State = MouseAction.None; m_LastState = MouseAction.None; internal enum MouseAction None, Left, LeftTop, Top, RightTop, Right, RightBottom, Bottom, LeftBottom 对我有用0 丢个板砖0 引用 举报 管理 TOP fienol (郁郁馒头) 等级: #9楼 得分:0回复于:2008-03-27 14:06:32第一项没有用,因为我绘制的标题栏没有显示了,其他的还有效,只是水平拖拽,即从左往右改变大小时,仍然有闪烁,因为其中要更改width代码如下switch (m_MousePointPosition) case EnumMousePointPosition.MouseDrag: lCtrl.Left = lCtrl.Left + e.X - p.X; lCtrl.Top = lCtrl.Top + e.Y - p.Y; break; case EnumMousePointPosition.MouseSizeBottom: lCtrl.Height = lCtrl.Height + e.Y - p1.Y; p1.X = e.X; p1.Y = e.Y; /记录光标拖动的当前点 break; case EnumMousePointPosition.MouseSizeBottomRight: lCtrl.Width = lCtrl.Width + e.X - p1.X; lCtrl.Height = lCtrl.Height + e.Y - p1.Y; p1.X = e.X; p1.Y = e.Y; /记录光标拖动的当前点 break; case EnumMousePointPosition.MouseSizeRight: lCtrl.Width = lCtrl.Width + e.X - p1.X; / lCtrl.Height = lCtrl.Height + e.Y - p1.Y; p1.X = e.X; p1.Y = e.Y; /记录光标拖动的当前点 break; case EnumMousePointPosition.MouseSizeTop: lCtrl.Top = lCtrl.Top + (e.Y - p.Y); lCtrl.Height = lCtrl.Height - (e.Y - p.Y); break; case EnumMousePointPosition.MouseSizeLeft: lCtrl.Left = lCtrl.Left + e.X - p.X; lCtrl.Width = lCtrl.Width - (e.X - p.X); break; case EnumMousePointPosi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论