I have an empty win32 project.
CASE WM_CHAR:
under this case I need to store each keystroke in an array, then output it to the screen using
TextOut();
I figured it's going to be something like this:
char store[LARGE_NUMBER];
then under the case wm_char header I store the character in store then use a counter to move along the array for each key which is pressed. I just don't know how to record a specific key on the keyboard, not just any key - which calls the wm_char case.
Thanks
The wParam parameter holds the character code of the key that was pressed. Take a look at the documentation. lParam holds further information about the key press (was it a special key, was the key held down etc.).
Related
To handle text input I've set up a char-event callback with glfwSetCharCallback, and to handle non-text keypresses (arrow keys & hotkeys) I've set up a key-event callback with glfwSetKeyCallback.
What happens in this situation is that for a key press of a character key, I get two calls, one in the key-event callback, and then one in the char-event callback. This can cause unwanted effects - for example let's suppose the user configured the key "a" to enter "Append Mode" of a text editor - after it enters the mode it will also enter the character "a".. Is there a good way to handle this?
So far I've relied on both events arriving together before glfwPollEvents returns, and have merged them. But I get reports that this scheme doesn't work well on some Ubuntu systems..
I've been having trouble with this one as well. After some rudimentary debugging I found that if you press, hold then release a 'typable' key (meaning a key which may fire both the glfwKeyCallback and glfwCharCallback), the output is as follows:
KeyCallback - pressed
CharCallback - typed
KeyCallback - repeated
CharCallback - typed
(3. and 4. repeat until key is released)
KeyCallback - released
With this, and judging from the fact that there is a 0ms delay between the two events firing, they're probably fired sequentially. The solution I came up with (is rather janky), and involves creating some sort of KeyEvent structure:
(examples are in C++)
enum KeyEventType
{
Pressed,
Repeated,
Released
}
struct KeyEvent
{
KeyEventType Type;
int Key;
unsigned char Codepoint;
bool IsTyped;
}
and store it along with an index variable, such as
[main/input class]
std::vector<KeyEvent> m_KeyEvents;
size_t m_LastKeyEventIndex;
in the main file.
Then, when the glfwKeyCallback fires, push a new KeyEvent into the vector:
[glfwKeyCallback]
KeyEventType type = (action == GLFW_PRESS ? KeyEventType::Pressed : (action == GLFW_REPEAT ? KeyEventType::Repeated : KeyEventType::Released));
KeyEvent event = KeyEvent(type, key);
m_KeyEvents.push_back(event);
m_LastKeyEventIndex = m_KeyEvents.size() - 1;
and if the glfwCharCallback fires, we know from the debugging that it should be (immediately) after the corresponding keyCallback event, so you can modify the last added entry in the vector to add the codepoint and mark it as a 'typed' event, after-the-fact. This also gives the added benefit of tying the actual key that was pressed to the generated codepoint, which could come in useful.
[glfwCharCallback]
m_KeyEvents.at(m_LastKeyEventIndex).Codepoint = codepoint;
m_KeyEvents.at(m_LastKeyEventIndex).IsTyped = true;
Finally, in the main loop when you go to call glfwPollEvents(), process all those pending KeyEvents and then clear the vector and reset the index.
I haven't fully tested this yet, but some very rudimentary debugging shows this as a promising solution, resulting in the following*:
*I'm using a custom Key enum in place of the int Key. You could probably use glfwGetKeyName() to get the printable key name, however this resulted in exceptions for me when pressing some keys.
I created a dialog MainDialog.cpp with 2 edit controls whose IDs are IDC_EDITCONTROL_A and IDC_EDITCONTROL_B, and have variables defined as m_editControlA and m_editControlB, respectively.
Also, I have 2 buttons whose IDs are IDC_MFCBUTTON_KEY_X and IDC_MFCBUTTON_KEY_Y, and variables are m_buttonKeyX and m_buttonKeyY, respectively.
Below is the code in the source file
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CMainDialog, CDialogEx)
CMainDialog::CMainDialog(CWnd* pParent): CDialogEx(IDD_MAIN_DIALOG, pParent)
{
}
CMainDialog::~CMainDialog()
{
}
void CMainDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDITCONTROL_A, m_editControlA);
DDX_Control(pDX, IDC_EDITCONTROL_B, m_editControlB);
DDX(Control(pDX, IDC_MFCBUTTON_KEY_X, m_buttonKeyX);
DDX(Control(pDX, IDC_MFCBUTTON_KEY_Y, m_buttonKeyY);
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialogEx)
ON_EN_CHANGE(IDC_EDITCONTROL, &CMainDialog::OnEnChangeEditA)
ON_BN_CLICKED(IDC_MFCBUTTON_KEY_X, &CMainDialog::OnBnClickedButtonX)
ON_BN_CLICKED(IDC_MFCBUTTON_KEY_Y, &CMainDialog::OnBnClickedButtonY)
END_MESSAGE_MAP()
void CMainDialog::OnBnClickedButtonX()
{
m_editControlA.SetWindowTextW(_T("X")); // test
}
void CMainDialog::OnBnClickedButtonX()
{
m_editControlA.SetWindowTextW(_T("Y")); // test
}
I am trying to understand how I can have each button send their respective character (i.e. X or Y in this example) to the selected edit control if one is selected. Essentially, I would like to simulate keyboard input.
I have read the docs about how to simulate keyboard events and also the sendMessage but I could not understand how to implement it since my C++ knowledge is very basic. Also, following my previous question I have found that the GetFocus would be useful but still my main issue currently is sending the input.
Any example code or useful link could be very useful for me to learn how I can simulate a keyboard input inside an app.
The characters are sent from the OS to the edit controls using the WM_CHAR message.
In reality it is a bit more complex than that, but you do not need to emulate the entire WM_KEYUP WM_KEYDOWN message sequence, since its end result is to generate a WM_CHAR message.
You can use CWnd::PostMessage to send characters directly to your edit controls, even when they do not have the focus.
You have probably already found the documentation for WM_CHAR here: https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms646276(v=vs.85).aspx
oops.. excuse my french, ths english doc is here
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx
(just changing the fr-fr to en-us does the trick, it probably works for all other languages, neat!
wParam holds the character you want to send. Either an plain ASCII character, or one of the VK_ constants... I suggest you use the unicode version WM_CHARW, as most windows software uses unicode nowadays. The notation for wide chars is either L'X' or _T('X'), the unicode (UTF-16) character type is wchar_t.
lParam contains other keystroke details, 0 should be fine for what you want to do.
to send X, simply call
m_editControlA.PostMessage(WM_CHAR, _T('X'));
When using the _T() notation, the character (or string) literal between the parenthesis will be automatically converted to the right character width for your app's unicode setting (you should set that to UNICODE, since that's what the OS is using, and is also the only valid encoding for Windows CE, for example, and you should get used to manipulating this type.
the _T() macros and _t* overrides for almost all C library functions operating on strings are defined in tchar.h, which is included by Visual Studio in stdafx.h. Under MFC, you'll mostly use CString, but it's good to know where these things are.
[EDIT] When you get that running, you should start playing with WM_KEYDOWN. You will discover that PostMessage(WM_CHAR, VK_ESCAPE) directly to your dialog does not close it, while a PostMessage(WM_KEYDOWN, VK_ESCAPE) does. And that m_editBox.PostMessage(WM_KEYDOWN, _T('X')) will send a lower key 'x' to your edit box. But that's another topic to ivestigate.
Have fun with MFC!
For your last question:
Sure, but it gets a bit more complicated, as your button will gain focus, as soon as you click on it. You'd have to create handlers for EN_SETFOCUS for eeach of your edit boxes, and add a CWnd* data member to keep track of the last edit box that had focus.
Your EN_SETFOCUS handlers should look something like this
void CdlgDlg::OnEnSetfocusEdit1()
{
m_pWndLastFocus = &m_edit1;
}
Don't forget to set the pointer to NULL in your constructor and to chjeck it's valid before calling m_pWndLastFocus->PostMessage() though.
The way to synthesize input in MFC is by using the SendInput method.
What is the way to handle non-latin keys pressed with Qt?
For example, for 'W' key pressed QKeyEvent::key() returns 87, but for 'Ц' - the same key in the russian layout - it returns 1062.
So I can't use constants like Qt::Key_W for checking which key has been pressed: they won't work if a user switches the layout.
Thank you
The meaning of a key depends on the currently selected layout. What you observe is correct. If you pressed that key in any other application, you wouldn't get a W, but a Ц (C).
A given key means Qt::Key_W only if it's in a layout that produces the Roman W.
If you intend to refer to physical keys, you can try using QKeyEvent::nativeScanCode() and/or QKeyEvent::nativeVirtualKey(). These values are platform-dependent, of course.
I'm trying to limit the access of the users of my program to the keyboard. To do that I've defined a low level keyboard hook:
LRESULT CALLBACK lowLevelKeyboardProc(int key, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT* pkbhs = (KBDLLHOOKSTRUCT*)lParam;
switch (key)
{
case HC_ACTION:
....
and hooked it:
m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc, 0, 0);
I need the users to be able to use only the alphanumeric chars, ~, #, # ... only the chars that can be in a password (printable chars).
What would be the easiest way to differentiate between those chars and all the others using the low level keyboard hook parameters: int key, WPARAM wParam, LPARAM lParam ?
The program is written in c++ and compiled in VC2010.
All help is appreciated!
Before actually answering your question, I have a couple of questions for you:
Why would you want to do this globally, using a global low-level keyboard hook?
Although sometimes they are the only way to solve a problem, using a global hook like this is generally strongly discouraged for many reasons. There are many better ways of preventing a user from entering invalid or unacceptable data. For example, I would just disable the keys you don't want for a particular control or set of controls (e.g. all textboxes). That way, the user can still use keyboard shortcuts and other non-alphanumeric keys to interact with your application, which is critical for accessibility reasons. Remember that a global hook will affect all of the other threads running on the machine, not just your app—that is probably not what you want.
Even if you do decide to use a global hook, are you sure that you really need to disable all of the non-alphanumeric keys? What about Backspace and Delete? Shouldn't the user be able to delete things? And what about Tab? Enter? And what about modifier keys, like Shift, Ctrl, and Alt: are those allowed?
Please seriously reconsider whether you really need a low-level hook before continuing forward with this design. If you need help on devising another solution, please ask a new question, describing what you want to accomplish (e.g., I want to prevent users from entering any non-alphanumeric characters in a textbox control; here is the code I use to create my textbox…).
But if you insist on ignoring my advice, the solution is rather simple: investigate the members of the KBDLLHOOKSTRUCT structure that is passed to the hook procedure. The vkCode member gives you the virtual key code of the key that was pressed. Chances are, that is all the information you need. But just in case it's not, the hardware scan code of the key is also provided in the scanCode member.
Unfortunately, the code that you currently have is wrong. The first parameter to the hook callback procedure is indeed an int, but it is not a key code. Rather, it is a code that signals how the hook procedure should process the message. Use it like this:
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// If nCode is greater than or equal to HC_ACTION, process the message.
if (nCode >= HC_ACTION)
{
KBDLLHOOKSTRUCT* pkbhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
// Handle the keys as you wish here.
//
// Remember that pkbhs->vkCode gives you the virtual key code
// of the key that was pressed.
//
// To prevent a particular key from being processed, you should
// return a non-zero value (e.g. 1) immediately.
}
// Pass the message on.
return CallNextHookEx(m_hHook, nCode, wParam, lParam);
}
And when you install the hook, there is absolutely no need to cast the function pointer. Pointless casts like this just hide potential compile-time errors, leading to a crash at runtime. Write it simply:
m_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, 0, 0);
Suppose I have a 2D array. It has four rows and four columns. Now I want that initially I place some marker in the array at some location. Say, array[x][y] = 1 -> marker. I want to move this marker in the array in 8 dimensions by using buttons. Like, on up, location is [x-1][y]. Down is [x+1][y]. Left is [x][y-1]. And right is [x][y+1]. Now I have my logic that this is how I will do it!
1st Question: How to associate my buttons of up down sideways to move in the array?
2nd Question: How will I tackle the other four dimensions as I'll be using two buttons for other complex 4 changing location as <^ two buttons are pressed and location now is [x-1][y-1]!
Kindly direct me or help me with the button associations.
You can use a keyboard hook to trigger your logic when the arrow keys are pressed. You would define a callback function containing code like:
if ( WM_KEYDOWN == wParam && VK_UP == lParam )
//do up logic
else if ( WM_KEYDOWN == wParam && VK_DOWN == lParam )
//do down logic
else if ....
For the diagonal buttons, you can use the home, pgup, pgdn, and end keys on the numeric keypad of the keyboard (this would require a keyboard with numeric keypad). These buttons correspond to the arrow combinations like <^, and would keep the implementation simple.
For information on how to use a keyboard hook, see this post:
C++ Win32 keyboard events
For list of virtual key codes (ie VK_UP) see this link:
http://msdn.microsoft.com/en-us/library/ms927178.aspx