How to prevent arrow keys from changing the UI state? - c++

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.

Related

Differentiating between password and other kind of keyboard inputs in a keylogger

I am writing a keylogger for windows. I am planning to get the pressed key with GetAsyncKeyState(KEY) and a hidden console. After a key press has been identified I will get the current focused windows with GetForegroundWindow and indentify which program was on top when the key was pressed. I also want to be able to Differentiate between key presses for passwords and other kind of inputs. Is there a way to do it? How?
I am not writing a malicious software. This is for an assignment in Advanced Programming course.
If the foreground app is using standard Win32 UI controls, then try this:
use GetForegroundWindow() to get the HWND of the foreground window.
then use GetWindowThreadProcessId() and GetGUIThreadInfo() to get the foreground window's currently focused child control.
then use GetClassName() to check if it is a standard EDIT control (this check might fail in some UI frameworks! You might have to use the UI Automation API to detect the control type)
then use GetWindowLong/Ptr() to check if it has the ES_PASSWORD style applied.
However, if the foreground app is not using standard Win32 UI controls, and/or is custom-drawing them, or the like, then all bets are off.

How can I prevent RegisterHotKey from blocking the key for other applications?

I am writing a win32 application that needs to take hotkeys while not on focus(it runs in the background without drawing a window). I use RegisterHotKey to assing a few keys but that blocks the for every other process. For example I assign the 'c' key and when I press it in notepad nothing happens.
RegisterHotKey() registers global hotkeys. Hotkeys are processed before regular keyboard input processing, meaning that if you register a hotkey successfully, pressing that key will result in you getting your hotkey message rather than the app with focus getting the normal WM_KEYDOWN/WM_CHAR messages. You have effectively blocked other apps from seeing that key press.
This is by design.
Obviously the solution to avoid clashes like you describe is to not register a hotkey that other applications may use. If you register C without any qualifiers as a hotkey, then no other program will see the C key being pressed. Instead you should use qualifiers like Ctrl/Shift/Alt to prevent your hotkey from interfering with the normal use of the keyboard.
There is no way to register a hotkey that's global unless some other program is active. If you want to achieve the situation where, say, your hotkey works while the desktop is active but nothing else is, you could use a message hook to inject code into the desktop's process (via SetWindowsHookEx()) and intercept key presses that way. But you can't do it with RegisterHotKey().
I just tried UnregisterHotKey(), simulated the key with keybd_event(), then RegisterHotKey() again. I don't recommend it as a production code, it's probably better to use hooks for that, but as a quick hack I just wanted to say that it works.
GetAsyncKeyState()
can be used to determine if certain keys are pressed, even when the program is running in the background.

Keyboard messages from child controls

I am currently developing a user interface DLL that uses the WIN32 API. The DLL must work for numerous platforms, XP, WIN CE, etc. I have managed to incorporate docking, anchoring and so on but appear to have a problem regarding owner-drawn buttons. I can draw the button's correct state, focus, clicked, default. However, I cannot receive key notifications. I specifically want to perform a click operation on a button that currently has focus, should the user press enter.
Note that I am using a windows message loop rather than a dialog message loop. I use windows hooks to hook into the window creation and set the user data to 'point' to my control instance. If I test for WM_KEYDOWN in the main message loop I can get a handle to my button control instance and could forward the message to the relevant control. Unfortunately, I am dealing with a lot of legacy code and this may not be an ideal solution.
So, my question is what is the best way forward. Is subclassing the button control's window procedure a viable option or is there an easier way?
Many thanks in advance.
The comments above are correct. The button with focus should be getting the key messages. But buttons don't (by themselves) respond to Enter--they respond to Space. It sounds like what you're missing is the typical dialog keyboard navigation, like Tab key moving the focus and Enter activating the "default" button.
If you've got a typical Windows message pump, and you want the keyboard behavior normally associated with dialogs, then you need to use the IsDialogMessage API in your message loop. This means your window is essentially a "modeless dialog".
Looks like standard window proc subclassing should do the trick. See http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx for details.

Ampersand accelerators cause a beep in a Win32 dialog

I have a dynamically created toolbar on a plain Win32 dialog. My buttons are added with & shortcuts which correctly puts underscore to characters following ampersand but pressing Alt+(char) causes a beep and the button is not clicked.
It has been a while since I have done Win32 API development. Is there something that needs to be done to a dynamically created child window (toolbar) in order for the accelerator keys to work?
This could be something really obvious that I am missing...
Well... You have to write code to handle these keypresses and convert them into WM_COMMAND messages. The traditional way to do this is to define an accelerator table and process them using TranslateAccelerator() - but of course, you're free to do it however you like... Just make sure the keys you handle jibe with the keys you underline!
You might also find this KB article helpful: How to use accelerator keys within a modal dialog box in Visual C++... Or, for a more in-depth (and MFC-free) look at implementing custom message processing in dialogs, check out Raymond Chen's articles on the dialog manager, specifically part 4: The dialog loop and part 9: Custom accelerators in dialog boxes (but seriously, read the whole thing, you know you want to...)
The beep indicates that the command isn't handled by any window in your app.
Since you created the toolbar dynamically, I would guess that the toolbar window isn't set up properly as a child window of your main window (i.e., it's parent and owner window are not set).
To test: click on the toolbar so it has the focus, then press Alt- and it should work.

DLL plugin that creates a parented window doesn't handle messages correctly

I'm creating a plugin framework, where my application loads a series of plugin DLL's, then creates a new window and pass this new window's handle to the plugin. The plugin can, then, use this handle to create their own GUI.
Everything seems to be working very well. The only problem is that when I press TAB on a plugin widget (An editbox, for example), it doen't jump to another widget. I figured out that some Windows messages are passed, and some others aren't. The WM_KEYDOWN is passed for other keys, because I can type on the editbox, but this message doesn't handle TAB key.
Hope somebody has a hint.
I'm using Borland VCL with CBuilder, but I think I could use any framework under WIN32 to create these plugins, since they never know how their parent windows were created.
It's very complex matter indeed.
When you hit TAB focus jumps to another control only when these controls belong to a Modal Dialog Box. In fact there are some buttons like ESC, LEFT, RIGHT, DOWN, UP, TAB which modal dialog message function treats in a special way. If you want these keys to behave in similar way with modeless dialog box or any other window you should change you message processing function and use IsDialogMessage inside. You'll find more information about IsDialogMessage function in MSDN also to better understand this stuff you may check as well Dialog Boxes section.
And, as was mentioned before, you should set WS_TABSTOP and WS_GROUP styles when needed.
Good luck!
I believe you'll have to take the following steps:
Subclass your edit controls (and other controls as needed).
Capture the WM_KEYDOWN message in your edit control's WndProc.
Check to see if the shift key is currently held down (using GetKeyState or similar).
Call GetWindow, passing in a handle to your edit control and either GW_HWNDPREV or GW_HWNDNEXT depending on whether shift is held down. This will give you the handle to the window that should receive focus.
Call SetFocus and pass in the window handle you got in step 4.
Make sure you handle the case where your edit controls are multiline, as you might want to have a real tab character appear instead of moving to the next control.
Hope that helps!
I believe you suffer from having a different instance of the VCL in each of your dlls and exes. Classes from the dll are not the same as the ones from your exe, even if they are called the same. Also global variables (Application, Screen) are not shared between them. Neither is the memory since they both have their own memory manager.
The solution is to have the dlls and the exe share the VCL library and the memory manager. I am not a BCB developer, but a Delphi developer. In Delphi we would just use the rtl and the vcl as runtime packages. Maybe you could do the BCB equivalent.
A DLL has its own TApplication object.
to provide uniform key handling. when the DLL Loads.
assign the DLL::TApplication to the EXE::TApplication
Be sure to do the reverse on exit.
--
Michael