5

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.

Here is a photo showing the effect I want to get

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
grzenio_l
  • 63
  • 1
  • 5
  • 2
    Each of the panels can be a top-level border-less `Form` owned by `Form1`. `Form1` has a transparency key equal to its back color and those owned forms has opacity. – Reza Aghaei Jun 24 '18 at 18:45
  • The idea seemed good, but unfortunately it doesn't work. I do not know if I understood it well. I did it so that I set Form1.IsMdiContainer = true, and Form1.TransparencyKey = Color.FromArgb(171, 171, 171) (equals to background color when Form is MdiContainer). This unfortunately did not give the desired result, becouse Form1 isn't transparent. I do not know if transparency doesn't work when Form1 is IsMdiContainer. Except when I did Form2 owned by Form1 then Form2 parameter Opacity doesn't change the transparency of Form2. – grzenio_l Jun 25 '18 at 06:52
  • Owned forms are not the same as MDIchildren. They are not hosted in the owner form. They are just on top of owner form. You should keep them together. – Reza Aghaei Jun 25 '18 at 06:53
  • Another option for you is using [layered windows](https://stackoverflow.com/a/33531201/3110834). 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 you somehow can make those controls working). – Reza Aghaei Jun 25 '18 at 06:58
  • Based on your comment here → *[OP](https://stackoverflow.com/questions/51012168/c-sharp-windows-forms-semi-opacity#comment89028231_51012258): If there is any other language / environment in which I can deal with > this problem, of course I am ready to try it.* I suggest you using `WPF`. – Reza Aghaei Jun 25 '18 at 08:24

2 Answers2

4

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:

enter image description here

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

enter image description here

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:

enter image description here

<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>
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Thanks so much for your help, you gave me lots of useful information. For my project I don't need using controls (buttons, textboxes), so "Windows Forms - Layered Windows" solution can be good. I've tried this solution and it works well but I will test it more when I get home from work. I will also try "WPF". Unfortunately I do not have enough reputation for my rating to be included. – grzenio_l Jun 25 '18 at 09:13
  • You're welcome. No worries, you will gain more reputation by asking good questions or sharing good answers. – Reza Aghaei Jun 25 '18 at 09:42
  • As always in stackoverflow, we have some invisible downvoters around! – Reza Aghaei Jun 25 '18 at 12:57
  • I think not only on stackoverflow :P – grzenio_l Jun 25 '18 at 13:34
  • Ok, @RezaAghaei , I know it is an old post. I use the PixelPerAlpha version to show my splash screen. How can I use an label to that form to show some progress? What I mean, is to show a label and to be able to change its text from main form. How to repaint it?! You said so in your answer! – Vali Maties Jun 08 '20 at 19:27
  • @ValiMaties Take a look at [this article](https://www.codeproject.com/Articles/20758/Alpha-Blended-Windows-Forms) and if it's not what you are looking for, then I think it's better to ask a new question :) – Reza Aghaei Jun 09 '20 at 19:15
  • Thanks @RezaAghaei , but I cannot post anymore questions on Stack for 4-5 months ago... And, no, it is not working on my VS2019, latest version, 16.6.2 – Vali Maties Jun 09 '20 at 19:32
  • @ValiMaties Should not be matter of VS. If I have any idea about the solution, I'll share a summary in the comments with you; however, in general if you have any issue with posting new questions, maybe you can [contact](https://stackoverflow.com/contact) support. – Reza Aghaei Jun 10 '20 at 08:08
  • If it's a single dialog/splash screen, I think WPF would be an easy solution for you. – Reza Aghaei Jun 10 '20 at 08:12
  • It's an application which starts with this splash screen. In this time, as splash screen is displayed, some jobs are running to be able to create my database and to create controls in main form. So, this splash screen must interact with user showing the progress of my jobs, on a label. – Vali Maties Jun 10 '20 at 08:20
  • I have sent to contact address as I have been blocked to post questions.. I have to wait their response. Thanks Reza again! – Vali Maties Jun 10 '20 at 08:21
0

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.

  • 1
    The question is tagged C#, not VB. – Sebastian Hofmann Jun 24 '18 at 17:24
  • you can use carlosag convertor for converting this code to the c# one. I think the idea is enough to solve the issue rather than the code.. ;) – Amrita Srivastava Jun 24 '18 at 17:35
  • That's right, the question is about C#, not VB, but it doesn't matter, because I've seen the same solution in C#, and it doesn't work like I would like. With this solution transparency only works locally, only with elements on Form. The entire Panel is not transparent to the desktop. Below I attach how it looks with this solution. [link](https://i.imgur.com/DZnAA0I.png) – grzenio_l Jun 24 '18 at 17:40
  • "the question is about C#, not VB" @grzenio_l, your question revolves for around manipulating WinForm controls to achieve the desired effect. The .Net language used to implement the solution should be no concern. Why would you choose to limit the possibility of getting a solution just to impose a personal preference? – TnTinMn Jun 24 '18 at 23:51
  • This is not crucial which language I will use. I'm learning to use C# language because I have experience in programming microcontrollers in C and C ++, and C# is closest to this languages. If there is any other language / environment in which I can deal with this problem, of course I am ready to try it, although the syntax of the VB language is not very clear to me and I would rather avoid it. – grzenio_l Jun 25 '18 at 07:01
  • @AmritaSrivastava This [trick](https://stackoverflow.com/a/32402532/3110834) will not work here. For this problem, you need to use one of the solutions described in the other answer. – Reza Aghaei Jun 25 '18 at 10:31