简体   繁体   English

.NET COM Server中的C#WinForms控件不会重绘

[英]C# WinForms control in .Net COM Server won't redraw

I have a COM server app which uses some WinForms controls which, frankly, do not seem to be redrawing when their properties (Text, BackColor, etc) are changed. 我有一个使用某些WinForms控件的COM服务器应用程序,坦率地说,当更改了它们的属性(Text,BackColor等)时,它们似乎并未重绘。

I have tried invoking txtControlName.Invalidate() as well as .Update() and neither seem to be affecting anything. 我尝试调用txtControlName.Invalidate()以及.Update() ,但似乎都没有影响任何东西。

It is a business requirement that we stick to .Net 2.0 and provide a visually responsive and interesting UI, and while I realize I can probably force redraws with WinAPI SendMessage() I would much rather have .Net handle all this stuff -- there are enough hacks in place and we don't want to add any more. 这是一项业务需求,我们坚持.Net 2.0并提供视觉响应和有趣的UI,尽管我意识到我可以用WinAPI SendMessage()强制重绘,但我宁愿让.Net处理所有这些内容-足够多的黑客,我们不想再添加任何东西。

Finally, I wanted to note that the .Net COM server is hosted inside an unmanaged application. 最后,我想指出.Net COM服务器托管在一个非托管应用程序中。

Thanks! 谢谢!

Tom 汤姆

Addendum: 附录:

At this time, the actual updating code looks like: 此时,实际的更新代码如下所示:

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

        }

    }

}

Addendum #2: 附录2:

Spy++ reports that the WM_SETTEXT call originating from .Net's Text setter is failing, much like my own WM_SETTEXT calls. Spy ++报告说,源自.Net的Text setter的WM_SETTEXT调用失败,就像我自己的WM_SETTEXT调用一样。

Addendum #3: SOLVED 附录3:已解决

Turns out the problem was a combination of a broken message pump and some P/Invoke calls that did more harm than good. 原来问题是消息泵损坏和一些P / Invoke调用的结合,弊大于利。 As the library was started via COM there was no .Net message pump and adding Application.Run() inside a new thread allows everything to respond the way it should. 由于该库是通过COM启动的,因此没有.Net消息泵,并且在新线程中添加Application.Run()可以使所有内容以应有的方式进行响应。 It seems to be a good idea to make sure all forms-based interactions start from a thread with that call. 确保所有基于表单的交互都从带有该调用的线程开始似乎是一个好主意。

The generic diagnostic is that there is something wrong with the message pump. 通用诊断是消息泵有问题。 You are not complaining that the controls do not paint themselves at all so it seems unlikely that this is completely broken. 您并不是在抱怨控件根本不会自己绘画,因此看起来完全不可能被打破。 If this is an occasional painting problem then the diagnostic is that you've got a threading problem. 如果这是偶发的绘画问题,则诊断为您遇到了穿线问题。 In other words, you are updating the control properties, or calling Invalidate/Update, from the wrong thread. 换句话说,您正在从错误的线程更新控件属性,或调用“无效/更新”。

Windows Forms has built-in diagnostics for this, active when a debugger is attached. Windows Forms具有内置的诊断功能,在连接调试器时处于活动状态。 Make sure you don't set the Control.CheckForIllegalCrossThreadCalls to false. 确保没有将Control.CheckForIllegalCrossThreadCalls设置为false。

Next place to look is the message pump itself. 下一个要看的地方是消息泵本身。 When you display the forms with their Show() method instead of ShowDialog() then your unmanaged message pump will be dispatching messages. 当您使用其Show()方法而不是ShowDialog()显示表单时,您的非托管消息泵将分派消息。 That has some undesirable side-effects by itself, keyboard accelerators won't work anymore, nor does tabbing. 它本身具有一些不良的副作用,键盘加速器将不再起作用,也无法进行制表。 Check if the problem disappears if you use ShowDialog(). 如果使用ShowDialog(),请检查问题是否消失。


Your comment provides another hint at what might the problem. 您的评论为问题可能提供了另一个提示。 If you get False from InvokeRequired when you know that you're calling from another thread and you don't see any visible sign of your update then you are using the wrong Form object reference. 如果您知道从另一个线程进行调用时从InvokeRequired收到False, 并且看不到任何可见的更新迹象,则您使用的是错误的Form对象引用。 Possibly one you created with the new operator. 可能是您使用new运算符创建的一个。 Make sure you use the existing one, Application.OpenForms[] can give you a reference if you have trouble getting one. 确保使用现有的,如果遇到困难,Application.OpenForms []可以为您提供参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM