Skip to content

Commit

Permalink
Merge pull request #167 from samsonwang/master
Browse files Browse the repository at this point in the history
Windows raise widget example
  • Loading branch information
itay-grudev committed Mar 16, 2023
2 parents f1e1508 + 35f3cbd commit 40601bf
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 29 deletions.
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
}

0 comments on commit 40601bf

Please sign in to comment.