winform开发的时候,因为自身窗体都是window窗体风格,可操作性不大,往往不能根据UI提供的方案进行界面的UI搭建。因此会采用自定义的窗体作为父类窗体,将所有界面统一风格并避免代码重写。当然,如果需要实现很漂亮的界面,还是建议wpf或者Unity或其他方式实现,winform的控件有一定的局限性,有时候UI设计的按钮或者其他控件达不到效果,可能需要控件重绘来解决,相对来说不是那么友好。
如下图所示的风格,实现之后,可以直接像Form类一样使用。
全部代码在此
基础讲解
首先是新建一个窗体A,作为之后所有窗体的父类,这样的好处就是需要修改皮肤的时候,不用一个个改,只需要修改这个父类窗体A即可。
A的属性设置需要如下:
去掉原有的标题栏,自己用图片控件或者Panel搭建标题头
使用该皮肤只需要继承该窗体即可。
最小化、最大化、关闭功能实现
private void pb_min_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void pb_max_min_Click(object sender, EventArgs e)
{
MaxNormalSwitch();
}
private void pb_close_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// 最大化和正常状态切换
/// </summary>
private void MaxNormalSwitch()
{
if (this.WindowState == FormWindowState.Maximized)//如果当前状态是最大化状态 则窗体需要恢复默认大小
{
this.WindowState = FormWindowState.Normal;
//
this.pb_max_min.Image = FormAndUserControls.Properties.Resources.最大化1;
}
else
{
//防止遮挡任务栏
//this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
this.WindowState = FormWindowState.Maximized;
//最大化图标切换
this.pb_max_min.Image = FormAndUserControls.Properties.Resources.最大化;
}
this.Invalidate();//使重绘
}
自定义属性
属性支持自定义,则使用的时候,能在属性模块直接修改。如下所示,在属性的杂项中。
可根据自己的需要添加其他自定义属性。
/// <summary>
/// 窗体标题
/// </summary>
private string titleText;
[Description("窗体标题")]
public string TitleText
{
get { return titleText; }
set
{
titleText = value;
lb_Tilte.Text = titleText;
this.Text = value;
}
}
/// <summary>
/// 窗体标题是否显示
/// </summary>
private bool titleVisible = true;
[Description("窗体标题是否显示")]
public bool TitleVisible
{
get { return titleVisible; }
set
{
titleVisible = value;
lb_Tilte.Visible = titleVisible;
}
}
/// <summary>
/// 窗口默认大小
/// FormSize.NORMAL OR FormSize.MAX
/// </summary>
private FormWindowState defaultFormSize = FormWindowState.Normal;
[Description("窗口默认大小")]
public FormWindowState DefaultFormSize
{
get { return defaultFormSize; }
set
{
defaultFormSize = value;
MaxNormalSwitch();
}
}
窗体大小自由拖拽
我用的是几个panel用来确定从哪里拖拽,也有其他方式,比如判断鼠标是否移出窗体之类的,个人习惯下面的方式实现。
如图,红色区域放置了几个panel
对panel设置属性(例如右边竖线panel,是用来控制窗体右边宽度调整):
设置其随着窗体高度变化而变化
设置鼠标出现在上面的时候显示左右移动的箭头
所有panel可根据需要实现的效果设置完成。
添加拖拽事件(例如左右两边的是水平拖拽,最下面是上下拖拽,两个角为对角线拖拽):
绑定代码如下:
#region 窗体大小自由更改
//改变窗体大小
public const int WMSZ_LEFT = 0xF001;
public const int WMSZ_RIGHT = 0xF002;
public const int WMSZ_TOP = 0xF003;
public const int WMSZ_TOPLEFT = 0xF004;
public const int WMSZ_TOPRIGHT = 0xF005;
public const int WMSZ_BOTTOM = 0xF006;
public const int WMSZ_BOTTOMLEFT = 0xF007;
public const int WMSZ_BOTTOMRIGHT = 0xF008;
public void SetSize(int type)
{
ReleaseCapture();
SendMessage(this.Handle, WM_SYSCOMMAND, type, 0);
this.pb_max_min.Image = FormAndUserControls.Properties.Resources.最大化1;
}
//上下拖拽绑定的事件
private void Form1_MouseDownVertical(object sender, MouseEventArgs e)
{
//Cursor = Cursors.SizeNS;
SetSize(WMSZ_BOTTOM);
}
//水平拖拽绑定的事件
private void Form1_MouseDownHorizontal(object sender, MouseEventArgs e)
{
if (sender is Panel panel)
{
int type = 0;
switch (panel.Tag.ToString())
{
case "0":
type = WMSZ_LEFT;
break;
case "1":
type = WMSZ_RIGHT;
break;
}
SetSize(type);
}
}
//左对角线拖拽绑定的事件
private void Form1_MouseDownLeftAndButtom(object sender, MouseEventArgs e)
{
SetSize(WMSZ_BOTTOMLEFT);
}
//右对角线拖拽绑定的事件
private void Form1_MouseDownRightAndButtom(object sender, MouseEventArgs e)
{
SetSize(WMSZ_BOTTOMRIGHT);
}
public void AdjuestSize()
{
panel11.Location = new Point(this.Width - panel11.Width, panel11.Location.Y);
panel11.Height = this.Height - 20;
panel3.Width = this.Width - panel3.Location.X ;
panel4.Location = new Point(this.Width - panel4.Width, panel4.Location.Y);
panel6.Height = this.Height - panel6.Location.Y - 15;
panel8.Location = new Point(panel8.Location.X, this.Height - panel8.Height);
panel9.Location = new Point(15, panel8.Location.Y);
panel9.Width = this.Width - panel9.Location.X - 10;
panel10.Location = new Point(this.Width - 32, this.Height - 32);
//panel_control.Size = new Size(this.Width- panel_control.Location.X- buttomWidth, this.Height- panel_control.Location.Y-10);
}
private void MyForm_Load(object sender, EventArgs e)
{
AdjuestSize();//必须在此调整位置
}
#endregion
实现窗体可拖动
#region 实现边框拖拽
[DllImport("user32.dll")]//拖动无窗体的控件
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]
public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MOVE = 0xF010;
public const int HTCAPTION = 0x0002;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
//拖动窗体
ReleaseCapture();
SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
this.pb_max_min.Image = FormAndUserControls.Properties.Resources.最大化1;
}
#endregion