Przesłanie komunikatu postępu do drugiej aplikacji

0

Zastanawiam się w jaki sposób można by było zrealizować przekazanie w komunikacie do drugiej aplikacji postępu tej pierwszej.

Standardowo do wysyłania komunikatów używam tego sposobu:

{Aplikacja odbierająca komunikat}
const
  KOMUNIKAT_1 = WM_USER + 1234;
  {
  Kluczową sprawą jest określenie takiego identyfikatora, który nie będzie kolidował z innymi,
  zarezerwowanymi już komunikatami.
  Do stałej WM_USER należy dodać jakąś wartość, której górna granica wynosi 31 734.
  }

type
  TForm1 = class(TForm)
  private
    procedure KomunikatDoAplikacji(var Msg : TMessage); message KOMUNIKAT_1;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.KomunikatDoAplikacji(var Msg: TMessage);
begin
 {Wartość zwrotna jako pozytywne odebranie komunikatu}
 Msg.Result := 1;
 
 //instrukcje do wykonania w ramach odebrania komunikatu
end;




{Aplikacja wysyłająca komunikat}
const
  KOMUNIKAT_1 = WM_USER + 1234;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function FindWindowExt(Text: string): hWnd;
var
 Han: hWnd;
 cTitle: array [0..254] of Char;
 sTitle: string;
begin
 Han  := FindWindow(nil, nil);
 Text := AnsiLowerCase(Text);

 while Han <> 0 do
   begin
    GetWindowText(Han, cTitle, 255);
    sTitle := cTitle;
    if cTitle = '' then
      begin
       Han := GetWindow(Han, GW_HWNDNEXT);
       Continue;
      end;

    sTitle := AnsiLowerCase(sTitle);
    Application.ProcessMessages;
    if Pos(Text, sTitle) <> 0 then Break;
    Han := GetWindow(Han, GW_HWNDNEXT);
  end;

 Result := Han;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Han: hWnd;
begin
 Han := FindWindowExt('TYTUŁ_OKNA_APLIKACJI');
 
 {Jeśli aplikacja zwróci wartość zwrotną 1 podaną w aplikacji odbierającej}
 if SendMessage(Han, KOMUNIKAT_1, 2, 20) = 1 then ShowMessage('Komunikat przekazany!')
 else ShowMessage('Błąd. Komunikat nie został przekazany!');
end;

Tym sposobem można według mnie wysyłać tylko proste informacje typu (akcja rozpoczęta/zakończona). Nie znam możliwości, aby w komunikacie przesłać zmieniającą się wartość, która pełniła by rolę informacji o postępie.

Jak to można wykonać ?

0

Parametry WParam, LParam ?

0

A czy te parametry nie są przekazywane tylko w momencie uruchomienia drugiej aplikacji przez pierwszą ?

Komunikaty mogą być przekazywane w każdej chwili.

0

Zapewne jako doświadczony programista Opi czytałeś lub używałeś komunikatu WM_COPYDATA. Zobacz poniższe źródło.
Zmienna Msg.CopyDataStruct.dwData może przechowywać liczby typu Cardinal, a więc możesz to wykorzystać u siebie.
http://www.speedyshare.com/files/23770642/multi_file_open.rar

0

Jak widać jeszcze niezbyt doświadczony ;)

W jaki sposób ten przykład pracuje ?
Podczas kopiowania plików w Windows pokazuje postęp ?

0
Opi napisał(a)

A czy te parametry nie są przekazywane tylko w momencie uruchomienia drugiej aplikacji przez pierwszą ?

Komunikaty mogą być przekazywane w każdej chwili.

Są przekazywane wtedy kiedy przekazujesz. Jeśli to ma być progress, to śmiało możesz wykorzystać WParam i LParam. Możesz też zamiast SendMessage używać PostMessage - czyli umieszczenie komunikatu w kolejce bez oczekiwania na odpowiedź drugiej aplikacji.

WM_COPYDATA jest tu IMHO armatą na muchy.

b

0
Opi napisał(a)

W jaki sposób ten przykład pracuje ?
Podczas kopiowania plików w Windows pokazuje postęp ?

Ten przykład dodaje do Memo w tej samej instancji programu parametry podane przy uruchamianiu programu. Jednak na tej
sadadzie powinieneś wiedzieć jak wykorzystac Msg.CopyDataStruct.dwData do przekazania tylko liczby. Choć może faktycznie
b0bik ma rację, tylko dla liczby powinien wystarczyć własny komunikat i standardowo dostępne parametry LParam, i WParam.

0

Dziękuję. Tak to rozwiązałem:

{Aplikacja wysyłająca}
const
  KOMUNIKAT_POSTEP = WM_USER + 5500;

procedure TForm1.PostepTestClick(Sender: TObject);
var
 i: SmallInt;
 Han: HWND;
begin
 Han := FindWindow('TForm1', 'Aplikacja 2');

 for i := 0 to 100 do
   begin
    Sleep(Random(50));
    Application.ProcessMessages;
    SendMessage(Han, KOMUNIKAT_POSTEP, i, 0);
   end;
end;
{Aplikacja odbierająca}
const
  KOMUNIKAT_POSTEP = WM_USER + 5500;

 private
    procedure Postep(var Msg : TMessage); message KOMUNIKAT_POSTEP;

procedure TForm1.Postep(var Msg: TMessage);
begin
 Msg.Result := 1; // wartość zwrotna

 Gauge1.Progress := Msg.wParam;
end;

Przy okazji znalazłem dość rozbudowany tutorial o komunikatach:
http://www.gamedev.pl/articles.php?x=view&id=153

1 użytkowników online, w tym zalogowanych: 0, gości: 1