VB.NET自定义控件(自定义图形)刷新问题

VB.NET自定义控件(自定义图形)刷新问题,vb.net,controls,gdi+,Vb.net,Controls,Gdi+,我用两个项目创建了一个简单的解决方案。第一个项目(类库)包含一个名为Container的自定义控件,该控件使用圆角绘制自身。第二个项目(windows窗体)是一个测试应用程序 如果我在第二个项目中向主窗体添加一个容器实例,它会很好地显示圆角。另外,当我运行第二个项目时,我可以看到容器 然而,当我开始移动表单(点击并按住标题栏)时,尤其是当我快速移动表单时,所有的图形都被弄乱了,一次又一次地绘制,但没有首先清除它的表面 我可以在Form1.Move事件中调用Container1.Refresh()

我用两个项目创建了一个简单的解决方案。第一个项目(类库)包含一个名为Container的自定义控件,该控件使用圆角绘制自身。第二个项目(windows窗体)是一个测试应用程序

如果我在第二个项目中向主窗体添加一个容器实例,它会很好地显示圆角。另外,当我运行第二个项目时,我可以看到容器

然而,当我开始移动表单(点击并按住标题栏)时,尤其是当我快速移动表单时,所有的图形都被弄乱了,一次又一次地绘制,但没有首先清除它的表面

我可以在Form1.Move事件中调用Container1.Refresh(),但我不想每次都设置它,因为这也意味着我必须在
Form1.Resize
事件中调用Container1.Refresh(),谁知道还有哪个事件

容器(控件)类本身是否存在一个事件,我应该在其中调用Me.Refresh()或Me.Update()或Me.Invalidate()

供参考(Form1.vb)

供参考(Container.vb):


这里不需要强制重画(在正常情况下),因为一旦控件被轻推,重画就会自动强制

但是,您需要做的是在绘制任何其他内容之前清除控件的背景:否则,您的绘制操作将与以前的绘制过程混合。只需添加一个

e.Graphics.Clear(BackColor)
在事件处理程序中执行其他绘图操作之前。此外,考虑使用<代码> OnPaint <代码>方法,而不是<代码> Prase<代码>事件,因为您对控件进行了子类化,不必求助于<代码> Prase< /Cudio>事件处理程序。


对于记录,
Refresh
强制执行通常不需要的同步重画。相反,使用
Invalidate
将重画请求排入默认窗口消息队列。

在我看来,您的
Container
类并没有绘制其整个区域-通常控件负责绘制其整个矩形

为了拥有一个不这样做的控件(具有透明区域(如圆角),您需要为控件提供
WS_EX_transparent
属性。请注意,这是一个Windows API主题,而不是.NET主题,因此您正朝着一些次要的巫毒方向前进

虽然它是用C#编写的,但CodeProject文章似乎确实与您试图实现的目标直接相关

要引用这篇文章,首先需要重写UserControl的构造函数并配置后台:

public TranspControl()
{
     SetStyle(ControlStyles.SupportsTransparentBackColor, true);
     SetStyle(ControlStyles.Opaque, true);
     this.BackColor = Color.Transparent;
}
然后,需要重写
CreateParams()
方法来设置控件样式
WS_EX_TRANSPARENT

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x20;
        return cp;
    }
}
这就是你的问题:

Dim r As Rectangle = e.ClipRectangle
将其更改为:

Dim r As Rectangle = Me.ClientRectangle

调用图形。清除仍然不能真正做到这一点。。。这就是发生的情况:罗普斯塔:在你的照片中,背景没有被清除。在添加清除代码后,您是否重新编译了项目?那它看起来就不一样了。但是,重新编译对于IDE来说是必要的,这样IDE才能注意到这些更改!
Dim r As Rectangle = e.ClipRectangle
Dim r As Rectangle = Me.ClientRectangle