拖放过程中的重绘问题

7

我希望在DragEnter和DragLeave事件期间触发拖动目标控件重新绘制自身(通过invalidate或refresh)。 代码大致如下:

protected override void OnDragEnter (DragEventArgs drgargs)
{
  //-- Set a property that affects drawing of control, then redraw
  this.MyProperty = true;
  this.Refresh(); //-- Does nothing???      
}

protected override void OnDragLeave (EventArgs e)
{
  //-- Set a property that affects drawing of control, then redraw
  this.MyProperty = false;
  this.Refresh(); //-- Does nothing???      
}

它实际上并没有重新绘制控件,Refresh()在这些事件中不会调用OnPaint方法。有什么方法可以做到这一点吗?我可能在这里理解有误。
更新:jasonh提供的答案实际上并不起作用。当使用Invalidate()或Invalidate(rect)时,控件实际上不会更新。这是在拖放操作期间被调用的。还有其他想法吗?您能在拖放期间触发控件的重绘吗?谢谢!
更新2:我创建了一个示例项目,并无法使其失效。唉...我最终追踪到一些在OnPaint中引起问题的代码。因此,这事实上更多地是我不理解调试器的工作方式(它从未命中OnPaint中的断点...仍然不知道为什么)。Invalidate()、Refresh()都可以工作。JasonH得到了答案,因为它最终是正确的,并且还展示了如何使控件的部分失效...我不知道这一点。谢谢您的所有帮助!

我猜你没有将AllowDrop设置为true。 - jasonh
是的,AllowDrop属性已设置为true。拖放正在进行中。只是控件的重绘没有发生(在Invalidate()或Refresh()之后OnPaint未被调用)。 - Greg McGuffey
2个回答

4

调用this.Invalidate()方法可以使窗体/控件重新绘制。如果你知道具体的区域,可以调用其中一个重载方法来指定要使其无效化的区域。例如:

Rectangle toInvalidate = new Rectangle(drgargs.X - 50, drgargs.Y - 50, 50, 50);
this.Invalidate(toInvalidate);

那将使得拖动目标周围50像素范围内的区域无效。

2
这个不起作用。问题明确是关于在拖放事件期间执行此操作的。如果它对你有效,那么我肯定是做错了什么...<困惑>... - Greg McGuffey
1
不确定为什么我被踩了,因为Invalidate正好做了它应该做的事情。 - jasonh
请确保UserControl的AllowDrop属性设置为true。我已在一个简单的项目中进行了测试,将字符串绘制到控件上,并且根据用户是否拖动到控件上(我正在测试的内容)会改变颜色。您能否发布一个不起作用的项目示例,以便我可以帮助您解决问题? - jasonh
为什么会被踩?Invalidate是强制重绘控件的正确方式。 - Ed S.
我没有对此回答或任何回答进行反对投票...因为声望值不够。我可能错在我的代码上,但是使无效的调用没有起作用。也许在其他情况下应该/会起作用,但在我的情况下没有。我只是发表评论,并指出我知道我可能做错了什么。只是试图找出问题所在。我正在创建一个示例应用程序,以查看是否可以在另一个环境中复制此问题。 - Greg McGuffey
显示剩余2条评论

2
这里有三种看似适用的方法: Control.Invalidate() - 将控件(区域或矩形)标记为需要重新绘制,但不会强制重新绘制,当其他所有事情都被处理并且应用程序变得空闲时,重新绘制才会触发。 Control.Update() - 如果任何部分已被无效,则立即使控件重新绘制。 Control.Refresh() - 导致控件无效,并更新(立即重新绘制自身)。
因此,Refresh() 是正确的方法。我会在刷新方法调用上设置断点,看看它是否/何时被触发。

它被触发了。它执行了,但实际上并没有导致 OnPaint 被调用。 - Greg McGuffey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接