C# Windows Forms semi-opacity

匆匆过客 提交于 2021-02-05 06:44:24

问题


I have already read many topics about opacity/transparency on Windows Forms in C#, but it's not the effect I would like to get. I would like Form to be 100% transparent, but transparency of the Panel was adjustable, and the transparency effect was transferred to the elements behind Form (Windows desktop, web browser e.t.c.). The attached photo shows the effect that I would like to get (I made them in a graphic program). I will be grateful for your help.


回答1:


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

So in addition to Windows Forms solutions, I'll share a WPF solution as well (which is a better framework to satisfy this requirement):

  • Windows Forms - Owned Forms
  • Windows Forms - Layered Windows
  • WPF - Transparent Form and Control Opacity

Windows Forms - Owned Forms

As an option you can use Owned Forms.

Each of the panels can be a top-level border-less Form owned by the main form. The main has a transparency key equal to its back color and those owned forms has opacity. This way you should handle moving of the main form and move the owned forms as well:

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 Forms - Layered Windows

As an option you can use Layered Windows.

This way you can create the semi transparent image at run-time and set it as background image of your form. But your form will not receive any paint event and so hosting control on such form is pointless (however they are working and you somehow can force those control repaint).

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 - Transparent Form and Controls having Opacity

A better framework to satisfy such UI requirement is WPF.

To do so, you can set Background of window to Transparent and WindowStyle to None and set AllowTransparency to True. Also for each control you can simply set Opacity value:

<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>



回答2:


panel doesn't have opacity property. For making a panel transparent you should use a customised panel like this...

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

after creating this control you can add this panel to form and can set opacity according to you.

and the form has its own opacity property that can be set easily.



来源:https://stackoverflow.com/questions/51012168/c-sharp-windows-forms-semi-opacity

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