0

我正在尝试在我的控件的 OnPaint() 方法中使用(这可能已经是我的问题)e.Graphics.CopyFromScreen() 来准备可以在其上绘制控件内容的背景。目标是一个带有圆角和其他特定功能的工具提示,以替换默认的 Windows 工具提示。

理想情况下,工具提示可以抗锯齿并混合到背景中,但是在紧要关头我可以容忍锯齿边界。这也可能是必要的,因为控件通常会覆盖带有 OpenGL 覆盖的控件,并且整个混合过程可能最终成为一场噩梦。

我创建了一个自定义用户控件,它的持久实例属于我的应用程序的主窗体,覆盖了 OnPaint 和 OnPaintBackground 方法。然而,透明度的应用具有挑战性。据我了解,传递给paint方法的图形对象从当前VisibleClipBounds的副本开始,通常第一步是用纯色清除控件并开始绘制主要特征。我的第一个想法是绕过填充并开始在捕获的背景上绘图。对于第一次重绘,这可以正常工作,但随后的重绘会保留以前的内容,而不是重新捕获背景。我希望 CopyFromScreen 会专门从其捕获中消除当前的绘图控件,以便从一个干净的基础开始,但事实并非如此,

其他解决方案及其排列,例如

SetStyle(ControlStyles.SupportsTransparentBackColor, True)

Me.BackColor = Color.Transparent

e.Graphics.Clear(Color.FromArgb(0,0,0,0))

迄今为止没有产生适当的结果。

我从使用透明键颜色的透明表格开始。这适用于别名,但使用表单作为工具提示似乎过多并导致烦人的伪影(其中一些可以克服),例如任务栏按钮的临时存在,底层表单的焦点丢失以及随后在主机表单标题中的视觉反馈酒吧颜色。控件的重量要轻得多,但我正在努力使它与表单一样好用。

在这一点上,我只是问如何达到预期的结果,以及 CopyFromScreen 是否是该解决方案的一部分。

4

2 回答 2

2

这是要阅读的大量文本 - 但解决透明度以实现自定义形状的表单/控件...... Control.Region 可以做同样的事情:

[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
    int nLeftRect, // x-coordinate of upper-left corner
    int nTopRect, // y-coordinate of upper-left corner
    int nRightRect, // x-coordinate of lower-right corner
    int nBottomRect, // y-coordinate of lower-right corner
    int nWidthEllipse, // height of ellipse
    int nHeightEllipse // width of ellipse
    );

private void CreateRegion()
{
    this.Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 40, 40));
}
于 2012-06-26T20:03:27.730 回答
0

如果您的控件设置为顶级窗口并且您在 Windows 7 或 8 上运行它,请检查 DwmEnableBlurBehindWindow。在参数结构中,我将 enable 设置为 true,并为模糊创建一个 1x1 像素的区域。将 BackColor 和 TransparencyKey 设置为黑色,这给了我一个完全透明的窗口(完成鼠标传递),我可以用完全 alpha 透明度(使用 Graphics.FromHwnd)绘制 32 位图像。这种方法的一个好处是,如果窗口移动或背景发生变化,Windows DWM 会完成所有工作——我不必更新任何东西。

于 2013-01-31T03:36:30.907 回答