代码之家  ›  专栏  ›  技术社区  ›  Tom Corelis

.NET COM服务器中的C WinForms控件不会重新绘制

  •  1
  • Tom Corelis  · 技术社区  · 14 年前

    我有一个COM服务器应用程序,它使用一些WinForms控件,坦率地说,当它们的属性(文本、背景色等)更改时,这些控件似乎不会被重新绘制。

    我试着去召唤 txtControlName.Invalidate() 以及 .Update() 两个都没有影响到任何事情。

    我们坚持使用.NET 2.0,并提供一个视觉响应和有趣的用户界面,这是一项业务需求,虽然我意识到我可能可以使用winapi强制重画。 SendMessage() 我更愿意让.NET处理所有这些东西——有足够的黑客,我们不想再添加更多。

    最后,我想指出.NET COM服务器托管在非托管应用程序中。

    谢谢!

    汤姆

    附录:

    此时,实际更新代码如下:

    public void UpdateSt(int? seq, string text) {
    
        Control.CheckForIllegalCrossThreadCalls = true;
    
        if (this.lblText.InvokeRequired) {
    
            this.lblText.Invoke(new MethodInvoker(() => {
    
                UpdateSt(seq, text);
    
            }));
    
        } else {
    
            if (text != String.Empty) {
    
                lblText.Text = text;
                //WinAPI.InvalidateRect(lblText, true);
                lblText.Refresh();
                //WinAPI.SendMessage(lblText.Handle, (uint)WinAPI.WM.SETTEXT, 0, new StringBuilder(text));
                DebugTrace("lblText says '" + lblText.Text + "', is supposed to say '" + text + "'.");
            }
    
            if (imgSeq.HasValue) {
    
                // not implemented yet
    
            }
    
        }
    
    }
    

    附录2:

    Spy++报告来自.NET文本设置器的wm_settext调用失败,这与我自己的wm_settext调用很相似。

    附录3: 解决了的

    结果发现,问题在于消息泵故障和一些P/Invoke调用的组合,它们弊大于利。由于库是通过COM启动的,因此没有.NET消息泵和添加 Application.Run() 在一个新的线程中,所有的东西都可以以它应该的方式响应。确保所有基于窗体的交互都从具有该调用的线程开始似乎是一个好主意。

    1 回复  |  直到 14 年前
        1
  •  1
  •   Hans Passant    14 年前

    一般的诊断是消息泵有问题。你并没有抱怨这些控件根本没有自己绘制,所以看起来这不太可能完全被破坏。如果这是一个偶然的绘画问题,那么诊断是你有一个线程问题。换句话说,您正在更新控件属性,或者从错误的线程调用invalidate/update。

    Windows窗体具有此的内置诊断程序,在附加调试程序时处于活动状态。确保未将control.checkForIllegalCrossThreadCalls设置为false。

    接下来要看的是消息泵本身。当用show()方法而不是showdialog()显示表单时,非托管消息泵将调度消息。这本身就有一些不良的副作用,键盘加速器将不再工作,选项卡也不会工作。如果使用ShowDialog(),请检查问题是否消失。


    您的评论提供了另一个提示,说明问题可能是什么。如果您知道从另一个线程调用时,invokeRequired会出错 在使用错误的表单对象引用时,您没有看到任何可见的更新迹象。可能是用新操作符创建的。请确保使用现有的application.openforms[]在获取引用时遇到问题,可以为您提供一个引用。