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);
Related
I am writing small c++ application using QT creator and i have a problem, I want to get selecting text from any application, I am using to this QClipboard library (SIGNAL(selectionChanged())), but it doesn't work properly admittedly i am getting selected text, but only after I release a mouse button. I would like to get selected text in "real time" without mouse button up. Is there any simple way to do it?
first you need to add this header file: QClipboard
then...
connect(qApp->clipboard, SIGNAL(selectionChanged), this, SLOT(your_slot()));
void your_slot() {
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(qApp->clipboard->text());
}
http://doc.qt.io/qt-5/qclipboard.html#selectionChanged
It looks like that is only supported well on X11, like Linux.
If you are interested in tracking mouse selections in your program in realtime, you can look directly at the mouse events or keyboard events, or the Rich Text Processing framework (QTextCursor).
You could also send a copy call while the mouse is down on a timer, and then look at the dataChanged signal.
Hope that helps.
I have a derived class for wxFrame (MyFrame) (for OSX - Yosemite platform), where it calls:
Bind(wxEVT_TASKBAR_RIGHT_DOWN), &HandleTaskBarEvent, this);
The issue is HandleTaskBarEvent is not being invoked when I right click the icon in the dock.
I see the generic right click menu that Mac has (Open at Login, Keep in Dock, etc) for the main icon in the dock.
Also, I created a wxTaskBarIcon. I am guessing this will be utilized for the minimized icon in the dock after the frame is minimized.
systemIcon = new wxTaskBarIcon(); //declared in header
systemIcon.Bind(wxEVT_TASKBAR_RIGHT_DOWN, &HandleTaskBarEvent, this);
Popup = new wxMenu(); //declared in header
QuitMenu = new wxMenuItem(Popup, wxID_ANY, wxString(wxT("Quit")), wxEmptyString, wxITEM_NORMAL); //declared in header
Popup->Append(QuitMenu)
Popup->Bind(wxEVT_COMMAND_MENU_SELECTED, &CloseFunc, this, QuitMenu->GetId());
This is inside the same derived class(MyFrame).
I call Iconize() inside that MyFrame same function, which works as expected. It minimized the window.
This is the HandleTaskBarEvent function (virtual)
void MyFrame::HandleTaskBarEvent(wxTaskBarIconEvent& event)
{
if(event.GetEventType() == wxEVT_TASKBAR_RIGHT_DOWN)
{
systemIcon->PopupMenu(Popup);
}
}
I saw this post : Mouse Events of WxPython TaskBarIcon on Mac OSX are not triggering
and there seems to be a bug about it. But I am not able to find that bug or its status online. It is mentioned that the issue is with wxPython, but seems related to my problem.
Also I created a derived class for wxTaskBarIcon and overrode CreatePopupMenu and made systemIcon as an instance of MyTaskBarIcon, but that function is not being triggered for any clicks(left,right, etc). Also the main wxFrame 's Bind callback (HandleTaskBarEvent) is not being triggered, hence the systemIcon is not being able to popup the menu.
I am not using mouse for my Mac (using trackpad instead). Not sure if it should make any difference to right click code, but adding the information here anyways.
So I am thinking this could be wxWidget-OSX specific issue, because the code works on Windows as expected.
Does anyone know if this is purely wxWidget-OSX incomplete feature, if there is any open bugs about it, and more importantly if there is any solution to show the popup menu items for the minimized icon in the dock, and to handle the click events for the menu.
Thanks in advance.
This is a limitation of the OS X wxTaskBarIcon implementation. See wxTaskBarIcon on OSX - two-finger click does not send mouse event and related/linked issues.
The only way I know of (on OS X) is overriding wxTaskBarIcon::CreatePopupMenu().
You should be able to have something like:
MyApp::wxApp/
MyTaskBarIcon::wxTaskBarIcon (override CreatePopupMenu(), return a new wxMenu)
This is the model I use in a few applications and it works the same on Windows and OS X (albeit no specific click handlers as mentioned).
I want to create a onscreen keyboard for a desktop application. The application will be built in Qt 5. I have couple of questions, please clarify them.
What is the replacement of QInputContext in Qt5? (Because I read somewhere about onscreen keybord by implementing QInputContext but this is not supported by Qt 5.)
Where can I find QPlatformInputContext and QInputPanel (on an internet search I found these two as alternatives of QInputContext but not sure about that and also I was unable to find them)?
My requirements:
Keyboard will not use QML or any external library (already build other keyboards).
Keyboard will use Qt Gui (traditional).
I understand there are two challenges you would have:
Getting notified as to when to show/hide the on-screen keyboard, based on the focus being on text widgets
How to post key-press event to the text widgets
ANSWER
As for the former, you could use QObject::InstallEventFilter() on widgets that you want to provide the keyboard service to. You can then look for the mouseReleaseEvent along the lines of the Qt code in the link.
This can be achieved by using QCoreApplication::postEvent()
As for QPlatformInputContext, get the example of a Qt Virtual Keyboard here.
I took me quite a while to find out how to do this in QT5 without qml and too much work. So thought I'd share:
#include <QCoreApplication>
#include <QGuiApplication>
#include <QKeyEvent>
void MainWindow::on_pushButton_clicked()
{
Qt::Key key = Qt::Key_1;;
QKeyEvent pressEvent = QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, QKeySequence(key).toString());
QKeyEvent releaseEvent = QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &pressEvent);
QCoreApplication::sendEvent(QGuiApplication::focusObject(), &releaseEvent);
}
The clue here is that by clicking buttons (if you would manually make your keyboard), launches a sendevent to the current object thas has focus (for example a textbox). You could of course hardcode a textbox, but that only works if you have only a single input to use your keyboard for.
The last thing you have to make sure, is to set the focusPolicy of your keyboard buttons to NoFocus, to prevent focus from shifting when the keyboard is pressed.
Credits go to https://www.wisol.ch/w/articles/2015-07-26-virtual-keyboard-qt/
Hope this helps someone.
A good example is given in here http://tolszak-dev.blogspot.com.tr/2013/04/qplatforminputcontext-and-virtual.html
uses Qt Quick for on screen keyboard.
You can check it.
I just got this working in my awesome Qt app. Here is how I did it.
For Android and iOS:
QObject::connect(lineEdit, SIGNAL(returnPressed()), qApp->inputMethod(), SLOT(hide()));
For iOS:
Subclass QLineEdit and add the following:
void focusOutEvent(QFocusEvent * fe)
{
QLineEdit::focusOutEvent(fe);
#ifdef Q_OS_IOS
if(fe->reason() == Qt::OtherFocusReason)
{
// Done was pressed!
emit returnPressed();
}
#endif
}
Btw, the QInputMethod docs don't say much about how to access it from c++. You have to get an instance from QGuiApplication, like I did above.
Hope that helps.
Qt now provides a virtual keyboard framework in Qt 5.5.
http://doc.qt.io/QtVirtualKeyboard/
I have not tried it, so I can't say how easy it is to use. It looks like it's QML-based.
(It says it's for Linux and boot2qt, but it can also be built for Windows according to the building page (http://doc.qt.io/QtVirtualKeyboard/build.html))
my question is how to send some key's to any application from application that is running in background? Let's say that I made shortcut to LEFT ARROW key which is ALT+S, and than I want whenever I'm in any application and when I press ALT+S that background application response that shortcut and send to currently opened program LEFT ARROW key.
Here is a code that I made in Embarcadero c++ 2010 to simulate arrow left when pressing alt+s every 200 milisecond's:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
bool bBothPressed = GetAsyncKeyState(VK_MENU) && GetAsyncKeyState(0x53);
if(bBothPressed){
// ShowMessage("control!");
keybd_event(VK_LEFT, 0, 0, 0);
}
}
... and this work fine for my application, but what I want to know is how to include that code for global scope (any application), not just for this application.
I strongly encourage you to use RegisterHotKey instead of GetAsyncKeyState. That way you won't need a loop nor a Timer, thus making your application more reliable and responsive.
To simulate the keypresses to another application/window, you need to:
A) Focus the specific window:
BringWindowToTop(hwnd);
SetForegroundWindow(hwnd);
SetFocus(hwnd);
B) Send the keydown + keyup events:
keybd_event(keycode, 0, KEYEVENTF_KEYDOWN, 0);
keybd_event(keycode, 0, KEYEVENTF_KEYUP, 0);
This should suffice. However, keep in mind the user might be already pressing one of the keys you're simulating, thus the result might not be what you're expecting. To avoid that, you need to check if the keys are already being pressed (use GetAsyncKeyState here), then send a keyup before doing B.
UPDATE:
If you wish to send the keypresses to whatever application is currently on the foreground (being focused), you can skip A.
SendInput() looks like it may be useful to you.
I need to determine when my Qt 4.4.1 application receives focus.
I have come up with 2 possible solutions, but they both don’t work exactly as I would like.
In the first possible solution, I connect the focusChanged() signal from qApp to a SLOT. In the slot I check the ‘old’ pointer. If it ‘0’, then I know we’ve switched to this application, and I do what I want. This seems to be the most reliable method of getting the application to detect focus in of the two solutions presented here, but suffers from the problem described below.
In the second possible solution, I overrode the ‘focusInEvent()’ routine, and do what I want if the reason is ‘ActiveWindowFocusReason’.
In both of these solutions, the code is executed at times when I don’t want it to be.
For example, I have this code that overrides the focusInEvent() routine:
void
ApplicationWindow::focusInEvent( QFocusEvent* p_event )
{
Qt::FocusReason reason = p_event->reason();
if( reason == Qt::ActiveWindowFocusReason &&
hasNewUpstreamData() )
{
switch( QMessageBox::warning( this, "New Upstream Data Found!",
"New upstream data exists!\n"
"Do you want to refresh this simulation?",
"&Yes", "&No", 0, 0, 1 ) )
{
case 0: // Yes
refreshSimulation();
break;
case 1: // No
break;
}
}
}
When this gets executed, the QMessageBox dialog appears. However, when the dialog is dismissed by pressing either ‘yes’ or ‘no’, this function immediately gets called again because I suppose the focus changed back to the application window at that point with the ActiveWindowFocusReason. Obviously I don’t want this to happen.
Likewise, if the user is using the application opening & closing dialogs and windows etc, I don’t want this routine to activate. NOTE: I’m not sure of the circumstances when this routine is activated though since I’ve tried a bit, and it doesn’t happen for all windows & dialogs, though it does happen at least for the one shown in the sample code.
I only want it to activate if the application is focussed on from outside of this application, not when the main window is focussed in from other dialog windows.
Is this possible? How can this be done?
Thanks for any information, since this is very important for our application to do.
Raymond.
I think you need to track the QEvent::ApplicationActivate event.
You can put an event filter on your QApplication instance and then look for it.
bool
ApplicationWindow::eventFilter( QObject * watched, QEvent * event )
{
if ( watched != qApp )
goto finished;
if ( event->type() != QEvent::ApplicationActivate )
goto finished;
// Invariant: we are now looking at an application activate event for
// the application object
if ( !hasNewUpstreamData() )
goto finished;
QMessageBox::StandardButton response =
QMessageBox::warning( this, "New Upstream Data Found!",
"New upstream data exists!\n"
"Do you want to refresh this simulation?",
QMessageBox::Yes | QMessageBox::No) );
if ( response == QMessageBox::Yes )
refreshSimulation();
finished:
return <The-Superclass-here>::eventFilter( watched, event );
}
ApplicationWindow::ApplicationWindow(...)
{
if (qApp)
qApp->installEventFilter( this );
...
}
When your dialog is open, keyboard events don't go to your main window. After the dialog is closed, they do. That's a focus change. If you want to ignore the case where the focus switched from another window in your application, then you need to know when any window in your application has the focus. Make a variable and add a little more logic to your function. This will take some care, as the dialog will lose focus just before the main window gains focus.
Looking at the Qt docs it seems that focus events are created each time a widget gets the focus, so the sample code you posted won't work for the reasons you stated.
I am guessing that QApplication::focusedChanged does not work the way you want because some widgets don't accept keyboard events so also return null as the "old" widget even when changing focus within the same app.
I am wondering whether you can do anything with QApplication::activeWindow()
Returns the application top-level window that has the keyboard input focus, or 0 if no application window has the focus. Note that there might be an activeWindow() even if there is no focusWidget(), for example if no widget in that window accepts key events.