Application hangs when hosting managed control as CWnd

144 views Asked by At

My application has ATL-based GUI (CWnd, CDialog,...) and it consists of multiple pages (CDialog). One of these pages is otherwise empty but it has a placeholder frame (CWnd) that resizes with the dialog. Everything is built as x64.

When the page loads, it asks for a control handle from managed (C#) side of the application using COM-interop, and adds the control to the dialog as CWnd that is created from that handle:

Managed implementation simplified:

// Class "ManagedControlProvider"
private Control myUserControl;
public long CreateControl()
{
  myUserControl = /*Create some new inheritant of UserControl */
  myUserControl.Dock = DockStyle.Fill;
  return myUserControl.Handle.ToInt64();
}

Native side simplified:

// 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);

I have done this multiple times and it usually works exactly as is should. But sometimes, like now, I'm experiencing application hangs without any clear reason. With my current control this seems to happen roughly 5s after the focus is set to some other desktop application.

I have verified that the issue is not in the managed control's lifetime or GC. Also it's reproducible in debug build so optimizations are not to blame. When the hang occurs, I can attach debugger and see that some ATL loop keeps on going but that's the only piece of code I'm able to see in stack (imo this indicates that the message loop is somehow caught in infinite loop without interacting with my code).

Now for the dirties fix ever: I added a separate thread to my managed control that invokes this.Focus() every second on the UI thread. Obviously this is a ridiculous hack but it works as long as I pause the focusing everytime user opens combos etc (otherwise they get closed every second).

What am I doing wrong or what could cause this somewhat unpredictable behavior?

1

There are 1 answers

0
Simo Erkinheimo On

I don't know why or what it has to do with anything, but the application hang somehow originated from WM_ACTIVATE. So the solution was to override WINPROC at the main CDialog and block forwarding of that message. Everything has been working without any issues since then.

I'll not mark this as answer because I don't know why this solution works.