Pressing Alt hangs the application - winapi

I'm programming a Windows application that doesn't have a menu. Every time I press Alt, it receives the WM_ENTERMENULOOP event and hangs until I press a key.
I've tried other applications without menu (like the MS .chm file viewer) and they exhibit the same behavior.
There is no difference between forwarding the event to DefWindowProc or processing it.
Is there a way to stop Windows from entering the menu loop if there is no menu? Alternatively, is there a way to exit it manually as soon as the event is received?

Process WM_SYSKEYDOWN and WM_SYSKEYUP manually (dont' pass them to DefWindowProc) if you want to disable entering menu loop.
Also, you may want to process WM_SYSCHAR and return TRUE for this message to avoiding beeps for keystrokes like Alt+SomeKey

Scalable code after parsing window message and return correct result with NO call DefWindowProc.
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
return (LRESULT)1;
https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-syskeydown
https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-syskeyup
https://learn.microsoft.com/en-us/windows/win32/menurc/wm-syschar
Return value
An application should return zero if it processes this message.

Related

SendMessage(WM_SYSCOMMAND) failed when mouse captured

I'm using the win32sdk, but some messages would never work as expected while mouse was captured by calling SetCapture(), such as:
case WM_LBUTTONDOWN:
SetCapture(hWnd);
SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
ReleaseCapture();
return 0;
The Window won't be maximized. but why?
Additional,
1. if I use PostMessage() instead, it works.
2. if I use PostMessage() instead and remove the ReleaseCapture(); statement, it doesn't work again.
In general:
PostMessage is asynchronous and you call ReleaseCapture() before WM_SYSCOMMAND is processed. So you have only one question: Why you can't maximize if mouse is captured?
I haven't found any info on this but read here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx
"When the mouse is captured, menu hotkeys and other keyboard accelerators do not work." I suppose WM_SYSCOMMAND is not processed also because of this restriction. May be it was done like this to keep coords consistent.
As norekhov said menu hotkeys don't work when the mouse is captured. When the mouse is captured the the only action a user can take that will result in the WM_SYSCOMMAND message being sent is to use a system menu hotkey.
Note that the WM_SYSCOMMAND message is only meant to be used to notify a window of a user initiated action. When you send it to a window, you're in essence trying to mimic a user's action. In this case you don't need to do this. You can tell the window to maximize itself directly:
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
In this case it won't appear to be a user command, so it won't be ignored because the mouse has been captured.

Win32 App (Aero): Prevent dialog move

I've a dialog based Win32-app on Win7-Aero which only displays a dialog. The dialog should have a title bar. I don't want that the user can move the dialog on the screen.
I've no luck so far... handling WM_NCHITTEST, WM_SYSCOMMAND... setting SWP_NOMOVE.
What is the best way to achieve NoMove? I think DWM changes something on Win7.
You could do this by handling WM_WINDOWPOSCHANGING and when you see an attempted move, change the coordinates back to where they should be. E.g.
switch (uMsg)
{
case WM_WINDOWPOSCHANGING:
if (!(reinterpret_cast<LPWINDOWPOS>(lParam)->flags & SWP_NOMOVE))
{
reinterpret_cast<LPWINDOWPOS>(lParam)->x = g_iMyXCoord;
reinterpret_cast<LPWINDOWPOS>(lParam)->y = g_iMyYCoord;
}
return 0;
}
You would probably need to add some intelligence to this to distinguish between attempted moves by the user, and moves that your own program makes (or that the system makes if necessary - e.g. if a monitor disappears for instance).
Even though you say it doesn't work, I would have thought you could also do this by trapping WM_NCHITTEST and returning HTBORDER whenever HTCAPTION would have been returned - however you would have to do this by sub-classing the window rather than in the DialogProc (because you would need to call the default handler first and then process/change the return value). Same for WM_SYSCOMMAND (to catch moves the user attempts via the system menu).

Modeless dialog keyboard handling (winapi)

I've got an application with a main window which has a bunch of controls, including the spacebar, which is handled by a simple method called onSpacebar(). On top of that main window, I've got a persistent modeless dialog.
I need the spacebar to behave the exact same way, regardless of whether the dialog has focus, or the main window has focus.
This dialog is backed by a DialogProc which looks something like this:
BOOL CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_NOTIFY:
std::cout<< "WM_NOTIFY" <<std::endl;
switch(LOWORD(wParam))
{
// which component caused the message?
case COMP_TREE:
if(((LPNMHDR)lParam)->code == NM_DBLCLK){
onDoubleclk()
}
//...
break;
// other components...
}
break;
case WM_CLOSE:
// the dialog can only be closed when the whole app is closed
//EndDialog(hDlg, IDCANCEL);
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
From what I gather, I should call my onSpacebar() method from within the DialogProc, similarily how I handle the double click. I can see that WM_NOTIFY is received by the dialog when the spacebar is pressed (the phrase WM_NOTIFY is printed to cout), but I can't seem to differentiate the spacebar notification from the other numerous notifications the dialog receives.
Please, tell me how to recognize that the particular WM_NOTIFY was in response to a spacebar keypress.
A WM_NOTIFY message is not the standard way that a window processes key press events. When a key is pressed, your window should be receiving WM_KEYDOWN, WM_KEYUP, and possibly WM_CHAR messages. WM_NOTIFY serves an entirely different purpose altogether: passing on a message from a common control to its parent window.
So the fact that you're receiving a WM_NOTIFY message in response to a key press is a fairly unusual thing, explainable when you understand how focus works (which is key to solving your ultimate question).
In Windows, only one window can be focused at a time, and the currently focused window is the one that receives all keyboard input. Thus, if a dialog box has the focus, it will receive key press notifications. If a child control on that dialog box has the focus, it (not its parent dialog) will receive key press notifications. And there is a focusable child control on a dialog box, it will always receive the focus in preference to its parent dialog, therefore it will also always receive key press notifications.
So the likely explanation for your curious WM_NOTIFY messages is that one of the common controls on your dialog has the focus, it is receiving the space key press event, and after processing it, passing on a notification to its parent window (your dialog) in the form of a WM_NOTIFY message. As you might imagine, this is not a reliable method of detecting that the space bar has been pressed.
Instead, you need to figure out some way of trapping key press notifications before they get sent to the focused control. To do that, you'll need to modify your application's message loop to trap WM_KEYDOWN or WM_KEYUP messages before calling either DispatchMessage or IsDialogMessage.
If the key event corresponds to the space bar, you will call your onSpacebar function and indicate that the message was handled, preventing it from being passed on and processed by another window.
If the key event does not correspond to the space bar, then you will need to handle the message as you usually would, ensuring that it does get passed on and processed by the other window.
Since this approach filters out space key presses at a global level, it solves both the problems of child controls on a dialog stealing the key press and the other modeless dialog. However, you do need to be careful because it's very easy to screw things up so that the user can't navigate your dialog using the keyboard at all.
More fundamentally, I think your idea to handle presses of the space bar is fundamentally flawed. The logic of certain common controls basically requires that they process presses of the space bar. For example, consider a textbox: if you filter out all presses of the space bar at a global level, the user will never be able to type a space in a textbox. If you insist on handling the space bar, you will need to check the focused control in your global handler, and if it's a textbox (or other common control that you wish to receive spaces), pass it on; otherwise, handle it yourself.
Honestly, what I'd do instead is choose a more unique key combination (like, I don't know, Ctrl+Space) and set that up as an accelerator. Presumably, your global message loop is already processing accelerator keys by calling the TranslateAccelerator function, so that would take care of all the dirty work for you. No code is even required—you'd do everything simply by editing the accelerators resource file in your project. The MSDN documentation on keyboard accelerators is here, but you'll probably have an easier time consulting your favorite book on Visual C++.

During XGrabKey(board), discover which window had been focused

A program has called XGrabKey() to make a hotkey.
The user presses that key combination (while another window is focused).
The program receives control to do something in response to the key combination. Meanwhile, the program has been temporarily focused (because of the effects of XGrabKey (see man XGrabKey, man XGrabKeyboard)).
I want the program to create a synthetic X event (a keypress or mouse click) to the originally focused window. In some cases this means I need to focus that window before sending it the event (Firefox ignores synthetic events when it is not focused), which means I need to know which window it is. How can I find out which window it is?
Wait for the next FocusOut event, verify that the mode is set to NotifyUngrab, get the focus with XGetInputFocus(), and send away your synthetic events.

Why is WM_CLOSE not handled automatically by DefDlgProc?

When I create a dialog using DialogBox, it won't close unless I handle WM_CLOSE in my own DLGPROC function and call EndDialog.
I know that this is by design, but I'm interested why was it chosen for WM_CLOSE not to be handled automatically by DefDlgProc? Are there any good reasons for that?
Ask yourself this:
What would the default handling of WM_CLOSE be? Calling EndDialog? I think EndDialog would only work in very rare situations.
Other suggestions:
validating user input in the dialog, showing errors if input is out-of-range or otherwise not valid, not ending the dialog
closing child windows, releasing resources/memory that child windows of the dialog are using, releasing COM-Objects, basically: cleaning up first and then end the dialog.

Resources