Merge pull request #167 from samsonwang/master

Windows raise widget example
This commit is contained in:
Itay Grudev 2023-03-16 15:18:12 +02:00 committed by GitHub
commit 40601bf733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 29 deletions

View File

@ -59,7 +59,7 @@ jobs:
cmake . ${{ matrix.additional_arguments }}
cmake --build .
- name: Build calculator example CMake
- name: Build calculator example with CMake
working-directory: examples/calculator/
run: |
cmake . ${{ matrix.additional_arguments }}
@ -71,6 +71,12 @@ jobs:
cmake . ${{ matrix.additional_arguments }}
cmake --build .
- name: Build windows_raise_widget example with CMake
working-directory: examples/windows_raise_widget/
run: |
cmake . ${{ matrix.additional_arguments }}
cmake --build .
- name: Setup MSVC environment for QMake
uses: ilammy/msvc-dev-cmd@v1
@ -80,7 +86,7 @@ jobs:
qmake
${{ matrix.make }}
- name: Build calculator example QMake
- name: Build calculator example with QMake
working-directory: examples/calculator/
run: |
qmake
@ -91,3 +97,9 @@ jobs:
run: |
qmake
${{ matrix.make }}
- name: Build windows_raise_widget example with QMake
working-directory: examples/windows_raise_widget/
run: |
qmake
${{ matrix.make }}

View File

@ -7,36 +7,15 @@ application can bring it's primary instance window whenever a second copy
of the application is started.
On Windows the ability to bring the application windows to the foreground is
restricted, see [AllowSetForegroundWindow()][https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx] for more
details.
restricted, see [AllowSetForegroundWindow()](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx) for more details.
The background process (the primary instance) can bring its windows to the
foreground if it is allowed by the current foreground process (the secondary
instance). To bypass this `SingleApplication` must be initialized with the
`allowSecondary` parameter set to `true` and the `options` parameter must
include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more
details.
`allowSecondary` parameter set to `true` .
Here is an example:
If the widget is minimized to Windows task bar, `QWidget::raise()` or
`QWidget::show()` can not bring it to the front, you have to use Windows API
`ShowWindow()` .
```cpp
if( app.isSecondary() ) {
// This API requires LIBS += User32.lib to be added to the project
AllowSetForegroundWindow( DWORD( app.primaryPid() ) );
}
if( app.isPrimary() ) {
QObject::connect(
&app,
&SingleApplication::instanceStarted,
this,
&App::instanceStarted
);
}
```
```cpp
void App::instanceStarted() {
QApplication::setActiveWindow( [window/widget to set to the foreground] );
}
```
You can find [demo code](examples/windows_raise_widget/main.cpp) in the examples directory.

View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.7.0)
project(windows_raise_widget LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_WIN32_EXECUTABLE TRUE)
# SingleApplication base class
set(QAPPLICATION_CLASS QApplication)
add_subdirectory(../.. SingleApplication)
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core Widgets REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)

View File

@ -0,0 +1,59 @@
#include <QWidget>
#include "singleapplication.h"
#ifdef Q_OS_WINDOWS
#include <Windows.h>
#endif
void raiseWidget(QWidget* widget);
int main(int argc, char *argv[]) {
#ifdef Q_OS_WINDOWS
SingleApplication app(argc, argv, true);
if (app.isSecondary()) {
AllowSetForegroundWindow( DWORD( app.primaryPid() ) );
app.sendMessage("RAISE_WIDGET");
return 0;
}
#else
SingleApplication app(argc, argv);
#endif
QWidget* widget = new QWidget;
#ifdef Q_OS_WINDOWS
QObject::connect(&app, &SingleApplication::receivedMessage,
widget, [widget] () { raiseWidget(widget); } );
#else
QObject::connect(&app, &SingleApplication::instanceStarted,
widget, [widget] () { raiseWidget(widget); } );
#endif
widget->show();
return app.exec();
}
void raiseWidget(QWidget* widget) {
#ifdef Q_OS_WINDOWS
HWND hwnd = (HWND)widget->winId();
// check if widget is minimized to Windows task bar
if (::IsIconic(hwnd)) {
::ShowWindow(hwnd, SW_RESTORE);
}
::SetForegroundWindow(hwnd);
#else
widget->show();
widget->raise();
widget->activateWindow();
#endif
}

View File

@ -0,0 +1,10 @@
# Single Application implementation
include(../../singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=QApplication
QT += widgets
SOURCES += main.cpp
win32{
LIBS += User32.lib
}