Output Keyboard/Mouse Presses? - c++

In my program, I want to replicate the user pressing a key on the keyboard and mouse clicks.
Think about it like an auto-typer where the program types something in a word document over and over at various delays.
Any ideas on how to do this?
Thanks for your time.

I would suggest QTest namespace key and mouse simulation functions, e.g.
QTest::keyClick()
QTest::mouseClick()
You'll find documentation here

For simulating key presses you can use the QKeyEvent class which describes a key event and post that using QCoreApplication::postEvent.
QKeyEvent *event = new QKeyEvent ( QEvent::KeyPress, Qt::Key_Enter);
qApp->postEvent (receiver, event)
You can set the global position of the mouse by
QCursor::setPos(100,100);
Simulating the mouse events are like:
QMouseEvent * event = new QMouseEvent ((QEvent::MouseButtonPress), QPoint(500,500),
Qt::LeftButton,
Qt::LeftButton,
Qt::NoModifier );
qApp->postEvent((QObject*)this,(QEvent *)event);

Look at my answer in the next topic. Answer has a link to OS depended implementation of Keyboard / Mouse event generation. It can be helpful for you.

Related

Emulate a global keypress in Qt

I am building a Qt Application for a raspberry pi, which is connected to a rotary encoder. When the user presses the rotary encoder button, the application registers the hardware interrupt from the button and emits a signal which the application can intercept.
The challenge is that the application has multiple windows that can be displayed, and I would like to simply have a function which translates the button press signal into a global key press that can be registered by any active window in the application, without having to add extra logic to determine which window is active to send the key press directly to it. Is there a way to simulate a system-wide key press so that whatever window is in focus will get it?
So far, I have the following snippet of code, though it requires a reference to a specific QObject to direct the keypress to:
QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter);
QCoreApplication::postEvent (receiver, event);
where receiver is the object to direct the keypress too. Any ideas?
To broadcast a key event to all top-level widgets (i.e. windows):
for(auto w : qApp->allWidgets())
{
if(w->isTopLevel())
{
qApp->postEvent(w, new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));
}
}
To directly send the event to the active window (the foremost one):
qApp->postEvent(qApp->activeWindow(), new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier));

Windows c++ simulate click admin

I have a program in Qt5 Windows 10 where I simulate clicks (to help a friend with a disability with a special device). I use SendInput. The problem is that when I simulate a click to press a key on the Windows Virutal Keyboard (osk.exe), it does not work. In fact, it works but only if I run the program as administrator. However, I would like it to work even when the program is not run as admin.
Any suggestions ?
Qt has everything you need in order to simulate input, so you don't need to use SendInput
First, create a QMouseEvent and then call QCoreApplication::postEvent
The implementation would depend on what exactly you want to simulate, but your code would look something like this:
// Pos is the position of the click
QMouseEvent *me = new QMouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::postEvent(reciever, me); // Where reciever is a QObject handling the event
EDIT: Another snippet worth trying:
#include <windows.h>
QApplication::desktop()->cursor().setPos(globalX,globalY);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 1, 1, 0, 0);

Qt or any other lang. Event Loop

I'm a c++ programmer on Qt platform.
I'm wondering, how does the event loop "knows" to which widget to send an event, mainly mouse/keyboard events?
Is it done based on mouse coordinates and z-order?
What about events from keyboard?
Thanks
The event loop doesn't know. This is done in other bits of code.
The term you're looking for with the keyboard is "focus". Exactly one window has focus, systemwide (or at least one window per keyboard on multi-user systems). The OS delivers the keystrokes to that window. Qt just finds the Qt object from the native window handle. Similarly, mouse clicks are mostly handled by the OS.
It doesn't know.
When you want to capture an event, you must create an event filter that either captures the event, or allows it to be passed down.
Here's a very simple event filter that I created some time ago:
bool OGL_widget::eventFilter(QObject *obj, QEvent *event) {
switch (event->type()) {
case QEvent::KeyRelease:
case QEvent::KeyPress: {
QKeyEvent *key = static_cast<QKeyEvent*> (event);
if (!key->isAutoRepeat())
key_event_queue << *key;
}
break;
case 1001:
case 1002: {
Savestate_event *save = static_cast<Savestate_event*> (event);
save_event_queue << *save;
}
break;
}
return QObject::eventFilter(obj, event);
}
Take a look at this well written article of events at Qt docs.

Qt Key Event not behaving similar to keyboard

I am trying to programmatically send key board presses. This works for the tab key and others, but for the space it does not.
Code looks like this for Tab and Space:
QKeyEvent *event = new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
QCoreApplication::postEvent(this->viewer, event);
QKeyEvent *event = new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Space, Qt::NoModifier);
QCoreApplication::postEvent(this->viewer, event);
When I do the tab press programmatically it changes between buttons, but when I programmatically press space it does not press the button (it get greyed as it was pressed, but the screen does not change as it should). When i do press space on my keyboard the button gets pressed and the screen changes.
Any idea why the behavior is not the same?
The solution here was to send KeyRelease event after sending KeyPress event. As shown here:
QKeyEvent *event = new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Space, Qt::NoModifier);
QCoreApplication::postEvent(this->viewer, event);
QKeyEvent *event = new QKeyEvent(QKeyEvent::KeyRelease, Qt::Key_Space, Qt::NoModifier);
QCoreApplication::postEvent(this->viewer, event);

Qt: open context menu on mouse press

I'm trying to change the default behavior of context menus: Instead of opening on the release event of the right mouse button, I want it to open on the press event, and it's actions to be triggered on the release event). On one widget I could overload the mousePressEvent() and fire a custom contextmenu event, but I want it to be global to all the context menus of my program...
Any ideas?
Thanks.
I was trying to implement a widget base on top of QWidget with a custom way to handle context menu to suit your needs when I realize that using ActionsContextMenu policy with actions directly own by the widget does exactly the behavior you are expecting. (Qt 4.6.2 & 4.7 on linux, didn't try on windows yet but I don't know why the behavior should be different).
Is that a policy you can use ? If you don't really need external menus, I'll suggest to go with this solution.
Otherwise you will have to create your own widget base with a custom QMenu member. You should use the Qt::PreventContextMenu policy to guarantee the right click to end in the void mousePressEvent(QMouseEvent *event) of your widget. In this event handler make sure to show your menu. In your menu re-implement the void mouseReleaseEvent( QMouseEvent *event) if it don't trigger the current action do it your-self with the mouse position (in the event) and the QAction* actionAt( const QPoint & pt) const. But be careful the void mouseReleaseEvent( QMouseEvent *event) of the QMenu is already re-implemented from QWidget and may do some stuff you want to preserve !
EDIT
It's kind of sad but this behavior seems to be different by design on windows the void QMenu::mouseReleaseEvent(QMouseEvent *e) does the following:
Extracted form qmenu.cpp, Qt 4.6.2 sdk
#if defined(Q_WS_WIN)
//On Windows only context menus can be activated with the right button
if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
#endif
d->activateAction(action, QAction::Trigger);
I don't know what the topCausedWidget() does in life but it's kind of explicit that only left button release will trigger the current action ...
One simple solution for you will be to re-implement your QMenu with this line commented ...
Sounds like you need to create your own class based on QMenu, and use it for every context menu in your program.
Check here for a reference.