views:

2984

answers:

5

Hey all. I'm trying to see about handling events in a console application. I would prefer to not use silent WinForms (though I understand that that's one way) to do it. I've read over a similar question and its response. See response text below (link):

The basic requirement of an STA thread is that it needs to run a message pump. In Windows Forms, you can use Application.Run. Or you could write the message pump by hand, using user32!GetMessage & DispatchMessage. But it's probably easier to use the one in WinForms or WPF.

What the basic structure of a program that uses "user32 -> GetMessage" & "user32 -> DispatchMessage"?

+1  A: 

Pretty good tutorial. Here is p/invoke stuff for GetMessage and DispatchMessage. It's all down hill from here. :)

JP Alioto
+2  A: 

See the topic "Using Messages and Message Queues" in MSDN (under Win32 and COM Development > User Interface > Windows User Experience > Windows Management > Windows User Interface > Windowing > Messages and Message Queues; you'll probably need to take a look at the other articles and samples in the same section). Quick summary, omitting error handling and using C syntax rather than C# for reasons discussed below:

RegisterClass(...);
CreateWindow(...);
ShowWindow(...);  // probably not in your case
while (GetMessage(&msg, NULL, 0, 0)) {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

As you can see from the window setup boilerplate, this still relies on "silent windows," albeit created and message-pumped via the Win32 API rather than through WinForms. So you're not really gaining anything by doing this way. Hence my feeling there's not much point translating this stuff into C# -- if the only solution to your problem is an invisible window, you may as well use an invisible Windows Form and all the friendly wrappers that come with that platform.

However, if you're not actually using a Windows Forms control like the poster of the linked question, then you can quite happily use .NET events in a console application. The restriction to STA and the need for a message pump is specific to receiving events from WinForms and ActiveX controls like the WebBrowser (or messages from Win32 HWNDs, though that doesn't necessarily require STA).

itowlson
A: 

What kind events do you want to handle? Setting up a message pump will allow you to process Windows API messages. But since this is a console app, I can't think of any Windows API messages that would be of interest.

We tend to think of "Events" as being associated with Windows messages because controls in Windows Forms application respond to user input using EventHandler delegates, which are called in response to Windows API messages. However, there's no reason you can't use delegates in a console app; and you don't need a message pump. You can even use the EventHandler delegate, altough it will seem out of place because it won't be resonding to Windows API messages.

Of course there are other kinds of "events" that you might be interested in. The most common kind of event scenario involving a console app is to wait for input from the console (stdin). It's also common to block on a WaitHandle or other synchronization object if there are multiple threads in use. Both of these cases could be considered a type of event handling.

If you create a hidden window (a time honored practice), you'll still need a Windows message to respond to. So the question is: to what, or to whom, are you trying to respond?

Paul Keister
A: 

I would use the Application.Run method. I don't think it creates a hidden window automatically, it just pumps the messages, which is what you need to satisfy the STA requirement.

Writing your own message pump using PInvoke doesn't offer any advantage and referencing System.Windows.Forms isn't much of a burden because it's already on every machine you may encounter.

jachymko
A: 

I've got a console app that needs to intercept keystrokes system wide. I have a USB device that sends out F17-F22 as keystrokes when any of the buttons on it are pressed.

I want to intercept the keystroke, react appropriately and then swallow the keypress event so no app actually gets the keystroke.

I have a hook set up: hhook = SetWindowsHookEx(WH_KEYBOARD_LL, khpDelegate, Marshal.GetHINSTANCE(this.GetType().Module), 0);

But from what I see, the delegate is only called when the application goes through the message pump, which, as a console app, I don't do.

Jabmist