Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows raise widget example #167

Merged
merged 3 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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 }}
33 changes: 6 additions & 27 deletions Windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
16 changes: 16 additions & 0 deletions examples/windows_raise_widget/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
59 changes: 59 additions & 0 deletions examples/windows_raise_widget/main.cpp
Original file line number Diff line number Diff line change
@@ -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
}
10 changes: 10 additions & 0 deletions examples/windows_raise_widget/windows_raise_widget.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Single Application implementation
include(../../singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=QApplication

QT += widgets
SOURCES += main.cpp

win32{
LIBS += User32.lib
}