[WinAPI] Cum fortez o singura instanta pentru aplicatie?

Folosire Windows API in programe C/C++ (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum fortez o singura instanta pentru aplicatie?

Post by Ovidiu Cucu » 23 Oct 2007, 17:45

Problema
Cine a prins programare pentru Windows pe 16 biti stie ca se putea testa parametrul hPrevInstance din WinMain pentru a vedea daca o alta instanta a aplicatiei deja ruleaza.
In Win32 acest parametru si-a pierdut semnificatia fiind intotdeauna NULL, deci nu poate fi folosit.
Totusi ce metode ar fi pentru a limita aplicatia mea la o singura instanta?

Rezolvare
O metoda simpla ar fi sa inregistram o clasa cu nume unic pentru fereastra principala si apoi de a apela functia ::FindWindow. Pentru a asigura unicitatea numelui de clasa se poate folosi o conventie de genul <my company name>.<application name>.window class.<number> sau si mai bine, un string generat cu utilitarul GUIDGEN (care este distribuit cu Visual Studio).

Exemplu 1

Code: Select all

LPCTSTR const g_pszWindowClass = 
            _T("D2907B5A-A466-4ea8-9382-F5DCFAE04B33");

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   HWND hWnd = ::FindWindow(g_pszWindowClass, NULL);
   if(NULL != hWnd)
   {
      // A prevous running instance already created a window with the given class name.
      // Bring it to front then return. 
      if(::IsIconic(hWnd))
         ::ShowWindow(hWnd, SW_RESTORE);
    
      ::SetForegroundWindow(hWnd);
      return FALSE;
   }
   // no previous instance, so continue...
   // ...
}

ATOM MainWndRegisterClass(HINSTANCE hInstance)
{
   // register a window class with a unique name
   WNDCLASSEX wcex;
   // ...
   wcex.lpszClassName = g_pszWindowClass;
   return RegisterClassEx(&wcex);
}
Alta metoda, chiar mai simpla, care nu necesita neaparat existenta unei fereste si foarte des utilizata este de a crea un named mutex. Functia CreateMutex va failiza iar GetLastError va intoarce codul ERROR_ALREADY_EXISTS daca un mutex cu acelasi nume a fost deja creat.

Exemplu 2

Code: Select all

LPCTSTR const g_pszMutexName =  
            _T("61C25515-3A80-422d-AE82-B6B81B35CD50");

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   ::CreateMutex(NULL, TRUE, g_pszMutexName);
   if(ERROR_ALREADY_EXISTS == ::GetLastError())
   {
      // another running instance already created the mutex, so exit.
      return 0;
   }
   // no previous instance, so continue...
   // ...
}

<< Back to Windows API Index



Post Reply