简体   繁体   English

带不透明度的 WinForm 控件

[英]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.我有一个表单,它本身有一些控件(btnCreateReport,pnlDarkLayer)。我有一个适合表单的面板(Dock = Fill),它位于所有控件的背面。当用户单击 btnCreateReport 按钮时,我调用 pnlDarkLayer BringToFront 方法,经过一些计算后,我调用按钮的 SendToBack() 方法。我想在表单控件上绘制一个暗层并禁用表单上的所有控件。 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.我需要像 forms 的 opacity 属性来控制它们。

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.但是我在我的表单中看不到 ProgressForm。

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

Transparent controls in WinForms are transparent relative to their parent, not to other controls. WinForms 中的透明控件相对于它们的父控件是透明的,而不是相对于其他控件。 Transparency in WinForms is more akin to camouflage than true transparency. WinForms 中的透明度更像是伪装,而不是真正的透明度。 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.该页面还提供了一个代码示例(遗憾的是在 vb 中)来说明这是如何完成的。

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(). Form1 class 有两个主要方法,Shroud() 和 Unshroud()。

The Shroud() method takes a snapshot of the form, and copies it into a bitmap, which is then 'darkened'. Shroud() 方法获取表单的快照,并将其复制到 bitmap,然后“变暗”。 The controls are then hidden, and the bitmap is painted on the form.然后隐藏控件,并在窗体上绘制 bitmap。

The UnShroud() method restores the controls, and tells the form to no longer draw the bitmap. UnShroud() 方法恢复控件,并告诉窗体不再绘制 bitmap。

It requires two private variables: one to store the bitmap, and a flag that maintains the current state.它需要两个私有变量:一个用于存储 bitmap,另一个用于维护当前 state 的标志。

It also overrides OnPaint() because it needs to draw the background image when it is 'shrouded'.它还覆盖 OnPaint(),因为它需要在“遮蔽”时绘制背景图像。

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.如果表格被其他 forms 遮挡,则它们将包含在屏幕截图中。 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.注意:如前所述,在 Windows 中实现透明度的唯一方法是所有相关控件的全面合作,这是一项艰巨的任务。 Anything else (including this solution) is really just trickery.其他任何事情(包括这个解决方案)实际上都是骗人的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM