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.