具有不透明度的WinForm控件

时间:2011-05-24 06:18:52

标签: c# winforms opacity

我有一个自身有一些控件的表单(btnCreateReport,pnlDarkLayer)。我有一个适合表单的面板(Dock = Fill),它位于所有控件的背面。当用户点击btnCreateReport按钮时,我调用pnlDarkLayer BringToFront方法,经过一些计算,我调用了按钮的SendToBack()方法。我想在窗体控件上绘制一个暗层,并禁用窗体上的所有控件。 可能吗?感谢。

也许这段代码可以帮助你理解我的目的:

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;

}

此代码隐藏了所有控件,但我不想隐藏窗体上的控件。我想在它们上绘制一个暗层。用户必须能看到控件。 我需要像控件一样的表单的不透明属性。

我测试了这个:

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

更新:我测试过这个:(使用表单代替面板)

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;

}

但是我无法以我的形式看到ProgressForm。

2 个答案:

答案 0 :(得分:6)

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

  

WinForms中的透明控件是   透明相对于他们的父母,   而不是其他控制。透明度   WinForms更类似于伪装   比真正的透明度。透明的   控制实际上并没有让你看到   它背后的控制通过   形成。它要求其父母绘制它   拥有“透明”的背景   控制。这就是透明的原因   控件显示它背后的形式,但是   掩盖任何其他控制。

     

实现相对于的透明度   其他控件需要做同样的事情   事情,但规模更大:相反   只是要求父母画画   前景控制的背景,   控件需要询问所有控件   在它背后绘制它的背景。   这仅适用于控件   提供一些方法来请求   他们被吸引而不会被吸引   自动更新时   背景控制的图像变化。

该页面还提供了一个代码示例(在vb中,遗憾地),以显示如何完成此操作。

答案 1 :(得分:6)

如果我理解正确,您希望在操作运行时“变暗”表单的内容。

正如有人在此之前所说,做正确的事情非常棘手。但有一种方法可以轻松完成,只需一次预订(见下文)。

看看这个源代码:

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

Form1类有两个主要方法,Shroud()和Unshroud()。

Shroud()方法获取表单的快照,并将其复制到位图中,然后将其“变暗”。然后隐藏控件,并在表单上绘制位图。

UnShroud()方法恢复控件,并告诉表单不再绘制位图。

它需要两个私有变量:一个用于存储位图,另一个用于维护当前状态。

它还会覆盖OnPaint(),因为它需要在“遮蔽”时绘制背景图像。

注意:通过截取表单的屏幕截图来实现遮挡。这意味着形式必须是覆盖点上最顶层的形式。如果表单被其他表单遮盖,则它们将包含在屏幕截图中。我希望这不会对你造成任何问题。

注意:如前所述,实现Windows透明度的唯一方法是所有相关控件的全面合作,这是一项艰巨的任务。其他任何东西(包括这个解决方案)实际上都是骗局。