How to simulate user input to a native QFileDialog in Windows?
-
In Windows, I need to simulate user input to a
QFileDialogfor opening a file. More specifically, I need to:- enter the name of the file to open
- accept the dialog
The
QFileDialogwas opened in native mode (which is the default on Windows), something which I can't change.findChildren<QWidget*>()returns an empty list on such a native dialog, so I can't programmatically sendQKeyEvent's to aQLineEdit(in order to simulate entry of the file name), or send aQMouseEventto the "Open" button (in order to simulate acceptance of the dialog).I tried the following:
fileDialog->selectFile("C:/foo/bar.txt"); // (1) static_cast<QDialog*>(fileDialog)->accept(); // (2)Note about (2): This weird cast is necessary, because
QDialog::accept()is public, butQFileDialog::accept()is protected. Sinceaccept()is virtual, (2) callsQFileDialog::accept(), as intended.After (1), I can see
C:/foo/bar.txtentered in the edit field of the dialog.(2), however, does not work: the dialog remains open. When debugging into
QFileDialog::accept(), I can see the reason ofaccept()'s failure: the call toQFileDialog::selectedUrls()(qfiledialog.cpp, line2700) returns an empty list. This, in turn, is due to the fact thatQFileDialogPrivate::userSelectedFiles()(qfiledialog.cpp, line1216) also returns an empty list.So, is there a way to do that with the Qt API, or should I dive into the (ugly!) Windows API?
My environment: Windows 10, Visual Studio 2017, Qt 6.1
-
@dave2
Synthesizing Qt key and mouse events with a native file dialog will not work, I am afraid. The native dialog doesn't know about Qt.You can either send Qt events to a non-native dialog, as proposed by @mpergand. Or you dive into the Windows API to simulate what needs to be simulated.
-
In Windows, I need to simulate user input to a
QFileDialogfor opening a file. More specifically, I need to:- enter the name of the file to open
- accept the dialog
The
QFileDialogwas opened in native mode (which is the default on Windows), something which I can't change.findChildren<QWidget*>()returns an empty list on such a native dialog, so I can't programmatically sendQKeyEvent's to aQLineEdit(in order to simulate entry of the file name), or send aQMouseEventto the "Open" button (in order to simulate acceptance of the dialog).I tried the following:
fileDialog->selectFile("C:/foo/bar.txt"); // (1) static_cast<QDialog*>(fileDialog)->accept(); // (2)Note about (2): This weird cast is necessary, because
QDialog::accept()is public, butQFileDialog::accept()is protected. Sinceaccept()is virtual, (2) callsQFileDialog::accept(), as intended.After (1), I can see
C:/foo/bar.txtentered in the edit field of the dialog.(2), however, does not work: the dialog remains open. When debugging into
QFileDialog::accept(), I can see the reason ofaccept()'s failure: the call toQFileDialog::selectedUrls()(qfiledialog.cpp, line2700) returns an empty list. This, in turn, is due to the fact thatQFileDialogPrivate::userSelectedFiles()(qfiledialog.cpp, line1216) also returns an empty list.So, is there a way to do that with the Qt API, or should I dive into the (ugly!) Windows API?
My environment: Windows 10, Visual Studio 2017, Qt 6.1
@dave2
Seems to work with non native dialog:QApplication app(argc, argv); QFileDialog fileDialog; fileDialog.setOption(QFileDialog::DontUseNativeDialog); fileDialog.selectFile( your file ); fileDialog.show(); QTimer::singleShot(2000, [&fileDialog]() { QKeyEvent press(QEvent::KeyPress, Qt::Key_Return,0); qApp->sendEvent(&fileDialog,&press); QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return,0); // seems optional qApp->sendEvent(&fileDialog,&release); qDebug()<<fileDialog.selectedFiles(); }); -
Hi,
Can you explain your use case ? Are you implementing tests ?
-
@dave2
Synthesizing Qt key and mouse events with a native file dialog will not work, I am afraid. The native dialog doesn't know about Qt.You can either send Qt events to a non-native dialog, as proposed by @mpergand. Or you dive into the Windows API to simulate what needs to be simulated.
-
@dave2
Seems to work with non native dialog:QApplication app(argc, argv); QFileDialog fileDialog; fileDialog.setOption(QFileDialog::DontUseNativeDialog); fileDialog.selectFile( your file ); fileDialog.show(); QTimer::singleShot(2000, [&fileDialog]() { QKeyEvent press(QEvent::KeyPress, Qt::Key_Return,0); qApp->sendEvent(&fileDialog,&press); QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return,0); // seems optional qApp->sendEvent(&fileDialog,&release); qDebug()<<fileDialog.selectedFiles(); }); -
@dave2
Synthesizing Qt key and mouse events with a native file dialog will not work, I am afraid. The native dialog doesn't know about Qt.You can either send Qt events to a non-native dialog, as proposed by @mpergand. Or you dive into the Windows API to simulate what needs to be simulated.
@Axel-Spoerl That's what I was fearing, but thanks for confirming.
-
D dave2 has marked this topic as solved on