Entwickler-Ecke

Windows API - Kommunikation Screensaver <-> Programm


matze - Mi 27.04.05 18:51
Titel: Kommunikation Screensaver <-> Programm
Hallo !

Ich muss zwischen einem laufenden Programm von mir und einem Screensaver von mir Daten (strings) austauschen.
Mein Problem ist, dass ich nicht weiß wie ich sowas machen kann.
da der Bildschirmschoner, wenn er gestartet ist, ja in einem anderen desktop kontext läuft, kann man ihn oder das Programm nicht mit FindWindow finden, folglich auch das WM_COPYDATA nicht verwenden.
wie kann ich das denn sonst lösen ?

Danke


BenBE - Mi 27.04.05 18:53

Vielleicht hilft Dir ein Blick auf das Stichwort Suche in: Delphi-Forum, Delphi-Library IPC. Da sollte auch Source von mir mit dabei sein (Suche in: Delphi-Forum, Delphi-Library MUTEXIPC)


matze - Mi 27.04.05 20:15

danke für den tipp.
ich werd das mal ausprobieren !


feuerwaran - So 01.05.05 16:33

Hallo matze,

Das Problem hatte ich auch :)

Mein Vorschlag: Benutze Memory Mapped files. z.B.:


Zuerst mal eine typisierten Struktur erstellen. Das muß so sein, weil du gleich im Prinzip einen Speicherbereich in Windows belegst und diese fast so behandelt wird wie eine Datei.

Auf beiden Seiten der Anwendungen:


Delphi-Quelltext
1:
2:
3:
4:
5:
type
  TMyData = record
    meinstring:shortstring;
end;
  MyData: ^TMyData;


Auf dem, der den MMF erzeugen und nachher zerstören soll


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
procedure create_mmf_and_view;
begin
  MyData_Handle:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,sizeof(PMyData),PCHAR('MyData'));
  if MyData_HANDLE <> 0 then
  begin
    MyData := MapViewOfFile(MyData_Handle,FILE_MAP_WRITE,0,0,0);
    if MyData = nil then
    begin
      if MessageBox(Application.Handle,
                    pchar('Error after API-Call: MapViewOfFile'),
                    pchar('Application Terminate?'),
                    MB_YESNO) = IDYES then
      begin
        Application.terminate;
      end;
    end;
  end
  else
    if MessageBox(Application.Handle,
                  pchar('Error after API-Call: CreateFileMapping'),
                  pchar('Application Terminate?'),
                  MB_YESNO) = IDYES then
    begin
      Application.terminate;
    end;
end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure close_mmf_and_view;
begin
  if UnmapViewOfFile(MyData)=False then
  begin
    if MessageBox(Application.Handle,
                  pchar('Error after API-Call: UnmapViewOfFile'),
                  pchar('Application Terminate?'),
                  MB_YESNO) = IDYES then
    begin
      Application.terminate;
    end;
  end;
  CloseHandle(MyData_Handle);
end;



Auf der Seite der Anwendungen, die da lesen und schreiben sollen


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function open_mmf_view():boolean;
var
  MyData_HANDLE:Cardinal;
begin
   MyData_HANDLE:=OpenFileMapping(FILE_MAP_WRITE,TRUE,PCHAR('MyData'));

   if MyData_HANDLE <> 0 then
   begin
      MyData := MapViewOfFile(MyData_Handle,FILE_MAP_WRITE,0,0,0);
   end;
   Result := MyData_HANDLE <> 0;
end;



Delphi-Quelltext
1:
2:
3:
4:
function close_mmf_view:boolean;
begin
   Result := UnmapViewOfFile(MyData);
end;



So das wars :) Das mit Mutexes ist etwas komplizierter, aber wenn du konsistente Daten haben möchtest sinnvoll. Aber ich sag mir:"Du bist der Programmierer. DU!!! mußt wissen was mit deinen Daten wann und wo passiert" :) Außerdem hatte ich Probleme mit dem typ string. Scheint so, das dieser Typ dynamischen ursprungs ist. Ich denke ich hab sowas in der Online Hilfe gelesen. Deshalb habe ich shortstring genommen, weil der nen festen Wert von 256 Bytes hat. Ich hoffe ich konnte dir helfen.

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.


matze - Mo 02.05.05 12:51

wow. vielen dank für deine hilfe !


feuerwaran - Mo 02.05.05 14:54

Ich habe da noch eine Kleinigkeit entdeckt. Also im 2. Abschnitt MyData und MyData_Handle global definieren und beim close_mmf_view noch ein CloseHandle(MyData_Handle); schreiben. OK? Man muß ja nicht unbedingt unnötigerweise Leichen liegen lassen :)