`

C#.Net创建不规则窗体的几种方法

阅读更多

现在,C#创建不规则窗体不是一件难事,下面总结一下:

一、自定义窗体

一般为规则的图形,如圆、椭圆等。

做法:重写Form1_Paint事件(Form1是窗体的名字),最简单的一种情况如下:

  1. System.Drawing.Drawing2D.GraphicsPath shape = new System.Drawing.Drawing2D.GraphicsPath();  
  2. shape.AddEllipse(0,0,this.Height, this.Width);  
  3. this.Region = new Region(shape); 

即重绘窗体的规则。

二、利用背景图片实现

1.  设置窗体的背景图片,其中背景图片是24位(不包括24)以下的位图(BMP图片),并且要设置TansparencyKey的值,一般为你背景图片的背景色,即创建不规则图片时的底色,一般设为你图片中没有的颜色。

这种做法的不好的地方就是背景图片一定要16位或者更低的,而且还要确保客户端的显示。如果监视器的颜色深度设置大于 24 位,则不管 TransparencyKey 属性是如何设置的,窗体的非透明部分都会产生显示问题。若要避免出现这种问题,请确保“显示”控制面板中的监视器颜色深度的设置小于 24 位。当开发具有这种透明功能的应用程序时,请牢记应使您的用户意识到此问题。

实现步骤如下:

1. 新建windows application

2. 选择窗体,找到BackgroundImage属性,点击打开新的窗口,选择下面的导入资源文件,选择你的不规则的BMP图片

3. 找到窗体的TansparencyKey,将它设置为你背景图片的背景色(如黄色)

4. 找到窗体的FormBorderStyle,将其设置为none,即不显示标题栏

5. 运行

<!--[endif]-->

2.       跟背景图片一样的图形,不过是动态加载,遍历位图以实现不规则窗体。它的原理是这样的,在Form的load事件中写方法使得窗体的描绘区域发生改变。

实现步骤如下:

1. 建立winform应用程序

2. 找到窗体的Load事件,双击进行编辑

3. 编写方法,主要的代码如下:

  1. class BitmapRegion  
  2. {  
  3.     public BitmapRegion()  
  4.     { }  
  5.  
  6.  
  7.     /// <summary>   
  8.     /// Create and apply the region on the supplied control  
  9.     /// 创建支持位图区域的控件(目前有button和form)  
  10.     /// </summary>   
  11.     /// <param name="control">The Control object to apply the region to控件</param>   
  12.     /// <param name="bitmap">The Bitmap object to create the region from位图</param>   
  13.     public static void CreateControlRegion(Control control, Bitmap bitmap)  
  14.     {  
  15.         // Return if control and bitmap are null  
  16.         //判断是否存在控件和位图  
  17.         if (control == null || bitmap == null)  
  18.             return;  
  19.  
  20.         // Set our control''s size to be the same as the bitmap  
  21.         //设置控件大小为位图大小  
  22.         control.Width = bitmap.Width;  
  23.         control.Height = bitmap.Height;  
  24.         // Check if we are dealing with Form here   
  25.         //当控件是form时  
  26.         if (control is System.Windows.Forms.Form)  
  27.         {  
  28.             // Cast to a Form object  
  29.             //强制转换为FORM  
  30.             Form form = (Form)control;  
  31.             // Set our form''s size to be a little larger that the  bitmap just   
  32.             // in case the form''s border style is not set to none in the first place   
  33.             //当FORM的边界FormBorderStyle不为NONE时,应将FORM的大小设置成比位图大小稍大一点  
  34.             form.Width = control.Width;  
  35.             form.Height = control.Height;  
  36.             // No border   
  37.             //没有边界  
  38.             form.FormBorderStyle = FormBorderStyle.None;  
  39.             // Set bitmap as the background image   
  40.             //将位图设置成窗体背景图片  
  41.             form.BackgroundImage = bitmap;  
  42.             // Calculate the graphics path based on the bitmap supplied   
  43.             //计算位图中不透明部分的边界  
  44.             GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);  
  45.             // Apply new region   
  46.             //应用新的区域  
  47.             form.Region = new Region(graphicsPath);  
  48.         }  
  49.         // Check if we are dealing with Button here   
  50.         //当控件是button时  
  51.         else if (control is System.Windows.Forms.Button)  
  52.         {  
  53.             // Cast to a button object   
  54.             //强制转换为 button  
  55.             Button button = (Button)control;  
  56.             // Do not show button text   
  57.             //不显示button text  
  58.             button.Text = "";  
  59.  
  60.             // Change cursor to hand when over button   
  61.             //改变 cursor的style  
  62.             button.Cursor = Cursors.Hand;  
  63.             // Set background image of button   
  64.             //设置button的背景图片  
  65.             button.BackgroundImage = bitmap;  
  66.  
  67.             // Calculate the graphics path based on the bitmap supplied   
  68.             //计算位图中不透明部分的边界  
  69.             GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);  
  70.             // Apply new region   
  71.             //应用新的区域  
  72.             button.Region = new Region(graphicsPath);  
  73.         }  
  74.     }  
  75.     /// <summary>   
  76.     /// Calculate the graphics path that representing the figure in the bitmap   
  77.     /// excluding the transparent color which is the top left pixel.   
  78.     /// //计算位图中不透明部分的边界  
  79.     /// </summary>   
  80. /// <param name="bitmap">The Bitmap object to calculate our graphics path from</param>   
  81.     /// <returns>Calculated graphics path</returns>   
  82.     private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)  
  83.     {  
  84.         // Create GraphicsPath for our bitmap calculation   
  85.         //创建 GraphicsPath  
  86.         GraphicsPath graphicsPath = new GraphicsPath();  
  87.         // Use the top left pixel as our transparent color   
  88.         //使用左上角的一点的颜色作为我们透明色  
  89.         Color colorTransparent = bitmap.GetPixel(0, 0);  
  90.         // This is to store the column value where an opaque pixel is first found.   
  91.    // This value will determine where we start scanning for trailing opaque pixels.  
  92.         //第一个找到点的X  
  93.         int colOpaquePixel = 0;  
  94.         // Go through all rows (Y axis)   
  95.         // 偏历所有行(Y方向)  
  96.         for (int row = 0; row < bitmap.Height; row++)  
  97.         {  
  98.             // Reset value   
  99.             //重设  
  100.             colOpaquePixel = 0;  
  101.             // Go through all columns (X axis)   
  102.             //偏历所有列(X方向)  
  103.             for (int col = 0; col < bitmap.Width; col++)  
  104.             {  
  105.         // If this is an opaque pixel, mark it and search for anymore trailing behind   
  106.                 //如果是不需要透明处理的点则标记,然后继续偏历  
  107.                 if (bitmap.GetPixel(col, row) != colorTransparent)  
  108.                 {  
  109.                     // Opaque pixel found, mark current position  
  110.                     //记录当前  
  111.                     colOpaquePixel = col;  
  112.               // Create another variable to set the current pixel position   
  113.                     //建立新变量来记录当前点  
  114.                     int colNext = col;  
  115.                // Starting from current found opaque pixel, search for anymore opaque pixels   
  116.             // trailing behind, until a transparent   pixel is found or minimum width is reached   
  117.                     ///从找到的不透明点开始,继续寻找不透明点,一直到找到或则达到图片宽度   
  118.                 for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)  
  119.                         if (bitmap.GetPixel(colNext, row) == colorTransparent)  
  120.                             break;  
  121.             // Form a rectangle for line of opaque   pixels found and add it to our graphics path   
  122.                     //将不透明点加到graphics path  
  123.             graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));  
  124.                     // No need to scan the line of opaque pixels just found   
  125.                     col = colNext;  
  126.                 }  
  127.             }  
  128.         }  
  129.         // Return calculated graphics path   
  130.         return graphicsPath;  
  131.     }  

4. 运行

<!--[endif]-->

三、调用类库实现

主要就是根据一些坐标,然后根据这些坐标绘制窗体

代码如下:

  1. public Form3()  
  2.         {  
  3.             InitializeComponent();  
  4.             //创建不规则窗体  
  5.             POINTAPI[] poin;  
  6.             poin = new POINTAPI[5];  
  7.             poin[0].x = 90;  
  8.             poin[0].y = 90;  
  9.             poin[1].x = this.Width;  
  10.             poin[1].y = 0;  
  11.             poin[2].x = Width;  
  12.             poin[2].y = this.Height / 2;  
  13.             poin[3].x = Width / 2;  
  14.             poin[3].y = Height / 2;  
  15.             poin[4].x = 0;  
  16.             poin[4].y = Width;  
  17.             Boolean flag = true;  
  18.             IntPtr hRgn = CreatePolygonRgn(ref poin[0], 8, 1);  
  19.             SetWindowRgn(this.Handle, hRgn, ref flag);  
  20.             this.BackColor = Color.BurlyWood;  
  21.         }  
  22.         [StructLayout(LayoutKind.Sequential)]  
  23.         private struct POINTAPI  
  24.         {  
  25.             internal int x;  
  26.             internal int y;  
  27.         }  
  28.         [DllImport("gdi32.dll")]  
  29.  private static extern IntPtr CreatePolygonRgn(ref POINTAPI lpPoint,int nCount,int nPolyFillMode);  
  30.         [DllImport("user32.dll")]  
  31.  private static extern IntPtr SetWindowRgn(IntPtr hWnd,IntPtr hRgn, ref Boolean bRedraw);  
  32.         //设置窗体显示状态  
  33.         [DllImport("user32.dll")]  
  34. private static extern int SetWindowPos(IntPtr hwnd,int hWndInsertAfter,int x,int y,int cx,int cy,int wFlags);  
  35.         private void Start_Btn_Click(object sender, EventArgs e)  
  36.         {//始终显示在前面  
  37.             SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 1);  
  38.         }  
  39.         private void button1_Click(object sender, EventArgs e)  
  40.         {  
  41.             //最小化始终显示在前面  
  42.             SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 0);  
  43.         } 

当然,我们也可以自定义窗体的动作,如按着某个轨迹一定,下面的代码中的BackgroundForm程序中就小试了一下,效果还不错,下面是这些程序的效果图(有点乱)和代码:
 

代码下载:http://files.cnblogs.com/alexis/IrregularForm.rar

代码是.Net 2.0的,也可以转换为其他版本的,只要运行主程序即可。

以上的四种方法有利也有弊,希望大家提意见或者更好的解决方案。

分享到:
评论

相关推荐

    C#创建不规则窗体的几种方式

    C#创建不规则窗体的几种方式,对winform的不规则窗体开发一定是最不错的学习哟!

    asp.net知识库

    .NET20 一种简单的窗口控件UI状态控制方法 翻译MSDN文章 —— 泛型FAQ:最佳实践 Visual C# 3.0 新特性概览 C# 2.0会给我们带来什么 泛型技巧系列:如何提供类型参数之间的转换 C#2.0 - Object Pool 简单实现 ...

    亮剑.NET深入体验与实战精要2

    4.7 无标题窗体拖动的两种方法 183 4.8 让程序只启动一次——单实例运行 184 4.9 实现系统托盘和热键呼出 185 4.10 进程与多线程的区别 190 4.11 创建多线程应用程序 191 4.12 WinForm开发常见问题 194 4.12.1 如何...

    亮剑.NET深入体验与实战精要3

    4.7 无标题窗体拖动的两种方法 183 4.8 让程序只启动一次——单实例运行 184 4.9 实现系统托盘和热键呼出 185 4.10 进程与多线程的区别 190 4.11 创建多线程应用程序 191 4.12 WinForm开发常见问题 194 4.12.1 如何...

    C#微软培训资料

    1.2 .NET 与 C#.6 1.3 C#语言的特点.8 1.4 小 结 .11 第二章 运行环境 全面了解.NET.12 2.1 .NET 结构.12 2.2 公用语言运行时环境与公用语言规范.13 2.3 开 发 工 具 .17 2.4 小 结 .19 第三章 编写...

    net学习笔记及其他代码应用

    6.如果在一个B/S结构的系统中需要传递变量值,但是又不能使用Session、Cookie、Application,您有几种方法进行处理? 答 : this.Server.Transfer 7.请编程遍历页面上所有TextBox控件并给它赋值为string.Empty? ...

    抓图神器2016 with update 3

    下拉列表只列出了几种常见的,若需要从中提取图片的分页的链接末尾不符合其中任何一种正则表达式,用户可自行手动输入。 如果不从二级页面中提取图片,只提取指定网页中的图片,分页正则表达式一栏不填或者选择...

    抓图神器2016

    下拉列表只列出了几种常见的,若需要从中提取图片的分页的链接末尾不符合其中任何一种正则表达式,用户可自行手动输入。 如果不从二级页面中提取图片,只提取指定网页中的图片,分页正则表达式一栏不填或者选择...

    ExtAspNet_v2.3.2_dll

    ExtAspNet - ExtJS based ASP.NET Controls with Full AJAX Support ExtAspNet是一组专业的Asp.net控件库,拥有原生的AJAX支持和丰富的UI效果, 目标是创建没有ViewState,没有JavaScript,没有CSS,没有...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    -在2009-03-03 v1.3.0曾经提到这个兼容问题,并有这样的规则,如果Asp.net的按钮AJAX提交,必须设置UseSubmitBehavior="false" --也就是说生成的input的type不能是"submit",而这个限制在有些情况下是不可原谅的...

    领域驱动设计与模式实战

    7.7.2 创建规则类,离开最不成熟的阶段 7.7.3 设置规则列表 7.7.4 使用规则列表 7.7.5 处理子列表 7.7.6 一个API改进 7.7.7 自定义 7.7.8 为使用者提供元数据 7.7.9 是否适合用模式来解决此问题 7.7.10 复杂规则又是...

    vc++ 应用源码包_6

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    vc++ 应用源码包_5

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    vc++ 应用源码包_1

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    vc++ 应用源码包_2

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    vc++ 应用源码包_3

    代码里用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要再把函数头部改来改去。 IOCP反弹远控客户端模型,外加上线服务端,全部代码注释! 如题。这个是IOCP远程控制软件的...

    用递归的方法画分形图

    用递归的方法画分形图 ...完全支持动态换肤(*.rss),支持不规则窗体,支持美工设计自定义界面生成方案。 完全多线程,自定义窗口类换肤支持。 内含15种专业皮肤(.rss)文件。 内含SkinDesigner 皮肤文件开发工具。 ...

    vc++ 开发实例源码包

    18:单线程下载时不能创建临时文件. 19:下载流文件(rm,Media Player). Notepad++ V5.6.8 源码! 如题。 OA精灵代码 c++版 一套oa系统。 ocxdlgtest dll的一个实例。 OD反汇编引擎(带VC修改版和原版) 如题。主要...

Global site tag (gtag.js) - Google Analytics