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
Related
I am trying to implement default Emacs shortcuts supported by macOS.
Example of the code:
void InputField::keyPressEventInner(QKeyEvent *e) {
if(e->modifiers().testFlag(Qt::MetaModifier) && e->key() == Qt::Key_A) {
// Does not work
}
I've tried to use QGuiApplication::keyboardModifiers():
if(QGuiApplication::keyboardModifiers().testFlag(Qt::MetaModifier) && e->key() == Qt::Key_A) {
// does not work
}
QKeyEvent::nativeModifiers() always returns 0 when a modifier key is pressed.
Note: I use MetaModifier because according to the official documentation:
On macOS, the ControlModifier value corresponds to the Command keys on the keyboard, and the MetaModifier value corresponds to the Control keys.
How do I catch the Control key?
Qt 5.12.8
XCode 11.7
Update:
I can catch either Ctrl or a:
if(e->modifiers() & Qt::MetaModifier))
or
if(e->key() == Qt::Key_A)
Like this, I wanna print the shortcut text.
But I don't wanna use code like this :
this->newAction->setShortcut(QKeySequence::New);
Because I handle shortcuts by using my KeyAction classes.
If I use setShortcut(), my KeyAction classes is ignored.
Is there any solution for only printing shortcut text?
Or Do I have to set text like "새 파일(&N)\t\tCtrl + N" ?
I wanna print text aligned.
Thanks for your help.
Answer based on the comments of TFry.
Set the shortcut as usual (using QAction::setShortcut).
To prevent triggering the action and to stop the event-propagation when the shortcut is pressed, you must accept all ShortcutOverride-events in the top-level window (i.e., MainWindow, usually):
MainWindow::MainWindow(...)
{
installEventFilter(this);
}
bool MainWindow::eventFilter(QObject* o, QEvent* e)
{
if (o == this && e->type() == QEvent::ShortcutOverride) {
e->accept();
}
return QMainWindow::eventFilter(o, e);
}
I'm stuck: How do I prevent the virtual Shift key from being considered during accelerator translation? For instance, if my accelerator table contains a single entry of Ctrl+A (to select everything in currently focused window, say), then I would want the corresponding command be detected when Ctrl+A is pressed as well as if Ctrl+Shift+A is pressed (but contrary, I still want the Alt key to play its role, so Ctrl+Shift+A shound't translate to my command).
This post didn't help. I think I'm calling the TranslateAccelerator function while I'm still in the message loop (see code below and correct me if I'm wrong).
I tried to outsmart Windows by getting the current keyboard status when I see a WM_KEYDOWN message, manually change the virtual Shift key status to "not pressed," do the accelerator translation, and revert my manual modifications. In code:
BOOL CHexaEditor::PreTranslateMessage(PMSG pMsg){
// pre-processing the Message
if (::GetFocus()==m_hWnd){ // I'm not sure if this is mandatory in MFC
if (pMsg->message==WM_KEYDOWN){
BYTE keyboardState[256];
::GetKeyboardState(keyboardState);
const BYTE shiftState0=keyboardState[VK_SHIFT];
keyboardState[VK_SHIFT]=0; // 0 = "not pressed"
const BOOL result=::TranslateAccelerator(m_hWnd,hDefaultAccelerators,pMsg);
keyboardState[VK_SHIFT]=shiftState0;
::SetKeyboardState(keyboardState);
return result;
}else
return ::TranslateAccelerator(m_hWnd,hDefaultAccelerators,pMsg);
}else
return FALSE;
}
No success so far, any help highly appreciated. Thanks :-)
So the correct answer is (thanks to ybungalobill above):
BOOL CHexaEditor::PreTranslateMessage(PMSG pMsg){
// pre-processing the Message
if (::GetFocus()==m_hWnd){
if (pMsg->message==WM_KEYDOWN){
BYTE keyboardState[256];
::GetKeyboardState(keyboardState);
const BYTE shiftState0=keyboardState[VK_SHIFT];
keyboardState[VK_SHIFT]=0;
/* --> */ ::SetKeyboardState(keyboardState); // this line was missing
const BOOL result=::TranslateAccelerator(m_hWnd,hDefaultAccelerators,pMsg);
keyboardState[VK_SHIFT]=shiftState0;
::SetKeyboardState(keyboardState);
return result;
}else
return ::TranslateAccelerator(m_hWnd,hDefaultAccelerators,pMsg);
}else
return FALSE;
}
I am currently dealing with a multi-form application and am having issue registering a del key press, the application that requires the del key is a form with a frame on it with objects painted on it that can be selected, upon pressing the del key the selected objects are to be deleted via a deleteObjects method. The code I am currently using is as follows
void __fastcall TF_Image::KeyUpKbd( WORD &Key )
{
if(Key == VK_DELETE || Key == VK_DKEY)
{
deleteSelectedObjects();
}
}
(Note: There are other paramenters in the function call but they aren't used)
TF_Image inherits from TFrame
I have tried mapping other keys other than the del key ie the D key and have found that the method is called with no problem. I have discovered that when pressing (physically) the del key the methods associated with KeyUp & KeyDown are not called.
Edit: So i've attempted to add the DeleteSelectedOb() method to my WndProc method without much luck either.
void __fastcall TF_ImgBrowserOA::WndProc(TMessage &Message)
{
if (Message.Msg == WM_KEYDOWN)
{
if (Message.WParam == VK_DELETE)
{
F_Image->DeleteSelectedOb();
}
}
//code that manages window resize
TForm::WndProc(Message);
}
The WndProc method doent appear to respond to keystrokes
So after cleaning up some code in some other modules and removing unneccessary menu's I decided to go back and look at this section again after I found a similar piece of code implementing a similar function, I couldn't see much difference between them and so I recompiled and attempted to run my Delete function from the KeyDown event and for some reason it just worked, I suspect it came down to an issue of another element holding focus in the Application. As a precaution I also called a SetFocus() to the frame in which I required this code to operate in. Its still a mystery to me why this didn't work intially though.
Here is a snippet for my TRichEdit control (Script_Edit).
TWndMethod *PrevWndProc = Script_Edit->WindowProc;
Script_Edit->WindowProc = MyWndProc;
void __fastcall My_Form::MyWndProc(TMessage &Message) {
switch (Message.Msg) {
case WM_KEYDOWN: {
// Check for DELETE and BACKSPACE keys
if( Message.WParam == VK_BACK ||
Message.WParam == VK_DELETE
) {
// Do whatever you need
}
break;
default:
// call default handler if not processed
PrevWndProc(Message);
}
}
You can't get much closer to the message core than this with VCL...
I am trying to understand how to handle various events with Qt and have found an issue I cannot understand with key modifiers e.g. Ctrl Shift Alt etc. I have made a default Qt GUI Application in Qt Creator extending QMainWindow and have found that the following example does not produce understandable results.
void MainWindow::keyPressEvent(QKeyEvent *event)
{
qDebug() << "Modifier " << event->modifiers().testFlag(Qt::ControlModifier);
qDebug() << "Key " << event->key();
qDebug() << "Brute force " << (event->key() == Qt::Key_Control);
}
Using the modifiers() function on the event never is true while the brute force method returns the correct value.
What have I done wrong?
Try using this to check for shift:
if(event->modifiers() & Qt::ShiftModifier){...}
this to check for control:
if(event->modifiers() & Qt::ControlModifier){...}
and so on. That works well for me.
EDIT:
To get the modifiers of a wheel event, you need to check the QWheelEvent object passed to your wheelEvent() method:
void MainWindow::wheelEvent( QWheelEvent *wheelEvent )
{
if( wheelEvent->modifiers() & Qt::ShiftModifier )
{
// do something awesome
}
else if( wheelEvent->modifiers() & Qt::ControlModifier )
{
// do something even awesomer!
}
}
According to the documentation, QKeyEvent::modifiers cannot always be trusted. Try to use QApplication::keyboardModifiers() static function instead.
From Qt 5 Doc. – Qt::KeyboardModifiers QKeyEvent::modifiers() const:
Warning: This function cannot always be trusted. The user can confuse it by pressing both Shift keys simultaneously and releasing one of them, for example.