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,
GenericRootAutomationPeer
will be created by framework, which callsGetWindowText
Windows API.Probably there is a way to deinitialize the
HwndSource
when it closes, so that the Automation is not called on non-existing window, but I haven't found it yet.