question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Native QWidget in HwndHost works, but no override methods are called except BuildWindowCore, why?

See original GitHub issue
  • .NET Core Version: 6.0.402
  • Windows version: 21H2
  • Does the bug reproduce also in WPF for .NET Framework 4.8? I don’t know
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc…)? I don’t know

Problem description:

I have a native window created in Qt with Qt Widgets. I embed the window in WPF with the help of a class derived from HwndHost. The embedding works and I can see the widget, and basic mouse interaction also works. However I would want to receive further events, for example keyboard events. Also I would like the DestroyWindowCore method to be called. But I can get neither of this to work. In my understanding, a good start for keyboard support would be to get WndProc or OnGotKeyboardFocus working, but I fail to see how to proceed…

Any help would be greatly appreciated!

I have the following override method that works:

        protected override HandleRef BuildWindowCore(HandleRef aHWNDParent)

And I have the following overrides that never get called, not on key presses, not on mouse interaction, not on closing the application, never (checked with logging, and with the coreclr debugger):

        protected override void DestroyWindowCore(HandleRef aHWND)
        protected override IntPtr WndProc(IntPtr aHWND, int aMessage, IntPtr aWParam, IntPtr aLParam, ref bool aHandled)
        protected override bool TabIntoCore(TraversalRequest request)
        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
        protected override bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers)

Actual behavior:

The override methods are not called.

Expected behavior:

The override methods are called.

Minimal repro:

This is my WPF HwndHost container window. In this I place a QWidget that is rendered from a separate thread, the Qt UI thread. The widget works and behaves correctly but never gets keyboard focus, and none of my override methods are called.

using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;
using System.Windows.Input;

namespace Managed.WPF
{
    public class TestNativeWidget : HwndHost
    {
        private static Serilog.ILogger mLogger => Serilog.Log.ForContext<TestNativeWidget>();

        protected IntPtr mTestNativeWidgetHandle = IntPtr.Zero;

        public TestNativeWidget()
        {
        }

        protected override HandleRef BuildWindowCore(HandleRef aHWNDParent)
        {
            var reParentTask = Task.Run(() =>
            {
                NativeBindingHolder.Get().reParentWidgetSlot(NativeWindowType.TestNativeWidget, aHWNDParent.Handle);
                mTestNativeWidgetHandle = NativeBindingHolder.Get().getWidgetHandleSlot(NativeWindowType.TestNativeWidget);
            });

            while (!reParentTask.IsCompleted && !reParentTask.IsFaulted)
            {
                Dispatcher.CurrentDispatcher.Invoke(new Action(delegate { }), DispatcherPriority.Background);
            }

            if (reParentTask.IsFaulted) throw reParentTask.Exception;

            return new HandleRef(this, mTestNativeWidgetHandle);
        }

        protected override void DestroyWindowCore(HandleRef aHWND)
        {
            NativeBindingHolder.Get().destroyNativeEmbeddedWidgetSlot(NativeWindowType.TestNativeWidget);
        }

        protected override IntPtr WndProc(IntPtr aHWND, int aMessage, IntPtr aWParam, IntPtr aLParam, ref bool aHandled)
        {
            return base.WndProc(aHWND, aMessage, aWParam, aLParam, ref aHandled);
        }

        protected override bool TabIntoCore(TraversalRequest request)
        {
            OperatingSystemMethodsBindings.SetFocus(mTestNativeWidgetHandle);
            return true;
        }

        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            if (!e.Handled)
            {
                OperatingSystemMethodsBindings.SetFocus(mTestNativeWidgetHandle);
            }

            base.OnGotKeyboardFocus(e);
        }

        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            base.OnLostKeyboardFocus(e);
        }
    }
}

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
miloushcommented, Jan 11, 2023

@emmenlau including a project people can run and reproduce the issue with might help

0reactions
emmenlaucommented, Jan 20, 2023

Ok I’ll try to make a public repo with a repro. Can you install Qt yourself somehow, for example through the OS, or vcpkg or as a download from the Qt website?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Force BuildWindowCore member of a HwndHost derived ...
I use a class derived from HwndHost to host a Win32 window. It is in turn used within a user control. That user...
Read more >
Walkthrough: Hosting a Win32 Control in WPF
Override the DestroyWindowCore and WndProc methods of HwndHost. You must override these methods to satisfy the HwndHost contract, but you ...
Read more >
Why "override" ? (Repost)
First it improves readability - reading someone else's code you know at a glance that this is an overridden virtual method. It's also...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found