How to dispatch messages for multiple dialogs in an ATL exe - winapi

Microsoft had a knowledge base article describing how to modify the message loop in at ATL .exe so that modeless dialogs can receive appropriate messages.
I was wondering how to elegantly do this if you have potentially multiple modeless dialogs, and you don't know which dialogs might exist at any given time. Like perhaps the .exe hosts several different COM classes, each with different dialogs, and who knows which one might be instantiated.
Would you create a global set of hwnds, and have each dialog class place its hwnd in the set upon creation, and then have the message loop iterate through the set calling IsDialogMessage (and TranslateAccelerator)?

The message specifies its target (which might be a child of the actual dialog), I would handle this by having a set of dialog pointers and then simply iterate the set testing each with IsChild() and only when the right dialog HWND is found would I use IsDialogMessage.
The alternative is to walk up the ancestor tree from the HWND in the MSG translating HWNDs to objects somehow and when you get to a window that is a dialog use IsDialogMessage.

WTL's solution for this challenge is to have a specialized message loop class which registers itself in static container so that dialogs could discover message loops for the threads they belong to.
Dialogs can register themselves with these message loops via CMessageLoop::AddMessageFilter and have their callbacks invoked once it comes to translating the messages.
Example:
// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);

Related

How to not display a UI?

MSDN at this link states that there is a flag
CMIC_MASK_FLAG_NO_UI
The system is prevented from displaying user interface elements (for example, error messages) while carrying out a command.
However, it also indicates that the structure has
nShow
Type: int
A set of SW_ values to pass to the ShowWindow function if the command displays a window or starts an application.
which I think contradicts each other as there is no indication I can set the latter parameter to 0 and there is no SW_NOSHOW parameter in the ShowWindow documentation.
Is it even possible to suppress that window? If yes - how?
TIA!!
There is some ambiguity about which UI we are talking about here.
There are UI things related to invoking the command (asking for network share password, error message on failure etc.) and CMIC_MASK_FLAG_NO_UI certainly applies here. I don't know how relevant nShow is though. The caller does not know which UI might be displayed and it makes zero sense for the callee to allow its error MessageBox to be maximized etc. Respecting SW_HIDE might end up stuck waiting for the user to interact with a window they can't see.
The other UI is actually the thing that is executed. In the cases where a new process is started we are looking at a ShellExecuteEx call. CMIC_MASK_FLAG_NO_UI is passed on as SEE_MASK_FLAG_NO_UI (same integral value) and MSDN just says "Do not display an error message box if an error occurs" for this flag. Here however, nShow is relevant and can trickle all the way down to CreateProcess.
This is how I personally deal with this situation:
Set CMIC_MASK_FLAG_NO_UI if you are going to display your own error UI in case of failures or if you are running in a silent/automated mode of execution.
Only set nShow to something other than SW_SHOW when you control the action being executed. For example, you know cmd.exe is getting called and you need to hide the console window with SW_HIDE.
It is important to remember that CMINVOKECOMMANDINFO is parsed by the default IContextMenu shell32 implementations for various shell objects (files, control panel etc.) and by 3rd-party context menu handlers. You cannot assume that they are going to respect your wishes.

What's the preferred way for notifying a parent window from a customized control?

I have a custom Windows controls that superclass standard ones. I would like my custom controls to notify its parent window of certain events. What's the best practice for doing so?
Send the parent window a window message in the WM_USER or WM_APP range. This won't work since the values could collide if another child control tried the same thing.
Send the parent window WM_NOTIFY. This seems like the right thing to do, but since I'm extending a standard Windows control, how can I ensure that the notification code I use won't collide with one normally sent by the base class (now or in the future)?
Send the parent window a window message from RegisterWindowMessage. This should be sufficient to avoid unintentional collisions, but Microsoft recommends using it only for inter-process messages.
Have the control provide a mechanism for the application to specify what WM_APP message to use for notifications. This seems like the only robust approach, but it also feels a bit like overkill. (Or, instead of specifying a window message, I suppose that the application could pass down a function pointer.)
I've seen a similar question, but the sole answer there is tied to MFC and doesn't really address avoiding collisions.
What do other people usually do? Do they use one of the first three approaches and not worry about it? I'd like my controls to be suitable for broader consumption outside of my application, so I'd also prefer using standard Win32.
Edit: Tried to clarify what I'm looking for.
Since you are superclassing an existing window class and augmenting its behaviour, then you are correct to worry about collisions with existing messages. Because of that I feel that you have to use a message in the WM_APP range. You could equally well use RegisterWindowMessage but I agree that is overkill.
So I noticed that the notification code ranges defined in CommCtrl.h all look like:
#define NM_FIRST (0U- 0U) // generic to all controls
#define NM_LAST (0U- 99U)
...
#define TRBN_FIRST (0U-1501U) // trackbar
#define TRBN_LAST (0U-1519U)
So Microsoft's common controls at least have defined ranges (and are likely to always be large unsigned values). Therefore if I super- or subclass standard controls and use notification codes incrementing from 0, I think that I should be safe against current and future versions of Windows.
(If I were deriving from third-party controls, then those third-party controls would need to define their own reserved ranges. Otherwise all bets would be off.)

Good or evil - SetParent() win32 API between different processes

The SetParent function takes a child and new parent window handle.
This also seems to work when the child window is in a different Windows process.
I have seen a post that claims this is not officially supported, but the current docs don't mention this any more. Is this a flaw in the current docs, or did this behavior change?
HWND WINAPI SetParent(
__in HWND hWndChild,
__in_opt HWND hWndNewParent
);
You can have a parent-child relationship with the windows in different processes. It's tricky to get it to work right in all cases. You may have to debug various strange symptoms.
Normally, windows in separate processes would get their messages from separate input queues using separate message pumps. When you use SendMessage to a window in another process, it's actually posted to the other window's queue, processed there, and the return is effectively marshaled back to the original process. So if one of the processes stops handling messages, you can effectively lock up the other as well. (That's true even within a process when the windows are created on different threads and the thread queues haven't been attached.)
But when you set up the parent/child relationship among windows in different threads, Windows attaches those input queues together, forcing the message processing to be synchronous. You're no longer in the normal case, but you face the same kinds of problems: a hang in the processing for one window effectively hangs the other process.
Watch out for messages that pass pointers in the params. The pointers will not be valid in the receiving process. (There are a couple of exceptions, like WM_COPYDATA, which recreates the data in the receiving process for you. But even those have limitations.)
You have to be especially careful when the windows are being destroyed. If possible, disconnect the parent-child relationship before destroying either window. If it's not possible, then it's probably best to manually destroy the child window before the parent is destroyed. Normally, destroying a parent will cause the children to be destroyed automatically, but it's easy to get hangs when the child is in another process (or un-attached thread).
In newer versions of Windows (Vista+), you can also hit some security speedbumps if the processes run at different integrity levels.
Thanks to IInspectable who pointed out an error in my earlier answer.
Just remove WS_CHILDWINDOW from the child window. It avoid locks.
Sorry, that has not been helped

Ruby Win32Api get single character non-blocking

I'm trying to write a simple game working with two threads, one thread to get input from the user, and another thread to animate some scenes. I'm able to get characters without pressing ENTER just fine, but it blocks in the animating thread until the user presses a key. Does anyone know of a way to get a character from the keyboard non-blocking?
If you're looking to checkup on a handful of specific keys, GetAsyncKeyState() can be used to poll for state. Otherwise, you should implement a message loop and handle WM_CHAR messages in your application.
You can access raw win32 functions with a library similar to the following if your environment doesn't already support the win32 functions you need.
RAA - win32-api # raa.ruby-lang.org
Here are relevant links for GetAsyncKeyState().
GetAsyncKeyState() # MSDN
Virtual-Key Codes # MSDN (used as values for GetAsyncKeyState and other functions)
If you decide to go with a message loop, you'll need to implement it on the same thread that hosts the window for your application. A short explanation is available here:
Message Loop in Microsoft Windows # Wikipedia
As shown at that link, there isn't a whole lot to a message loop. Your framework may already have one running behind the scenes to host the window containing your graphics. If this is the case, you don't need a 2nd thread for input; but you will need to intercept and handle windows messages for that host window.
If you have to implement a message loop on your own, you can use the skeleton at the wikipedia link. The DispatchMessage call will direct a windows message to the appropriate window handler. You will need to look for a matching stub or handler for windows messages in your ruby framework, and handle WM_CHAR from there.
DispatchMessage # MSDN
WM_CHAR # MSDN
If you wish to know when keys are pressed/depressed, then you will want to handle WM_KEYUP and WM_KEYDOWN messages.
WM_KEYUP # MSDN
WM_KEYDOWN # MSDN
Also note, GetAsyncKeyState() can be called and returns key state even while another application is in the foreground. Handle WM_ACTIVATE and WM_SETFOCUS/WM_KILLFOCUS messages so that your application ignores or defers checks while a different window is active if you only care about key state while your window is the primary foreground window.
WM_ACTIVATE # MSDN
WM_SETFOCUS # MSDN
WM_KILLFOCUS # MSDN
I have used rubygame for this. It gives you the ability to attach functions to keyboard events with minimal code. RubySDL and GoSu will give you similar functionality.
If you don't want to go that route with game related gems take a look at this on how to check if data is available in IO object. This could be use to poll the keyboard.

How advisable is not having a message loop in WinMain?

This may be the simplest win32 program ever ..
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdLine, int show)
{
MessageBox(0, "Hello world..", "Salutations!", MB_OK);
return 0;
}
.. which makes no calls whatsoever to the usual GetMessage() call. My question is this: if my program doesn't process any window messages, can the OS cope with that? I.e., does it cause memory leaks? Or some other resource that wouldn't be apparent unless I ran it 16K times?
In a broader sense, exactly how 'dependent' is Win32 on applications taking care of their messages? I would hope that when the compiler links the executable as a windows program, that the run-time would be capable of cleaning up any kind of message queue, be it emptied or not.
Just a technicality, but you do have a window, and you do have a message loop, just not in your code.
The call to MessageBox() creates a window (of class #32770) and runs a local message loop, not returning to your code till the message loop drops out, presumably when WM_NCDESTROY is sent. I think it's the same message loop that runs in response to DialogBox().
But you could substitute your call to MessageBox() with anything else that really doesn't create a message loop, and you'll still be fine. Windows doesn't care if you have a message loop, although some functionality (primarily UI related) is difficult or impossible to use without it. In fact, you don't have to link to user32 at all, and some apps that have no user interface don't.
Now if you create a window and don't process messages for it in some way, Windows XP and up will replace your window with a "ghost" window that has a white client area and Task Manager will tell the user that the application is not responding.
Although it seems so at first, the message loop is not magic or a strictly required part of Windows boilerplate. It is highly ingrained as a standard in most Windows applications, though, because it's the best way to handle the dispatching of window messages. The "event-driven" nature of most Windows applications makes us forget sometimes that Windows applications were originally designed to be single-threaded, and in this model, it is code running within that single thread, not some unseen force within the operating system, that must make every function call within our code. The addition of multithreading changed that somewhat, but the basic model still remains the same.
EDIT
A note about message queues:
As is mentioned elsewhere, a message queue is only created (and on a per-thread basis) when a window is created by that thread. Your example program, upon creating a message box, does create a message queue. But this queue need not be empty when your application exits. This queue is just a memory structure. It's a block of memory that can hold a certain number of message objects (specifying destination hWnd, message id, wParam, lParam, system time when message was posted, mouse position when message was posted, and some data that allows the derivation of keyboard and mouse button state when the message was posted), along with pointers to the head and tail of the queue (I assume it's a circular queue). When the application exits, this memory, like all memory belonging to the process, is summarily freed.
There are, of course, other things that must be cleaned up outside your process. The OS must keep a table of all existing windows, for example, along with the thread and process that created them. Of course, these are all cleaned up automatically as well.
Since you don't have a window, you don't need a message loop. In Win32 the messages are sent to windows, not to applications.
You do have a message loop - MessageBox is a modal dialog and therefore contains a message loop within.
You don't have to create windows. But still, there are some kind of messages, like
WM_TIMER
WM_TIMECHANGE
WM_CLIPBOARDUPDATE
WM_COPYDATA
WM_POWER
that you may need. So, a ghost window hanging around wouldn't be bad.
If you don't have a window, then that is fine, but if you do then you need to make sure that you pump messages for it. Otherwise the system can hang on broadcast messages waiting for you to respond. This is important for things like COM which create hidden windows for message processing. If your main thread does not pump messages (e.g., by calling WaitForSingleObject) then calls to your COM objects will not be processed, and any programs which send broadcasts will appear to hang.
I have read somewhere (and can't find the reference) is that Windows will create a message queue on demand. If you never call a function that looks for a message queue, one will never be created. And this occurs on a per-thread basis.

Resources