WM_SETFOCUS message and NULL wParam - c++

I've a simple Win32 Windows app with a single, main window. Inside the window procedure I'd like to investigate a WM_SETFOCUS message. The doc says:
A handle to the window that has lost the keyboard focus. This
parameter can be NULL.
This is my case - I'm getting just NULL. What does it mean and why dont I get a handle to for e.g the desktop when the desktop was a previos top, active window?

32-bit Windows introduced an asynchronous input model. One consequence of this change is that the focus window is now recorded per thread (or input-attached group of threads).
Initially, a thread attached to an input queue doesn't have a focus window, so the first time a program sees a WM_SETFOCUS message, its wParam is NULL. There are other reasons why WM_SETFOCUS can have NULL as its parameter, but those aren't interesting here.
Bonus reading:
Eventually, nothing is special any more

Related

Purpose of WM_CREATE message?

What's the point of having the WM_CREATE message when you can create windows without it.
Calling void CreateWindowA outside of WM_CREATE works so what's the deal?
WM_CREATE message is received by window procedure when window is created and not shown yet. You can prepare initial state. For example, you can create controls (child windows), set default values for controls, etc. If something is wrong, you can cancel creation of window and it will not be shown. In other words, in WM_CREATE you can add custom extension to CreateWindow API.
There are many reasons why an application could want/need to intercept the WM_CREATE message. For example, you may want to check a for a particular condition, and prevent the actual creation if that condition is wrong: you can do this by returning -1 from the WndProc that handles the message (see the documentation):
If an application processes this message, it should return zero to
continue creation of the window. If the application returns –1, the
window is destroyed and the CreateWindowEx or CreateWindow function
returns a NULL handle.
What's the point of having the WM_CREATE message when you can create
windows without it.
If you don't handle WM_CREATE message explicitly, it is actually handled by system via DefWindowProc(hwnd, uMsg, wParam, lParam); implicitly. So you see the window visible.
WM_CREATE message is sent before the CreateWindowEx or CreateWindow function returns, that give you an opportunity to intervene the result of mentioned function. You can allow (return zero to continue creation of the window) or prevent (returns –1, the window is destroyed) the window to be visible, and how it will looks like.
The WM_NCCREATE and WM_CREATE message are sent before the window
becomes visible. That makes them a good place to initialize your
UI—for example, to determine the initial layout of the window.
Refer to "Managing Application State", "WM_CREATE message".

Blocking Keyboard Play/Pause Button in Win 8

I am writing an application that needs to temporarily disable the Play/Pause button that appears on multimedia keyboards.
Normally, a key can be blocked quite easily by installing a low level keyboard hook (WH_KEYBOARD_LL) where the KeyboardProc intercepts the key (in this case VK_MEDIA_PLAY_PAUSE) and returns 1 instead of calling CallNextHookEx. I have tried this with other keys (including the Windows key VK_LWIN) and this works perfectly. I also have no problems with this method under Windows 7 where all keys, including VK_MEDIA_PLAY_PAUSE get blocked.
Windows 8 is a different story. When my application has input focus, everything works as expected, meaning the VK_MEDIA_PLAY_PAUSE key gets blocked and no other application responds to it. However, when my application loses focus, my hook procedure gets called (this was verified by sending out a OutputDebugString) but other applications respond to key even though I return 1. As soon as my app gets focus again, everything is block as it should.
After some investigation, I found that the multimedia keys not only generate keystrokes but also generate WM_APPCOMMAND messages so I added ShellProc (WH_SHELL) hook with the following hook procedure:
LRESULT __declspec(dllexport)__stdcall CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam)
{
// Do we have to handle this message?
if (nCode == HSHELL_APPCOMMAND)
{
OutputDebugStringX(">>>>> HSHELL_APPCOMMAND");
// Process the hook if the hNotifyWnd window handle is valid
short AppCommand = GET_APPCOMMAND_LPARAM(lParam);
switch (AppCommand)
{
case APPCOMMAND_MEDIA_NEXTTRACK:
case APPCOMMAND_MEDIA_PLAY_PAUSE:
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
case APPCOMMAND_MEDIA_STOP:
OutputDebugString(">>>>>ShellProc got a media command");
return 1;
}
}
// Call the next handler in the chain
return CallNextHookEx (hsh, nCode, wParam, lParam);
}
This procedure is only getting called when my app has input focus. Whenever I have input focus and return 1 the Play/Pause command gets blocked. As soon as I lose focus the procedure does not get called/hooked.
Anyone have any idea as to what is going on? As I have mentioned, the code works for other keys, just not the multimedia keys. Everything works fine in Windows 7.
Alternatively, can anyone suggest another way of blocking the multimedia keyboards Play/Pause button?
From the MSDN documentation for ShellProc:
HSHELL_APPCOMMAND: The user completed an input event (for example, pressed an application command button on the mouse or an application command key on the keyboard), and the application did not handle the WM_APPCOMMAND message generated by that input. [Emphasis added.]
The emphasized portion suggests that your hook callback only gets called after an application ignores the WM_APPCOMMAND. In other words, you're too late.
To catch the message in flight, I think you need a different type of hook. Perhaps WH_GETMESSAGE or WH_CALLWNDPROC.
But why are you trying to prevent the users from interacting with their applications as they choose?

How do I stop Windows from blocking the program during a window drag or menu button being held down?

I am novice with Win32, and I have been pursuing a problem (if it can be called a problem at all) with Windows blocking your program's flow during the event when a user grabs the window title bar and moves it around the screen.
I have no legitimate reason to solve this problem, except that it bothers me. A few possibilities include removing the frame altogether, but it seems an inconvenient hack. Some games (single player) do not find this a problem at all. I have read however, that multiplayer games might experience problems when the program freezes as it expects continuous flow of information and can be overwhelmed after such a delay.
I have tried adding this to my WindowProc
switch (uMsg)
{
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
PostQuitMessage(0);
return 0;
...
...
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
And this seems a quick hack, except that when I mousedown over the close icon I can pull the mouse away and let go without closing the program, and during that time, when the close icon is held down, the program once again is blocked.
Furthermore, I do not know how to manually include the code necessary to move the window when the user clicks the titlebar and drags the mouse. For starters I do not know which uMsg's and wParam's to handle.
My question is then, how do I disallow blocking during the case when the user clicks down the exit button (or minimize/maximize buttons) while still handling the case when the mouse is clicked and released over the button, and how do I allow the user to move/drag the window without it blocking the program (or what message is sent when the title bar is clicked without it being a button or menu)?
I am creating the window with WS_SYSMENU | WS_MINIMIZEBOX.
I still want the program to respond to minimize, maximize, and exit commands.
If multi-threading can fix it, then that is interesting, but I wonder if I can get it to work on single-core processors. And I have read about hooks, but the MSDN page is still hard for me to interpret.
Why Is My App Freezing?—An Introduction to Message Loops & Threads
This phenomenon is not isolated to any particular message. It's a fundamental property of the Windows message loop: when one message is being processed, no other message can be processed at the same time. It's not exactly implemented this way, but you can think of it as a queue, where your app pulls the messages out of the queue to process in the reverse order that they are inserted.
Therefore, spending too long processing any message is going to suspend the processing of other messages, effectively freezing your application (because it cannot process any input). The only way to solve this problem is the obvious one: don't spend too long processing any one message.
Often that will mean delegating the processing to a background thread. You will still need to handle all messages on the main thread, and the background worker threads need to report back to the main method when they are finished. All interaction with the GUI needs to happen on a single thread, and that is almost always the main thread in your application (which is why it is often called the UI thread).
(And to answer an objection raised in your question, yes, you can operate multiple threads on single processor machines. You won't necessarily see any performance improvements, but it will make the UI more responsive. The logic here is that a thread can only do one thing at a time, but a processor can switch between threads extremely rapidly, effectively simulating doing more than one thing at a time.)
More useful information is available here in this MSDN article: Preventing Hangs in Windows Applications
Special Cases: Modal Event Processing Loops
Certain window operations on Windows are modal operations. Modal is a common word in computing that basically refers to locking the user into a particular mode where they cannot do anything else until they change (i.e. get out of that) modes. Whenever a modal operation is begun, a separate new message processing loop is spun up and message handling happens there (instead of your main message loop) for the duration of the mode. Common examples of these modal operations are drag-and-drop, window resizing, and message boxes.
Considering the example here of window resizing, your window receives a WM_NCLBUTTONDOWN message, which you pass to DefWindowProc for default processing. DefWindowProc figures out that the user intends to start a move or resize operation, and entered a moving/sizing message loop located somewhere deep in the bowels of Windows' own code. Thus, your application's message loop is no longer running because you've entered into a new moving/sizing mode.
Windows runs this moving/sizing loop as long as the user is interactively moving/sizing the window. It does this so that it can intercept mouse messages and process them accordingly. When the moving/sizing operation completes (e.g., when the user releases the mouse button or presses the Esc key), control will return to your application code.
It is worth pointing out that you are notified that this mode change has occurred via the WM_ENTERSIZEMOVE message; the corresponding WM_EXITSIZEMOVE message indicates that the modal event-processing loop has exited. That allows you to create a timer that will continue to generate WM_TIMER messages that your application can process. The actual details of how this is implemented are relatively unimportant, but the quick explanation is that DefWindowProc continues to dispatch WM_TIMER messages to your application inside of its own modal event processing loop. Use the SetTimer function to create a timer in response to the WM_ENTERSIZEMOVE message, and the KillTimer function to destroy it in response to the WM_EXITSIZEMOVE message.
I only point that out for completeness, though. In the majority of Windows apps that I've written, I've never needed to do that.
So, What Is Wrong With My Code?
Aside from all of that, the behavior you describe in the question are unusual. If you create a new, blank Win32 application using the Visual Studio template, I doubt you will be able to replicate this behavior. Without seeing the rest of your window procedure, I can't tell if you're blocking on any messages (as discussed above), but the part I can see in the question is wrong. You must always call DefWindowProc for messages that you do not explicitly process yourself.
In this case, you might be fooled into thinking that you're doing that, but WM_SYSCOMMAND can have lots of different values for its wParam. You only handle one of those, SC_CLOSE. All of the rest of them just get ignored because you return 0. That includes all of the window moving and resizing functionality (e.g. SC_MOVE, SC_SIZE, SC_MINIMIZE, SC_RESTORE, SC_MAXIMIZE, etc. etc.).
And there's really no good reason to handle WM_SYSCOMMAND yourself; just let DefWindowProc take care of it for you. The only time you need to handle WM_SYSCOMMAND is when you've added custom items to the window menu, and even then, you should pass every command that you do not recognize on to DefWindowProc.
A basic window procedure should look like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
It is also possible that your message loop is wrong. The idiomatic Win32 message loop (located near the bottom of your WinMain function) looks like this:
BOOL ret;
MSG msg;
while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// An error occurred! Handle it and bail out.
MessageBox(nullptr, L"Unexpected Error", nullptr, MB_OK | MB_ICONERROR);
return 1;
}
}
You do not need hooks of any kind. The MSDN documentation on these is very good, but you're right: they're complicated. Stay away until you have a better understanding of the Win32 programming model. It is a rare case indeed where you need the functionality provided by a hook.
If multi-threading can fix it, then that is interesting but I wonder
if I can get it to work on single-core processors. And I have read
about hooks, but the MSDN page is still hard for me to interpret.
You can use multiple threads on a single-core processor. Performance would be better on multi-core systems, but that shouldn't prevent you from writing multithreaded applications. Anyway, go for it.
By printing all messages sent to WindowProc it appears WM_NCLBUTTONDOWN is sent last before the block occurs. You could check the mouse location after this event occurs, but it seems an inconvenient way to solve a simple problem.

How could I detect when my application is minimized?

I have a program with an option to enable minimizing to the taskbar's notification area. In order for this to work, I need a reliable way of detecting when the user has minimized the application.
How can I do that using the Windows API in a C++ application?
When the user minimizes the window (either using the box on the title bar, or by selecting the "Minimize" option from the system menu), your application will receive a WM_SYSCOMMAND message. The wParam parameter of that message will contain the value SC_MINIMIZE, which indicates the particular type of system command that is being requested. In this case, you don't care about the lParam.
So you need to set up a message map that listens for a WM_SYSCOMMAND message with the wParam set to SC_MINIMIZE. Upon receipt of such a message, you should execute your code to minimize your application to the taskbar notification area, and return 0 (indicating that you've processed the message).
I'm not sure what GUI framework you're using. The sample code could potentially look very different for different toolkits. Here's what you might use in a straight Win32 C application:
switch (message)
{
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MINIMIZE)
{
// shrink the application to the notification area
// ...
return 0;
}
break;
}
I think you are looking for WM_SIZE. When you get this, check the wParam to get the specifics. Here is the MSDN page.
WM_SIZE
You can check the area size returned from GetClientRect - if zero it's minimised, works for me but may not work in all cases.
That's what IsIconic is supposed to determine, but it doesn't work consistently for me. (Oh, for a consistent way to determine this...)
For completeness, there's also GetWindowPlacement. The window state is revealed in the showCmd member of the WINDOWPLACEMENT structure, and if the window is minimized it has a value of 2, or SW_SHOWMINIMIZED.

win32 DialogBox app: how to show text from callback on the DialogBox?

I'm working on a win32 DialogBox based app. This uses DialogBox() to create the dialog box, and has a dialog box procedure which does all the usual things.
The dialog box has some static text controls on it, and generally I'm showing text in these via SendDlgItemMessage() from within the dialog box procedure.
However at one point the DialogBox initiates a lengthy operation. This operation has a callback with a series of status messages. I'm having some trouble showing these messages on the dialog box, for two reasons:
The callback function doesn't know what the dialog box HWND is, because it gets called from the code which carries out the lengthy operation. I suppose I can define a file scope HWND variable and copy the dialog box HWND into it from the dialog box procedure just before the lengthy operation is started. That way, the callback function could have access to the dialog box HWND. But that seems awfully kludgy: is there a more elegant way?
The dialog box procedure is blocked while the lengthy operation happens. This doesn't matter because it's an embedded system. But will Windows even show the text in the dialog box if I issue a SendDlgItemMessage() while the dialog box procedure is blocked?
edit I've done some investigations using SendDlgItemMessage() to send a WM_SETTEXT to a static text control on a dialog. The text is displayed immediately even if the dialog box procedure is blocked.
Well, your dialog HWND is a singleton so it isn't the end of the world. But yes, the standard way this is done is by passing an opaque pointer to the code that gets the job done. Compare with the lParam argument of EnumWindows() for example, the callback gets that pointer back.
Whether a control repaints itself immediately is an implementation detail. I only know of progress bar doing this. You could call UpdateWindow on the dialog window handle to get any pending paint updates flushed to the screen.
The all-around better mouse trap is to perform long running tasks on a worker thread. Avoids Windows displaying the "Not Responding" ghost window, avoids timeouts on broadcast messages and numerous potential deadlock problems. But tends to be tricky to get right, you cannot update the window directly from the worker thread.