我的应用程序具有基于ATL的GUI(CWnd,CDialog等),它包含多个页面(CDialog)。这些页面之一否则为空,但具有占位符框架(CWnd),该占位符框架随对话框调整大小。一切都以x64构建。
页面加载时,它将使用COM-interop从应用程序的托管(C#)端请求控件句柄,并将控件作为从该句柄创建的CWnd添加到对话框:
简化了托管实施:
// Class "ManagedControlProvider"
private Control myUserControl;
public long CreateControl()
{
myUserControl = /*Create some new inheritant of UserControl */
myUserControl.Dock = DockStyle.Fill;
return myUserControl.Handle.ToInt64();
}
本国语言简化:
// Call the managed class. Lifetime of m_pManagedControlProvider
// is ensured elsewhere.
LONGLONG lHandle = m_pManagedControlProvider->CreateControl();
// m_pUserCtrlAsCWnd is CWnd*
m_pUserCtrlAsCWnd = CWnd::FromHandle((HWND)lHandle);
m_pUserCtrlAsCWnd->SetParent(this);
// m_ControlFrame is just a native helper-CWnd the dialog that
// resizes with it a so gives us the size we want to set for the
// managed control. This code is also call in every resize -event.
RECT winRect;
m_ControlFrame.GetWindowRect(&winRect);
ScreenToClient(&winRect);
m_pUserCtrlAsCWnd->SetWindowPos(NULL,
winRect.left, winRect.top, winRect.right - winRect.left,
winRect.bottom - winRect.top, 0);
我已经做了多次,并且通常完全可以正常工作。但是有时候,像现在一样,我正在经历应用程序挂起而没有任何明确的原因。在我目前的控制下,这似乎发生在将焦点设置到其他桌面应用程序后大约5秒钟。
我已验证问题不在托管控件的生命周期或GC中。而且,它在调试版本中是可复制的,因此不要责怪优化。挂起时,我可以附加调试器,并看到一些ATL循环继续进行,但这是我在堆栈中可以看到的唯一代码(imo这表明消息循环以某种方式陷入了无限循环中,而没有与之交互)我的代码)。
现在已经解决了肮脏的问题:我向托管控件中添加了一个单独的线程,该线程在UI线程上每秒调用一次this.Focus()。显然,这是一个荒谬的技巧,但是只要我每次用户打开连击等等(否则他们每秒都关闭)时我就停止聚焦,它就可以工作。
我在做错什么,或者可能导致这种无法预测的行为?
答案 0 :(得分:0)
我不知道为什么或与它有什么关系,但是该应用程序以某种方式挂起源自WM_ACTIVATE。因此,解决方案是在主CDialog上重写WINPROC并阻止该消息的转发。从那时起,一切一直没有任何问题。
我不会将此答案标记为答案,因为我不知道为什么该解决方案有效。