Programmieren mit C++

Borland C++

32-Bit-Programmierung

Nur eine Instanz starten

Wie wird unter WIN32 mittels C++Builder erreicht, daß nur eine Instanz gestartet werden kann?

Frage

Der C++Builder erzeugt automatisch eine formularlose Hauptdatei, deren Dateiname dem Projektnamen entspricht. In dieser Datei ist die Funktion WinMain() implementiert, die alle Formulare erzeugt und die Anwendung startet. Eine einfache Variante dieser Datei mit Defaultbezeichner wäre:

#include 
#pragma hdrstop
 
USEFORM("Unit1.cpp", Form1);
USERES("Project1.res");
 
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
 try
 {
  Application->Initialize();
  Application->CreateForm(__classid(TForm1), &Form1);
  Application->Run();
 }
 catch (Exception &exception)
 {
  Application->ShowException(&exception);
 }
 return 0;
}

Hier wird zunächst die Anwendung initialisiert und das Formular erzeugt. Kommt es zu einem Fehler, wird automatisch in die Fehlerbehandlung gesprungen, die eine einfache Fehlermeldung ausgibt.

Soll eine Anwendung nur einmal gestartet werden, muß die entsprechende Abfrage in die Funktion WinMain() integriert werden. Dazu implementiert die Funktion GetPrevInstName zunächst eine komfortable Möglichkeit, den Fenstertitel der Anwendung zu ermitteln, wobei der String „PREVINST:“ vorangestellt wird.

Lösung

char* GetPrevInstName()
{ 
  char *Buf, *temp;
 
  Buf  = (char *) malloc(MAX_PATH);
  temp = (char *) malloc(MAX_PATH);
 
  GetWindowText(Application->Handle,
                Buf, MAX_PATH);
 
  strcpy(temp, "PREVINST:");
  strcat(temp, Buf);
 
  free(Buf);
 
  return temp;
}

Die Haupt-Programmschleife verwendet zur Feststellung, ob bereits eine Instanz der Anwendung installiert ist, ein Mutex-Objekt. Dazu wird zunächst der Anwendungstitel mit dem Default-Titel vorbelegt.

Funktion GetPrevInstName

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  THandle Mutex;
  
  Application->Title = "Single_App";

Anschließend wird das Mutex-Objekt erzeugt.

Funktion WinMain()

  Mutex = (int)CreateMutex(
                   NULL, true,
                   GetPrevInstName() );

Die Funktion CreateMutex returniert dann, wenn bereits eine Instanz gleichen Namens existiert, den Wert 0, also ein NULL-Handle, zurück. Zusätzlich ist auch noch der allgemeine Fehlerstatus des Aufrufs über GetLastError() zu prüfen. Liefern beide Tests Negativresultate, kann die Anwendung wie gewohnt gestartet werden.

  if ((Mutex != NULL) && (GetLastError() == 0))
  {
    Application->Initialize();
    Application->CreateForm(__classid(TForm1), &Form1);
    try
    {
      Application->Run();
    }
    catch (Exception &exception)
    {
      Application->ShowException(&exception);
    }

Abschließend ist der ggfs. erzeugte Mutex zu zerstören.

    if (Mutex != 0) 
      CloseHandle(&Mutex);
  }

War das Programm bereits gestartet, kann die vorhergehende Instanz ermittelt und aktiviert werden. Dazu wird ein Fenster mit dem entsprechenden Titel via FindWindow() gesucht. Da die Mutex-Abfrage zuvor eine Instanz gefunden hat, sollte dieser Aufruf nicht fehlschlagen.

Mutex-Objekt erzeugen

  else
  {
    HWND    PrevInst;
    char    s[30];  
    strcpy(s, (Application->Title).c_str()); 
    Application->Title = "$%$%$";
    PrevInst = FindWindow(NULL, s);

Wird das Fenster gefunden, kann die vorhergehende Instanz angezeigt werden. Dazu wird diese entweder restauriert, wenn sie als Symbol vorliegt, oder einfach nach vorn gebracht und aktiviert.

Fenster ermitteln

    if (PrevInst != 0)
    {
      if (IsIconic(PrevInst))
        ShowWindow(PrevInst, SW_RESTORE);
      else
        BringWindowToTop(PrevInst);

Die aktuelle Instanz der Anwendung wird nicht mehr benötigt und muß beendet werden.

Fenster der vorherigen Instanz anzeigen

      Application->Terminate();
    }                         
  }
  return 0;
}

Anwendungsin-stanz terminieren





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 02:48:28 von textarchiv.alojado.de