microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.27k stars 674 forks source link

How to launch a Window from the Application class in WinUI? #6725

Open akash07k opened 2 years ago

akash07k commented 2 years ago

I'm creating a WinUI application which will run in background initially without launching a window. Means I've removed the below lines from the OnLaunched method: m_window = new MainWindow(); m_window.Activate(); Now the thing is that I've implemented a keyboard hook by which I want to give a shortcut key to the user to launch the window. As soon as user is pressing the shortcut key, we are getting the exception such as:

An exception of type 'System.Runtime.InteropServices.COMException' occurred in WinRT.Runtime.dll but was not handled in user code
The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))

I'm trying to launch the window by using DispatcherQueue.TryEnqueue method but that method is not showing in intellisense. Please guide me that how should I launch the window? What should I do?

akash07k commented 2 years ago

Anyone please? This is quite urgent for me

castorix commented 2 years ago

You can just comment _mwindow.Activate(); Then when I use a Hotkey (with RegisterHotKey ) I can show and activate the window in WM_HOTKEY with this.Activate();

akash07k commented 2 years ago

@castorix Yes, I too have removed the said line from my Application class's OnLaunched method. Now I'm unable to do m_window.activate when we press the shortcut key. I'm using H.Hooks lib for keyboard hook. Can it due to different thread? Is it possible that keyboard hook is running on different thread?

castorix commented 2 years ago

I don't use any external library I also tested with a Hook (SetWindowsHookEx) and it works fine (WH_KEYBOARD_LL and 0 for dwThreadId)

akash07k commented 2 years ago

So are you able to launch the MainWindow from the raised event by the hook? @castorix

castorix commented 2 years ago

So are you able to launch the MainWindow from the raised event by the hook?

Yes, this.Activate(); shows the window and sets it to foreground when the key is pressed from the hook procedure

akash07k commented 2 years ago

Seems that you are doing it (this.Activate() from the MainWindow class. And I'm trying it from the App class. This.activate will only be available in MainWindow class not in Application class. And the thing is that upon my app launches, I don't want to show/launch any window at all. That's why I'm hooking the keyboard from the application class. So the thing is that,if I'm doing MainWindow window = MainWindow(); window.Activate(); from the OnLaunched method or constructor then it's getting launched. However if I'm trying the same from the Hook event then it's raising the error. It seems it is happening because Keyboard Hook is on another thread. I think I'm clear now. If no, then I'll share my exact code for your reference then. @castorix

castorix commented 2 years ago

Without window.Activate(); the window is just hidden and shown in the shortcut (otherwise, it should be created when the key is pressed)

akash07k commented 2 years ago

Exactly, but if I'm creating the window in key event then it is giving me the error: The application called an interface that was marshalled for a different thread. (0x8001010E

castorix commented 2 years ago

I just tested by creating everything in App.xaml.cs and it still works (but not a good method I think to create a window in a shortcut...)

StephenLPeters commented 2 years ago

@marb2000 @bpulliam FYI

akash07k commented 2 years ago

@castorix I don't know if it is a wrong way. if it is a wrong way then I'd love if someone from MSFT please guides me on this

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 5 days.

akash07k commented 1 year ago

Not stale

xiaopoyang-msft commented 10 months ago

@akash07k Obviously your Keyboard Hook is on another thread, which is indicated by the encountered runtime exception and verified by H.Hooks lib.

Optimized, runs hooks in a separate thread. ...

Just use SetWindowsHookEx as @castorix does. In consideration of your way, you need to maintain the lifetime of the created window(s) through keystrokes of the hot key.

akash07k commented 10 months ago

I actually don't want to use SetWindowsHook because it requires more boilerplate for my usecase. I want to use H.Hooks lib instead. any guidance on that please? Also, I'm not clear with:

In consideration of your way, you need to maintain the lifetime of the created window(s) through keystrokes of the hot key.

@akash07k Obviously your Keyboard Hook is on another thread, which is indicated by the encountered runtime exception and verified by H.Hooks lib.

Optimized, runs hooks in a separate thread. ...

Just use SetWindowsHookEx as @castorix does. In consideration of your way, you need to maintain the lifetime of the created window(s) through keystrokes of the hot key.

xiaopoyang-msft commented 10 months ago

Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); You may refer to the DispatcherQueue of the UI thread in the H.Hooks lib thread. See Change CoreDispatcher.RunAsync to DispatcherQueue.TryEnqueue and the WinUI-Gallery sample for more information.

In consideration of your way, you need to maintain the lifetime of the created window(s) through keystrokes of the hot key.

How about a user raising a succession of keystrokes of the hot key? You should avoid creating windows per keystroke.