zoukankan      html  css  js  c++  java
  • [转]Winform不规则窗体的实现心得

    本文转自:http://www.cnblogs.com/haiq/articles/1751777.html

    Winform窗体通常都是矩形的,而本人在需要将一幅图片作为窗体背景,并且窗体边框呈现为图片外轮廓的不规则边缘时,却发现Framework并没有提供直接的实现。经过一通百度、Google和查阅 MSDN 后,发现实现的途径主要有以下几种:

    1. 覆盖 Form 本身的绘制,自己用代码重绘。
    2. 设置窗体的 TransparencyKey 为窗体设置背景图片边缘要成为不规则边框的部分的颜色。
    3. 根据图片或者其它的方式创建不规则的 GraphicPath 生成 Region,指定给窗体的 Region 属性。

        这三种方法各有优劣:

    • 第1种最麻烦,因为要靠代码一点点抠,要达到良好效果不容易,也不易于以后的修改。
    • 第2种最简单,但有制约条件:a、图片的边缘部以外必须是TransparencyKey指定的颜色,并且图片的其它部分不能有这种颜色,否则会被不加区分的变为透明,而导致窗体出现镂空。b、系统必须运行在 24 位色下。因此,这种方法并不实用。
    • 第3种的复杂程度介于1、2之间,并且控制也比较灵活。故本人选择了这种实现方式。

          对于第3种方法,网上大多数的文章都只是介绍了实现的原理和一些简单的 Demo 代码。直接照做可能会遇到以下的一些问题而影响显示效果:

    • 窗体的边缘和作为背景的图片外轮廓不重叠,出现错位。
    • 界面上的控件布局时不容易定位于背景图片的相对位置。

          解决这两个问题很简单,是要注意一些操作的细节。先看实现代码:

     

                           

    不规则窗体的实现

     1             //从指定的位图中获取透明度大于 10 的区域;
     2              Bitmap img = (Bitmap)pictbox.Image;
     3             GraphicsPath grapth = BitmapUtil.GetNoneTransparentRegion(img, 10);
     4             this.Region = new Region(grapth);
     5             
     6             //要显示的图片设置为窗体背景;
     7              this.BackgroundImage = pictbox.Image;
     8             this.BackgroundImageLayout = ImageLayout.Zoom;
     9
    10             //在修改窗体尺寸之前设置窗体为无边框样式;
    11              this.FormBorderStyle = FormBorderStyle.None;
    12             this.Width = pictbox.Image.Width;
    13             this.Height = pictbox.Image.Height;

     

     

     

     

          BitmapUtil.GetNoneTransparentRegion 方法的实现如下:

      

     

    读取位图的非透明区域

     1         /// <summary>
     2         /// 返回指定图片中的非透明区域;
     3         /// </summary>
     4         /// <param name="img">位图</param>
     5         /// <param name="alpha">alpha 小于等于该值的为透明</param>
     6         /// <returns></returns>
     7          public static GraphicsPath GetNoneTransparentRegion(Bitmap img, byte alpha)
     8         {
     9             int height = img.Height;
    10             int width = img.Width;
    11
    12             int xStart, xEnd;
    13             GraphicsPath grpPath = new GraphicsPath();
    14             for (int y = 0; y < height; y++)
    15             {
    16                 //逐行扫描;
    17                  for (int x = 0; x < width; x++)
    18                 {
    19                     //略过连续透明的部分;
    20                     while (x < width && img.GetPixel(x, y).A <= alpha)
    21                     {
    22                         x++;
    23                     }
    24                     //不透明部分;
    25                     xStart = x;
    26                     while (x < width && img.GetPixel(x, y).A > alpha)
    27                     {
    28                         x++;
    29                     }
    30                     xEnd = x;
    31                     if (img.GetPixel(x - 1, y).A > alpha)
    32                     {
    33                         grpPath.AddRectangle(new Rectangle(xStart, y, xEnd - xStart, 1));
    34                     }
    35                 }
    36             }
    37             return grpPath;
    38         }

     

     

     

     

           以上的代码中,解决边框与背景出现错误的办法是“在修改窗体尺寸之前设置窗体为无边框样式”,因为,窗体的长宽是包含在窗体标题栏的尺寸的,而背景显示图片的工作区是除去窗体标题栏的。

           解决在设计时“界面控件在背景图片上的布局问题”可以也很简单,通过一些操作技巧就可以达到,具体如下:

    • 设计窗体时,通过Visual Studio窗体设计器将背景图片设置为窗体背景,将 BackgroundImageLayout 属性设为 Zoom,这样就能在设计时观察到背景。
    • 采用 TableLayoutPanel 面板进行布局,布局上采用相对尺寸。控件布局在网格之中,网格的行列的宽度值都按百分比定位。这样就不需要关注窗体显示尺寸的绝对值,在实际显示的时候,哪怕窗体大小发生改变,界面上控件与背景图片的相对位置也能保持设计时的相对定位。

     

  • 相关阅读:
    sscanf 与 ssprintf 用法 (转载--https://www.cnblogs.com/Anker/p/3351168.html)
    PYTHON网络爬虫与信息提取[信息的组织与提取](单元五)
    PYTHON网络爬虫与信息提取[BeautifulSoup](单元四)
    PYTHON网络爬虫与信息提取[网络爬虫协议](单元二)
    Python网络爬虫与信息提取[request库的应用](单元一)
    scikit-learn实现ebay数据分析 的随笔
    machine leanring 笔记 vectorization
    machine learning 笔记 normal equation
    machine leanring 笔记 octave命令笔记
    UVa 1354 天平难题 Mobile Computing
  • 原文地址:https://www.cnblogs.com/freeliver54/p/3024216.html
Copyright © 2011-2022 走看看