I have a non-MFC, non-ATL C++ app that routinely creates notification balloons on a system tray icon. If, on pre-Vista boxes, the user locks the screen - these newly created "balloons are queued", which creates a mess when the user finally logs back in. There could be dozens or hundreds of balloons waiting. The timeout set for each balloon does not apply until the user logs back in!!
So to solve this, I need to know either:
Is there a way to cancel any outstanding balloon I made, when a new balloon arrives?
Should I instead check for a "session lock" / "screen lock" and stop creating balloons in the user's absence?
Regarding option #2, what message do I listen for in the windows loop to capture an account lock / session lock? I tried the event WM_ENDSESSION, but my app acted like it didn't see it. Is that the right event? Do I need to register for it?
Of course if there is a simpler way to solve this, I'd love to know. Certainly for Vista and later, the NIF_REALTIME uFlags option solves the problem handily.
p.s. I'm appalled that I can't find a list of windows messages online with descriptions. All I found was a list without descriptions, and it isn't even hosted by Microsoft!!!
Regarding option (2) you need to register interest in 'SessionNotifications', using the function WTSRegisterSessionNotification:
WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags);
You pass in the handle to the window to receive the message WM_WTSSESSION_CHANGE, and use the flag NOTIFY_FOR_THIS_SESSION, which indicates you want to get messages when session events occur.
Session events you would be interested in are WTS_SESSION_LOCK and WTS_SESSION_UNLOCK. Please bear in mind that you must use the corresponding deregister function WTSUnRegisterSessionNotification:
WTSUnRegisterSessionNotification(HWND hWnd);
You need to keep track of the locked/unlocked/connected/disconnected state of the session, which allows you to decide when to schedule balloon messages.
Related
I need to pump COM messages while waiting for an event to fix a deadlock. It's better to pump as few messages as possible just to process that COM call. The best candidate for this role is CoWaitForMultipleHandles but starting from Vista it pumps WM_PAINT in addition to COM messages. Pumping WM_PAINT is too dangerous for me from re-entrance perspective and I don't want to install a custom shim database as a solution for this problem.
I'm trying to pump COM messages sent to the hidden message-only window manually.
I have found two ways to get HWND of the hidden window:
((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA using ntinfo.h from .NET Core. This seems to be undocumented and not reliable solution in terms of future changes.
Find window of OleMainThreadWndClass as suggested in this question. The problem is that CoInitialize does not create the window. It is created later on first cross-apartment call which may or may not happen in my application. Running the search loop every time I need HWND is bad from performance perspective but caching HWND seems impossible because I don't know when it's created.
Is there a way to determine if the hidden window is created for the current apartment? I suppose it will be cheaper than the loop and then I could find and cache HWND.
Is there a better way to pump COM messages without pumping WM_PAINT?
Update: you can force the window creation by calling CoMarshalInterThreadInterfaceInStream for any interface. Then call CoReleaseMarshalData to release the stream pointer. This is what I end up doing along with the search for OleMainThreadWndClass.
WM_PAINT is generated when there is no other message in the message queue and you execute GetMessage or use PeekMessage.
But WM_PAINT is only sent if you Dispatch it. Also there is no new WM_PAINT message until a window is invalidated again.
So it depends on you if you dispatch a WM_PAINT message or not. But be aware, there are other chances of reentrances like a WM_TIMER message.
The details about this are in the docs for WM_PAINT.
From my point of view the best solution would be to set you application in a "wait" mode, that even can handle WM_PAINT in this undefined waiting state. You know when you are reentered. It is always after a WM_PAINT... or similar messages that arrive like other input messages. So I don't see any problems here. An STA has one thread and you always process messages to an end, until you execute GetMessage, launch a modal dialog or show a MessageBox. When you are inside some message handling, nothing will disturb you.
Maybe an other solution would be to wait inside a second thread for this event. This thread may not have any windows and you can translate the event to anything you need in your application.
So you question may not have enough information how this deadlock really appears. So this answer may not be sufficient.
After writing als this I tend to the opinion that this is an XY problem.
I have a thread that send update messages to a window, I use ::SendMessage() and ::PostMessage() APIs.
I go in and out of multiple dialogs and register the dialog that I am currently in with the thread via the window handle (m_hWnd). If I exit all the way out, the main application window doesn't handle these messages. For that reason I don't register that window. At this point the thread will have the handle of an older window which now doesn't exist.
Is it okay if it sends messages to that non-existent window? I am assuming it should not do any harm but wanted to double check.
No, it is not ok to post a message to a deleted window.
There is no guarantee noone will set up shop at that address just after the previous tennant is gone.
If you use a NULL window handle, you'll post a thread message to the current threads message queue. SendMessage as far as I could google shoul be a no-op.
Might be harmless enough.
Now, we get tricky:
Under specific cicumstances it does not matter, pre-supposing well-behaved applications.
A message like WM_NULL should not make anything happen.
A window-message you globally registered in your application using RegisterWindowMessage, if you can guarantee none of your applications windows created in the meantime will choke on it.
I have a multiple dialog MFC client app that i am working on. This client can receive a lot of messaging (>10Hz) to the main dialog, which often performs some small function, then forwards that message onto the another dialog for processing.
In my specific case, the main dialog receives messages relating to a vehicle location, updates a couple fields on that GUI, then passes it on vi a PostMessage to a window that displays all the vehicle information.
So basically, my question is this: what is the difference b/w posting the message, or just calling the dialog.update (which is a function i created)?
Well, since we don't know what your dialog.update() does, how are we to know what the difference is?
If you are doing another PostMessage, I'm not sure what the point of that is. Your program has to wait for another iteration of the message loop to retrieve your newly posted message and possibly another message could be received before that one is posted. Instead of PostMessage, you could use SendMessage which will send the message straight to the WndProc without having to iterate the message loop for another message.
I am thinking that if you are multi-threaded, then sending or posting messages will be a little more thread safe since Windows should switch contexts automatically. If you are single threaded, then it probably shouldn't matter.
I believe your application is multithreaded, and one of the thread is receivng the data, and is different than GUI thread. You should use PostMessage only from other thread to this dialog, and not SendMessage or direct call.
If you are receiving too many messages, you should buffer them - either by count (say 5000), or by some timeout. You may keep the messages into vector, list or any other collection you like. Later, when sending, post the address of this collection as WPARAM (or LPARAM) to the dialog. Dialog will get it, in a single bunch and would process it. This approach may not be correct as I am not aware about other design perspetives of your application.
You would need to trial-and-error approach, see where you get the actual performance and stability benefits.
Is there a way to notice the release of a hot-key button registered with RegisterHotKey?
I get a WM_HOTKEY message every time I press the hot-key but I need to know when the key was released
There is no specific notification for that specific action. You will have to write a DLL that implements a global keyboard hook via SetWindowsHookEx(), then you will receive individual keypress up/down notifications and can match them up to your WM_HOTKEY notifications as needed.
Use RegisterHotkey to detect the key going down, then use polling with GetAsyncKeyState until the key is no longer down. This avoids the complexity of SetWindowsHookEx and the polling is generally acceptable since it is only done while the hotkey is being held down.
I try to send a mouse click event to a game application. First, i use Spy++ to find what message the application receive. I see something like : WM_MOUSEACTIVATE, WM_WINDOWPOSCHANGING, WM_ACTIVATEAPP, WM_ACTIVATE, WM_SETFOCUS, ...
i try to send the same as i see on Spy++ but it doesn't work. How to send mouse click to a game application without give it focus? . it's run in window mode. Thanks in advance.
You want WM_LMOUSEDOWN. You can always check MSDN for the documentation on which messages mean what.
The best way to automate applications and games is via SendInput. While in theory it should be possible to drive an application via WM_LUBTTONDOWN etc, many applications read the key state directly via lower level APIs (such as GetAsyncKeyState) which don't change their state to reflect the messages processed from the message queue.
Using SendInput requires actually setting the game to the foreground as the input events are synthesized at a low level and are thus delivered to the active/focused window.