Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinForm Control with Opacity

I have a form that has some controls on itself(btnCreateReport,pnlDarkLayer).I have a panel that fit to form(Dock = Fill) and it is on the back of all controls.when user click on the btnCreateReport button ,I call pnlDarkLayer BringToFront method and after some calculation I call SendToBack() method of the button.I want to draw a dark layer on form controls and disable all of controls on the form. Is it possible? Thanks.

Maybe this code help u to understand my purpose:

private void btnCreateReport_Click(object sender, EventArgs e)
{
    pnlDarkLayer.BackColor = Color.FromArgb(100, Color.Gray);         

    pnlDarkLayer.BringToFront();
    btnCreateReport.Enabled = false;

    Thread ProcessReport = new Thread(new ThreadStart(ProcessingReport));
    ProcessReport.Start();
    while (ProcessReport.IsAlive)
    {
        Application.DoEvents();
    }
    pnlDarkLayer.SendToBack();

    btnCreateReport.Enabled = true;

}

This code hide all of controls but i don't want to hide controls on the form.I want to draw a dark layer on them.And User must can see controls. I need something like opacity property of forms for their controls.

I have test this:

pnlDarkLayer.CreateGraphics().CompositingMode=System.Drawing.Drawing2D.CompositingMode.SourceOver;

Update: I have test this one: (use a form instead of panel)

private void btnCreateReport_Click(object sender, EventArgs e)
{          

    btnCreateReport.Enabled = false;

    frmProgress ProgressForm = new frmProgress();
    ProgressForm.TopLevel = false;
    ProgressForm.Parent = this;
    ProgressForm.BringToFront();
    this.Controls.Add(ProgressForm);
    ProgressForm.Show();

    Thread ProcessReport = new Thread(new ThreadStart(ProcessingReport));
    ProcessReport.Start();

    while (ProcessReport.IsAlive)
    {
        Application.DoEvents();
    }
    ProgressForm.Close();
    btnCreateReport.Enabled = true;

}

But I can't see the ProgressForm in my form.

like image 871
Saleh Avatar asked May 24 '11 06:05

Saleh


2 Answers

From http://support.microsoft.com/kb/943454

Transparent controls in WinForms are transparent relative to their parent, not to other controls. Transparency in WinForms is more akin to camouflage than true transparency. A transparent control doesn’t actually let you see the control behind it through the form. It asks its parent to draw its own background on the "transparent" control. This is why a transparent control shows the form behind it, but covers up any other controls.

To implement transparency relative to other controls requires doing the same thing but on a larger scale: instead of just asking the parent to draw on the foreground control’s background, the control needs to ask all controls behind it to draw on its background. This will only work for controls which provide some method to request that they be drawn and will not automatically update when the background control’s image changes.

The page also provides a code example (in vb, sadly) to show how this is done.

like image 168
Edwin de Koning Avatar answered Nov 15 '22 06:11

Edwin de Koning


If I understand correctly, you want to 'darken' the contents of the form while an operation is running.

As someone's said before here, it's very tricky to do right. But there is a way to get it done easily, with one reservation (see below).

Look at this source code:

public partial class Form1 : Form
{
    private Bitmap _background;
    private bool _isShrouded;

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        if (true == _isShrouded && null!=_background)
            e.Graphics.DrawImage(_background, 0, 0);
    }

    public void Shroud()
    {
        if (false == _isShrouded)
        {
            CreateScreenshot();

            HideControls();

            _isShrouded = true;

            this.Invalidate();
        }
    }

    public void Unshroud()
    {
        if (true == _isShrouded)
        {
            ShowControls();

            _isShrouded = false;

            this.Invalidate();
        }


    }

    private void HideControls()
    {
        foreach (Control control in this.Controls)
            control.Visible = false;
    }

    private void ShowControls()
    {
        foreach (Control control in this.Controls)
            control.Visible = true;
    }

    private void CreateScreenshot()
    {
        Rectangle area = this.RectangleToScreen(this.ClientRectangle);
        Bitmap screenGrab = new Bitmap(area.Width, area.Height);

        Brush dark = new SolidBrush(Color.FromArgb(128, Color.Black));

        Graphics g = Graphics.FromImage(screenGrab);
        g.CopyFromScreen(area.Location, Point.Empty, area.Size);
        g.FillRectangle(dark, 0, 0, area.Width, area.Height);
        g.Dispose();

        _background = screenGrab;
    }
}

The Form1 class has two main methods, Shroud() and Unshroud().

The Shroud() method takes a snapshot of the form, and copies it into a bitmap, which is then 'darkened'. The controls are then hidden, and the bitmap is painted on the form.

The UnShroud() method restores the controls, and tells the form to no longer draw the bitmap.

It requires two private variables: one to store the bitmap, and a flag that maintains the current state.

It also overrides OnPaint() because it needs to draw the background image when it is 'shrouded'.

Note: The shrouding works by taking a screenshot of the form. This means that the form MUST BE the top-most form at the point of shrouding. If the form is obscured by other forms then they will be included in the screenshot. I hope that this won't be a problem for you.

Note: As said before, the only way to achieve transparency in Windows is full cooperation from all controls involved, and that's an arduous task. Anything else (including this solution) is really just trickery.

like image 41
Edwin Groenendaal Avatar answered Nov 15 '22 06:11

Edwin Groenendaal