C# Winform 中真正意义的透明控件

若如初见. 提交于 2019-12-10 03:35:27

在稍微复杂的交互应用中,避免不了耗时的操作,这时候总希望给用户明确的提示,表示程序在运行中暂时不能进行其他操作。显示一个半透明的处于等待状态的遮罩层是很好的方法。在Web应用程序中直接设置Div的透明度然后覆盖操作界面就好,但是Winform的好像并没有提供透明度之类的属性。关于Background 中的 Transport 是特指背景透明的,其实质是继承父容器的背景颜色或者图片,在效果上看起来是一致的,但是如果父容器中包含其他的控件,则这种透明是无法显示这些控件的。此外还有一种真正意义的透明,它在隐藏在 ControlStyles  的特性设置中。

    // 摘要: 
    //     指定控件的样式和行为。
    [Flags]
    public enum ControlStyles
    {
       ...
        // 摘要: 
        //     如果为 true,则控件被绘制为不透明的,不绘制背景。
        Opaque = 4,
         //
        // 摘要: 
        //     如果为 true,控件接受 alpha 组件小于 255 的 System.Windows.Forms.Control.BackColor 以模拟透明。仅在
        //     System.Windows.Forms.ControlStyles.UserPaint 位设置为 true 并且父控件派生自 System.Windows.Forms.Control
        //     时才模拟透明。
        SupportsTransparentBackColor = 2048
       ...
    }

在枚举定义中可以看到 背景透明(SupportsTransparentBackColor) 和透明度(Opaque)的定义。操作系统在创建控件句柄时会传递这些设置过的特性,最终实现我们想要的效果。

使用.Net 的组建模型,只要在继承子类的初始化中设置这些属性即可。

SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);

对于透明只需要设置 ControlStyles.Opaque 即可,后面俩个选项有利于增强控件绘制更新的效率。当然这里的“透明“  是完全的透明,直接显示它下面的父容器内容,这样赤果果的感觉太过突兀了。

这里可以再引入 透明度(Alpha)的概念了,透明度的实现可以在绘制事件中通过 Argb 颜色模式去控制,参考代码如下:

/// <summary>
/// 自定义绘制窗体
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
	//// 定义颜色的透明度
	Color drawColor = Color.FromArgb(this._alpha, this.BackColor);
	//// 定义画笔
	Pen labelBorderPen = new Pen(drawColor, 0);
	SolidBrush  labelBackColorBrush = new SolidBrush(drawColor);
	//// 绘制背景色
	e.Graphics.DrawRectangle(labelBorderPen, 0, 0, Size.Width, Size.Height);
	e.Graphics.FillRectangle(labelBackColorBrush, 0, 0, Size.Width, Size.Height);

	base.OnPaint(e);
}


除了套用组建模型,也可以使用更底层的句柄参数来达到同样的效果,这时候需要重载 CreateParams 属性,如下:

/// <summary>
/// 控件透明特性
/// </summary>
protected override CreateParams CreateParams
{
	get
	{
		CreateParams cp = base.CreateParams;
		// 开启 WS_EX_TRANSPARENT,使控件支持透明
		cp.ExStyle |= 0x20;  
		return cp;
	}
}

但是,我在尝试后发现 CreateParams 方式会发生边界阴影的问题,应该是同样缺少某些特性设定吧,大家找到的话可以Mark给我哈,谢谢

MSDN 关于扩展特性的说明 扩展的窗口样式  


下面贴俩张前后的效果图:

           

链接是一个实现的控件类,以供参考:LoadingPanel

调用也比较简单 :

 // 打开遮罩层
 loadingPanel1.ShowWaitingPanel();
 // 关闭遮罩层
 loadingPanel1.CloseWaitingPanel();

@MISS BingBing  o(^▽^)o

Good Good study ,Day Day  Up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!