[MFC] Cum fortez o singura instanta pentru aplicatie?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Cum fortez o singura instanta pentru aplicatie?

Post by Ovidiu Cucu » 23 Oct 2007, 18:23

Intrebare
Cum as putea impune ca aplicatia mea MFC (MDI, SDI sau dialog-based) sa ruleze numai intr-o singura instanta?

Raspuns
Am prezentat in acest tip cum se rezolva problema intr-o aplicatie WinAPI folosind doua metode: prima, inregistrand o clasa cu nume unic apoi apeland FindWindow pentru a vedea daca o fereastra cu acelasi nume de clasa deja exista si, a doua, folosind un named mutex.
In MFC, s-ar aplica aceleasi metode cu deosebirea ca in primul rand plasez codul la inceputul functiei InitInstance.

Exemplu 1

Code: Select all

// MyApp.h
extern const CString g_strMainFrmClass;

// MyApp.cpp
const CString g_strMainFrmClass =
           _T("D2907B5A-A469-4ea8-9382-F5DCFAE04B33");

BOOL CMyApp::InitInstance()
{
   CWnd* pWnd = CWnd::FindWindow(g_strMainFrmClass, NULL);
   if(NULL != pWnd)
   {
      // A prevous running instance already created a window with the given class name.
      // Bring it to front then return. 
      if(pWnd->IsIconic())
         pWnd->ShowWindow(SW_RESTORE);
    
      pWnd->SetForegroundWindow();
      return FALSE;
   }
   // no previous instance, so continue...
   // ... 
}
Pentru o aplicatie MDI sau SDI, schimb numele clasei (in mod normal asignat default de MFC) prin suprascrierea functiei CFrameWnd::PreCreateWindow.

Code: Select all

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
   WNDCLASS wcls;
   ::ZeroMemory(&wcls, sizeof(WNDCLASS));
   wcls.style = CS_DBLCLKS;
   wcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
   wcls.lpfnWndProc = ::DefWindowProc;
   wcls.lpszClassName = g_strMainFrmClass;

   AfxRegisterClass(&wcls);

   cs.lpszClass = g_strMainFrmClass;

   return TRUE;
}
Pentru o aplicatie dialog-based s-ar parea ca e o problema: dialogurile fac parte din clasa predefinita "#32770". Nu-i nimic, se poate rezolva si aceasta. Trebuie doar aruncat un ochi la Cum schimbam numele clasei unui dialog?

In incheiere, un mic exemplu si cu metoda "named mutex".

Exemplu 2

Code: Select all

const CString g_strMutexName = 
           _T("F2908B5A-A477-4ea8-9382-F5DCFAE04B34");

BOOL CMyApp::InitInstance()
{
   ::CreateMutex(NULL, TRUE, g_strMutexName);
   if(ERROR_ALREADY_EXISTS == ::GetLastError())
   {
      // another running instance already created the mutex, so exit.
      return FALSE;
   }
   // no previous instance, so continue...
   // ...
}
<< Back to MFC index



Post Reply