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);

  }
 }
}
//---------------------------------------------------------------------------

Uruchamiając program z parametrem exit program zakończy działanie, w przeciwnym wypadku zostanie wyświetlony parametr!

Mam nadzieje, iż  zrozumieliście mnie. Pozdrawiam Błażej.