Winform不规则窗体的实现心得
2010-02-12 11:55
253 查看
Winform窗体通常都是矩形的,而本人在需要将一幅图片作为窗体背景,并且窗体边框呈现为图片外轮廓的不规则边缘时,却发现Framework并没有提供直接的实现。经过一通百度、Google和查阅 MSDN 后,发现实现的途径主要有以下几种:
覆盖 Form 本身的绘制,自己用代码重绘。
设置窗体的 TransparencyKey 为窗体设置背景图片边缘要成为不规则边框的部分的颜色。
根据图片或者其它的方式创建不规则的 GraphicPath 生成 Region,指定给窗体的 Region 属性。
这三种方法各有优劣:
第1种最麻烦,因为要靠代码一点点抠,要达到良好效果不容易,也不易于以后的修改。
第2种最简单,但有制约条件:a、图片的边缘部以外必须是TransparencyKey指定的颜色,并且图片的其它部分不能有这种颜色,否则会被不加区分的变为透明,而导致窗体出现镂空。b、系统必须运行在 24 位色下。因此,这种方法并不实用。
第3种的复杂程度介于1、2之间,并且控制也比较灵活。故本人选择了这种实现方式。
对于第3种方法,网上大多数的文章都只是介绍了实现的原理和一些简单的 Demo 代码。直接照做可能会遇到以下的一些问题而影响显示效果:
窗体的边缘和作为背景的图片外轮廓不重叠,出现错位。
界面上的控件布局时不容易定位于背景图片的相对位置。
解决这两个问题很简单,是要注意一些操作的细节。先看实现代码:
BitmapUtil.GetNoneTransparentRegion 方法的实现如下:
以上的代码中,解决边框与背景出现错误的办法是“在修改窗体尺寸之前设置窗体为无边框样式”,因为,窗体的长宽是包含在窗体标题栏的尺寸的,而背景显示图片的工作区是除去窗体标题栏的。
解决在设计时“界面控件在背景图片上的布局问题”可以也很简单,通过一些操作技巧就可以达到,具体如下:
设计窗体时,通过Visual Studio窗体设计器将背景图片设置为窗体背景,将 BackgroundImageLayout 属性设为 Zoom,这样就能在设计时观察到背景。
采用 TableLayoutPanel 面板进行布局,布局上采用相对尺寸。控件布局在网格之中,网格的行列的宽度值都按百分比定位。这样就不需要关注窗体显示尺寸的绝对值,在实际显示的时候,哪怕窗体大小发生改变,界面上控件与背景图片的相对位置也能保持设计时的相对定位。
覆盖 Form 本身的绘制,自己用代码重绘。
设置窗体的 TransparencyKey 为窗体设置背景图片边缘要成为不规则边框的部分的颜色。
根据图片或者其它的方式创建不规则的 GraphicPath 生成 Region,指定给窗体的 Region 属性。
这三种方法各有优劣:
第1种最麻烦,因为要靠代码一点点抠,要达到良好效果不容易,也不易于以后的修改。
第2种最简单,但有制约条件:a、图片的边缘部以外必须是TransparencyKey指定的颜色,并且图片的其它部分不能有这种颜色,否则会被不加区分的变为透明,而导致窗体出现镂空。b、系统必须运行在 24 位色下。因此,这种方法并不实用。
第3种的复杂程度介于1、2之间,并且控制也比较灵活。故本人选择了这种实现方式。
对于第3种方法,网上大多数的文章都只是介绍了实现的原理和一些简单的 Demo 代码。直接照做可能会遇到以下的一些问题而影响显示效果:
窗体的边缘和作为背景的图片外轮廓不重叠,出现错位。
界面上的控件布局时不容易定位于背景图片的相对位置。
解决这两个问题很简单,是要注意一些操作的细节。先看实现代码:
//从指定的位图中获取透明度大于 10 的区域; Bitmap img = (Bitmap)pictbox.Image; GraphicsPath grapth = BitmapUtil.GetNoneTransparentRegion(img, 10); this.Region = new Region(grapth); //要显示的图片设置为窗体背景; this.BackgroundImage = pictbox.Image; this.BackgroundImageLayout = ImageLayout.Zoom; //在修改窗体尺寸之前设置窗体为无边框样式; this.FormBorderStyle = FormBorderStyle.None; this.Width = pictbox.Image.Width; this.Height = pictbox.Image.Height;
BitmapUtil.GetNoneTransparentRegion 方法的实现如下:
/// <summary> /// 返回指定图片中的非透明区域; /// </summary> /// <param name="img">位图</param> /// <param name="alpha">alpha 小于等于该值的为透明</param> /// <returns></returns> public static GraphicsPath GetNoneTransparentRegion(Bitmap img, byte alpha) { int height = img.Height; int width = img.Width; int xStart, xEnd; GraphicsPath grpPath = new GraphicsPath(); for (int y = 0; y < height; y++) { //逐行扫描; for (int x = 0; x < width; x++) { //略过连续透明的部分; while (x < width && img.GetPixel(x, y).A <= alpha) { x++; } //不透明部分; xStart = x; while (x < width && img.GetPixel(x, y).A > alpha) { x++; } xEnd = x; if (img.GetPixel(x - 1, y).A > alpha) { grpPath.AddRectangle(new Rectangle(xStart, y, xEnd - xStart, 1)); } } } return grpPath; }
以上的代码中,解决边框与背景出现错误的办法是“在修改窗体尺寸之前设置窗体为无边框样式”,因为,窗体的长宽是包含在窗体标题栏的尺寸的,而背景显示图片的工作区是除去窗体标题栏的。
解决在设计时“界面控件在背景图片上的布局问题”可以也很简单,通过一些操作技巧就可以达到,具体如下:
设计窗体时,通过Visual Studio窗体设计器将背景图片设置为窗体背景,将 BackgroundImageLayout 属性设为 Zoom,这样就能在设计时观察到背景。
采用 TableLayoutPanel 面板进行布局,布局上采用相对尺寸。控件布局在网格之中,网格的行列的宽度值都按百分比定位。这样就不需要关注窗体显示尺寸的绝对值,在实际显示的时候,哪怕窗体大小发生改变,界面上控件与背景图片的相对位置也能保持设计时的相对定位。
相关文章推荐
- [转]Winform不规则窗体的实现心得
- WinForm 窗体圆角、平角(不规则窗体)实现的几种方法
- wxWidgets 不规则透明WinForm窗体(通过透明图片实现)
- Windows 中不规则窗体的编程实现
- Winform窗体文本框实现拖拽获得目录或文件路径(C#)
- 在Winform界面中实现对多文档窗体的参数传值
- C# 在winform中隐藏或者去除c#的标题栏并实现窗体移动附代码
- winform实现任务栏隐藏、通知栏图标及右键、类似QQ隐藏窗体等功能
- VC++玩转炫酷悬浮窗3---GDI+完美实现不规则窗体
- 利用委托实现winform窗体间通信
- Qt 不规则窗体的实现
- WinForm:DockPanel实现窗体的停靠
- C# winform窗体动画实现
- vc里实现不规则窗体
- winform登录窗体实现记住密码功能
- WinForm程序启动时不显示主窗体的实现方法
- C#.NET vs2010中使用IrisSkin4.dll轻松实现WinForm窗体换肤功能
- winform窗体应用程序,实现开机自启动代码
- 实现c#中winform窗体嵌入并操作可视化Excel表格
- BS网站与Winform窗体的数据交互(WebService实现)