.NET Windows窗体透明控件
我想在Windows Forms应用程序中模拟" Web 2.0"灯箱风格的UI技术。也就是说,通过"缩小"窗口客户区域中的所有其他内容来吸引对某些前景控件的注意。
显而易见的解决方案是创建一个控件,该控件只是一个部分透明的矩形,可以停靠在窗口的客户区域并置于Z-Order的前面。它需要像玻璃的脏痛一样起作用,通过它仍然可以看到其他控件(并因此继续进行绘制)。这可能吗?
我进行了不错的狩猎,自己尝试了一些技巧,但到目前为止没有成功。
如果不可能的话,还有另一种方法吗?
请参阅:http://www.useit.com/alertbox/application-design.html(在"灯箱"部分下的屏幕截图以说明我的意思)。
解决方案
回答
表单本身具有完美的属性"不透明度",但我认为大多数单独的控件都没有。我们必须自己绘制它。
回答
大的调光矩形很好。
另一种方法是:
滚动我们自己的基本Form类可以说是MyLightboxAwareForm类,该类将侦听LightboxManager中的LightboxEvent。然后让我们所有的表格都继承自" MyLightboxAwareForm"。
在任何Lightbox上调用Show方法后,LightboxManager将向所有MyLightboxAwareForm实例广播一个LightboxShown事件并使它们自己变暗。
这样做的好处是,正常的Win32窗体功能将继续起作用,例如,当我们单击窗体的模式对话框之一时,窗体的任务栏刷新,或者鼠标悬停/鼠标下移事件的管理仍将正常工作等。
如果我们想要矩形调光样式,可以将逻辑放在MyLightboxAwareForm中
回答
每个表单都具有"不透明度"属性。将其设置为50%(或者代码中的0.5),这样将是半透明的。删除边框,并在我们要聚焦的表单之前最大程度地显示边框。我们可以更改表单的背景色,甚至可以设置背景图像以实现不同的效果。
回答
我们可以在.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; } }
创建此DarkenArea窗口并将其放置在窗体的客户区域上。然后,我们需要能够在没有焦点的情况下显示窗口,因此我们将需要以以下方式进行平台调用以在不激活窗口的情况下进行显示...
public void ShowWithoutActivate() { // Show the window without activating it (i.e. do not take focus) PlatformInvoke.ShowWindow(this.Handle, (short)SW_SHOWNOACTIVATE); }
我们需要使它实际绘制一些东西,但要在要保持突出显示的控件区域中排除绘制。因此,请覆盖OnPaint处理程序并绘制黑色/蓝色或者任何我们想要的颜色,但要排除要保持明亮的区域...
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // Do your painting here be exclude the area you want to be brighter }
最后,如果用户尝试执行某些疯狂操作(例如单击深色区域),则需要覆盖WndProc,以防止鼠标与窗口交互。像这样的东西
protected override void WndProc(ref Message m) { if (m.Msg == (int)WM_NCHITTEST) m.Result = (IntPtr)HTTRANSPARENT; else base.WndProc(ref m); }
这应该足以获得所需的效果。准备好反转效果时,请处置DarkenArea实例并继续。
回答
我可能会用到这是一个很酷的主意,谢谢。无论如何,我的解决方案真的很简单...在我们当前的表格上打开一个新的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(); }
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(); }
我们可以根据自己的喜好来做一些基本的事情,但这只是添加用户控件,然后在主窗体上设置灯箱窗体,并设置bounds属性以在正确的位置呈现完整的透明度。在我的快速示例中没有处理表单拖动和关闭灯箱表单以及UserControl之类的事情。哦,别忘了处理掉我遗漏的Graphics实例(太晚了,我真的很累)。
这是我在20分钟内完成的演示