C#仿QQ皮肤-实现原理系列文章导航
http://www.cnblogs.com/sufei/archive/2010/03/10/1682847.html
一周要过去了,本来打算多写点的,还是时间不够啊,费话不多说,开始写代码,今天 我们要做的是一个窗体,这个窗体是基于窗体FormBase,就是我们上一节所说到的FormBase与基用户控件FormBase1的实现 里面的FormBase窗体, 有关 FormBase的实现还请大家去看相应文章,这里不再做过多的说明。
我们先看一下实现的效果吧,第一张图是 实现,第二张是正常使用时的样子
下面看一下怎么实现吧,
第一步,创建窗体
我们右键单击文件夹选择添加窗体就行了,名称当时是“ FunctionFormBase”,然后单击确定,我们的窗体的大小不需要做任何的修改,那是因为那是继承自窗体FormBase而来的,上节我们讲过了, 他的大小是固定的,所以在这里不用再做设置;
只要这样一行继承的语句就OK了
/// FunctionFormBase基窗体
/// 是构造EntryForm和SkinForm窗体的基础
/// </summary>
public partial class FunctionFormBase : FormBase
第二步,窗体的UI布局实现
我们可以看到第一张图,就是窗体的UI布局,相信大家一看就能明白是怎么实现 的,我还是大致的说一下是怎么会事吧。窗体一共是三个Panel
代码实现为:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
// ptbTopMiddle
//
this .ptbTopMiddle.Dock = System.Windows.Forms.DockStyle.Fill;
this .ptbTopMiddle.Location = new System.Drawing.Point( 10 , 0 );
this .ptbTopMiddle.Name = " ptbTopMiddle " ;
this .ptbTopMiddle.Size = new System.Drawing.Size( 669 , 31 );
this .ptbTopMiddle.TabIndex = 2 ;
this .ptbTopMiddle.TabStop = false ;
// pnlBackGroup
//
this .pnlBackGroup.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this .pnlBackGroup.Dock = System.Windows.Forms.DockStyle.Fill;
this .pnlBackGroup.Location = new System.Drawing.Point( 0 , 31 );
this .pnlBackGroup.Name = " pnlBackGroup " ;
this .pnlBackGroup.Size = new System.Drawing.Size( 689 , 444 );
this .pnlBackGroup.TabIndex = 9 ;
//
// ptbBottomMiddle
//
this .ptbBottomMiddle.Dock = System.Windows.Forms.DockStyle.Fill;
this .ptbBottomMiddle.Location = new System.Drawing.Point( 10 , 0 );
this .ptbBottomMiddle.Name = " ptbBottomMiddle " ;
this .ptbBottomMiddle.Size = new System.Drawing.Size( 669 , 37 );
this .ptbBottomMiddle.TabIndex = 3 ;
在ptbTopMiddle左面是一个lblText 右面是两个CommandButton,这个控件是 我自己写的实现方法后面会提到这里不做详细说明,在ptbTopMiddle的两端分别是两个Panel,用来实现窗体的边角,和低部的ptbBottomMiddle 形式是一样的,下面我给出这些控件的初始代码
,我是通过Controls.Remove方法来实现 的,具体的代码如下所示
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
this .Controls.Remove( this .pnlRight);
this .Controls.Remove( this .pnlLeft);
this .Controls.Remove( this .pnlBackGroup);
this .Controls.Remove( this .pnlCaption);
this .Controls.Remove( this .pnlBottom);
好了我们的布局就到这里吧
第三步,ptbTopMiddle功能实现
因为我们的窗体是一个Panel,所以在移动和鼠标松开时的效果要处理一下,先说一下标题和最小化吧
标题是个Label,我们需要重写定义一下,怎么样来实现呢,我们只要重写一下窗体的Text属性就行了。实现如下
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
// 最小化
public new bool MinimizeBox
{
get
{
return base .MinimizeBox;
}
set
{
base .MinimizeBox = value;
this .btnMin.Visible = value;
}
}
还有最后一个关闭按钮,这个更简单了,一个Close方法搞定
private void btnClose_Click( object sender, EventArgs e)
{
this .Close();
}
第四步,窗体移动效果
我们的窗体是没有实际的标题的所以 在这里要处理一下移动时的效果
在这里用到了一些Api,具体的说明 请大家参考代码中的类文章Win32类 ,一共有两个方法一个是鼠标移动时的方法
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
private void caption_MouseUp( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && ((Control)sender).Cursor == Cursors.Default && e.Y <= SystemInformation.CaptionHeight)
{
Win32.TrackPopupMenu(Win32.GetSystemMenu(Handle, 0 ).ToInt32(), 2 , Cursor.Position.X, Cursor.Position.Y, 0 , Handle, 0 );
}
}
第五步,窗体样式 实现
样式方面第一个重点就是Windows消息的处理,跟其实窗体的实现原理是一样的,不同 是WindowsApi和消息,因为消息在这里还要用的到所以我加了个ref,呵呵 ,ref(ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中)
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/// Windows消息处理
/// </summary>
/// <param name="m"> Message </param>
protected override void WndProc( ref Message m)
{
switch (m.Msg)
{
case Win32.WM_COMMAND:
Win32.SendMessage(Handle, Win32.WM_SYSCOMMAND, ( int )m.WParam, ( int )m.LParam);
break ;
case Win32.WM_SYSCOMMAND:
base .WndProc( ref m);
if (m.WParam.ToInt64() == Win32.SC_RESTORE)
{
this .Height += 6 ;
this .Width += 6 ;
}
else if (m.WParam.ToInt64() == Win32.SC_MAXIMIZE)
{
Application.DoEvents();
}
break ;
default :
base .WndProc( ref m);
break ;
}
}
这个窗体的样式 除了Windows消息还有一个ReSetFormBitmap方法,因为这个方法是FromBase窗体 里我们在这里需要重写一下,
跟原先的方法实现是一样的,只是我要改几张图片,呵呵
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/// 设置窗体样式
/// </summary>
public override void ReSetFormBitmap()
{
this .pnlCaption.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
this .ptbTopLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertl.bmp " ));
this .ptbTopMiddle.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
this .ptbTopRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertr.bmp " ));
this .ptbLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderml.bmp " ));
this .ptbRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordermr.bmp " ));
this .ptbBottomLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbl.bmp " ));
this .ptbBottomMiddle.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbm.bmp " ));
this .ptbBottomRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbr.bmp " ));
this .pnlBackGroup.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bg.bmp " ));
Bitmap closeBitmap = new Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.CloseBtn.bmp " )));
this .btnClose.NormalImage = closeBitmap.Clone( new Rectangle( 0 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
this .btnClose.MouseMoveImage = closeBitmap.Clone( new Rectangle( 37 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
this .btnClose.MouseDownImage = closeBitmap.Clone( new Rectangle( 74 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
Bitmap minBitmap = new Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.MinBtn.bmp " )));
this .btnMin.NormalImage = minBitmap.Clone( new Rectangle( 0 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .btnMin.MouseMoveImage = minBitmap.Clone( new Rectangle( 31 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .btnMin.MouseDownImage = minBitmap.Clone( new Rectangle( 62 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .CurrentSkinColor = SkinColor.Default;
}
文章中用到的所有素材请大家到源文件中去查找这里不再做过多的说明
到这里基本全部实现了,更具体的还请大家参考 源代码
老规矩这里附上窗体的所有实现 代码
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CRD.Common;
using System.Drawing.Imaging;
namespace CRD.WinUI.Forms
{
/// <summary>
/// FunctionFormBase基窗体
/// 是构造EntryForm和SkinForm窗体的基础
/// </summary>
public partial class FunctionFormBase : FormBase
{
// 构造器
public FunctionFormBase()
{
// 设置默认的皮肤
this .SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true );
InitializeComponent();
// 移除FormBase现有控件
this .Controls.Remove( this .pnlRight);
this .Controls.Remove( this .pnlLeft);
this .Controls.Remove( this .pnlBackGroup);
this .Controls.Remove( this .pnlCaption);
this .Controls.Remove( this .pnlBottom);
}
/// <summary>
/// Windows消息处理
/// </summary>
/// <param name="m"> Message </param>
protected override void WndProc( ref Message m)
{
switch (m.Msg)
{
case Win32.WM_COMMAND:
Win32.SendMessage(Handle, Win32.WM_SYSCOMMAND, ( int )m.WParam, ( int )m.LParam);
break ;
case Win32.WM_SYSCOMMAND:
base .WndProc( ref m);
if (m.WParam.ToInt64() == Win32.SC_RESTORE)
{
this .Height += 6 ;
this .Width += 6 ;
}
else if (m.WParam.ToInt64() == Win32.SC_MAXIMIZE)
{
Application.DoEvents();
}
break ;
default :
base .WndProc( ref m);
break ;
}
}
/// <summary>
/// 设置窗体样式
/// </summary>
public override void ReSetFormBitmap()
{
this .pnlCaption.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
this .ptbTopLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertl.bmp " ));
this .ptbTopMiddle.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
this .ptbTopRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertr.bmp " ));
this .ptbLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderml.bmp " ));
this .ptbRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordermr.bmp " ));
this .ptbBottomLeft.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbl.bmp " ));
this .ptbBottomMiddle.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbm.bmp " ));
this .ptbBottomRight.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbr.bmp " ));
this .pnlBackGroup.BackgroundImage = Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bg.bmp " ));
Bitmap closeBitmap = new Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.CloseBtn.bmp " )));
this .btnClose.NormalImage = closeBitmap.Clone( new Rectangle( 0 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
this .btnClose.MouseMoveImage = closeBitmap.Clone( new Rectangle( 37 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
this .btnClose.MouseDownImage = closeBitmap.Clone( new Rectangle( 74 , 0 , 37 , 22 ), PixelFormat.Format64bppPArgb);
Bitmap minBitmap = new Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.MinBtn.bmp " )));
this .btnMin.NormalImage = minBitmap.Clone( new Rectangle( 0 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .btnMin.MouseMoveImage = minBitmap.Clone( new Rectangle( 31 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .btnMin.MouseDownImage = minBitmap.Clone( new Rectangle( 62 , 0 , 31 , 22 ), PixelFormat.Format64bppPArgb);
this .CurrentSkinColor = SkinColor.Default;
}
/// <summary>
/// 重写的OnLoad
/// </summary>
protected override void OnLoad(EventArgs e)
{
this .Controls.Add( this .pnlRight);
this .Controls.Add( this .pnlLeft);
this .Controls.Add( this .pnlBackGroup);
this .Controls.Add( this .pnlCaption);
this .Controls.Add( this .pnlBottom);
if ( ! DesignMode)
{
this .Hide();
}
base .OnLoad(e);
Win32.SetWindowLong( this .Handle, - 16 ,Win32.GetWindowLong( this .Handle, - 16 ) - Win32.WS_MAXIMIZEBOX );
this .Show();
}
// 关闭按钮
private void btnClose_Click( object sender, EventArgs e)
{
this .Close();
}
// 最小化
private void btnMin_Click( object sender, EventArgs e)
{
this .WindowState = FormWindowState.Minimized;
}
// 移动标题时
private void Caption_MouseMove( object sender, MouseEventArgs e)
{
((Control)sender).Cursor = Cursors.Default;
if (e.Button == MouseButtons.Left)
{
Win32.ReleaseCapture();
Win32.SendMessage(Handle, 274 , 61440 + 9 , 0 );
}
}
// 标题
public override string Text
{
get
{
return base .Text;
}
set
{
base .Text = value;
if ( this .lblText != null )
this .lblText.Text = this .Text;
}
}
// 最小化
public new bool MinimizeBox
{
get
{
return base .MinimizeBox;
}
set
{
base .MinimizeBox = value;
this .btnMin.Visible = value;
}
}
// 鼠标松开时
private void caption_MouseUp( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && ((Control)sender).Cursor == Cursors.Default && e.Y <= SystemInformation.CaptionHeight)
{
Win32.TrackPopupMenu(Win32.GetSystemMenu(Handle, 0 ).ToInt32(), 2 , Cursor.Position.X, Cursor.Position.Y, 0 , Handle, 0 );
}
}
}
}