当表单位于下面时,回调期间的 OnPaint 事件?

发布于 2024-08-31 17:14:26 字数 1573 浏览 2 评论 0原文

想象一下以下场景:

this.SetStyle(ControlStyles.UserPaint, true); //this doesn’t change anything

…

void OpenSomeForm()
{
    SomeForm sf = new SomeForm();
    sf.SomeEvent += new … (SomeEventOcurred);
    sf.ShowDialog();
}

private void SomeEventOcurred(…)
{
    OnePanelInThisForm.Invalidate();
}

private void OnePanelInThisForm_Paint(object sender, PaintEventArgs e)
{
     DoSomeDrawing(e.Graphics);
}

现在,OnePanelInThisForm 在加载表单时可以正确绘制。但如果 SomeEventOcurred 是从“SomeForm”触发的,则绘制事件不会触发。如果我关闭并重新打开表单,它会正确地重新绘制。 如果我向执行的表单添加一个按钮:OnePanelInThisForm.Invalidate();面板已正确重新喷漆。

我缺少什么?

更新:澄清。 (为什么我们不首先这样做……)

我有一个 FORM_A。此 FORM_A 有一个覆盖 Paint 事件的面板。这是一个标准的 WinForm。在画图中它画了一个圆圈。这有效。结果 FORM_A 有一个打开 FORM_B 的按钮。但在此之前,它会订阅 FORM_B 中名为:SomeEvent 的自定义事件。 (参见上面的示例)。因此 FORM_B 可以告诉 FORM_A 有关“SomeEvent”的信息。

现在,FORM_B也是一个普通的WinForm。它有一个普通的按钮。在该按钮的 Click 事件中,它打开 FORM_C。 FORM_C 还有一个名为 SomeEvent 的事件,显然 FORM_B 订阅了该事件。和以前一模一样。这个想法是 FORM_C 有一个按钮可以触发该事件,通知感兴趣的订阅者。在这种情况下,当 FORM_C 触发事件时,FORM_B 被订阅并感兴趣。

当 FORM_B 收到回调时,它所做的唯一事情就是……通知感兴趣的各方(在本例中为 FORM A)该事件已被触发。

现在,即使表单 C 仍然是顶级表单,调用堆栈也会返回到 FormA,返回到定义为第一个事件的回调的方法。

这段代码执行。它所做的只是 somePanel.Invalidate() (或 Refresh(),结果相同)。

该面板的 PAINT 方法中的断点表明该代码没有被调用。尽管已失效,但不会引发 Paint 事件。我认为发生这种情况是因为表单(以及面板)实际上被 FORMB 和 FORMC (仍然打开)覆盖。

仅此而已。如果我关闭表单 C,然后关闭表单 B,表单 A 仍然不会引发绘制事件。我尝试过使表单激活面板无效,但这种情况没有发生。

如果我关闭表格 A 并重新打开它,绘图当然是正确的。

希望这能让它更清楚。

代码并不多,因为这非常简单,FORM A > B> C(火灾事件)-> B-> A->无效()。

Imagine the following scenario:

this.SetStyle(ControlStyles.UserPaint, true); //this doesn’t change anything

…

void OpenSomeForm()
{
    SomeForm sf = new SomeForm();
    sf.SomeEvent += new … (SomeEventOcurred);
    sf.ShowDialog();
}

private void SomeEventOcurred(…)
{
    OnePanelInThisForm.Invalidate();
}

private void OnePanelInThisForm_Paint(object sender, PaintEventArgs e)
{
     DoSomeDrawing(e.Graphics);
}

Now, OnePanelInThisForm draws correctly when the form loads. But if SomeEventOcurred is Fired from “SomeForm”, the paint event is not fired. If I close and reopen the form it correctly repaints.
If I add a button to the form that executes: OnePanelInThisForm.Invalidate(); the panel is correctly repaint.

What am I missing?

UPDATE: Clarification. (why don’t we do this in the first place…)

I have a FORM_A. This FORM_A has a Panel that overrides the Paint event. It’s a standard WinForm. In the Paint it draws a circle. This works. Turns out that FORM_A has a button that opens FORM_B. But before doing that, it subscribes to a custom event in FORM_B called: SomeEvent. (see the sample above). So FORM_B can tell FORM_A about “SomeEvent”.

Now, FORM_B is also a normal WinForm. And it has a normal Button. In the Click event of that button, it opens FORM_C. FORM_C also has an event called SomeEvent and obviously FORM_B subscribes to that event. Exactly like before. The idea is that FORM_C has a button that will trigger that event, notifying the interested subscribers. In this case, when FORM_C fires the event, FORM_B is subscribed and interested.

When FORM_B receives the Call Back, the only thing it does is… notify the interested parties (in this case, FORM A) that the event was fired.

Now, even while Form C is still the top form, the callstack goes back to FormA, to the method defined as callback from the 1st event.

This code Executes. All it does is really somePanel.Invalidate() (or Refresh(), same results).

A Breakpoint in the PAINT method of that panel, reveals that the code doesn’t get called. No Paint event is raised despite being invalidated. I assume that happens because the form (and therefore the panel) is actually covered by FORMB and FORMC (still open).

And that’s all. If I close form C and then Form B, form A still DOESN’T raise the paint event. I’ve tried invalidating the panel on Form activation, but that doesn’t happen.

If I close the form A and reopen it, the drawing is, of course, correct.

Hope this makes it more clear.

There isn’t really much code as this is pretty simple, FORM A > B > C (fire event) -> B -> A -> Invalidate().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稀香 2024-09-07 17:14:26

尝试使用 Refresh() 而不是 Invalidate()。无论如何,这对我来说似乎更一致。

Try using Refresh() instead of Invalidate(). That seems to work more consistently for me, anyways.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文