Ensure all key events get sent to main window? - c++

Is there a way to ensure that all WM_KEYDOWN events find their way into my main window regardless of who has focus? this is mainly for global things such as Delete, and hotkeys such as CTRL A and CTRL S. The problem is if another control has focus, all of these stop working. Is there maybe a better way of doing this than putting them in my main window's WM_KEYDOWN event?
Thanks

Yes, you do it in your message loop. At the exact location where a traditional message loop has the TranslateAccelerator() call. Which performs the same kind of operation, catching short-cut keystrokes and turning them into WM_COMMAND messages. A typical class library implements this with a "PreProcessMessage" method.

Related

Simulate ALT+F4 key press in C++

I`m making a c++ application with the KINECT. I basically want to use it to send alt f4 to close the current focused window not my application, as you would normally pressing alt f4 on the keboard. Thanks in advance.
Im already using VkKeyScanA to input a few other keys but i just cant find the key code for alr+f4
There's more than one way to do this. Emulating keystrokes is the last thing you should do, very hard to get right since you cannot control the keyboard state of the process well enough.
First one is GetForegroundWindow + SendMessage to send the WM_SYSCOMMAND, SC_CLOSE command. Which is what Alt+F4 does when it is processed by the default window procedure. Which in turn sends WM_CLOSE by default if the program did not override the WM_SYSCOMMAND processing.
If you create your own window then you should favor avoiding trying to find the foreground window. Send WM_APPCOMMAND with the APPCOMMAND_CLOSE command to your own window. Your call to DefWindowProc() forwards the command through several layers to the shell.
In case you are considering a more forceful way, like WM_CLOSE then do review Raymond Chen's recent blog post.

WM_LBUTTONDOWN + WM_LBUTTONUP combination making drag view

I am using below code in my application's view on particular event to simulate a left mouse click.
SendMessage(WM_LBUTTONDOWN);
SendMessage(WM_LBUTTONUP);
Once this code executed a mouse drag view appears. How to avoid this drag view after simulating the mouse click?
When I monitored via SPY++ I got the both messages are sent like below,
WM_LBUTTONDOWN fwKeys: MK_LBUTTON xPos : 752 yPos:85
WM_BUTTONUP fwKeys:0000 xPos:752 yPos 85
I suspect the WM_LBUTTONUP message not sent properly.
What is the fwKeys : 0000 indicates?
Is there any think wrong in sendMessage of WM_LBUTTON up in the above code?
First of all, if that is your real code, you are "simulating" the mouse click improperly. There's more to a WM_LBUTTONDOWN or WM_LBUTTONUP than the message itself: there's data packed in the wParam and lParam values of the message.
You could easily see that if you had taken a second to look at the MSDN pages for WM_LBUTTONDOWN and WM_LBUTTONUP. They describe exactly what the wParam and lParam values mean in this context. And, by the way, this would also answer your question about the meaning of "fwKeys" in Spy++.
But really, if you need to simulate mouse events, then do it the right way: call the mouse_event function. It's whole purpose in life is to synthesize mouse events.
On to your other question: how to disable the drag view: it depends on what kind of control you're dealing with. For example, if you had a tree view control, then you could set the TVS_DISABLEDRAGDROP style on the control, as stated on MSDN. If you want to disable drag & drop for that control permanently, then set the flag when you create the control. If you only want to disable it temporarily, during your synthesized input operations, then that's a bit trickier - you can use CWnd::ModifyStyle to temporarily remove the TVS_DISABLEDRAGDROP but you will also need to add code to enable it again, after you finish sending your synthesized mouse movements and the control has finished processing them.
With all that said, what exactly are you trying to achieve? There may be an easier way to solve the problem that you are trying to address.
Thanks for all your answers and support.
I am working on a already developed application which requires this solution. Finally I found that the WM_LBUTTONDOWN handler was already defined in my view. This takes time to execute. Since I used SendMessage which posts message to a thread's message queue and return immediately, before the WM_LBUTTONDOWN finished, the next message WM_LBUTTONUP is called. So the WM_LBUTTONUP was failing.
I used PostMessage as below,
PostMessage(WM_LBUTTONDOWN);
PostMessage(WM_LBUTTONUP);
This resolves my problem.

Modeless dialogs and accelerators

I want to perform some action when the user presses CTRL+S inside a modeless dialog.
Accelerators would be perfect for this, except that I don't have control over the thread's message loop (think plugin), so I can't call TranslateAccelerator.
A nested message loop is not an option because the main application does a lot of processing in between calls to PeekMessage.
Is there some way I can 'force' the existing message loop to handle my accelerator?
Is there any other way besides accelerators to catch CTRL+S?
I thought about using a Window hooks on WH_GETMESSAGE, which gets called before returning from GetMessage or PeekMessage. But I'm not sure what would happen after I successfully called TranslateAcellerator, I can't let the application know I handled it.
WH_MSGFILTER would require the app to implement a call to CallMsgFilter, which it doesn't from a quick glance with a debugger.
My last idea was subclassing the control which is what I'm trying to avoid. That would require some mechanism to signal the keypress event to the parent window, which I don't think is a great design. Also, if I add more controls I would have to subclass every single one.
Thanks for any hints.
This is a fairly infamous interop problem, it rears its ugly head also when using Winforms to implement UI in a native program. Microsoft's recommendation is a rough-and-tumble one: start your own thread to display the window so you can pump your own message loop. You'll need SetParent() to avoid Z-order problems. Scary stuff, do consider a modal dialog thrice before committing to this.
Can you use WM_GETDLGCODE? http://msdn.microsoft.com/en-us/library/ms645425(v=vs.85).aspx

How to prevent arrow keys from changing the UI state?

I am developing a Tetris game using C++ in combination with the plain old WinAPI, GDI and GDI+. The applications window contains a few UI controls along with a static control that is used for painting the game state. I am using a keyboard hook so that I can respond to the arrow keys to move the current block and the space bar to drop the block.
However, the keystrokes also affect the UI. Moving the arrow keys may change the radio or combobox selection state and pressing the space bar may trigger a button or checkbox, depending on which control currently has focus.
Is there a way to prevent this from happening? My temporary hack is to force focus on a hidden textbox. I would appreciate a cleaner solution.
If you're using a WH_KEYBOARD_LL or a WH_KEYBOARD keyboard hook, you can return 1 from the hookproc to prevent the key from being passed to the rest of the system.
Do no call the next hookproc in that case.
However, this could play havoc with things that use hooks and come after you in the hook chain.
If you're writing a GDI app, you have a message loop already, is there any reason you're not using the message loop to look for KEY_UP/KEY_DOWN messages?
You can set other controls so they will not take focus...
Is this a real hook (set with SetWindowsHook)? If so, you could return a non zero value from the hookproc when you handle the message, and Windows will not pass the message along to the dialog.

C++ console keyboard events

Is there any way to get key events in a Windows console? I need a way to get keydown and keyup events quickly without a GUI. I've tried using getch(), but it doesn't get keyups and waits until a key has been pressed to return.
Use ReadConsoleInput() API. Watch for events of kind KEY_EVENT. This won't work for all keydown events (Ctrl-key, shift-key, Pause-key cannot be read), but most can be read.
Use GetNumberOfConsoleInputEvents to avoid blocking.
You can use GetKeyState or GetAsyncKeyState, but that won't give you keydown/keyup events. It will only tell you what keys are currently down.
So if you really need to get the keydown/keyup events, you could install a hook.
A Console window has a window handle that is owned by code in Windows and a message pump, also owned by code in Windows.
You can get the window handle of of the console window by using GetConsoleWindowThen install a WH_CALLWNDPROC hook using SetWindowsHookEx to listen in on messages send to the console window.
You might try a WH_MSGFILTER hook instead. I don't know if this works for console windows, but it would generate less messages to be ignored if it does work.
I was just curious, how comes such a logical question doesn't have any explanation on Google,
So one has to ask it here. So I googled for: "keyboard events console application" and
guess what ... first 2 links are interesting (but unfortunately, not exactly answers to your question):
Processing mouse / keyboard input on MSDN.
Console event handlers (like Ctrl-C and window close button).
There are a number of ways. GetKeyboardState would be one of the most obvious.
You can also try SetConsoleCtrlHandler