How to capture Ctrl+Plus in Qt? - c++

How can I capture Ctrl++ in QWidget::keyPressEvent?
This is my current code (simplified):
void foo::keyPressEvent(QKeyEvent *event)
{
if (event->modifiers() == Qt::ControlModifier)
{
switch (event->key())
{
case Qt::Key_Plus:
// do something
break;
}
}
}
Which works, but only for + on the alphanumeric part of the keyboard. When I press Ctrl++ on the numeric keypad, it doesn't do anything.
Thank you

After some debugging I found out that when a key is pressed on the numeric keypad, the Qt::KeypadModifier is added to event modifiers. So the simple solution is to add this to the if statement:
if (event->modifiers() == (Qt::ControlModifier | Qt::KeypadModifiers))
{
// ...

Related

Changing the enabling to disabling content by giving condition to combo box

I have a certain selection in combo box. Based on that selection some items need to be enabled/disabled. However I am unable to do so. And also another problem is once a single option is selected I cant change it to another selection without backspace and typing that selection again.
m_d_lvlayers is the variable of IDC of combo box. Its type is CString.
void CThermalToolDlg::OnCbnSelchangeLvLayers()
{
// TODO: Add your control notification handler code here
if (m_d_lvlayers == "2" )
{
UpdateData();
GetDlgItem(IDC_LV3_CU)->EnableWindow(0);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(0);
//etc etc
UpdateData(0);
}
else if (m_d_lvlayers == "3")
{
UpdateData();
GetDlgItem(IDC_LV3_CU)->EnableWindow(1);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(1);
//etc etc
UpdateData(0);
}
else
{
UpdateData();
GetDlgItem(IDC_LV3_CU)->EnableWindow(1);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(1);
//etc etc
UpdateData(0);
}
}
I expect to get proper selections in combobox and corresponding enabling and disabling.
You need to call UpdateData(TRUE); first.
bSaveAndValidate
Flag that indicates whether dialog box is being initialized (FALSE) or data is being retrieved (TRUE)
void CThermalToolDlg::OnCbnSelchangeLvLayers()
{
UpdateData(TRUE); // Controls to Variables
if (m_d_lvlayers == "2" )
{
GetDlgItem(IDC_LV3_CU)->EnableWindow(FALSE);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(FALSE);
//etc etc
UpdateData(FALSE);
}
else if (m_d_lvlayers == "3")
{
GetDlgItem(IDC_LV3_CU)->EnableWindow(TRUE);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(TRUE);
//etc etc
UpdateData(FALSE);
}
else
{
GetDlgItem(IDC_LV3_CU)->EnableWindow(TRUE);
GetDlgItem(IDC_LV3_ICI)->EnableWindow(TRUE);
//etc etc
UpdateData(FALSE);
}
}
Although in your code it makes no sense to call UpdateData(FALSE); because all you are doing is setting the control window state to enabled.

Qt catch shift + 3 on one key press

I'm using Qt 5.11.
I need to catch shift + 3 on one key press. But this combination generates special character ^ because I'm using Turkish Q Keyboard. So I can't catch it without press shift + 3 again.
I tried shift modifiers and multiple key press solutions but not working.
I want to override ^. Is there any possible ways to do it?
Try the following it could work. Although according to the documentation, nativeVirtualKey could return 0 even if there is valid information. So not sure if it will work all the time. I tested it with a german, english and arabic keyboard.
Update (tested it with turkish keyboard layout)
void keyPressEvent(QKeyEvent *ev)
{
if ((ev->nativeVirtualKey() == Qt::Key_3 || ev->key() == Qt::Key_3) && ev->modifiers() == Qt::ShiftModifier)
{
//Do something
}
}
For turkish layout, ^ caret (a dead key), in addition to the above, you can catch the dead key press by overriding the nativeEvent function and calling the keyEvent function manually
bool nativeEvent(const QByteArray & eventType, void * message, long * result)
{
MSG *msg = reinterpret_cast<MSG*>(message);
if (msg->message == WM_DEADCHAR)
{
QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, Qt::Key_3, Qt::ShiftModifier);
}
}
One minor issue, the keyEvent will be called even if ^ is pressed in another language, not necessarily only with Shift+3, so this is an unexpected behaviour, but maybe for your case you can tell the user that both shift+3 or ^ are the shortcut for your specific function

How to check if a key sequence is press?

I would like to check if a key sequence is press. Like a password, i would like that to see the message box you must type "bcqwl" in right sequenze. I tried
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
while(true)
{
if(GetKeyState('B') & 0x8000)
{
cout<<"b has been press"<<endl;
if(GetKeyState('C') & 0x8000)
{
cout<<"c has been press"<<endl;
if(GetKeyState('Q') & 0x8000)
{
cout<<"Q has been press"<<endl;
if(GetKeyState('W') & 0x8000)
{
cout<<"W has been press"<<endl;
if(GetKeyState('L') & 0x8000)
{
MessageBox(NULL,"YES","YES",MB_OK);
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
}
But it doesn't works. He print "B has been press" ,many times but not infinitely times,if b is pressed. If after to press b I press c nothing happens.
So i tired:
step:
if(GetKeyState('B') & 0x8000)
{
cout<<"B has been press"<<endl;
goto step1;
}
else
{
goto step;
}
step1:
if(GetKeyState('C') & 0x8000)
{
MessageBox(NULL,"WORK","yes",MB_OK);
}
else
{
goto step;
}
But doesn't work.
I also tired:
#include <iostream>
#include <windows.h>
int main()
{
int progress = 0;
while(progress<=4)
{
if(GetKeyState('B') & 0x8000)
{
std::cout<<"b has been press"<<std::endl;
progress=1;
}
else
{
progress=0;
}
if(progress==1)
{
if(GetKeyState('C') & 0x8000)
{
std::cout<<"c has been press"<<std::endl;
progress=2;
}
else
{
progress=0;
}
}
if(progress==2)
{
if(GetKeyState('Q') & 0x8000)
{
std::cout<<"q has been press"<<std::endl;
progress=3;
}
else
{
progress=0;
}
}
if(progress==3)
{
if(GetKeyState('W') & 0x8000)
{
std::cout<<"w has been press"<<std::endl;
progress=4;
}
else
{
progress=0;
}
}
if(progress==4)
{
if(GetKeyState('L') & 0x8000)
{
std::cout<<"l has been press"<<std::endl;
progress=5;
}
else
{
progress=0;
}
}
}
return 0;
}
But that output "b has been press" for many times but not infinitely if i press b, and after if i press c nothing is happening, praticaly after press b and the program go in if(process==1) but if i press c nothing happen
P.S. sorry for my bad english.
The problem you are still having comes from the fact that you are in no way storing the progress in your key sequence.
Let's say your password is stored in a char array (for easier access to the single characters later on):
#define PWD_LEN 6 // bcqwl has a length of 5 characters but you need +1 for the '\0' (terminating character) at the end of your string
// ...
char password[PWD_LEN] = "bcqwl";
In addition you will need a counter:
#define PWD_LEN 5
// ...
char password[PWD_LEN] = "bcqwl";
int progress = 0;
while(true) { ... }
Both need to be stored before and outside the while loop because both store data that you don't want to reset in each iteration step in your loop.
The counter will be used to track the progress of the user towards completing the key sequence your password represents.
Whenever the user presses a key you will need to do the following checks:
Is the key allowed? - if you have a password abc but the user presses y or !, or something other then a, b or c the key is not allowed.
If the key is allowed take the character it represents and check if it's the same as the character in your password at index progress:
if ( key allowed )
{
if (password[progress] == '<your key character here>')
{
++progress;
}
else
{
// Handle incorrect key stroke relative to key sequence
}
}
Now in order to prevent the counter going bananas I would suggest doing all the checking upon key released, which unlike key pressed is a one time event. A key being pressed can also be part of key hold, in which case you will land in the else (from the code snippet above) many times, which might not be such a good idea.
If the key is ok and in terms of sequence it fits your password then you increase the progress so that in the next iteration step you can do the same check with a new released key event and a new index value for accessing your password array.
When your progress reaches the required value indicating that the key sequence is completed and that all the characters your password consists of have been "inserted" you can break the loop.
This is very basic so I hope that the instructions are clear enough for you to implement.
PREVIOUS ANSWER (now obsolete due to change in the question)
Unless other out-of-the-box way is available to do that (I haven't used GetKeyState() or anything else from windows.h) the general practice is to simply store the pressed state of each button (in an array, a struct etc.).
In your loop you can use a simple chain of if statements (but not nested like you do it!) to check which button is pressed during the current iteration step. Whenever a known key (one that you application wants to process) is pressed, you just need to toggle the respective state of that button in your array, struct or whatever other container you use to store this information:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
}
At the end or beginning of your while's body you can then ask for the state of each button and also make combined queries:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
// Do something
// Check for states of buttons
// ...
}
For example let's say you are using the following structure to store the key's state:
typedef struct Key
{
char keyCode;
bool pressed;
} Key;
Key keyA;
keyA.pressed = false;
you can simply do
if (keyA.pressed)
{
// Trigger some change that key 'A' controls
}
to check if your specific button is currently pressed and respectively trigger some action.
For key combinations things are not much different. You just need to use simply boolean logic to handle it:
if (keyA.pressed && keyB.pressed)
{
// Both key 'A' and 'B' are pressed - we have a key combo!
}
You can improve the readability of your code by storing all supported buttons in an array and even adding a nice enum to provide easy access to each button:
enum KeyCode
{
A,
B,
...
};
Key keys[n]; //with n being the number of keys you want to support and also the number of elements your enum has
// Access with an improved readability
if (keys[A].pressed && keys[B].pressed)
{
// ...
}
If you can't find any code for GetKeyState() in particular (highly unlikely) you can look at SDL for example.

Qt - know whether a pressed key is just a modifier

I'd like the child's handling of QKeyEvent not to be executed when it's just a modifier key that's being pressed. The following code does the job, but it's unwieldy to list them all like that. Is there a built-in way to do that?
void TextEditor::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Shift:
case Qt::Key_Control:
case Qt::Key_Alt:
case Qt::Key_Meta:
case Qt::Key_Mode_switch:
return QPlainTextEdit::keyPressEvent(event);
}
// handle the event...
}
You can use this QKeyEvent::modifiers() member for this purpose. If the result is
const bool isModifier = ( event->modifiers() != Qt::NoModifier );
true then the pressed key was a modifier.
So for you code it means the following modifications.
void TextEditor::keyPressEvent( QKeyEvent* event )
{
if ( event->modifiers() != Qt::NoModifier )
{
return QPlainTextEdit::keyPressEvent(event);
}
// Handle the event ...
}
Or if you want to handle some special key combination why not just use this way:
void TextEditor::keyPressEvent( QKeyEvent* aKeyEvent )
{
if ( aKeyEvent->matches( QKeySequence::Copy ) )
{
// Your copy stuff ...
return;
}
// else if ( aKeyEvent->matches( ... ) ) // Other key combinations ...
return QPlainTextEdit::keyPressEvent( aKeyEvent);
}
a better way to do this in 3 lines:
if(event->modifiers()){
event->ignore(); // or don't ignore and handle the event
// switching the modifiers
}
this is the modifiers defined by qt:
Qt::NoModifier
Qt::ShiftModifier
Qt::ControlModifier
Qt::AltModifier
Qt::MetaModifier
Qt::KeypadModifier
Qt::GroupSwitchModifier
you can do a switch for filtering.

How to make keyword to work instantly with no delay in Qt::4.6 (C++)?

OS:: win xp sp3.
Qt:: 4.6
I have class Gameboard in which i have some rectangle.I defined keyPressEvent for that rectangle in order to move him around the screen.Key_A :: rectangle.moveToLeft & Key_D :: rectangle.moveToRight.Problem is that keys work with delay.
When i release one key and press another one it takes some time before that one begin to work.I checked Qt online documentation and now for that effect but dont now how to make those keys to work instantly without delay beetween them?
code snippet:
//in Gameboard class
ship = new QRect(x,y,w,h);
void Gameboard::keyPressEvent(QKeyEvent* event)
{
switch(event->key()) {
case Qt::Key_A :
{
x = x-10;
ship->moveTo(x,y);
break;
}
case Qt::Key_D :
{
x = x+10;
ship->moveTo(x,y);
break;
}
}
}
Put input cursor into any applicable text box and press the 'A' key. What you'll see is once you press the key, letter 'A' will be printed, then there will be a pause, and then first letter 'A' will be quickly followed by many others. That's the way keypress events work. And your program is receiving them exactly like this. First you receive one event when the key is actually pressed, and then after a delay you get a lot of automatically repeated events, in case user wants to enter one character many-many times.
It works perfectly for text input, but in games you usually need smooth movement. If that's the case, you need to move your ship not upon receiving the event, but regularly, for example, on timer event. And you will need to catch both keyPressEvent and keyRelease event and use them to remember what movement keys are currently pressed. So you could for example do this:
struct Ship {
bool is_moving_left, is_moving_right;
QPoint position;
int speed;
...
void timerEvent()
{
if (is_moving_left) position.setX (position.x() - speed);
if (is_moving_right) position.setX (position.x() + speed);
}
...
};
...
void Gameboard::keyPressEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = true;
break;
case Qt::Key_D :
ship->is_moving_right = true;
break;
}
}
...
void Gameboard::keyReleaseEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = false;
break;
case Qt::Key_D :
ship->is_moving_right = false;
break;
}
}
Then just make sure Ship::timerEvent() gets called on every timer event in the game.