最近在编写C/S结构应用程序时,感觉窗体的标题栏样式太死板了,标题文字不能更改大小、颜色、字体等,按钮不能隐藏等问题,在网上也查找了许多相关的资料,没有找到合适的解决方案,发现许多人也在寻求这个问题,最后我决定自己研究动手画一个标题栏出来,经过今天一天的研究与编写,终于完成全部功能,现公布一下我的设计思路。

一、去掉Form类自带的标题栏                         

要去掉自带的标题栏有两种方法,第一方法是直接将FormBorderStyle设为 System.Windows.Forms.FormBorderStyle.None,但设置过后,窗体无法改变大小,考虑到后期这些功能还是需要的,所以我采用了第二种方法,第二种方法是可以忽略FormBorderStyle,只需要将ControlBox设为 false,并将Text设为空即可,这种方法隐藏标题栏,若FormBorderStyle不是固定模式,则可以通过拉伸窗体边框改变大小的。

二、创建自定义窗体类                                     

首先创建一个窗体,如下图:

然后去掉Text默认的文字,并将ControlBox设为 false,此时标题栏将自动隐藏掉了,如下图:

去掉标题栏后,就需要重画新的标题栏,画标题栏很简单,方法也很多,我这里是采用一个Panel,将Dock设为Top,让其项部固定,并设高度为30像素,再在其中添加三个按钮,依次为:button1(关闭),button2(最大化),button3(最小化),三个按钮的设为Size相同,且将Anchor都设为Top Right Bottom,这样就实现了让三个按钮在右边固定位置,如下图:

界面部份已经完工,剩下的就是编写代码了,由于代码较多,我先将代码贴出来,稍后再讲解。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace ZControls
{
/// <summary>
/// Copyright Zuowenjun
/// Site Url:http://www.zuowenjun.cn
/// QQ:77321032
/// Description:自定义窗体样式,实现标题可自定义化
/// </summary>
public partial class ZForm : Form
{
private bool moving = false;
private Point oldMousePosition; public new FormBorderStyle FormBorderStyle
{
get
{
return base.FormBorderStyle;
}
set
{
if (value != FormBorderStyle.Sizable && value != FormBorderStyle.SizableToolWindow)
{
titlepanel.Controls.Remove(button2);
}
base.FormBorderStyle = value;
}
} #region 隐藏父类的属性,使其不可见 [Browsable(false)]
public new string Text
{
get
{
return titlelabel.Text;
}
set
{ }
} [Browsable(false)]
public new bool ControlBox
{
get {
return false;
}
set
{
base.ControlBox = false;
}
} #endregion [Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[Description("窗体标题")]
public string Title
{
get { return titlelabel.Text; }
set { titlelabel.Text = value; }
} [Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[Description("窗体标题字体样式")]
public Font TitleFont
{
get
{
return titlelabel.Font;
}
set
{
titlelabel.Font = value;
}
} [Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[Description("窗体标题字体颜色")]
public Color TitleColor
{
get
{
return titlelabel.ForeColor;
}
set
{
titlelabel.ForeColor = value;
}
} [Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[Description("窗体标题栏背景色")]
public Color TitleBarBackColor
{
get
{
return titlepanel.BackColor;
}
set
{
titlepanel.BackColor = value;
}
} public new bool MaximizeBox
{
get
{
return titlepanel.Contains(button2);
}
set
{
if (!value)
{
titlepanel.Controls.Remove(button2);
}
else if (!titlepanel.Contains(button2))
{
titlepanel.Controls.Add(button2);
}
}
} public new bool MinimizeBox
{
get
{
return titlepanel.Contains(button3);
}
set
{
if (!value)
{
titlepanel.Controls.Remove(button3);
}
else if (!titlepanel.Contains(button3))
{
titlepanel.Controls.Add(button3);
}
}
} private void ResetTitlePanel()
{
base.ControlBox = false;
base.Text = null;
SetToolTip(button1, "关闭");
button2.Size = button1.Size;
SetToolTip(button2, "最大化或还原");
button3.Size = button1.Size;
SetToolTip(button3, "最小化");
} private void SetToolTip(Control ctrl, string tip)
{
new ToolTip().SetToolTip(ctrl, tip);
}
public ZForm()
{
InitializeComponent();
ResetTitlePanel();
} private void Titlebutton_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
switch (btn.Tag.ToString())
{
case "close":
{
this.Close();
break;
}
case "max":
{
if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
}
else
{
this.WindowState = FormWindowState.Maximized;
}
break;
}
case "min":
{
if (this.WindowState != FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Minimized;
}
break;
}
}
} private void Titlepanel_MouseDown(object sender, MouseEventArgs e)
{
if (this.WindowState == FormWindowState.Maximized)
{
return;
}
//Titlepanel.Cursor = Cursors.NoMove2D;
oldMousePosition = e.Location;
moving = true;
} private void Titlepanel_MouseUp(object sender, MouseEventArgs e)
{
//Titlepanel.Cursor = Cursors.Default;
moving = false;
} private void Titlepanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && moving)
{
Point newPosition = new Point(e.Location.X - oldMousePosition.X, e.Location.Y - oldMousePosition.Y);
this.Location += new Size(newPosition);
}
} private void Titlepanel_DoubleClick(object sender, EventArgs e)
{
if (titlepanel.Contains(button2))
{
button2.PerformClick();
}
} private void titlepanel_ControlRemoved(object sender, ControlEventArgs e)
{
switch (e.Control.Name)
{
case "button2":
{
if (titlepanel.Contains(button3))
{
button3.Left = button1.Left - button1.Width;
}
break;
}
}
} private void titlepanel_ControlAdded(object sender, ControlEventArgs e)
{
switch (e.Control.Name)
{
case "button2":
{
if (titlepanel.Contains(button3))
{
button3.Left = button2.Left - button2.Width;
}
break;
}
case "button3":
{
if (titlepanel.Contains(button2))
{
button3.Left = button2.Left - button2.Width;
}
break;
}
}
} }
}

以下是系统自动生成的代码:

namespace ZControls
{
partial class ZForm
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
} #region Windows 窗体设计器生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.titlepanel = new System.Windows.Forms.Panel();
this.titlelabel = new System.Windows.Forms.Label();
this.button3 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.titlepanel.SuspendLayout();
this.SuspendLayout();
//
// titlepanel
//
this.titlepanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
this.titlepanel.Controls.Add(this.titlelabel);
this.titlepanel.Controls.Add(this.button3);
this.titlepanel.Controls.Add(this.button2);
this.titlepanel.Controls.Add(this.button1);
this.titlepanel.Dock = System.Windows.Forms.DockStyle.Top;
this.titlepanel.Location = new System.Drawing.Point(, );
this.titlepanel.Margin = new System.Windows.Forms.Padding();
this.titlepanel.Name = "titlepanel";
this.titlepanel.Size = new System.Drawing.Size(, );
this.titlepanel.TabIndex = ;
this.titlepanel.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.titlepanel_ControlAdded);
this.titlepanel.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.titlepanel_ControlRemoved);
this.titlepanel.DoubleClick += new System.EventHandler(this.Titlepanel_DoubleClick);
this.titlepanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Titlepanel_MouseDown);
this.titlepanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Titlepanel_MouseMove);
this.titlepanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Titlepanel_MouseUp);
//
// titlelabel
//
this.titlelabel.AutoSize = true;
this.titlelabel.Location = new System.Drawing.Point(, );
this.titlelabel.Name = "titlelabel";
this.titlelabel.Size = new System.Drawing.Size(, );
this.titlelabel.TabIndex = ;
//
// button3
//
this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.button3.Font = new System.Drawing.Font("微软雅黑 Light", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)()));
this.button3.Location = new System.Drawing.Point(, );
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(, );
this.button3.TabIndex = ;
this.button3.Tag = "min";
this.button3.Text = "-";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.Titlebutton_Click);
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.button2.Font = new System.Drawing.Font("微软雅黑 Light", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)()));
this.button2.Location = new System.Drawing.Point(, );
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(, );
this.button2.TabIndex = ;
this.button2.Tag = "max";
this.button2.Text = "□";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.Titlebutton_Click);
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.button1.Font = new System.Drawing.Font("微软雅黑 Light", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)()));
this.button1.Location = new System.Drawing.Point(, );
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(, );
this.button1.TabIndex = ;
this.button1.Tag = "close";
this.button1.Text = "X";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.Titlebutton_Click);
//
// ZForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(, );
this.ControlBox = false;
this.Controls.Add(this.titlepanel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.Name = "ZForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.titlepanel.ResumeLayout(false);
this.titlepanel.PerformLayout();
this.ResumeLayout(false); } #endregion private System.Windows.Forms.Panel titlepanel;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label titlelabel;
}
}

代码中FormBorderStyle覆盖父类的同名属性,主要是实现根据不同的窗体,能够自动调整标题栏按钮,因为当FormBorderStyle为FormBorderStyle.Sizable或FormBorderStyle.SizableToolWindow时,才需要最大化按钮,否则都是不需要的。不需要的情况下,将移除最大化按钮对象button2,

titlepanel.Controls.Remove(button2);

由于隐藏自带的标题栏需要确保Text属性为空,ControlBox为False,所以我这里采取了重写这两个属性,并加上Browsable(false),让其在编辑器中不可见。

Title,TitleFont,TitleColor,TitleBarBackColor为新增自定义属性,分别用于设置标题文字,标题文字样式,标题文字颜色,标题栏背景色。

重写MaximizeBox与MinimizeBox两个属性,使其根据设为True与False时,能相应的调整标题栏按钮。

私有方法:ResetTitlePanel,用于重设标题栏按钮属性。

方法Titlebutton_Click这个简单,主要用于实现标题栏上三个按钮点击时所要执行的操作。

Titlepanel_MouseDown,Titlepanel_MouseUp ,Titlepanel_MouseMove 三个方法是用于实现点击鼠标右键并按住移动就能够移动窗体,Titlepanel_DoubleClick方法是实现双击时能够最大化或还原窗体功能。

最后的titlepanel_ControlRemoved与titlepanel_ControlAdded,实现的功能是当增加或移除按钮时,调整按钮的位置。

三、使用自定义窗体类                                     

使用就比较简单了,先是新增一个窗体,然后将窗体类的父类由Form改为自定义窗体类(ZForm)即可,然后再切换到设计视图页面,是不是发现界面已经变化了呢,这时候就可以依据的想法灵活设置窗体标题栏样式,如下图:

    public partial class Form1 : ZControls.ZForm
{
public Form1()
{
InitializeComponent();
}
}

将MaximizeBox设为False时,运行的效果,是不是有点爽啊!

好了,都说完了,其实也很简单,我相信大部份高手都是不屑一看的,但此处只是作为一个学习与参考,可能大家有更好的方法,欢迎大家交流,共同进步。

最后我上传源码,仅大家参考与改进:

Demo

——

Winform自定义窗体样式,实现标题栏可灵活自定义的更多相关文章

  1. WPF自定义Window样式(2)

    1. 引言 在上一篇中,介绍了如何建立自定义窗体.接下来,我们需要考虑将该自定义窗体基类放到类库中去,只有放到类库中,我们才能在其他地方去方便的引用该基类. 2. 创建类库 接上一篇的项目,先添加一个 ...

  2. WPF自定义Window样式(1)

    1. 引言 WPF是制作界面的一大利器.最近在做一个项目,用的就是WPF.既然使用了WPF了,那么理所当然的,需要自定义窗体样式.所使用的代码是在网上查到的,遗憾的是,整理完毕后,再找那篇帖子却怎么也 ...

  3. c#winform自定义窗体,重绘标题栏,自定义控件学习

    c#winform自定义窗体,重绘标题栏 虽然现在都在说winform窗体太丑了,但是我也能尽量让桌面应用程序漂亮那么一点点话不多说,先上图 重绘标题栏先将原生窗体设置成无边框,FormBoderSt ...

  4. WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 自定义 ...

  5. 【转】WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 自定义Window窗体样式: 基于自定义窗体实现自定义MessageB ...

  6. WPF 之 自定义窗体标题栏

    在WPF中自定义窗体标题栏,首先需要将窗体的WindowStyle属性设置为None,隐藏掉WPF窗体的自带标题栏.然后可以在窗体内部自定义一个标题栏. 例如,标题栏如下: <WrapPanel ...

  7. paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制

    源地址:http://blog.csdn.net/attilax/article/details/12343625 paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制 效果图: ...

  8. WPF自定义Window窗体样式

    资源文件代码: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation ...

  9. Java 自定义窗体(标题栏、窗体背景)

    感谢大佬:https://blog.csdn.net/ltx06/article/details/28996839 最近在书上看到这篇文章,觉得挺有意思.与大家分享一下,具体可以参见明日科技出版的&l ...

随机推荐

  1. redis 学习指南

    一.介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.一个高性能的key-value数据库.并提供多种语言的API.说到Key-Value数据库NoSQL数 ...

  2. RabbitMQ的安装使用

    1.下载安装 Rabbit MQ 是建立在强大的Erlang OTP平台上,因此安装RabbitMQ之前要先安装Erlang. erlang:http://www.erlang.org/downloa ...

  3. A Brief History of Scaling LinkedIn

    原文地址 LinkedIn started in 2003 with the goal of connecting to your network for better job opportuniti ...

  4. 【LeetCode】273. Integer to English Words

    Integer to English Words Convert a non-negative integer to its english words representation. Given i ...

  5. Top 10 Universities for Artificial Intelligence

    1. Massachusetts Institute of Technology, Cambridge, MA Massachusetts Institute of Technology is a p ...

  6. Solved: Qt Library LNK 2001 staticMetaObject error

          在链接Qt的库,比如QtGui4.lib,我这里是在链接QtSolutions_PropertyBrowser-head.lib的时候出现的链接错误.大概是说一个"XXXX::s ...

  7. iOS杂谈-我为什么不用Interface builder

    在互联网上关于Interface Builder的争吵每天都在发生,用和不用大家都有一大堆的理由.最近看了这篇文章,很多地方和作者有共鸣,结合自己的一些经历,就有了你现在所看到的东西,你可以把它当成前 ...

  8. 用Jekyll在github上写博客——《搭建一个免费的,无限流量的Blog》的注脚

    本来打算买域名,买空间,用wordpress写博客的.后来问了一个师兄,他说他是用github的空间,用Jekyll写博客,说很多人都这么做.于是我就研究了一下. 比较有价值的文章有这么几篇: htt ...

  9. java.lang.NullPointerException

    你妹的这是什么错误啊? Errors occurred during the build. Errors running builder 'Android Resource Manager' on p ...

  10. [原创]与来自facebook的朋友交流

    与来自facebook的朋友交流 老板的儿子在facebook工作,现在正好有个假期回来,老总让我们部门与之进行一次交流.其实主要是他讲一下那边情况,然后我们准备些问题,多扩展一下我们见识. 流程 交 ...