I'm trying to create a Window by creating HwndSource directly. At the moment I have an alternative solution - inheriting from Window class, but I'm just curious what's wrong with my HwndSource implementation. Since Window uses HwndSource in its core, I feel like there should be a way.
Here is the simplified version of my code:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
HwndSource wndPopup = new HwndSource(0, 0x12cf0000/*WS_VISIBLE|WS_OVERLAPPEDWINDOW*/, 0, 10, 10, 500, 500, "Test", IntPtr.Zero);
wndPopup.RootVisual = new Rectangle() { Fill = Brushes.Red, Width = 100, Height = 100 };
}
Window is created as expected, but after I close it (Alt+F4 or Close icon) and hover mouse over my main window, lots of messages are spitted into debugger:
Exception thrown: 'System.ComponentModel.Win32Exception' in WindowsBase.dll
Exception details are:
Exception thrown: 'System.ComponentModel.Win32Exception' in WindowsBase.dll
Additional information: Invalid window handle
Stack trace:
WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetWindowText(System.Runtime.InteropServices.HandleRef, System.Text.StringBuilder, int)
PresentationCore.dll!System.Windows.Automation.Peers.GenericRootAutomationPeer.GetNameCore()
PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
PresentationCore.dll!System.Windows.ContextLayoutManager.fireAutomationEvents()
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout()
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayoutCallback(object)
PresentationCore.dll!System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
PresentationCore.dll!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object)
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandler(object)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, object, int)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object, System.Delegate, object, int, System.Delegate)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl()
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, object, bool)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, object, bool)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, object)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke()
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue()
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr, int, System.IntPtr, System.IntPtr, ref bool)
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr, int, System.IntPtr, System.IntPtr, ref bool)
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, object, int)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object, System.Delegate, object, int, System.Delegate)
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, object, int)
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr, int, System.IntPtr, System.IntPtr)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object)
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window)
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window)
PresentationFramework.dll!System.Windows.Application.Run()
WpfCombox.exe!WpfCombox.App.Main()
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string, System.Security.Policy.Evidence, string[])
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, object, bool)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, object, bool)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, object)
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()
So, errors happens somewhere deep in framework code.
I tried filling other properties or adding cleanup to the Disposed handler, but that has no effect on the outcome. If I don't set RootVisual, there are no errors (but, of course, that's not an option).
Any ideas what I'm missing?
One solution I've found is to create an automation peer for the root visual. Otherwise,
GenericRootAutomationPeerwill be created by framework, which callsGetWindowTextWindows API.Probably there is a way to deinitialize the
HwndSourcewhen it closes, so that the Automation is not called on non-existing window, but I haven't found it yet.