.NET Windows窗体透明控件

Fak*_*Jim 15 .net user-interface winforms

我想在Windows窗体应用程序中模拟"Web 2.0"灯箱样式UI技术.也就是说,通过"调暗"窗口的客户区域中的所有其他内容来引起对某些前景控制的注意.

显而易见的解决方案是创建一个控件,它只是一个部分透明的矩形,可以停靠在窗口的客户区域并带到Z-Order的前面.它需要像玻璃一样肮脏的疼痛,通过它可以看到其他控件(因此继续自己画).这可能吗?

我有一个很好的打猎,并尝试了一些技术,但到目前为止一直没有成功.如果不可能,那么另一种方法是什么呢?

请参阅:http://www.useit.com/alertbox/application-design.html(在Lightbox部分下面的屏幕截图来说明我的意思.)

Phi*_*ght 14

你能用.NET/C#做这个吗?

是的,你当然可以但需要一点努力.我会推荐以下方法.创建一个没有边框或标题栏区域的顶级窗体,然后通过将TransparencyKey和BackColor设置为相同的值来确保它不绘制客户区背景.所以你现在有一个什么都没画的窗户......

public class DarkenArea : Form
{
    public DarkenArea()
    {
        FormBorderStyle = FormBorderStyle.None;
        SizeGripStyle = SizeGripStyle.Hide;
        StartPosition = FormStartPosition.Manual;
        MaximizeBox = false;
        MinimizeBox = false;
        ShowInTaskbar = false;
        BackColor = Color.Magenta;
        TransparencyKey = Color.Magenta;
        Opacity = 0.5f;
    }
}
Run Code Online (Sandbox Code Playgroud)

在表单的客户区域上创建并放置此DarkenArea窗口.然后你需要能够在没有它聚焦的情况下显示窗口,所以你需要以下面的方式调用平台来显示它而不会变得活跃...

public void ShowWithoutActivate()
{
    // Show the window without activating it (i.e. do not take focus)
    PlatformInvoke.ShowWindow(this.Handle, (short)SW_SHOWNOACTIVATE);
}
Run Code Online (Sandbox Code Playgroud)

你需要让它实际绘制一些东西,但在想要保持高亮显示的控件区域中排除绘图.因此,覆盖OnPaint处理程序并绘制黑色/蓝色或任何您想要的但排除您想要保持明亮的区域...

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    // Do your painting here be exclude the area you want to be brighter
}
Run Code Online (Sandbox Code Playgroud)

最后你需要覆盖WndProc以防止鼠标与窗口交互,如果用户尝试疯狂的事情,比如点击黑暗区域.像这样......

protected override void WndProc(ref Message m)
{
    if (m.Msg == (int)WM_NCHITTEST)
        m.Result = (IntPtr)HTTRANSPARENT;
    else
        base.WndProc(ref m);
}
Run Code Online (Sandbox Code Playgroud)

这应该足以获得预期的效果.当您准备好反转效果时,您将处置DarkenArea实例并继续.


Zer*_*nce 8

这是一个非常酷的主意 - 我可能会用它,谢谢.无论如何,我的解决方案非常简单...在当前的一个上打开一个新的50%不透明表单然后自定义为该表单绘制一个背景图像,其中一个矩形匹配您要突出显示的控件的边界填充的颜色透明度键.

在我的粗略样本中,我将此形式称为"LBform",它的内容是:

public Rectangle ControlBounds { get; set; }
private void LBform_Load(object sender, EventArgs e)
{
    Bitmap background = new Bitmap(this.Width, this.Height);
    Graphics g = Graphics.FromImage(background);
    g.FillRectangle(Brushes.Fuchsia, this.ControlBounds);

    g.Flush();

    this.BackgroundImage = background;
    this.Invalidate();
}
Run Code Online (Sandbox Code Playgroud)

Color.Fuchia是这种半透明形式的TransparencyKey,因此您将能够看到绘制的矩形并与主窗体上的任何边界内的任何内容进行交互.

在实验项目中我试图尝试这个,我使用了一个动态添加到表单的UserControl,但你可以很容易地使用表单上已有的控件.在主窗体(您正在模糊的那个)中,我将相关代码放入按钮单击:

private void button1_Click(object sender, EventArgs e)
{
    // setup user control:
    UserControl1 uc1 = new UserControl1();
    uc1.Left = (this.Width - uc1.Width) / 2;
    uc1.Top = (this.Height - uc1.Height) / 2;
    this.Controls.Add(uc1);
    uc1.BringToFront();

    // load the lightbox form:
    LBform lbform = new LBform();
    lbform.SetBounds(this.Left + 8, this.Top + 30, this.ClientRectangle.Width, this.ClientRectangle.Height);
    lbform.ControlBounds = uc1.Bounds;

    lbform.Owner = this;
    lbform.Show();
}
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以按自己的方式做一些基本的东西,但它只是添加了usercontrol,然后在主窗体上设置灯箱形式,并设置bounds属性以在正确的位置呈现完全透明.表单拖动和关闭灯箱表单和UserControl之类的东西在我的快速示例中没有处理.哦,不要忘记处理Graphics实例 - 我也离开了它(已经很晚了,我真的很累).

这是我20分钟的演示


Joe*_*orn 1

表单本身具有Opacity完美的属性,但我认为大多数单独的控件都没有。你必须亲自绘制它。