2

I'm trying to create a single instance Qt application and I'm at the point this works, but now I want to focus the already started instance when a second is started. QWidget::find(g_hWnd) should return the widget but it fails and crashes on w->show();

Any thoughts?

#pragma data_seg("Shared")
HWND g_hWnd = NULL;
#pragma data_seg()
#pragma comment(linker,"/section:Shared,rws")

int main(int argc, char *argv[])
{
    if (g_hWnd)
    {
        QWidget* w = QWidget::find(g_hWnd);
        w->show();
        return 0;
    }
    else
    {
        QApplication a(argc, argv);
        mainWindow w;
        w.show();
        g_hWnd = a.topLevelWidgets().at(0)->winId(); //or w.winId()?

        return a.exec();
    }
}

edit: I now see Trolltech released the QtSingleApplication class under LGPL.

Caleb Huitt - cjhuitt
  • 14,785
  • 3
  • 42
  • 49
corné
  • 788
  • 7
  • 14
  • Have you tried debugging both at the same time to determine the g_hWnd in the second application matches the first? – GManNickG Apr 23 '09 at 19:44
  • They don't match, but still it detects there's already a instance running. – corné Apr 23 '09 at 19:51
  • It's weird, sometimes one of the g_hWnd variables value is 0 and other times they match each other, but it still crashes on the find and focus of the qwidget. – corné Apr 23 '09 at 19:58

4 Answers4

10

You should use the qtsingleapplication API

edit- It's a separate download see here for both LGPL and Commercial editions

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • 4
    QtSingleApplication isn't part of any version of Qt. It's an unsupported add-on they make available out of the goodness of their hearts. You can find it here: http://www.qtsoftware.com/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication/ – Parker Coates Apr 23 '09 at 20:18
  • 2
    Oh wow, last time I checked it was only available for the commercial edition. I love Trolltech! – corné Apr 23 '09 at 20:21
  • corne, can you update your question to reflect the QtSingleApplication statement? Thanks. – swongu Apr 23 '09 at 20:50
  • The new location for QtSingleApplication is http://qt.gitorious.org/qt-solutions/qt-solutions/trees/master/qtsingleapplication – priomsrb Mar 14 '12 at 09:21
2
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QMessageBox>
#include <QSharedMemory>


int main(int argc, char *argv[])
{ 
    QApplication a(argc, argv);
     MainWindow w;

    QSharedMemory shared("61BB200D-3579-453e-9044-");
    if(shared.create(512,QSharedMemory::ReadWrite)==true)
    {
        QMessageBox msgBox;
        msgBox.setText("I am first.");
        msgBox.exec();
    }
    else
    {
        QMessageBox msgBox;
        msgBox.setText("i am already running.");
        msgBox.exec();
        exit(0);
    }
    //shared.AlreadyExists()

    w.show();
    return a.exec();
}
sth
  • 222,467
  • 53
  • 283
  • 367
0

This could be the problem you're having:

WId QWidget::winId () const

Returns the window system identifier of the widget.

Portable in principle, but if you use it you are probably about to do something non-portable. Be careful.

If a widget is non-native (alien) and winId() is invoked on it, that widget will be provided a native handle.

Note: We recommend that you do not store this value as it is likely to change at run-time.

Source

0

I doubt your method is going to work.

The best approach is still by running a local server (see QLocalServer) that listens from a specific socket. An newly launched instance will detect the running server and can pipe agreed command to e.g. set the focus, open a new file, etc.

A similar approach is to use named shared memory (see QSharedMemory). Same like before, if the shared memory exists already, the other side can control it by sending suitable commands.

Ariya Hidayat
  • 12,523
  • 3
  • 46
  • 39