我用 C# 创建了一个具有自定义按钮的应用程序。这些都有透明背景,因此我从 Control 继承并重写 CreateParams/OnPaintBackground 并添加了 InvalidateEx 函数。
现在我需要一个类似网格的布局(TableLayoutPanel),它也是透明的。我再次创建了自己的控件并覆盖 CreateParams/OnPaintBackground 并添加了 InvalidateEx 函数。在滚动条上,我看到背景“记住”了他所画的内容,因此我看到了重影(如果这是正确的词的话)。 将 InvalidateEx 函数连接到 Scroll 事件只会使面板在滚动时闪烁。
有办法消除闪烁吗?
public class GridLayout : TableLayoutPanel
{
public GridLayout()
{
this.Scroll += delegate { this.InvalidateEx(); };
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20; //Transparent
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// do nothing
}
protected void InvalidateEx()
{
if (Parent == null)
return;
Rectangle rc = new Rectangle(this.Location, this.Size);
Parent.Invalidate(rc, true);
}
}
我想过使用 WPF,但我没有这方面的经验,我需要在几天内创建它 -> Winforms。
尝试将 DoubleBuffered 属性设置为 true。 DoubleBuffered 是一个布尔属性,它“获取或设置一个值,该值指示该控件是否应使用辅助缓冲区重绘其表面以减少或防止闪烁。WinAPI 中的某些控件不公开 DoubleBuffered 属性。因此,您可能必须使用 Type.InvokeMember 正如我在下面的代码中所示,其中我以 DataGridView 控件为例。
typeof(DataGridView).InvokeMember
(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
myDataGridViewObject, // This is a variable of the object you are trying to set this property for.
new object[] { true }
);
Type.InvokeMember 的语法如下。
public object? InvokeMember
(
string name,
System.Reflection.BindingFlags invokeAttr,
System.Reflection.Binder? binder,
object? target,
object?[]? args
);
不要忘记根据需要添加命名空间。