CSkin博客

标题: 【异形窗体】完美实现无毛边异形窗体 [打印本页]

作者: 乔克斯    时间: 2014-7-11 13:45
标题: 【异形窗体】完美实现无毛边异形窗体
实现效果图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可达到背景透明,控件不透明的效果。)。



编辑受限制问题的解决:
[C#] 纯文本查看 复制代码

/// <summary>
/// 创建支持位图区域的控件(目前有button和form)
/// </summary>
/// <param name="control">控件</param>
/// <param name="bitmap">位图</param>
public static void CreateControlRegion(Control control, Bitmap bitmap)
{
    //判断是否存在控件和位图
    if (control == null || bitmap == null)
        return;

    control.Width = bitmap.Width;
    control.Height = bitmap.Height;
    //当控件是form时
    if (control is System.Windows.Forms.Form)
    {
        //强制转换为FORM
        Form form = (Form)control;
        //当FORM的边界FormBorderStyle不为NONE时,应将FORM的大小设置成比位图大小稍大一点
        form.Width = control.Width;
        form.Height = control.Height;
        //没有边界
        form.FormBorderStyle = FormBorderStyle.None;
        //将位图设置成窗体背景图片
        form.BackgroundImage = bitmap;
        //计算位图中不透明部分的边界
        GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
        //应用新的区域
        form.Region = new Region(graphicsPath);
    }
    //当控件是button时
    else if (control is System.Windows.Forms.Button)
    {
        //强制转换为 button
        Button button = (Button)control;
        //不显示button text
        button.Text = "";

        //改变 cursor的style
        button.Cursor = Cursors.Hand;
        //设置button的背景图片
        button.BackgroundImage = bitmap;

        //计算位图中不透明部分的边界
        GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
        //应用新的区域
        button.Region = new Region(graphicsPath);
    }
}

//计算位图中不透明部分的边界
private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
{
    //创建 GraphicsPath
    GraphicsPath graphicsPath = new GraphicsPath();
    //第一个找到点的X
    int colOpaquePixel = 0;
    // 偏历所有行(Y方向)
    for (int row = 0; row < bitmap.Height; row++)
    {
        //重设
        colOpaquePixel = 0;
        //偏历所有列(X方向)
        for (int col = 0; col < bitmap.Width; col++)
        {
            //如果是不需要透明处理的点则标记,然后继续偏历
            if (bitmap.GetPixel(col, row).A == 255)
            {
                //记录当前
                colOpaquePixel = col;
                //建立新变量来记录当前点
                int colNext = col;
                ///从找到的不透明点开始,继续寻找不透明点,一直到找到或则达到图片宽度
                for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)
                    if (bitmap.GetPixel(colNext, row).A < 255)
                        break;
                //将不透明点加到graphics path
                graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
                col = colNext;
            }
        }
    }
    return graphicsPath;
}


案例源码下载:点击跳转下载 密码: u1ts

作者: xiaobo    时间: 2014-7-22 22:51
文章很详细,但是美中不足的是文章包含了csdn的资源外链,并且需要积分下载。
作者: 佐佑    时间: 2014-8-2 23:03
楼主,这个DEMO和网上的那个Irregular界面demo一样。。难道是同一个人么。。
作者: 佐佑    时间: 2014-8-2 23:04
回头看到1楼的扣分。。好像明白了什么。。。
作者: MeeSii    时间: 2014-8-6 09:56
正好要一个。
作者: MeeSii    时间: 2014-8-6 10:00
错误        2        无法复制文件“D:\搜狗高速下载\无毛边异形窗体\Irregular\SkinForm\bin\Debug\f_in_box.dll”,原因是找不到该文件。        SkinForm

作者: xiaobo    时间: 2014-8-6 10:59
佐佑 发表于 2014-8-2 23:04
回头看到1楼的扣分。。好像明白了什么。。。

咳咳.忘记取消评分了
作者: 乔克斯    时间: 2014-8-6 16:29
MeeSii 发表于 2014-8-6 10:00
错误        2        无法复制文件“D:\搜狗高速下载\无毛边异形窗体\Irregular\SkinForm\bin\Debug\f_in_box.dll”,原 ...

这好久。。之前的错误了。。你可以替换成新版本的cskin.dll开发。这个版本报这个错是应为这个dll引用了一个不需要的f_in_box.dll。。而没有去除引用。
作者: 乔克斯    时间: 2014-8-6 16:29
佐佑 发表于 2014-8-2 23:03
楼主,这个DEMO和网上的那个Irregular界面demo一样。。难道是同一个人么。。

这玩意 - -就是我做的,好吧。
作者: 佐佑    时间: 2014-8-6 16:34
乔克斯 发表于 2014-8-6 16:29
这玩意 - -就是我做的,好吧。

看来老衲与施主有缘啊,一年前就认识了。。
作者: 乔克斯    时间: 2014-8-6 17:25
佐佑 发表于 2014-8-6 16:34
看来老衲与施主有缘啊,一年前就认识了。。


作者: 758132951    时间: 2017-3-11 10:11
谢谢楼主,共同学习
作者: xiaobai611    时间: 2017-11-10 17:14
楼主辛苦下载学习
作者: 752828765    时间: 2020-9-1 20:59
看看,学习学习
作者: chinesedragon    时间: 2021-3-8 23:06
文章很详细,非常好




欢迎光临 CSkin博客 (http://bbs.cskin.net/) Powered by Discuz! X3.2