Entwickler-Ecke

Windows API - Browserfenster öffnen & Handle erhalten


Ch0sen - Mi 11.08.10 23:24
Titel: Browserfenster öffnen & Handle erhalten
Hallo liebe Forengemeinde :-)

Ich beschäftige mich schon seit mehren Jahren mit Delphi, bin also kein Neuling mehr. Trotzdem bin ich nun auf ein Problem gestoßen, welches ich erstmals mit "googlen" nicht lösen konnte.
Es geht dabei um folgendes:

Ich möchte ein Browserfenster des Standardbrowsers öffnen - soweit so gut und nicht das Problem. Dabei möchte ich aber das Handle von GENAU diesem geöffneten Fenster bekommen. Wie ich im allgemeinen das Handle eines Fensters bekomme ist mir bekannt, doch das Ermitteln des Handles über den Fensternamen bringt mir nichts, da ich in meinem Programm mehrere Fenster mit der gleichen Website öffnen möchte. Zudem muss ich davon ausgehen, dass bereits ein oder mehrere Fenster mit der selben Website geöffnet sind.
Ich brauche also direkt nach dem Aufruf der ShellExecute das Handle des gerade geöffneten Browserfensters, um Programmintern eine Nummerierung vornehmen zu können.

Ich hoffe ich konnte mein Anliegen einigermaßen klar zum Ausdruck bringen und des weiteren natürlich, dass Ihr eine Lösung für mich habt.

Vielen Dank schon einmal,

Gruß Chosen


MaPsTaR - Mi 11.08.10 23:38

Soweit ich weiß gibt ShellExecute einen Wert zurück.
WIN-SDK hat folgendes geschrieben:
Return Values
If the function succeeds, the return value is the instance handle of the application that was run, or the handle of a dynamic data exchange (DDE) server application.

Bin mir aber nicht sicher, ob das gleichzeitig auch das Handle von dem Fenster ist.

EDIT:
Wenn du das neue Fenster öffnest sollte es doch im Vordergrund sein, oder?
Vielleicht hilft dir dann Handle := GetForegroundWindow; weiter.


Ch0sen - Mi 11.08.10 23:57

Ich danke dir für die schnelle Antwort MaPsTaR!

Der Rückgabewert der ShellExecute ist leider nicht das Handle, auf diese Idee war ich auch schon gekommen. Das wäre echt göttlich ^^
Er ist lediglich ein Fehlercode.
Auf die Idee mit dem "Fenster im Vordergrund" war ich bisher noch nicht gekommen. Ich denke das ist machbar, ich werde es auf jeden Fall mal versuchen und hier ein Feedback wiedergeben.

Natürlich bin ich trotzdem für weitere Lösungsansätze offen, falls jemand noch eine Idee hat.

Gruß Ch0sen


Narses - Do 12.08.10 00:02

Moin!

user profile iconCh0sen hat folgendes geschrieben Zum zitierten Posting springen:
Natürlich bin ich trotzdem für weitere Lösungsansätze offen, falls jemand noch eine Idee hat.
Keine Ahnung, ob das weiter hilft, aber Suche in: Delphi-Forum, Delphi-Library SHELLEXECUTEEX liefert zumindest das Prozess-Handle. :idea:

cu
Narses


Hidden - Do 12.08.10 09:09

Hi,

Wenn der Browser bereits läuft und du weitere Fenster öffnest, führt das bei aktuellen Browsern leider dazu, dass alle Tabs verloren gehen, sollten sie in der falschen Reihenfolge geschlossen werden.
Sollte der Browser entsprechend konfiguriert sein, hast deshalb gar keine andere Wahl als, einen neuen Tab im bereits existierenden Browser zu nehmen. :)

Zur Frage: Wenn es denn wirklich sein muss und die erklärte Methode nicht funktioniert, kannst du auch alle Handles von entsprechend benannten Browserfenstern listen, ein neues öffnen, wiederum auflisten und die Listen vergleichen -> Es sollte nur ein Handle hinzugekommen sein :)

lg,

E: Tippfehler ausgemerzt.


Ch0sen - Do 12.08.10 11:25

user profile iconMaPsTaR hat folgendes geschrieben Zum zitierten Posting springen:

EDIT:
Wenn du das neue Fenster öffnest sollte es doch im Vordergrund sein, oder?
Vielleicht hilft dir dann Handle := GetForegroundWindow; weiter.

Ja man sollte meinen das Fenster ist im Vordergrund, jedoch liefert mir die Routine Handle:=GetForegroundWindow; nicht das gewünschte Ergebnis :-(


user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Keine Ahnung, ob das weiter hilft, aber Suche in: Delphi-Forum, Delphi-Library SHELLEXECUTEEX liefert zumindest das Prozess-Handle. :idea:

Ich habe noch in der Nacht und auch heute morgen ein wenig mit dieser Funktion herumprobiert, leider jedoch ohne Erfolg. Man kommt durch diese Funktion zwar an die ThreadID sowie an die ProcessID ran (genau wie bei CreateProcess), doch alle weiteren Funktionen welche ich beim durchstöbern des Forums und des Internets gefunden und getestet habe um von der ThreadID/ProcessID auf das Windowhandle zu kommen schlugen fehl.

Schade, denn ich dachte dein Tipp bringt die Lösung.


user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
Wenn es denn wirklich sein muss und die erklärte Methode nicht funktioniert, kannst du auch alle Handles von entsprechend benannten Browserfenstern listen, ein neues öffnen, wiederum auflisten und die Listen vergleichen -> Es sollte nur ein Handle hinzugekommen sein :)

So ich bin gerade am Testen ob ich dies so hinbekomm', aber ich bin sehr zuversichtlich, denn soetwas in der Art habe ich schon einmal gemacht. Dass ich da nicht drauf gekommen bin, oh man ^^


Ich möchte hiermit nocheinmal allen für die schnellen Antworten und die zahlreichen Lösungsansätze danken! *Daumen hoch*

Gruß Ch0sen


Ch0sen - Do 12.08.10 15:16

So Dank des Schubsers von Hidden habe ich eine Lösung für mein Problem gefunden :-)


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:
type THandleArray = array of HWND;

function FindAllWindowsByTitle(WindowTitle: string): THandleArray;
var
  NextHandle: Hwnd;
  NextTitle: array[0..260of char;
begin
  //Erstes Fenster bekommen
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    //Text des Fensters holen und vergleichen
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      //dyn. Arr um 1 Element vergrößern
      setlength(Result,high(result)+2);
      Result[high(result)]:= NextHandle;
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
    end
    else
      //nächstes Fenster bekommen
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
end;

Hier noch der Aufruf sowie die Ausgabe in einer Listbox:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.Ausgabe;
var arr: THandleArray;
      i: Integer;
begin
  arr:= FindAllWindowsByTitle('Delphi-Forum.de');
  for i := 0 to high(arr) do listbox1.Items.Add(inttostr(arr[i]));
end;

Die Liste der so erhaltenen Handles brauche ich somit nur noch vergleichen mit der neuen Liste, wenn ich ein weiteres Browserfenster geöffnet habe und schon habe ich den Übeltäter *g*

Zum Abschluss möchte ich nocheinmal allen für ihre Ideen Danken, beim nächsten "unlösbar" scheinendem Problem werde ich gerne wieder auf eure Hilfe zurückgreifen :-)

Gruß Ch0sen


Edit: Vereinfachung (Vorschlag Stundenplan) umgesetzt.


Stundenplan - Do 12.08.10 15:23

Übrigens, du musst nicht die Größe des Arrays im ersten Element speichern, High(MyArray) gibt den Index des letzten Elements zurück! :wink:


Ch0sen - Do 12.08.10 15:27

user profile iconStundenplan hat folgendes geschrieben Zum zitierten Posting springen:
Übrigens, du musst nicht die Größe des Arrays im ersten Element speichern, High(MyArray) gibt den Index des letzten Elements zurück! :wink:


Nun ich habe nach einer solchen Funktion gesucht, nur diese nicht gefunden, danke für den Tipp, das verkürzt den Quelltext natürlich noch etwas :-)