Entwickler-Ecke

Windows API - Button in fremde Anwendung integrieren....


peeage - Di 20.02.07 21:20
Titel: Button in fremde Anwendung integrieren....
Hallo zusammen.


Besteht denn irgendwie die Möglichkeit einen Button irgendwo in die Form einer fremden Anwendung zu integrieren, hinter welchem auch bestimmte Befehlszeilen stehen (simples Bsp.: ShowMessage('test'); ).


Bedank mich schonmal für eure Antworten.


Karlson - Di 20.02.07 22:13

Nein. Der einzige Weg den ich als funktionierend ansehen würde setzt massives Wissen im Bereich Assembler vorraus. Je nachdem was du machen willst kann es sein, dass es die Möglichkeit gibt einen Umweg zu gehen.


peeage - Di 20.02.07 23:32

Hmmm .. Konnte ich mir schon fast denken.

Im Prinzip muss hinter diesem integrierten Button auch keine Funktion stecken. Ich will es nur realisieren das der Anwender aus einer anderen Anwendung heraus (Cobra Adress PLUS) meinem eigentlichen Programm die Information geben kann, dass der Button betätigt wurde.

Der Anwender drückt diesen Button in seinem Adressbuch (Cobra A. Pl.) und mein Programm liest dann die Adressfelder des geöffneten Kontaktes aus und übernimmt sie.


Was mir noch durch den Kopf ging:

Es gibt doch die Möglichkeit die Systembuttons (minimieren, maximieren, X, help) zu manipulieren.. Man könnte doch zb. die Funktion des "help" - buttons ausschalten und stetig abfragen, ob dieser Button gedrückt wurde. Wenn ja, dann liest mein Programm die Adressdaten aus. Würde das funktionieren? Wenn ja, kann ich den Text (Caption) des Buttons ändern, in diesem Fall das "?" ?? ..


Delete - Mi 21.02.07 00:02

Mit einem Programm, welches nicht für IPC (Interprozesskommunikation) vorgesehen wurde, nachträglich über Prozessgrenzen hinweg zu kommunizieren, ist nur mit einem erheblichen Aufwand verbunden und erfordert umfassendes Wissen bezüglich der WinAPI und wie Windows intern funktioniert.


Coder - Mi 21.02.07 00:20

Wie macht das denn MSN Messenger Plus?
Der fügt ja auch neue Controls in den Messenger ein.
Ich weis nur das der MSN-Messenger-Plus-Prozess immer im Hintergrund läuft.
Er ändert aber nicht die MSN Messenger .exe selbst.

MfG


alias5000 - Mi 21.02.07 00:25

Ich nehme mal ganz stark an, dass der MDN Messenger einfach eine Plugin- Schnittstelle zur Verfügung stellen wird ;)


Coder - Mi 21.02.07 00:54

user profile iconCoder hat folgendes geschrieben:
Wie macht das denn MSN Messenger Plus?
Der fügt ja auch neue Controls in den Messenger ein.
Ich weis nur das der MSN-Messenger-Plus-Prozess immer im Hintergrund läuft.
Er ändert aber nicht die MSN Messenger .exe selbst.


Hier steht wie der das macht
http://www.msghelp.net/showthread.php?tid=71839&page=1

MfG


IngoD7 - Mi 21.02.07 01:27

Lege einen Button1 mal auf dein Form - ganz nach links oben.

Starte mal den Rechner --> Start --> Ausführen --> "Calc"

Dann irgendwo (z.B. in ClickRoutine eines 2. Buttons) folgendes:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
begin
  button1.Parent:=nil;
  button1.ParentWindow:=FindWindow(nil,'Rechner');
  button1.ControlStyle:=button1.ControlStyle+[csClickEvents];
  button1.BringToFront;
end;


Schaue wo der Button anschließend landet. ;-)
Sollte er nicht sofort sichtbar sein, klicke mal unter dem Menüpunkt "Bearbeiten" im Rechner.
Wenn du den Button im Rechner klickst, wird seine OnClick-Routine in deiner Anwendung ausgeführt. Beendest du deine Anwendung, verschwindet er aus dem Rechner.
Der Button "gehört" jederzeit weiterhin deiner Anwendung und darin der Form, aus der er kam.

ACHTUNG: Das ist alles unausgegoren. Es dient lediglich als Ansatz!
Durch bestimmte Neuzeichenvorgänge verschwindet der Button manchmal.
Manchmal ist er nicht sofort sichtbar. Besonders dann, wenn auf dem Zielfenster an der Stelle andere Komponenten liegen.
Manchmal ist er aus demselben Grund teilweise von anderen Dingen verdeckt. Ob und wie das zu handeln ist, weiß ich nicht. Im Rechner geht es halbwegs, weil er recht viel Hintergrund "durchschimmern" lässt.

Probiere mal etwas herum.

Ohne Gewähr!


Karlson - Mi 21.02.07 03:11

Hey, das ist ja interessant und vor allem echt geschickt gelöst :lol:

Das setzt aber vorraus, dass eine zweitanwendung am Laufen ist. Wenn eine zweit Anwendung in Ordnung geht könnte man einen Button auch auf den Screen zeichnen und per Mousehook abfragen ob ein Klick über ihm stattgefunden hat. Ja seeeehr unsauber, ich weiss ;)

Btw. gibt es die Möglichkeit (wahrscheinlich per WinAPI) einen weiteren Button in den Fenstertitel hinzufügen.
Manche Programme arbeiten damit (z.B. ScreenMaker 5, die sog. SWORD-Buttons).

Das wäre doch genau das richtige für dich.

Okay, wie gesagt, keine Ahnung wie es geht, sollte per google aber sicher herauszufinden sein.


IngoD7 - Mi 21.02.07 08:44

user profile iconKarlson hat folgendes geschrieben:
Das setzt aber vorraus, dass eine zweitanwendung am Laufen ist.
Ja, "Zweitanwendung" = sein Programm, aus dem der Button "übertragen" wird und dass sowieso irgendwas auslesen soll (siehe sein zweites Posting).

user profile iconKarlson hat folgendes geschrieben:
Wenn eine zweit Anwendung in Ordnung geht könnte man einen Button auch auf den Screen zeichnen und per Mousehook abfragen ob ein Klick über ihm stattgefunden hat. Ja seeeehr unsauber, ich weiss ;)

Wenn die eigene Anwendung läuft, brauchst du keinen Mousehook. Lediglich die "Berechtigung", einen Mausklick selbst weiterzureichen, muss man dem Button geben (ControlStyle-Eigenschaft). Dann wird bei Klick seine eigene OnClick in der eigenen Anwendung ausgeführt.

Wenn man einen Button so auf den Desktop legt (mit ParentWindow:=GetDesktopWindow), schwebt der da völlig eigenständig rum und informiert bei Klick seine Geburtsanwendung (also die, wo er herkommt).


peeage - Mi 21.02.07 19:25

Vielen Dank für eure Antworten, und einen besonderen Dank an IngoD7.

Deine Lösung funktioniert wunderbar.



mfg


GTA-Place - Do 22.02.07 21:09

@Ingo: Das scheint nicht mit Childs des Hauptwindows zu funktionieren:


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:
27:
28:
29:
30:
31:
function FindWindowEx2(hParent: HWND; ChildClassName: string; ChildNr: Word): HWND;
var
  i: Word;
  hChild: HWND;
begin
  hChild := 0;
  Result := 0;
  ChildNr := ChildNr - 1;

  for i := 0 to ChildNr do
  begin
    hChild := FindWindowEx(hParent, hChild, PChar(ChildClassName), nil);
    if hChild = 0 then
      Exit;
    Result := hChild;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Wnd: HWND;
begin
  Wnd := FindWindow('TMainForm', 'TeamSpeak 2');
  Wnd := FindWindowEx2(wnd, 'TPanel', 1);
  Wnd := FindWindowEx(wnd, 0, 'TRichEditWithLinks', nil);

  Edit1.Parent := nil;
  Edit1.ParentWindow := Wnd;
  Edit1.ControlStyle := Edit1.ControlStyle+[csClickEvents];
  Edit1.BringToFront;
end;


Wird nicht nach vorne gebracht. Nimm ich nur das Hauptformular (TMainForm, Teamspeak 2) funktioniert es und wenn ich das mit Parent und Co. weglasse und dem 3. Wnd (TRichEditWithLinks) den Fokus gebe, kommt das Fenster nach vorne, also er findet das richtige Window.


IngoD7 - Fr 23.02.07 16:15

user profile iconGTA-Place hat folgendes geschrieben:
@Ingo: Das scheint nicht mit Childs des Hauptwindows zu funktionieren:

Bei mir schon. :idea:

Folgendes verschiebt einen Button erfolgreich aus der Quell-(Eigen-)Anwendung in eine Fremdanwendung auf ein Panel.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.BeamenClick(Sender: TObject);
//Btn ist Button, der aus Eigenanwendung in Fremdanwendung verschoben wird.
//Form1 ist Titel (Caption) des Hauptfensters der Fremdanwendung.
//Panel1 ist Titel (Caption) eines Panels im Hauptfenster der Fremdanwendung.
var
  hnd1, hnd2 : integer;
begin
  Btn.Parent:=nil;
  hnd1:=FindWindow(nil,'Form1');
  hnd2:=FindWindowEx(hnd1,0,nil,'Panel1');
  Btn.ParentWindow:=hnd2;
  Btn.ControlStyle:=Btn.ControlStyle+[csClickEvents];
end;

Bei diesem Test war das Zielpanel vorher leer.
Etwaige Schwierigkeiten, den verschobenen Buton im Ziel zu sehen, mögen weiter bestehen, wenn dort andere Komponenten sind.

Es ist und bleibt nur ein Ansatz. :-)