Fenster erkennen und verstecken

Für Fragen von Einsteigern und Programmieranfängern...
mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Fenster erkennen und verstecken

Beitrag von mzurhorst »

Hallo zusammen,
Ich möchte gerne ein kleines Programm schreiben welches beim Starten einen Parameter übergeben bekommt (String, Titel eines Chrome Fensters).
Dieses Programm soll dann das passende Browserfenster anhand des Strings erkennen und dieses Fenster dann verstecken.

Wie gehe ich denn am besten vor, um mir die passenden APIs zusammen zu suchen?

Danke und viele Grüße,
Marcus



Hintergrund Info:
Wir setzen auf der Arbeit Siemens Teamcenter ein. Der SSO Login erfolgt über einen Tab im Browser. Dieser hält die Session zwischen Client und Server. Wir haben nun das Problem, das User gerne mal den Browser (mit mehreren Tabs) schließen und anschließend die Verbindung zum Server verloren geht und im schlimmsten Fall Daten verloren gehen.
Möchte nun im Browser selbst eine Extension installieren welche den Tab erkennt und in einem separaten Chrome Fenster isoliert, so das nun gezielt dieses Fenster versteckt werden kann.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Fenster erkennen und verstecken

Beitrag von theo »

Verstehe nicht wirklich, was du machen willst.
Hilft das? https://linux.die.net/man/1/wmctrl

mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Re: Fenster erkennen und verstecken

Beitrag von mzurhorst »

Hallo Theo,

ich versuche nochmal, es zu erklären. Meine Aufgabe ist zweigeteilt:
1. isoliere ich einen bestimmten Tab eines Chrome-Browsers unter Win10 in einem separaten Fenster. Die erfolgt mit Hilfe einer Extension direkt im Browser.
2. möchte ich danach dieses Fenster unsichtbar machen, so dass es nicht versehentlich von einem Anwender geschlossen werden kann. Dazu benötige ich ein kleines Tool, welches das Browserfenster erkennt und versteckt.

Mir geht es hauptsächlich um die Frage, wo ich für Win10 die entsprechenden APIs finde für das Arbeiten mit Fenstern.
Wenn ich nach "hide window" suche, dann gibt es fast ausschließlich Treffer, wie ich das eigene Programm verstecke; nicht aber wie man ein anderes Fenster versteckt.
Evtl. suche ich auch mangels Erfahrung nach den falschen Begriffen.

Grüße,
Marcus

Warf
Beiträge: 1910
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fenster erkennen und verstecken

Beitrag von Warf »

Ich geh bei sowas so vor, du suchst nach funktionen der Windows API, also um möglichst viele ergebnisse zu finden suche ich nach winapi + suchbegriff. Nicht nach lazarus + suchbegriff oder Delphi + suchbegriff, oder sonst irgendwas (das kommt später). Ich suche also als erstes nach "winapi hide window" (auf englisch hat man auch grundsätzlich bessere chancen).
Eines der ersten ergebnisse ist ein Stack Overflow thread indem von der funktion ShowWindow gesprochen wird, also suchen wir danach: "MSDN ShowWindow" und kommen auf die Dokumentation: Link. Beschreibung: Sets the specified window's show state. Schaut so aus wie das was wir wollen.

Die argumente sind hWnd und nCmdShow, wobei nCmdShow der neue status ist, mit einer Liste von möglichen werten, für uns relevant SW_HIDE (0) "Hides the window and activates another window." Klingt doch super.
hWnd ist A handle to the window. Also ist das nächste was man sucht: "WinAPI get window handle by name", und man findet diesen Stackoverflow thread
Using FindWindow requires that you either know the window class or the window title. Both of these are not necessarily unique.

Direkt mit ner verlinkung zur MSDN seite von FindWindowA.
Dort steht dann das FindWindow 2 parameter annimmt: lpClassName und lpWindowName, mit der beschreibung:
If lpClassName is NULL, it finds any window whose title matches the lpWindowName parameter.

Also ergibt sich als programm ungefähr sowas:

Code: Alles auswählen

uses windows; // winapi funktionen sind in der windows unit
...
var handle: HWND;
...
  handle := FindWindowA(nil, 'Fenstertitel');
  ShowWindow(handle, SW_HIDE); //falls SW_HIDE nicht gefunden wird, schreib einfach den wert (0) direkt rein


Manchmal sind WinAPI funktionen nicht so straight forward wie FindWindowA und ShowWindow, da würde ich dann empfehlen nach beispielen zu suchen, aus erfahrung kann ich sagen das man bessere chancen (bei winapi zeugs) hat nach delphi als nach lazarus zu googlen, ich würde also sowas wie "delphi findwindow" oder so googlen. Wenn ich da nix finde würde ich nach C++ suchen und versuchen das zu übersetzen (geht meist sehr einfach).

Ansonsten, bei solchen suchen ist weniger immer mehr. Such nicht nach sowas wie "lazarus hide window of chrome by title", das ist viel zu spezifisch. Du suchst nach einer Windows lösung, ob das jetzt Lazarus, Delphi oder C++ ist relativ egal, die unterliegende API kann überall benutzt werden (Du willst nur kein .Net kram, also C# oder VB haben). Das das fenster von chrome ist ist auch relativ egal, was für ein fenster geht sollte auch für das nächst beste andere fenster gehen. Und das du nach dem titel suchst, ist auch im ersten schritt irrelevant, du willst erst mal wissen wie du ein fenster versteckst, wie du an das fenster das du verstecken willst rankommst ist erst der zweite schritt. Damit wird daraus: "winapi hide window".

Ich muss aber zugeben, ich wusste an dieser stelle schon das das so generisch geht (man kann mit der WinAPI beliebige fenster aus beliebigen prozessen heraus steuern), das muss aber natürlich nicht der fall sein. Es kann also auch hilfreich sein sowas zu suchen wie "winapi hide window different process" oder sowas. Dabei hätte man dann das selbe gefunden.

PS: Browser sind etwas sehr komplex (chrome ist praktisch ein betriebsystem) es kann also gut sein das es nicht so trivial ist wie für andere anwendungen. Ich wär mir nicht so sicher ob es einfach möglich ist das fenster zu finden (kann sein das das tatsächliche website fenster mit dem titel ein subfenster von einem namenlosen überfenster ist) um die suche einzuschränken kannst du entweder EnumWindows benutzen (stand auch in einem der stack overflow threads) oder das lpClassName argument von FindWindowA benutzen.
Gibt auch einige tools mit denen du dir die Window structure anschauen kannst (z.b. Inspect von Microsoft), es kann sehr oft hilfreich sein sich für sowas zu erst anzuschauen wie der kram intern tatsächlich aufgebaut ist, und sich dann eine suchstrategie für diesen speziellen fall zu suchen. Aber dann kann es natürlich sein das eine solche Lösung mit der nächsten Chrome version wiederum kaputt gehen kann.

Die wahrscheinlich sauberere lösung wäre es wahrscheinlich für die website nen eigenen chrome prozess zu starten und den dann komplett zu verstecken (statt nach einem einzelnen fenster zu suchen), da du das ProzessHandle direkt aus der TProcess klasse bekommen kannst, wenn du chrome aus lazarus heraus öffnest, oder du einfach webkit oder gecko oder so in deinem lazarus projekt laufen lässt, und dann über ein chrome plugin die cookies der seite an das lazarusprogramm schickst, damit dieser dann die website in seinem eigenen browser öffnen kann.
Aber ich würds erst mal naiv versuchen, vielleicht mach ich mir hier schon wieder viel zu viele gedanken, und der zweizeiler oben reicht schon

mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Re: Fenster erkennen und verstecken

Beitrag von mzurhorst »

Wow, guten Morgen.
Das war genau was ich suchte.

Tatsächlich hatte ich es um 2 Uhr bereits hin gekriegt, aber nicht mehr geantwortet. Habe aber nicht mit so einem Frühaufsteher gerechnet :D
Damit funktioniert es wie gewünscht.

Ich muss mal schauen, wie viel Arbeit genau ich da rein stecke. Das waren nun nur wenige Stunden, mit tollem Erfolg.
Bin aber kein ITler, sondern Anwender unserer Unternehmenssoftware. Wollte nur nicht glauben, dass es "nicht geht" und mir selbst einen Proof-of-Concept bauen.
Am Ende kann das gerne noch viel besser von einem Profi umgesetzt werden.

Vielen Dank für den Tipp mit "winapi", das macht Sinn wie du es erklärst.

Grüße,
Marcus

Code: Alles auswählen

 
//  https://msdn.microsoft.com/en-us/data/72szh9c7(v=vs.85)
//  https://www.swissdelphicenter.ch/de/showcode.php?id=327
 
function FindWindowByTitle(WindowTitle: string): Hwnd;
var
  NextHandle: Hwnd;
  NextTitle: array[0..260] of char;
begin
  // Get the first window
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    // retrieve its text
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      Result := NextHandle;
      Exit;
    end
    else
      // Get the next window
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
  Result := 0;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  h: hwnd;
begin
  h := FindWindowByTitle('Browsertitel');
  if h <> 0 then // if we found notepad
    ShowWindow(h, SW_HIDE)
  else
    ShowMessage('not found.');
end;   
 

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Fenster erkennen und verstecken

Beitrag von theo »

mzurhorst hat geschrieben:2. möchte ich danach dieses Fenster unsichtbar machen, so dass es nicht versehentlich von einem Anwender geschlossen werden kann. Dazu benötige ich ein kleines Tool, welches das Browserfenster erkennt und versteckt.


Genau das macht wmctrl, nur halt für Linux, von Windows hattest du nichts gesagt. :wink:

mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Re: Fenster erkennen und verstecken

Beitrag von mzurhorst »

Ja, stimmt.
Ich bin davon ausgegangen dass Lazarus-Code unabhängig vom OS ist und das hinter den Kulissen erledigt.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Fenster erkennen und verstecken

Beitrag von theo »

mzurhorst hat geschrieben:Ja, stimmt.
Ich bin davon ausgegangen dass Lazarus-Code unabhängig vom OS ist und das hinter den Kulissen erledigt.

Ich weiss nicht, ob es ein Unit gibt, die solche Funktionen X-Platform kapselt. Denkbar ist das.
Aber beim manipulieren fremder Fenster bzw. des Windowmanagers verlässt man natürlich den Kern der Anwendungsprogrammierung.
Ausserdem sind die Unterschiede in der Funktionalität wahrscheinlich recht gross zwischen den Systemen.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: Fenster erkennen und verstecken

Beitrag von wp_xyz »

mzurhorst hat geschrieben:Ja, stimmt.
Ich bin davon ausgegangen dass Lazarus-Code unabhängig vom OS ist und das hinter den Kulissen erledigt.

Im Prinzip, ja. Aber wenn du die Unit "Windows" verwendest, dann wird das Programm eben von Windows abhängig. Um unabhängig vom OS zu werden, gibt es die Units LCLIntf, LCLType, LCLProc und LMessages - dort werden viele betriebssystem-spezifische Aufrufe für andere widgetsets implementiert. ShowWindow ist auch mit dabei, FindWindow dagegen nicht - also bleibt das ganze trotzdem eine "windows-only" Lösung.

Warf
Beiträge: 1910
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fenster erkennen und verstecken

Beitrag von Warf »

mzurhorst hat geschrieben:Tatsächlich hatte ich es um 2 Uhr bereits hin gekriegt, aber nicht mehr geantwortet. Habe aber nicht mit so einem Frühaufsteher gerechnet :D

Ich bin nicht früh aufgestanden, sondern sehr spät schlafen gegangen :D

mzurhorst hat geschrieben:Ja, stimmt.
Ich bin davon ausgegangen dass Lazarus-Code unabhängig vom OS ist und das hinter den Kulissen erledigt.

So als faustregel, wenn du auf was einfluss nehmen willst was nicht mehr Teil der eigenen anwendung ist (z.b. Fremde fenster bearbeiten, Prozessspeicher auslesen, Desktop hintergrundbild setzen, etc.) musst du wahrscheinlich auf die SystemAPI zugreifen.

Lazarus hat das ziel das LCL anwendungen überall gleich laufen, nicht eine komplette SystemAPI zu streamlinen. Das wäre ein komplettes projekt für sich (bzw. es ist ein komplettes projekt für sich, nämlich das ist genau was Wine macht)

mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Re: Fenster erkennen und verstecken

Beitrag von mzurhorst »

Hallo nochmal.

Ich wollte mal fix den Test aus dem GUI in ein schlichtes Executable umwandeln, welches bei Start die Prozedur startet.

Allerdings kriege ich nun einen Fehler beim Kompilieren in dieser Zeile:

NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);

Application sei nicht deklariert. Kommt das nicht auf den uses Windows?

Danke und Grüße,
Marcus

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Fenster erkennen und verstecken

Beitrag von theo »

TApplication ist in Forms und für's GUI gedacht:
https://lazarus-ccr.sourceforge.io/docs ... ation.html

mzurhorst
Beiträge: 11
Registriert: Sa 21. Dez 2019, 21:51

Re: Fenster erkennen und verstecken

Beitrag von mzurhorst »

Huch, welcher Handle ist das denn? Ich dachte das sei derjenige on z. B. dem Chrome Fenster, was versteckt werden soll.
Den muss ich doch auch finden können wenn ich selbst kein GUI habe.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Fenster erkennen und verstecken

Beitrag von theo »

mzurhorst hat geschrieben:Huch, welcher Handle ist das denn?

Das ist das von deiner eigenen GUI Anwendung.
Wie und ob das, was du willst von Console bzw. Service geht, muss dir ein Windows Spezialist oder Google beantworten. Das weiss ich nicht.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Fenster erkennen und verstecken

Beitrag von pluto »

Ich hatte mal angefangen teile von "wmctrl" nach Pascal zu Konvertieren.
es ist aber noch sehr früh am Anfang, dass geht aber nur soweit ich weiß unter X11 basierten Desktops.

Ich kann die Arbeitsfläche Wechseln und ich kann eine Liste der Fenster holen, dabei gibt es jedoch noch hin und wieder ein Pointer Fehler.
Im Anhang findet ihr mein Projekt.

In der Hauptunit findet ihr auch den Link zum Github von wmctrl, danach habe ich mich gerichtet.

Edit1: Es ist mehr zum Zeigen.... es ist halt noch sehr früh am Anfang.
Dateianhänge
plwmCtrl.zip
(120.84 KiB) 100-mal heruntergeladen
MFG
Michael Springwald

Antworten