I'm self studying using the Pearson, Computer Graphics with OpenGL's book.
I'm currently trying to make a simple square move, but before I get ahead of myself I need to be sure I understand what keys are built into Glut.
I'm aware of the following keys:
GLUT_KEY_F1, GLUT_KEY_F2, ..., GLUT_KEY_F12 - F1 through F12 keys
GLUT_KEY_PAGE_UP, GLUT_KEY_PAGE_DOWN - Page Up and Page Down keys
GLUT_KEY_HOME, GLUT_KEY_END - Home and End keys
GLUT_KEY_LEFT, GLUT_KEY_RIGHT, GLUT_KEY_UP, GLUT_KEY_DOWN - Arrow
keys
GLUT_KEY_INSERT - Insert key
I either found them in my book or here on Stackoverflow in another post.
But are there any more? eg, for all keys on a keyboard and mouse?
Thanks.
glut divides key in keyboard by glutSpecialFunc w/c takes special keys such as F1,F2..., NUMPADS, etc. while glutKeyboardFunc takes all keys that can be represented by a character like the alphabets, numbers, ESC (27 in 'ASCII'), ENTER (32 in 'ASCII'), etc.
in summary, glutKeyboardFunc take char parameters that can be represented without using any '\' (backslash, like '\t', '\n') before any character the rest are handled by glutSpecialFunc
the keyboard have two sets of buttons: those that can be represented using ASCII code and those that could not. the ones that can be represented in ASCII returns 1 byte when pressed, the ones that couldn't return two bytes the first of which is NULL
glut abstract this by giving you two set of functions to handle keyboard events: one to handle normal ASCII standard buttons glutKeyboardFunc, the other to handle special two byte buttons glutSpecialFunc
the special function have constants for common keyboard special buttons :
GLUT_KEY_F1:0x0001,
GLUT_KEY_F2:0x0002,
GLUT_KEY_F3:0x0003,
GLUT_KEY_F4:0x0004,
GLUT_KEY_F5:0x0005,
GLUT_KEY_F6:0x0006,
GLUT_KEY_F7:0x0007,
GLUT_KEY_F8:0x0008,
GLUT_KEY_F9:0x0009,
GLUT_KEY_F10:0x000A,
GLUT_KEY_F11:0x000B,
GLUT_KEY_F12:0x000C,
GLUT_KEY_LEFT:0x0064,
GLUT_KEY_UP:0x0065,
GLUT_KEY_RIGHT:0x0066,
GLUT_KEY_DOWN:0x0067,
GLUT_KEY_PAGE_UP:0x0068,
GLUT_KEY_PAGE_DOWN:0x0069,
GLUT_KEY_HOME:0x006A,
GLUT_KEY_END:0x006B,
GLUT_KEY_INSERT:0x006C,
GLUT_KEY_REPEAT_OFF:0x0000,
GLUT_KEY_REPEAT_ON:0x0001,
GLUT_KEY_REPEAT_DEFAULT:0x0002.
mouse clicks can be handled with the glutMouseFunc and the constants associated with the mouse buttons are:
GLUT_LEFT_BUTTON:0x0000,
GLUT_MIDDLE_BUTTON:0x0001,
GLUT_RIGHT_BUTTON:0x0002
glut can also handle joysticks with the glutJoystickFunc which has the following constants:
GLUT_HAS_JOYSTICK:0x0264,
GLUT_OWNS_JOYSTICK:0x0265,
GLUT_JOYSTICK_BUTTONS:0x0266,
GLUT_JOYSTICK_AXES:0x0267,
GLUT_JOYSTICK_POLL_RATE:0x0268,
GLUT_JOYSTICK_BUTTON_A:0x0001,
GLUT_JOYSTICK_BUTTON_B:0x0002,
GLUT_JOYSTICK_BUTTON_C:0x0004,
GLUT_JOYSTICK_BUTTON_D:0x0008.
if you are using a gaming mouse or a keyboard/joystick with more buttons you can test for what each button returns by outputting the button pressed to the console then directly use this value in your code to know if one of those button is pressed
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 find that CEdit control has option 'Number' in its property, so that I can prevent user from enter non-digit character into this textbox - it is CEdit number control now.
If there is an option 'Number', I think maybe there is a way to remove leading zeros for CEdit which is just simple like option 'Number'.
I have tried Dialog Data Exchange with hope that it would remove leading zeros for me automatically, but it won't.
Then I think the way to do this is add EN_KILLFOCUS message for each of the CEdit number controls, but I find that exhausted.
So I think the better way to do that is add EN_KILLFOCUS, but all the CEdit number controls lose focus event point to one function, in this function I'll remove leading zero for the 'current' control, but in C# I can get the 'current' control, in C++ I don't know if it's supported.
Or inherit CEdit to make CEditNum - which implement lose focus remove leading zeros feature, but with this solution, I can't design it on the Visual Studio design window (I think). I hope there is a solution similar to this solution (which is a solution for Draw&Drop problem)
Anyway, before apply the final solution (EN_KILLFOCUS), I want to make sure if is there better way - least implement, reuse the existing implement of MFC.
A little explain about remove leading zeros: you enter: 00001 into the CEdit control, then lose focus, the CEdit control show you: 1. The idea is like MS Excel when you enter a number into its cell.
"but all the CEdit number controls lose focus event point to one function"
That is true, but you get the control ID of the control that's just lost focus as a parameter.
Add this to your Message table, replace IDC_FIRST, IDC_LAST with the first and last IDs of your edit controls, or use 0, 0xFFFFFFFF for all.
ON_CONTROL_RANGE(EN_KILLFOCUS, IDC_FIRST, IDC_LAST, OnKillFocus).
Here is the signature of OnKillFocus, and how to get a CWnd to apply changes.
void CMyDialogClass::OnKillFocus(UINT nID)
{
// you can further check if the ID is one of interest here...
// if your edit control control IDs are not contiguous, for example.
// you can get a CEdit* here, but only if you used DDX to map the
// control to a CEdit.
CWnd* pCtrl = GetDlgItem(nID);
if (pCtrl)
{
CString str;
pCtrl->GetWindowText(str);
// remove zeroes, or format as you like....
str.Format(_T("%d"), _tcstoi(str));
pCtrl->SetWindowText(str);
}
}
// if you mapped the control to a CEdit, here's how you can safely
// get a pointer to a CEDit
CEdit* pEdit = (CEdit*)GetDlgItem(nID);
ASSERT_KINDOF(CEdit, pEdit); // debug check
if (pEdit && pEdit->IsKindOf(RUNTIME_CLASS(CEdit))) // standard check
{
// ....
}
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.
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