C# 无边框异型窗体制作

我是一个C#的初学者 只要涉及到windows窗体编程 都希望窗体的外观比较好看 不是系统默认的那样

对于C# 更改窗体外观感觉并不那么轻松 更改窗体外观涉及到使用GDI+ 我所知道的有两种方法:

  1. 有系统边框的窗体  处理窗体的Paint方法,在paint方法中 参数e.Graphics属性将返回一个对象 用来作画  但是这个画布的区域是窗体的客户区 所以无法修改到窗体的标题栏 边框等位置的。要更改标题栏只有获取整个窗口的句柄 这样创建的画布是整个窗体区域 但是对于我这样的初学者来说 对于句柄 windowsAPI还很不熟悉 我相信大多数的初学者或者学生都和我有相同的困惑 所以我使用了第二种办法 无边框窗体
  2. 无边框的窗体 把FormBorderStyle的属性设置为none 就去掉了边框 剩下的窗体客户区和和整个窗体大小是相同的 再使用e.Graphics作画就是在整个窗体上作画 我主要也是描述这样的一种方法 相信对很多和我一样的人有很多帮助

对于一个窗体 它除了外观以外还有2个主要特征:1.可以拖动 可以拖拽大小 2.具有控制按钮 关闭 最大化 最小化。我主要描述第二种方法

题外话:在网上随便一搜C#自定义窗体之类的 总是出现一大片的文章 以无边框的为例 什么都说得很详细了 但是关键的拖动拖拽大小确没有 总是少掉了关键部分。不止是窗体的代码是这样 其它各类源代码也是如此 很难在网上下载到关键的代码和高质量的代码  个人觉得好多人喜欢学习别人的东西 确不愿意把自己会的 关键的东西拿出来和别人分享。导致现在网上的充斥着大量重复的无用的代码

回到主题 介绍处理无边框窗体的经验,下面是最终效果:

 

这就是一个无边框窗体 可以注意到它的外观 四个角是圆的 有控制按钮 并且还可以拖拽,当鼠标移动到窗体的四个角和边缘的时候可以拖拽大小

这个窗体没有标题栏和边框的限制 控件可以放在窗体上任何地方

下面就是直奔主题了:

先说一说制作这个窗体的思路(窗体集成自System.Windows.Forms.Form):

1.设置FormBorderStyle属性为none 让它成为一个无边框窗体

2.设置窗体的Region属性 该属性设置窗体的有效区域 而我们把窗体的有效区域设置为圆角矩形 窗体就变成圆角的了

3.自定义控件 3个按钮 控制窗体的最大化 最小化 还原 关闭

4.使窗体可以拖动 在边缘按下鼠标可以拖拽大小

主要涉及GDI+中两个重要的类 Graphics和GraphicsPath类 分别位于System.Drawing和System.Drawing.Drawing2D

首先我们创建一个C# windows窗体应用程序项目 将默认的Form1改名成MainForm 设置FormBorderStyle属性为none 让它成为一个无边框窗体

接着我们需要这样一个函数 private void  SetWindowRegion() 此函数设置窗体有效区域为圆角矩形,以及一个辅助函数 private GraphicsPath GetRoundedRectPath(Rectangle rect, int radius)此函数用来创建圆角矩形路径,将在SetWindowRegion()中调用它

public void SetWindowRegion()
{
    System.Drawing.Drawing2D.GraphicsPath FormPath;
    FormPath = new System.Drawing.Drawing2D.GraphicsPath();
    Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
    FormPath = GetRoundedRectPath(rect, 10);
    this.Region = new Region(FormPath);

}
private GraphicsPath GetRoundedRectPath(Rectangle rect, int radius)
{
    int diameter = radius;
    Rectangle arcRect = new Rectangle(rect.Location, new Size(diameter, diameter));
    GraphicsPath path = new GraphicsPath();

// 左上角
    path.AddArc(arcRect, 180, 90);

// 右上角
    arcRect.X = rect.Right - diameter;
    path.AddArc(arcRect, 270, 90);

// 右下角
    arcRect.Y = rect.Bottom - diameter;
    path.AddArc(arcRect, 0, 90);

// 左下角
    arcRect.X = rect.Left;
    path.AddArc(arcRect, 90, 90);
    path.CloseFigure();//闭合曲线
    return path;
}

在窗体尺寸改变的时候我们需要调用SetWindowRegion()将窗体变成圆角的

private void MainForm_Resize(object sender, EventArgs e) {     SetWindowRegion(); }

到此 窗体的形状部分就完成了 通过创建不同的GraphicsPath对象 可以将窗体设置为任意形状 三角形 六边形 椭圆 以及任何不规则图形来制作不规则窗体

然后可以通过给窗体设置背景图片或者在窗体上作画来更改外观 无论图片是什么形状只要超过了窗体有效区域的部分都会被裁掉 这样给换皮肤带来了极大的方便 只需要换一张背景图而已 不需要去做圆角图片 就像迅雷7那样 换皮肤就换一张背景图片

然后是自定义控件 3个按钮 通过GDI+可以绘制比较漂亮的按钮 这部分相对简单很多 就不叙述了,这方面的资料也很好找

将这3个按钮控件拖到窗体右上角设置它们的Anchor属性为top right 让它们的位置始终相对于窗体右上角改变 并编写它们的单击事件处理代码 模拟窗体的最大化最小化和关闭

这里需要注意一点的就是 最大化的时候直接使用this.WindowState = FormWindowState.Maximized会遮盖任务栏 在执行这行代码前先限制窗体的最大尺寸为屏幕的工作区

this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height); this.WindowState = FormWindowState.Maximized;

接下再运行的时候 窗体就是圆角 并且具有控制按钮了 只差拖动和拖拽大小了 下面完成最后一部分

实现这部分只能通过处理windows消息来完成 使用windows系统的功能来完成窗体的拖拽大小和移动 我们只需要处理WM_NCHITTEST消息就可以完成这部分功能 WM_NCHITTEST是告知鼠标事件位置的消息 是很常用的一个消息。查询MSDN API可以找到这些常量 WM_NCHITTEST常量地址http://msdn.microsoft.com/zh-cn/library/ms645618(en-us,VS.85).aspx

这里我们需要使用10个常量 1个WM_NCHITTEST 9个WM_NCHITTEST消息结果

代码

1 const int WM_NCHITTEST = 0x0084;  2 const int HT_LEFT = 10;  3 const int HT_RIGHT = 11;  4 const int HT_TOP = 12;  5 const int HT_TOPLEFT = 13;  6 const int HT_TOPRIGHT = 14;  7 const int HT_BOTTOM = 15;  8 const int HT_BOTTOMLEFT = 16;  9 const int HT_BOTTOMRIGHT = 17; 10 const int HT_CAPTION = 2;

定义好这些常量之后 就需要处理windows消息了 C#处理 windows消息就重写WndProc(ref Message Msg)函数

代码

protected override void WndProc(ref Message Msg) {     if (Msg.Msg == WM_NCHITTEST)     {         //获取鼠标位置         int nPosX = (Msg.LParam.ToInt32() & 65535);         int nPosY = (Msg.LParam.ToInt32() >> 16);         //右下角         if (nPosX >= this.Right - 6 && nPosY >= this.Bottom - 6)         {             Msg.Result = new IntPtr(HT_BOTTOMRIGHT);             return;         }         //左上角         else if (nPosX <= this.Left + 6 && nPosY <= this.Top + 6)         {             Msg.Result = new IntPtr(HT_TOPLEFT);             return;         }         //左下角         else if (nPosX <= this.Left + 6 && nPosY >= this.Bottom - 6)         {             Msg.Result = new IntPtr(HT_BOTTOMLEFT);             return;         }         //右上角         else if (nPosX >= this.Right - 6 && nPosY <= this.Top + 6)         {             Msg.Result = new IntPtr(HT_TOPRIGHT);             return;         }         else if (nPosX >= this.Right - 2)         {             Msg.Result = new IntPtr(HT_RIGHT);             return;         }         else if (nPosY >= this.Bottom - 2)         {             Msg.Result = new IntPtr(HT_BOTTOM);             return;         }         else if (nPosX <= this.Left + 2)         {             Msg.Result = new IntPtr(HT_LEFT);             return;         }         else if (nPosY <= this.Top + 2)         {             Msg.Result = new IntPtr(HT_TOP);             return;         }         else         {             Msg.Result = new IntPtr(HT_CAPTION);             return;         }     }     base.WndProc(ref Msg); }

最后 为了使窗体不会出现闪烁 可以使用双缓存 在重绘的时候进行双缓存 在窗体的Resize事件中重绘并使用双缓存

代码

private void MainForm_Resize(object sender, EventArgs e) {     SetStyle(ControlStyles.SupportsTransparentBackColor, true);     SetStyle(ControlStyles.AllPaintingInWmPaint, true);     SetStyle(ControlStyles.UserPaint, true);     SetStyle(ControlStyles.DoubleBuffer, true);     this.Refresh();     SetWindowRegion(); }

这可以有效消除窗体控制按钮的闪烁情况

时间: 2024-11-15 23:02:40

C# 无边框异型窗体制作的相关文章

c#无边框异形窗体制作

下面是最终效果:   这就是一个无边框窗体 可以注意到它的外观 四个角是圆的 有控制按钮 并且还可以拖拽,当鼠标移动到窗体的四个角和边缘的时候可以拖拽大小 这个窗体没有标题栏和边框的限制 控件可以放在窗体上任何地方 下面就是直奔主题了: 先说一说制作这个窗体的思路(窗体集成自System.Windows.Forms.Form): 1.设置FormBorderStyle属性为none 让它成为一个无边框窗体 2.设置窗体的Region属性 该属性设置窗体的有效区域 而我们把窗体的有效区域设置为圆角

【Reproduce】 C#中实现拖动无边框Form窗体

首先建一个Windows应用程序 将Form1的 FormBorderStyle属性设置为Noe 主要是在Form1窗体触发三个事件:Form4_MouseDown,Form4_MouseMove,Form4_MouseUp 代码如下:       public partial class Form1 : Form { Point mouseOff; //鼠标移动位置变量 bool leftFlag; //标签是否为左键 public Form1() { InitializeComponent(

WPF Tips: 无边框渐变色窗体示例

MainWindow.xaml <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="窗体名称" Height="350&

无边框窗体和后台创建控件

1.无边框窗体 最小化 最大化 关闭 按钮 不一定非要用按钮来做, 可以用图片 写事件,加上鼠标 移入移出 点击 来操作 MouseEnter-鼠标移入的时候发生的事件 private void pictureBox1_MouseEnter(object sender, EventArgs e) { pictureBox1.BackgroundImage = Image.FromFile(Application.StartupPath + "\\..\\..\\images\\btn_close

无边框窗体设置

#region 方法:无边框拖动窗体 Point mouseOff;//鼠标移动位置变量 bool RightFlag;//标签是否为左键 private void groupMenu_MouseUp(object sender, MouseEventArgs e) { if (RightFlag) { RightFlag = false;//释放鼠标后标注为false; } } private void groupMenu_MouseMove(object sender, MouseEvent

01.WPF中制作无边框窗体

[引用:]http://blog.csdn.net/johnsuna/article/details/1893319 众所周知,在WinForm中,如果要制作一个无边框窗体,可以将窗体的FormBorderStyle属性设置为None来完成.如果要制作成异形窗体,则需要使用图片或者使用GDI+自定义绘制. 那么,在WPF中,我们怎样制作一个无边框窗体呢? 答案是将Window的WindowStyle属性设置为None,即WindowStyle="None" .如果是非矩形的异形窗体,则

2017-4-26 winform tab和无边框窗体制作

TabIndex-----------------------------------确定此控件将占用的Tab键顺序索引 Tabstop-------------------------------指示用户是否可以使用Tab键为控件提供焦点 无边框窗体制作中,鼠标移入,移出,按下的事件:  最小化: Anchor------------------------------定义某个控件绑定到的容器的边缘,当控件锚定到某个边缘时,与制定边缘最接近的控件边缘与指定边缘之间的距离将保持不变.

PYQT设计无边框窗体

#UI.py,通过UI设计师制作后直接转换为UI.py脚本 # -*- coding: utf-8 -*-from PyQt4 import QtCore, QtGui try:    _fromUtf8 = QtCore.QString.fromUtf8except AttributeError:    _fromUtf8 = lambda s: s class Ui_Form(object):    def setupUi(self, Form):        Form.setObject

无边框窗体 timer控件

一.无边框窗体1.控制按钮如何制作 MouseEnter-鼠标移入的时候发生的事件 pictureBox1.BackgroundImage = Image.FromFile(Application.StartupPath + "\\..\\..\\images\\btn_close_highlight.png"); MouseLeave-鼠标移出的时候发生的事件 pictureBox1.BackgroundImage = Image.FromFile(Application.Start