I have to write an C# API for registering global hotkeys. To receive the WM_HOTKEY message, I use a System.Windows.Forms.NativeWindow
and run an own message loop with System.Windows.Forms.Application.Run(ApplicationContext)
. When the user wants to register a hotkey, he has to run a method called RegisterHotkey()
which stops the message loop with System.Windows.Forms.ApplicationContext.ExitThread()
, registers the hotkey with the RegisterHotKey()
(P/Invoke) function and starts the message loop again. This is required, because RegisterHotKey()
must be called within the same thread that created the window, which again must be instantiated within the same thread that runs the message loop.
The problem is, that if the user calls the RegisterHotkey()
method shortly after starting the thread which is running the message loop, ApplicationContext.ExitThread()
gets called before Application.Run(ApplicationContext)
and therefore the application blocks indefinitely. Does anybody know an approach for waiting for a message loop to be started?
Thanks in advance!
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".
So RegisterHotKey
needs to be called from the same thread that created the window and started the message loop. Why not inject the execution of RegisterHotKey
into your custom message loop thread? That way you do not need to stop and restart the message loop. You can just reuse the first one you started and avoid the strange race conditions at the same time.
You can inject a delegate onto another thread using ISynchronizeInvoke.Invoke
which will marshal that delegate onto the thread hosting the ISynchronizeInvoke
instance. Here is how it might be done.
void Main()
{
var f = new Form();
// Start your custom message loop here.
new Thread(
() =>
{
var nw = NativeWindow.FromHandle(f.Handle);
Application.Run(new ApplicationContext(f));
}
// This can be called from any thread.
f.Invoke(
(Action)(() =>
{
RegisterHotKey(/*...*/);
}), null);
}
I do not know...maybe you will want to call UnregisterHotKey
as well depending on the behavior you are after. I am not that familiar with these APIs so I cannot comment on how they might be used.
If you do not want that arbitrary Form
instance created then you could probably get away with submitting a custom message to the thread via SendMessage
and the like and processing it in NativeWindow.WndProc
to get the same effect that the ISynchronizeInvoke
methods provide automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With