..:: Jedinß instance aplikace ::..

N∞kdy pot°ebujeme aby naÜe aplikace m∞la jen jedinou instanci a p°i ka₧dΘm dalÜφm pokusu o jejφ spuÜt∞nφ se tato instance aktivovala a p°evzala parametry z p°φkazovΘho °ßdku. V tomto Φlßnku vßm ukß₧u velice jednoduch² zp∙sob jak toho docφlit. 

Postup vßm p°edvedu na MFC aplikaci zalo₧enΘ na dialogu, kterß p°i ka₧dΘm dalÜφm pokusu o svΘ spuÜt∞nφ zobrazφ MessageBox s v²pisem parametru se kter²m byla spuÜt∞na. (Pro jednoduchost jen prvnφho.)

Zde je postup:

Nejd°φve si zaregistrujeme zprßvu pomocφ funkce RegisterWindowMessage a ulo₧φme si ji do globßlnφ prom∞nnΘ. (Pou₧ijeme ji pozd∞ji.)

UINT WM_CHECK_ITS_ME = RegisterWindowMessage("27.4.2003 12:40:43 WM 2149asdf76gd");

Pozn.: Nezapome≥te, ₧e ve vÜech souborech, kde chcete prom∞nou tΘto zprßvy pou₧φvat krom∞ toho kde je registrovßna musφte ji v t∞chto souborech deklarovat jako extern.
(extern UINT WM_CHECK_ITS_ME;)

Detekci zda aplikace ji₧ b∞₧φ provedeme vytvo°enφm mutexu a zkontrolovßnφm zda ji₧ d°φve existoval. Je to mo₧nΘ proto₧e, pokud se pokusφme vytvo°it mutex se jmΘnem, kter² ji₧ byl vytvo°en, vrßtφ se nßm handle tohoto d°φve vytvo°enΘho mutexu a poslednφ chyba je nastavena na indikaci, ₧e mutex ji₧ p°ed vytvß°enφm existoval. (Nebo v p°φpad∞, ₧e mßme jin² objekt jßdra s tφmto jmΘnem se vrßtφ chybovß hodnota a poslednφ chyba se nastavφ na indikßtor, ₧e byl zakßzßn p°φstup.) JmΘno tohoto mutexu by m∞lo b²t takovΘ, aby se zajistilo, ₧e se v systΘmu nevyskytne jinß aplikace se systΘmov²m objektem se stejn²m jmΘnem. DoporuΦuji pou₧φt n∞jakΘho generßtoru unikßtnφch identifikßtor∙ a pokud jako jß ₧ßdn² nemßte tak v tomto °et∞zci pou₧φt aktußlnφ datum a Φas (na vte°iny) spolu s nßhodnou posloupnostφ znak∙.

Handle tohoto mutexu si samoz°ejm∞ ulo₧φme a p°i skonΦenφ aplikace bychom jej nem∞li zapomenout uvolnit. (Ikdy₧ by to m∞l sytΘm ud∞lat sßm, kdy₧ na to zapomeneme.)

Tak₧e zaΦneme tφm, ₧e si v t°φd∞ aplikace vytvo°φme prom∞nnou typu HANDLE mutexu.

class COneApp:public CWinApp

{

 

.........

private:

HANDLE hSIMutex;

........

 

};

PotΘ ve funkci InitInstance (kterß se volß jako ·pln∞ prvnφ) provedeme kontrolu zda aplikace ji₧ b∞₧φ. Na jejφ zaΦßtek p°idßme nßsledujφcφ k≤d.

BOOL COneApp::InitInstance()

{

// Vytvo°φme mutex s naÜφm unikßtnφm jmΘnem.

hSIMutex = CreateMutex( NULL, FALSE, _T("27.4.2003 12:40:43 2149asdf76gd"));

// Zkontolujeme zda ji₧ mutex existoval.

bool AlreadyRunning = ( GetLastError() == ERROR_ALREADY_EXISTS ||

GetLastError() == ERROR_ACCESS_DENIED);

//Pokud ji₧ b∞₧φ jinß instance naÜφ aplikace.

if (AlreadyRunning)

{

// Pokud se nßm poda°ilo zφskat mutex, uvolnφme jej.

if (hSIMutex)

{

ReleaseMutex(hSIMutex);

hSIMutex = NULL;

}

// Pokud byla aplikace spuÜt∞na s n∞jak²m parametrem.

if (__argc>1)

{

// Otev°eme pomocn² soubor, ulo₧φme do n∞j prvnφ parametr a zav°eme jej.

FILE* f;

f = fopen("transfer.txt","w");

fprintf(f,"%s",__argv[1]);

fclose(f);

}

/* Pomocφ funkce SendMessageTimeout zaÜleme vÜem okn∙m v systΘmu naÜφ zaregistrovanou zprßvu a jako jejφ parametr WPARAM p°edßme handle globßlnφ pam∞ti. */

DWORD result;

LRESULT ok = SendMessageTimeout(HWND_BROADCAST,

WM_CHECK_ITS_ME,

0, 0,

SMTO_BLOCK |

SMTO_ABORTIFHUNG,

200,

&result);

/* Sma₧eme pomocn² soubor. M∙₧eme si to dovolit, proto₧e funkce SendMessageTimeout neskonΦφ d°φve ne₧ je zprßva zpracovßna, nebo po intervalu udanΘm p°edposlednφm parametrem (v milisekundßch). Ale tento parametr musφte nßsobit poΦtem otev°en²ch oken, proto₧e tento interval je pro ka₧dΘ okno. Tj. kdy₧ mßte v systΘmu otev°eno 10 oken a interval 200 milisekund a  ₧ßdnΘ z nich tuto zprßvu nezpracuje, pak ne₧ tato funkce skonΦφ uplyne 2000 milisekun (tj. 2 sekundy). */

::DeleteFile("transfer.txt");

//Vrßtφme FALSE, Φφm₧ aplikaci ukonΦφme.

return FALSE;

}

/* Tady se pokraΦuje standartnφm zp∙sobem (tj. p∙vodnφ k≤d), pokud je to prvnφ instance tΘto aplikace. */

............

............

}

 

Poslednφ ·pravou t°φdy aplikace je p°etφ₧enφ virtußlnφ funkce ExitInstance, kterß se volß p°i ukonΦenφ aplikace a v nφ uvolnφme mutex.

int COneApp::ExitInstance()

{

// TODO: Add your specialized code here and/or call the base class

if (hSIMutex)

{

ReleaseMutex(hSIMutex);

hSIMutex = NULL;

}

return CWinApp::ExitInstance();

}

 

Te∩ jeÜt∞ musφme upravit t°φdu hlavnφho okna aplikace. (V tΘto ukßzkovΘ aplikaci je to dialog.) Na zaΦßtek definiΦnφho souboru p°idßme deklaraci prom∞nnΘ s naÜφ registrovanou zprßvou.

extern UINT WM_CHECK_ITS_ME;

Te∩ ji jeÜt∞ musφme odchytit. To provedeme v p°etφ₧enΘ virtußlnφ funkci WindowProc naÜeho dialogu.

LRESULT COneDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

// Pokud p°iÜla naÜe registrovanß zprßva.

if (message==WM_CHECK_ITS_ME)

{

// Otev°eme nßÜ pomocn² soubor.

char buffer[256];

FILE* f;

f = fopen("transfer.txt","r");

if (f)

{

/* Pokud se nßm jej poda°ilo otev°φt, naΦteme z n∞j parametr p°edan² dalÜφ instanci aplikace a zpracujeme jej. V tΘto ukßzkovΘ aplikaci pouze zobrazφme MessageBox s tφmto parametrem. */

fscanf(f,"%s",buffer);

fclose(f);

MessageBox(buffer,"Aplikace byla znovu spuÜt∞na.",MB_SYSTEMMODAL|MB_OK);

}

}

return CDialog::WindowProc(message, wParam, lParam);

}

Zdrojov² k≤d ukßzkovΘ aplikace si m∙₧ete stßhnout zde.