2011-05-24 147 views
7

WinForm的控制I有一个具有在其自身上某些控件(btnCreateReport,pnlDarkLayer).I具有适合于形成面板(基座=填充)形式,它是在所有controls.when使用者的背部点击的btnCreateReport按钮,我请pnlDarkLayer BringToFront方法和一些计算之后我请SendToBack()的button.I的方法希望借助表单控件的黑色层和禁用所有的控制形式。 这可能吗?谢谢。与不透明度

也许这个代码帮助ü理解我的目的:

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; 

} 

此代码隐藏所有的控制,但我不希望隐藏在form.I控制要对他们绘制的黑色层。用户必须能看到控件。 我需要像控件的窗体的不透明属性。

我有测试此:

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以我的形式出现。

+3

除了任何与不透明有关的事情,*请*不要使用调用'DoEvents'的那种循环。给ProcessingReport一些钩子用来在完成时调用一些代码,或者只是把最后一段代码放在ProcessingReport方法的末尾,记得使用BeginInvoke来确保它在UI线程。几乎所有情况下都应该避免使用'Application.DoEvents'。 – 2011-05-24 06:29:31

+0

那么线程完成工作后,我该怎么做? – Saleh 2011-05-24 06:31:20

+0

禁用所有控件,你也可以尝试这样做:foreach(控件中的控件){item.Enabled = false;} – Reniuz 2011-05-24 06:35:08

回答

6

从Winforms中http://support.microsoft.com/kb/943454

透明控制是 相对透明它们的父, 不其他控件。透明度 的WinForms更像是伪装 不是真正的透明度。透明 控制实际上并没有让你看到 通过 形式背后的控制。它要求其母公司在“透明”控件上绘制自己的背景 。这就是为什么一个透明的 控件显示其背后的窗体,但 涵盖了其他任何控件。

为了实现相对于其他 控制透明度的要求做同样的 的事情,但在更大的规模:只是要求家长对 绘制前台控制的背景,而不是 , 控制需要询问所有控件 背后它吸取其背景。 这只适用于 提供某种方法来请求 它们被绘制,而不会 当 后景控件的图像更改时自动更新。

该页面还提供了一个代码示例(在vb中,悲哀地),以显示这是如何完成的。

5

如果我理解正确的,你想进行操作时运行“变暗”形式的内容。

某人的前说到这里,这是非常棘手做对。但有一种方法可以轻松完成,只需一次预订(见下文)。

看这个源代码:

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()方法恢复控件,并告诉窗体不再绘制位图。

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

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

注意:屏蔽通过截取表单的方式工作。这意味着表单必须是隐藏点上的最顶层表单。如果表单被其他表单遮挡,则它们将被包含在屏幕截图中。我希望这不会成为你的问题。

说明:如前所述,在Windows中实现透明的唯一方法是所有控件的全面合作,这是一项艰巨的任务。其他任何东西(包括这个解决方案)都只是一种骗局。