【异形窗体】完美实现无毛边异形窗体

实现效果图1:

实现效果图2:

实现效果图3:

异形窗体的实现思路
(一)、采用UpdateLayeredWindow这个api函数基于Png图alpha通道绘制异形窗口
           优点:真正意义上的异形窗口
           缺点:用了WS_EX_LAYERED后当前窗体不处理paint事件,所以窗体上无法绘制控件,但这个控件确存在,而且可以响应事件

解决无法绘制控件方法:
              1、思路:
              采用双层窗口:底层背景窗口层与顶层控件层,用控件层Show()背景层,同时处理窗体的窗口移动事件,让另外一个窗体同步移动或者做其它事情。
        
              2、实现:
              底层背景层:采用UpdateLayeredWindow这个api函数基于带Alpha通道的Png图绘制 
              顶层控件层:
                  方法一:采用无边框窗口,把窗口背景颜色BackColor设置一个不常用颜色例如:ff00ff颜色,且把窗口TransparencyKey颜色属性设跟背景色BackColor一样(意义:去除带背景色的区域从而显示后面背景层)
                  方法二:采用无边框窗口,把窗口背景设为背景层对应位置的位图,给人一种透明的效果,但是编辑会有所限制。(SkinWhetherTank属性可以切换这两种透明模式)

优点:可以解决显示控件的问题,不影响控件的使用
             缺点:方法一会让部分控件有毛边,方法二会让窗体编辑受限制。(缺点有待解决,望高手指点)

属性:
              GradientTime:控件层渐变特效时长(越小越快)。
              MainPosition:窗口在绘图层位置。
              SkinBack:设置或获取绘图层窗口背景。
              SkinMobile:窗体是否可以移动。
              SkinOpacity:设置或获取绘图层窗口透明度(0-255)。
              SkinShowInTaskbar:绘图层是否出现在Windows任务栏中。
              SkinSize:设置或获取绘图层窗口大小。
              SkinTrankColor:绘图层需要透明的颜色。
              SkinWhetherTank:绘图层是否开启位图仿透明  注意(SkinOpacity < 255时,此属性为False可达到背景透明,控件不透明的效果。)。

 1 /// <summary>
 2 /// 创建支持位图区域的控件(目前有button和form)
 3 /// </summary>
 4 /// <param name="control">控件</param>
 5 /// <param name="bitmap">位图</param>
 6 public static void CreateControlRegion(Control control, Bitmap bitmap)
 7 {
 8     //判断是否存在控件和位图
 9     if (control == null || bitmap == null)
10         return;
11
12     control.Width = bitmap.Width;
13     control.Height = bitmap.Height;
14     //当控件是form时
15     if (control is System.Windows.Forms.Form)
16     {
17         //强制转换为FORM
18         Form form = (Form)control;
19         //当FORM的边界FormBorderStyle不为NONE时,应将FORM的大小设置成比位图大小稍大一点
20         form.Width = control.Width;
21         form.Height = control.Height;
22         //没有边界
23         form.FormBorderStyle = FormBorderStyle.None;
24         //将位图设置成窗体背景图片
25         form.BackgroundImage = bitmap;
26         //计算位图中不透明部分的边界
27         GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
28         //应用新的区域
29         form.Region = new Region(graphicsPath);
30     }
31     //当控件是button时
32     else if (control is System.Windows.Forms.Button)
33     {
34         //强制转换为 button
35         Button button = (Button)control;
36         //不显示button text
37         button.Text = "";
38
39         //改变 cursor的style
40         button.Cursor = Cursors.Hand;
41         //设置button的背景图片
42         button.BackgroundImage = bitmap;
43
44         //计算位图中不透明部分的边界
45         GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
46         //应用新的区域
47         button.Region = new Region(graphicsPath);
48     }
49 }
50
51 //计算位图中不透明部分的边界
52 private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
53 {
54     //创建 GraphicsPath
55     GraphicsPath graphicsPath = new GraphicsPath();
56     //第一个找到点的X
57     int colOpaquePixel = 0;
58     // 偏历所有行(Y方向)
59     for (int row = 0; row < bitmap.Height; row++)
60     {
61         //重设
62         colOpaquePixel = 0;
63         //偏历所有列(X方向)
64         for (int col = 0; col < bitmap.Width; col++)
65         {
66             //如果是不需要透明处理的点则标记,然后继续偏历
67             if (bitmap.GetPixel(col, row).A == 255)
68             {
69                 //记录当前
70                 colOpaquePixel = col;
71                 //建立新变量来记录当前点
72                 int colNext = col;
73                 ///从找到的不透明点开始,继续寻找不透明点,一直到找到或则达到图片宽度
74                 for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)
75                     if (bitmap.GetPixel(colNext, row).A < 255)
76                         break;
77                 //将不透明点加到graphics path
78                 graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
79                 col = colNext;
80             }
81         }
82     }
83     return graphicsPath;
84 }

转载之:CSkin论坛

案例源码下载:http://bbs.cskin.net/thread-54-1-1.html

时间: 2024-11-05 17:18:55

【异形窗体】完美实现无毛边异形窗体的相关文章

c#无边框异形窗体制作

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

C# 无边框异型窗体制作

我是一个C#的初学者 只要涉及到windows窗体编程 都希望窗体的外观比较好看 不是系统默认的那样 对于C# 更改窗体外观感觉并不那么轻松 更改窗体外观涉及到使用GDI+ 我所知道的有两种方法: 有系统边框的窗体  处理窗体的Paint方法,在paint方法中 参数e.Graphics属性将返回一个对象 用来作画  但是这个画布的区域是窗体的客户区 所以无法修改到窗体的标题栏 边框等位置的.要更改标题栏只有获取整个窗口的句柄 这样创建的画布是整个窗体区域 但是对于我这样的初学者来说 对于句柄

C# 窗体常用API函数 应用程序窗体查找

常用的处理窗体的API函数如下(注意:API函数必须放在窗体中...): 使用C#语言,要引用DllImport,必须要添加using System.Runtime.InteropServices命名空间 (1)获得当前前台窗体句柄 [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern IntPtr GetForegroundWindow(); 返回值类型

Extjs 窗体居中,双重窗体弹出时清除父窗体的鼠标事件

这个是监控窗体缩放的事件 缩放中居中主要在 'beforeshow' 和 'destroy'两个事件里面监控 var EditTempWindow; Ext.EventManager.onWindowResize(function() { if (EditTempWindow) { EditTempWindow.center() } }); Ext.define("Define.Class.EditWindow", { id: 'RoomEditWin', xtype: 'window

C#窗体皮肤制作(二):创建窗体库项目以及最小化、最大化、关闭按钮的实现

很高兴有朋友关注这篇博客,同时也十分抱歉让关注的朋友久等了,隔上一篇博客也有3个月没有更新,主要是由于3月份辞职,4月份初离职到期离开了北京高德,来到了上海张江.目前新工作也处于熟悉当中,希望大家能体谅.刚好这周末有点时间,我就接着写写,这篇博客主要是针对初学者,希望给为他们能提供一种较易理解的窗体皮肤制作思路,记得自己当初学习C#编程的时候也是摸着石头过河. 闲话少说,我还是接着上篇博客继续写,上次说明了下如何收集图片资源,这次就以360安全卫士来做示例进行模仿,本来也想过模仿下qq,但是qq

父窗体与子窗体的右键菜单合并(子窗体最大化后)

1 private void 打开子窗体ToolStripMenuItem_Click(object sender, EventArgs e) 2 { 3 Form2 f = new Form2();//创建窗体对象 4 f.MdiParent = this;//设置父窗体属性 5 f.Show();//显示窗体 6 f.Resize += //为窗体添加事件 7 new EventHandler(f_Resize); 8 } 9 10 void f_Resize(object sender,

Delphi MDI程序 父窗体如何调用当前活动子窗体的函数/过程

一个MDI文本文件编辑器打开了N个子窗体子窗体的.pas文件有一些public的过程和函数我想在父窗体调用当前活动的子窗体函数我用Self.ActiveChildForm无法调用直接frmEdit.xxxx运行出错求大家指导,谢谢! 回复于: 2013-01-21 15:31:31 将子窗口的函数定义为类函数calss function a(const s: string): Boolean; 有两种解决办法,一种就是上楼说的,定义成class function静态方法,第二种就是普通的方法:D

winform 加载窗体时弹出另一个窗体并显示进度条的源码

winform 加载窗体时弹出另一个窗体并显示进度条的源码 //frmA: 源窗体 //------------------------------------------ //引用 using System.Threading; BackgroundWorker worker; public frmA() { InitializeComponent(); worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandl

ShowDialog()弹出的窗体,关闭后,主窗体会闪烁的BUG

如图,要实现下列等待界面时,等待界面是以ShowDialog弹出的,发现关闭后,主窗体会闪烁一下的BUG,搞半天没搞明白啥原因. 过了几天后,搜索了下发现,在fm.ShowDialog(),显示出来时,其他位置再调用fm.Close(),后又调用了fm.Dispose(),注释掉了fm.Dispose()后,就好了.. ShowDialog()弹出的窗体,关闭后,主窗体会闪烁的BUG