I have a CFormView Dialog with Buttons to send commands for a hardware I/O.
I the user accidentally click the enter key, the command is executed. (the last button one, that has the focus).
How do you solve this in the correct way?
The way ist to use PreTranslateMessage. CHeck for WM_KEYDOWN and VK_ENTER. Ignore it or do whatever you want.
Background: CFormView::PreTranslateMessage later calls PreTranslateInput and this finally calls IsDialogMessage and this functions translates the Enter key to execute the default dialog button.
Related
according to the MessageBox documentation:
Return value
Type: int
If a message box has a Cancel button, the function returns
the IDCANCEL value if either the ESC key is pressed or the Cancel
button is selected. If the messagebox has no Cancel button, pressing
ESC has no effect.
What if I wish to have a a box that has no Cancel button but I want to distinguish between OK and close/ESC?
MessageBox() does not support the behavior you are looking for. You would have to hook the dialog directly, using SetWindowsHookEx() or SetWinEventHook(), in order to detect it being closed.
Use TaskDialogIndirect() instead. It has a TDF_ALLOW_DIALOG_CANCELLATION flag:
Indicates that the dialog should be able to be closed using Alt-F4, Escape, and the title bar's close button even if no cancel button is specified in either the dwCommonButtons or pButtons members.
All of those conditions will return IDCANCEL.
What if I wish to have a a box that has no Cancel button but I want to distinguish between OK and close/ESC?
Standard dialogs don't offer such behaviour because it is very poor design. As a point of principle, a GUI should allow actions to be performed by mouse or keyboard. A hidden action only accessible by keyboard is a sign of poor design.
If you really want to make such a dialog, you'll have to implement it yourself. However, you should not. Present the dialog with OK and Cancel buttons.
I am new to QT GUI programming and I am using QT Creator. The problem I am seeing is with my pushbutton and line edit when the user presses the enter key. My program opens a groupbox and allows the user to enter a password and press ok or cancel.
If the user presses the enter key when the line edit has focus, the program seems to emit a second signal for QAbstractButton animateClick(); So when the next group box opens and prompts the user to press ok or cancel, the program continues as if the user pressed the ok button.
I set up my Push buttons to allow the user to press the tab key and hit the enter key. In order to obtain this functionality I set okbutton->setAutodefault(true); and cancelButton->setAutodefault(true);
I also have a lineEdit for the user to enter a password and press enter. I set this up by connecting the return pressed signal to the ok button shown below.
connect(lineEdit, SIGNAL(returnPressed()), okButton, SIGNAL(clicked()));
I also tried to connect return pressed signal directly to the slot but the problem still occurs.
connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(chkPassword()));
If the user clicks the okButton with the mouse or I set okButton->setAutoDefault(false); the program functions as it should. I would like to know if it is possible to disable the animateClick signal that occurs when the line edit has focus.
Any help with this would be greatly appreciated.
Try never connecting lineEdit with the okButton, i.e. comment out this line in your code:
connect(lineEdit, SIGNAL(returnPressed()), okButton, SIGNAL(clicked()));
and check if the program behaves as you want it to.
Also, you might want to call
okButton->setDefault(true);
in addition to your setAutoDefault() calls on both buttons, depending on what exactly you want to happen when the user presses Enter with various things in focus. See this answer for more information on this subject.
I assume, since you never mention it, that you do not call setDefault() for any of your buttons. Thus, okButton is your first button with the autoDefault property set to true. This means that okButton becomes the dialog's "button of choice" whenever the dialog has to handle an Enter keypress that did not happen on some other autoDefault button (such as cancelButton in your case).
Everytime any widget in your dialog receives an Enter keypress and does not consume the event itself, the event ends up being handled by the dialog's default-button handling logic, which results in a click on the aforementioned "button of choice".
QLineEdit is not used for multi-line editing, so it probably just does not consume the key press event for Enter (while still handling it, in that it sends outs the returnPressed() signal). Thus, your connection of returnPressed() ends up doing whatever it is doing, and, additionaly, the default-button logic ends up clicking your button a second time.
Also check out this thread on the Qt project forums which seems to solve the same problem differently.
Calling SendInput to simulate pressing down left click appears to be executed after code written below said call to SendInput is executed.
I made a listbox and I want right click to select items from the list box so I decided to make the message WM_CONTEXTMENU call SendInput to simulate a left click immediately before opening a context menu, but I believe the context menu is popping up before the left click occurs, resulting in the left click clicking the edge of the context menu (which does nothing).
Adding MessageBox(0,0,0,0); right in between the call to SendInput and the creation of the popup menu results in the left click successfully occurring and selecting an item, this is the behaviour I expected and desire. Strangely calling Sleep(1000) after the call to SendInput delays the program but doesn't cause the SendInput to behave as expected.
EDIT: Yes I know one solution to my problem is to select it using LB_SETSEL, but I'm partially doing this for learning purposes and if I run into a similar problem using SendInput I want to know how to solve it, so please help me resolve this specific bug.
SendInput() merely injects keystrokes into the keyboard's input buffer and then exits immediately, letting your app do other things while Windows handles the keystrokes in the background as if the user had typed them manually. That is not the solution to your problem.
In your WM_CONTEXTMENU handler, simply send a LB_SETCURSEL message (for a single-select ListBox) or a LB_SETSEL message (for a multi-select ListBox) directly to the ListBox's HWND to select the desired list item(s) before then displaying your popup menu.
I have a stack of images on which I want to perform some operations. After processing each image, my program should pop up a dialog to prompt the user if they want to proceed with the next image or to abort. Before that, they should have an opportunity to do some manual changes either on the images or on the parameters. Anyway, they must have access to the windows of the applications, while the execution of the method that called the dialog should be blocked until the dialog is closed.
I tried to solve this with a QMessageBox, but if I open it via exec(), it blocks the entire application, and if I use show(), the execution of the program goes on without waiting for user's reaction.
Is there a convenient way to block the calling method or function with a dialog but permit the user to interact with other windows?
Thanks in advance for any hint.
You should split your method that you want to block into two parts. In the end of first part you need to show your dialog without blocking and connect "Next" button (for example) of the dialog to the slot that must contains second part of your old method. This slot will be executed only when user presses the button.
It's the right way to do it in Qt. You need posibly to change your code logic to implement this.
Also, do you really need the second dialog? You can place "Next" button to your main widget. You can also create another modal dialog that will contain some settings and "Next" button.
I've written a Qt GUI which contains some QSpinBoxes and QDoubleSpinBoxes, among other stuff. Everything works as intended, except for one thing: when I enter a number into the QSpinBoxes and finish the entry by pressing the "Enter" key, this also activates the first widget in the tab order: i.e. instead of just changing the value of my spin box, I'm also pressing the button at the top of my dialog - which I don't want. How can I fix this? (Note that I need to press Enter for the new value to be accepted, because the spin boxes' keyboard tracking is deactivated.)
EDIT: In case someone comes across a similar problem: http://developer.qt.nokia.com/doc/qt-4.8/eventsandfilters.html
I think what might be happening is the default button of a QDialog is being pressed when you press Enter.
If you are subclassing QDialog yourself, then one of your QPushButtons has it's default property set to true. If you revert that to false, then the button will not react to the Enter key unless in focus. The disadvantage here, is that your dialog can't be dismissed by pressing Enter, if you want to stick with the default values for example.