1

I have a C++/WinRT/UWP project. I need the HWND and HINSTANCE to be able to correctly initialize Direct Input, otherwise DirectInput manage only to enumerate the keyboard and mouse but not the joysticks.. don't ask me why, I even tried to get the TopMostWindow from the HInstance got with GetModule, it just return NULL when running from my C++/WinRT/UWP app, but works when running from a console app.

documentation https://learn.microsoft.com/en-us/windows/win32/api/corewindow/nn-corewindow-icorewindowinterop I have no idea how to cast my CoreWindow to ICoreWindowInterop. CComPtr is not availble and not usable in C++/WinRT, conflicts with IUnkwnown.

In the method App::OnLaunched(LaunchActivatedEventArgs const& e) I get the current window like this

CoreWindow w = Window::Current().CoreWindow().GetForCurrentThread();

Then I don't know how to get the ICoreWindowInterop from it. CoreWindow is a ICoreWindow , but I don't see any explanation in the Microsoft documentation :/

I tried casting and reinterpret casting without success ( compilation error ). I'm no COM/Windows expert, so I'm quite lost now.

Thanks for the help Cheers, Seb

SebKun
  • 105
  • 1
  • 10
  • What is the call you are making to initialize? Did you look at [Windows.Gaming.Input](https://learn.microsoft.com/en-us/windows/uwp/gaming/input-for-games)? Even though you can get the HWND, there's often nothing you can do with it from UWP (most of User / GDI will ignore UWP handles). – Peter Torr - MSFT Dec 30 '19 at 20:48
  • Gaming.Input support only devices supported on XBOX, so I can't enumerate my PC FFB Steering wheel, or button boxes, or my Fanatec shifter for example. Only, but I think I realize, it has nothing to do with having the HWND or not, I think, Microsoft locked the WPF app to ignore non official XBOX devices, even when running on PC, Microsoft being microsoft ....... – SebKun Dec 31 '19 at 10:05
  • Even [the raw controller](https://learn.microsoft.com/en-us/windows/uwp/gaming/raw-game-controller)? – Peter Torr - MSFT Dec 31 '19 at 16:20
  • I confirmed that W.G.I supports all sorts of things, *including the Sony and Nintendo controllers*, so the assumption that it's "only devices supported on XBOX" is incorrect. Please post the actual code you're using. – Peter Torr - MSFT Jan 02 '20 at 23:13

2 Answers2

5

The ICoreWindowInterop is not immediately available from a CoreWindow. The interface is cloaked, and as such will not show up when using IInspectable's introspection. You'll have to drop down to raw COM and explicitly query for the interface.

Kenny Kerr has written an article years ago (Windows 8, where’d you put my HWND?!) that details the required steps. There's still a bit of work required to get this to compile in a C++/WinRT application.

First up, you'll have to declare the ICoreWindowInterop interface. The following will suffice:

struct
__declspec(uuid("45D64A29-A63E-4CB6-B498-5781D298CB4F"))
__declspec(novtable)
ICoreWindowInterop : public IUnknown
{
    virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND* hwnd) = 0;
    virtual HRESULT STDMETHODCALLTYPE put_MessageHandled(unsigned char value) = 0;
};

Next, we need an IUnknown interface pointer to the CoreWindow. There is pre-built functionality as the free function get_unknown. To get this to compile, you'll have to #include <Unknwn.h> before including any C++/WinRT headers.

Once all that is in place, you can easily get the HWND given a CoreWindow instance:

HWND from_core_window(CoreWindow const& window)
{
    winrt::com_ptr<ICoreWindowInterop> interop {};
    winrt::check_hresult(winrt::get_unknown(window)->QueryInterface(interop.put()));
    HWND hwnd {};
    winrt::check_hresult(interop->get_WindowHandle(&hwnd));
    return hwnd;
}

There seems to be evidence that reaching down to the HWND will fail Microsoft Store certification. If that is an issue, you'll have to find a different solution.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • Thanks. Sadly it didnt help, I already read this document from KK. I didnt manage to have something work in VS2019 Com. + Windows 10 SDK. Lot of conflicts. But anyway Like I commented, I think the enumeration failed not because of the HWND, but Microsoft ignore devices that are not supported on XBOX even running on PC... so I have to use something else for my app... I'm going C#/WPF for UI and C++/DLL for runtime code. thanks again for trying to help. – SebKun Dec 31 '19 at 10:08
  • The code in this answer compiles fine for me. I placed it into a wizard-generated C++/WinRT Core Application, and put the `#include ` at the top of my precompiled header (pch.h). What conflicts did you get? – IInspectable Dec 31 '19 at 16:31
1

From this document, it mentions how to get the HWND. First query for the ICoreWindowInterop interface by using CoreWindow and then call the get_WindowHandle virtual function to get your app’s HWND. I try to convert the code to c ++ / winrt, you can check it.

App.h

namespace XXXX
{
    MIDL_INTERFACE("45D64A29-A63E-4CB6-B498-5781D298CB4F")
        ICoreWindowInterop : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(
            __RPC__deref_out_opt HWND * hwnd) = 0;

        virtual HRESULT STDMETHODCALLTYPE put_MessageHandled(
            boolean value) = 0;

    };

    struct App : AppT<App>
    {
        App();

        ......
    };
}

App.cpp

CoreWindow w = CoreWindow::GetForCurrentThread();
winrt::com_ptr<ICoreWindowInterop> interop;
winrt::check_hresult(winrt::get_unknown(w)->QueryInterface(interop.put()));

HWND hwnd;
winrt::check_hresult(interop->get_WindowHandle(&hwnd));
Faywang - MSFT
  • 5,798
  • 1
  • 5
  • 8
  • I read this document, that's the 1st thing that pop up in google search, didnt manage to have this working in C++/WinRT in Visual Studio 2019 comunity + Windows 10 SDK, – SebKun Dec 31 '19 at 10:06