C# Windows 形成半透明

C# Windows Forms semi-opacity

我已经阅读了很多关于opacity/transparency on Windows Forms in C# 的话题,但这不是我想要得到的效果。我希望Form是100%透明的,但是Panel的透明度是可调的,透明效果转移到Form后面的元素(Windows桌面,网络浏览器e.t.c.).所附照片显示了我想要得到的效果(我在图形程序中制作了它们)。我会很感激你的帮助。

面板没有不透明度 属性。要使面板透明,您应该使用这样的自定义面板...

Imports System.ComponentModel

Partial Public Class C_PANEL
Inherits Panel
Private Const WS_EX_TRANSPARENT As Integer = &H20

Public Sub NewP()
    SetStyle(ControlStyles.Opaque, True)
End Sub

Public Sub NewP(con As IContainer)
    con.Add(Me)
End Sub

Private iopacity As Integer = 50
<DefaultValue(50)>

Public Property Opacity() As Integer
    Get
        Return Me.iopacity
    End Get

    Set(value As Integer)
        If Value < 0 OrElse Value > 100 Then
            Throw New ArgumentException("value must be between 0 and 100")
        End If
        Me.iopacity = Value
    End Set
End Property

Protected Overrides ReadOnly Property CreateParams() _
          As CreateParams
    Get
        Dim cpar As CreateParams = MyBase.CreateParams
        cpar.ExStyle = cpar.ExStyle Or WS_EX_TRANSPARENT
        Return cpar
    End Get
End Property

Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Using brush = New SolidBrush(Color.FromArgb(Me.Opacity _
          * 255 / 100, Me.BackColor))
        e.Graphics.FillRectangle(brush, Me.ClientRectangle)
    End Using
    MyBase.OnPaint(e)
End Sub

End Class

创建此控件后,您可以将此面板添加到窗体中,并可以根据您的需要设置不透明度。

并且表单有自己的不透明度 属性,可以轻松设置。

: If there is any other language / environment in which I can deal with this problem, of course I am ready to try it.

所以除了Windows Forms的解决方案,我还会分享一个WPF的解决方案(这是一个更好的满足这个需求的框架):

  • Windows 表格 - 自有表格
  • Windows 表格 - 分层 Windows
  • WPF - 透明表单和控件不透明度

Windows 表格 - 自有表格

您可以选择使用自有表格。

每个面板都可以是主窗体拥有的顶级无边框窗体。主要有一个透明度键等于它的背景颜色,那些拥有的形式有不透明度。这样你应该处理主窗体的移动并移动拥有的窗体:

public partial class MyOwnerForm : Form
{
    public MyOwnerForm()
    {
        InitializeComponent();
        this.BackColor = Color.Magenta;
        this.TransparencyKey = Color.Magenta;
        this.StartPosition = FormStartPosition.Manual;
        this.DesktopLocation = new Point(100, 100);
        this.ClientSize = new Size(330, 330);
    }
    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);
        CreateForm(1, new Point(10, 10), new Size(150, 150)).Show();
        CreateForm(0.75, new Point(170, 10), new Size(150, 150)).Show();
        CreateForm(0.50, new Point(10, 170), new Size(150, 150)).Show();
        CreateForm(0.25, new Point(170, 170), new Size(150, 150)).Show();
    }
    protected override void OnMove(EventArgs e)
    {
        base.OnMove(e);
        if(OwnedForms.Length>0)
        {
            var p = PointToScreen(new Point(10, 10));
            var dx = p.X - OwnedForms[0].Location.X;
            var dy = p.Y - OwnedForms[0].Location.Y;
            foreach (var f in OwnedForms)
                f.Location= new Point(f.Location.X+dx, f.Location.Y+dy);
        }
    }
    Form CreateForm(double opacity, Point location, Size size)
    {
        var f = new Form();
        f.FormBorderStyle = FormBorderStyle.None;
        f.BackColor = Color.Lime;
        f.Opacity = opacity;
        f.StartPosition = FormStartPosition.Manual;
        f.DesktopLocation = PointToScreen(location);
        f.ClientSize = size;
        f.Owner = this;
        f.ShowInTaskbar = false;
        return f;
    }
}

Windows 表格 - 分层 Windows

作为一个选项,您可以使用

这样您可以在 运行 时创建半透明图像并将其设置为表单的背景图像。但是您的表单不会收到任何绘制事件,因此在这种表单上托管控件是没有意义的(但是它们正在工作并且您可以以某种方式强制这些控件重新绘制)。

public partial class MyLayeredForm : PerPixelAlphaForm
{
    public MyLayeredForm()
    {
        InitializeComponent();
        var bm = new Bitmap(230, 230);
        using (var g = Graphics.FromImage(bm))
        {
            using (var b = new SolidBrush(Color.FromArgb(255, Color.Lime)))
                g.FillRectangle(b, 10, 10, 100, 100);
            using (var b = new SolidBrush(Color.FromArgb(255 * 75 / 100, Color.Lime)))
                g.FillRectangle(b, 120, 10, 100, 100);
            using (var b = new SolidBrush(Color.FromArgb(255 * 50 / 100, Color.Lime)))
                g.FillRectangle(b, 10, 120, 100, 100);
            using (var b = new SolidBrush(Color.FromArgb(255 * 25 / 100, Color.Lime)))
                g.FillRectangle(b, 120, 120, 100, 100);
        }
        this.SelectBitmap(bm);
    }
}

WPF - 具有不透明度的透明表单和控件

满足这种 UI 要求的更好的框架是 WPF。

为此,您可以将 window 的 Background 设置为 Transparent,将 WindowStyle 设置为 None,并将 AllowTransparency 设置为 True。同样对于每个控件,您可以简单地设置 Opacity 值:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="261.154" Width="232.923" 
        Background="Transparent" AllowsTransparency="True" 
        WindowStyle="None" WindowStartupLocation="CenterScreen">
    <Grid Margin="0,0,0,0">
        <Grid HorizontalAlignment="Left" Height="100" 
              Margin="10,10,0,0" VerticalAlignment="Top" 
              Width="100" Background="Lime" Opacity="1"/>
        <Grid HorizontalAlignment="Left" Height="100"
              Margin="120,10,0,0" VerticalAlignment="Top"
              Width="100" Background="Lime" Opacity="0.75" 
              Grid.ColumnSpan="2"/>
        <Grid HorizontalAlignment="Left" Height="100"
              Margin="10,120,0,0" VerticalAlignment="Top"
              Width="100" Background="Lime" Opacity="0.50"/>
        <Grid HorizontalAlignment="Left" Height="100"
              Margin="120,120,0,0" VerticalAlignment="Top"
              Width="100" Background="Lime" Opacity="0.25"
              Grid.ColumnSpan="2"/>
    </Grid>
</Window>