ARTYKUŁ NADESŁANY
PRZEZ BŁAŻEJA.
Zablokowanie uruchomienia kopii programu z przekazaniem parametru do
wcześniej uruchomionego i aktualnie działającego programu!
Często chcemy zablokować uruchomienia kopii programu. Aby to zrobić najlepiej
będzie skorzystać
z
mutexów.
Tworzy się je za pomocą funkcji
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // pointer to security attributes
BOOL bInitialOwner, // flag for initial ownership
LPCTSTR lpName // pointer to mutex-object name
);
Następnie sprawdzamy czy nasz mutex już istnieje. Jeśli nie to uruchamiamy
program. W przeciwnym wypadku należy znaleźć uchwyt (
HWND
FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);
)do już uruchomionego
programu i wysłać, za pomocą funkcji
LRESULT SendMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);,
odpowiedni komunikat np. parametr z jakim uruchomiono program i zamknąć kopie
programu.
Aktualnie
działający program odbierze nasz komunikat i odpowiednio go przetworzy!
Tyle z
omówienia, teraz czas na przykład:
Na początek
otwieramy nowy projekt i zapisujemy go. W menu kompilatora wybieramy
Project->View Source.
W otwartym oknie
odnajdujemy linię:
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{ |
i wpisujemy:
|
int uchwyt; CreateMutex(NULL, false,
"UNIKALNA_NAZWA");
//unikalna nazwa tworzonego mutexa
if(GetLastError() > 0 ) //sprawdzamy
czy istnieje nasz mutex {
uchwyt = (int)FindWindow(NULL, "Nazwa
programu"); //Form1->Caption
COPYDATASTRUCT MyStruct;
char *str = ParamStr(1).c_str(); //pobranie
parametru z jakim uruchomiono program
MyStruct.dwData = 1; //dowolna liczba - przydatna jeśli wysyłasz różne dane
MyStruct.cbData = strlen(str)+1; //liczba bajtów, którą przesyłamy
MyStruct.lpData = str; //wskaźnik do naszej danej
SendMessage((void*)uchwyt, WM_COPYDATA, 1, (int)&MyStruct);
Application->Terminate();
} else
{ |
Pamiętajmy o
tym, że na dole kodu przed return 0 należy dopisać }. Inaczej
kompilator zgłosi błąd.
Następnie
przechodzimy do pliku źródłowego
Unit1.h po public wpisujemy:
MESSAGE void Param(TMessage &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TMessage, Param);
END_MESSAGE_MAP(TForm); |
Funkcja
MESSAGE void Param(TMessage &Message); służyć będzie do odbierania naszego
komunikatu WM_COPYDATA.
Teraz przechodzimy do pliku
Unit1.cpp
i
dopisujemy następującą funkcje:
MESSAGE void TForm1::Param(TMessage &Message)
{
if(Message.WParam == 1)
{
int IleBajtow;
IleBajtow = (PCOPYDATASTRUCT(Message.LParam))->cbData;
char *MyStr;
MyStr = new char[IleBajtow];
strcpy(MyStr, (char*)(PCOPYDATASTRUCT(Message.LParam))->lpData);
//tutaj możemy wykożystać przekazany komunikat
ShowMessage(MyStr);
//np. wyświetlając go
}
} |
Pamiętajmy
jeszcze o tym, aby nadać programowi odpowiedni tytuł: Form1->Caption="Nazwa
programu";
Przykład:
// Plik źródłowy np.
Poject1.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop //---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
#include "Unit1.h"
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{ int uchwyt; CreateMutex(NULL, false,
"UNIKALNA_NAZWA");
//unikalna nazwa tworzonego mutexa
if(GetLastError() > 0 ) //sprawdzamy
czy istnieje nasz mutex {
uchwyt = (int)FindWindow(NULL, "Nazwa
programu"); //Form1->Caption
COPYDATASTRUCT MyStruct;
char *str = ParamStr(1).c_str(); //pobranie
parametru z jakim uruchomiono program
MyStruct.dwData = 1; //dowolna liczba - przydatna jeśli wysyłasz różne dane
MyStruct.cbData = strlen(str)+1; //liczba bajtów, którą przesyłamy
MyStruct.lpData = str; //wskaźnik do naszej danej
SendMessage((void*)uchwyt, WM_COPYDATA, 1, (int)&MyStruct);
Application->Terminate();
} else
{
try
{
Application->Initialize();
Application->Title = "Nazwa programu";
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
}
return 0;
}
//--------------------------------------------------------------------------- |
// Plik źródłowy np.
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
MESSAGE void Param(TMessage &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TMessage, Param);
END_MESSAGE_MAP(TForm);
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif |
// Plik źródłowy np.
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
MESSAGE void TForm1::Param(TMessage &Message)
{
if(Message.WParam == 1)
{
int IleBajtow;
IleBajtow = (PCOPYDATASTRUCT(Message.LParam))->cbData;
char *MyStr;
MyStr = new char[IleBajtow];
strcpy(MyStr, (char*)(PCOPYDATASTRUCT(Message.LParam))->lpData);
//wykorzystaj MyStr
if(strcmp(MyStr,"exit")==0)
{
Application->Terminate();
}
else
{
ShowMessage(MyStr);
}
}
}
//--------------------------------------------------------------------------- |