neues Fenster automatisch erkennen

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

TVTomy
Posts: 2
Joined: 26 Mar 2018, 05:16

neues Fenster automatisch erkennen

26 Mar 2018, 06:35

Hallo!

Gibt es eine möglichkeit, dass automatisch im hintergrund erkannt wird, wann immer ein neues fenster vorhanden ist, damit dann eine bestimmte aktion durchgeführt wird?

Danke für die hilfe!
BoBo
Posts: 2515
Joined: 13 May 2014, 17:15

Re: neues Fenster automatisch erkennen

26 Mar 2018, 10:07

Welche art von anwendungsfenster soll denn erfasst werden?
just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

26 Mar 2018, 10:07

Moin,

eine Möglichkeit ist ein Timer, der regelmäßig die IDs der aktuellen Fenster abruft (siehe WinGet, ..., List - Beispiel #2) und mit dem Ergebnis des vorigen Aufrufs abgleicht. Wenn der aktuelle Aufruf eine ID liefert, die im vorigen Ergebnis nicht enthalten ist, ist das Fenster neu.
TVTomy
Posts: 2
Joined: 26 Mar 2018, 05:16

Re: neues Fenster automatisch erkennen

27 Mar 2018, 03:56

BoBo wrote:Welche art von anwendungsfenster soll denn erfasst werden?

Zum beispiel Excel, Word, Internet Explorer, Firefox, etc.
BoBo
Posts: 2515
Joined: 13 May 2014, 17:15

Re: neues Fenster automatisch erkennen

27 Mar 2018, 05:42

TVTomy wrote:
BoBo wrote:Welche art von anwendungsfenster soll denn erfasst werden?

Zum beispiel Excel, Word, Internet Explorer, Firefox, etc.
Also in der regel Windows konforme standard applications (nix JAVA ;) ) was es vereinfacht.
just me's vorschlag sollte da schon passen :)
Folllast
Posts: 67
Joined: 24 Jan 2018, 04:57

Re: neues Fenster automatisch erkennen

27 Mar 2018, 16:16

TVTomy wrote:Hallo!

Gibt es eine möglichkeit, dass automatisch im hintergrund erkannt wird, wann immer ein neues fenster vorhanden ist, damit dann eine bestimmte aktion durchgeführt wird?

Danke für die hilfe!


Oder mehrere WinWait?
User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

30 Apr 2018, 10:12

Das Problem mit Timer ist das das Programm die gesamte Zeit CPU-Zeit beansprucht. Um so kürzer das Intervall umso mehr. Selbst mit der schnellsten Untersuchung einer Liste kam ich bei meinen Versuchen nicht unter 10% Last, wenn die Erkennung neuer Fenster nicht über ein Intervall von 500ms gehen sollte. Wenn Du dann noch für mehrere Fenster automatische Funktionen bereitstellt dann erreicht Du fix 30% Auslastung.
Die Lösung ist OnMessage(). Darüber gibt es etliche Posts hier im Forum.
Aber alles was einen Vorteil hat, hat auch einen Nachteil. Die Auswertung der abgefangenen Nachrichten muss schnell erfolgen. Es ist aber auch wichtig das Schließen der Fenster abzufangen. Was machst Du mit dem Tool tip der noch angezeigt wird , wenn der User das Fenster schon lange geschlossen hat?
just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

30 Apr 2018, 15:56

Frosti wrote:Selbst mit der schnellsten Untersuchung einer Liste kam ich bei meinen Versuchen nicht unter 10% Last, wenn die Erkennung neuer Fenster nicht über ein Intervall von 500ms gehen sollte. Wenn Du dann noch für mehrere Fenster automatische Funktionen bereitstellt dann erreicht Du fix 30% Auslastung.

Mal abgesehen davon, dass TVTomy anscheinend nicht mehr auf eine Antwort wartet, ist das interessant. Mein Versuch mit einemTimerintervall von 10 ms zeigt im Taskmanager eine CPU-Auslastung von 0 %.
User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

01 May 2018, 13:59

Okay ich zeig dann mal den Code her, es wäre "genial" wenn ich es mir einfach nur schwer gemacht habe.
Und einen Tip könnte ich auch gebrauchen. Möglicherweise lerne ich noch was dazu. ( :dance: )

Code: [Select all] [Expand] [Download] (Unbenannt.ahk)GeSHi © Codebox Plus

just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

02 May 2018, 03:30

Moin,

meine Angabe zur CPU-Auslastung bezog sich auf die Abarbeitung einer mit WinGet, Liste, List erstellten Fensterliste bei der Suche nach neuen Fenstern. Dein Timer macht schon andere Dinge.

Was in Deinem Code zu sehen ist, spricht auf den ersten Blick nicht unbedingt für eine so hohe CPU-Auslastung. Das ist aber narürlich auch abhängig von der Leitsungsfähigkeit der Hardware, auf der das Skript läuft, und von weiteren Einstellung im Skript, wie

Dein Code macht es AHK aber auch nicht gerade leicht. Anweisungen wie

Code: [Select all] [Download] GeSHi © Codebox Plus

	If WinExist("ALBIS", "Patient hat in diesem Quartal") {
zwingen AHK immer wieder dazu, sich durch die Fensterliste und dann auch noch durch die Controls des Fensters zu hangeln. Die Win... und Control... Anweisungen bewirken viel weniger Aufwand, wenn man immer wenn möglich mit der ahk_id (HWND) arbeitet und/oder das "Zuletzt gefundene Fenster" 'benutzt', das von Anweisungen wie WinExist() oder IfWinActive gesetzt wird.

Als Beispiel für mögliche Verbesserungen mal ChipKartenNachfrage() und TeamViewerGSClose() (ungetestet):

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


Es könnte auch noch ewas bringen, MailAndTelegramWindow() und die zugehörige Abfrage

Code: [Select all] [Download] GeSHi © Codebox Plus

		;korrigiert die Fensterposition bei Veränderung der Position
If (WinActive("Telegram") or WinActive("Claws Mail")) {
MailAndTelegramWindow()
}
aufzuteilen. Aufgerufen wird die Funktion nur, wenn eines der Fenster aktiv ist. Innerhalb der Funktion spielt das dann aber keine Rolle. Hier könnte es sich auch lohnen, das zuletzt gefundene Handle (HWND) von "Claws Mail" in einer statischen Variablen zwischenzuspeichern. Es sollte eigentlich reichen, die Style und ExStyle Änderungen nur einmal zu machen.

Die Änderungenwirken sich aber nur aus, wenn die Fenster tatsächlich gefunden werden. Sollte die CPU-Last hauptsächlich durch die Fenstersuche im Timer entstehen, wird das nicht viel bringen. Es könnte aber etwas bringen, die wiederholten IfWInActive Anweisungen im Timer durch ein
zu ersetzen und anschließend selbst zu prüfen, ob das Fenster die Kriterien erfüllt. Und wenn eines der Fenster aktiv ist, können es die anderen nicht sein.

Die Funktionen AlbisHotKeyHilfe() und AlbisCaveVonToolTip() fehlen leider. Darin mag sich auch noch Zündstoff verbergen.

Edit:
Noch ein kleiner 'Verbesserungsvorschlag' um ein WinExist() einzusparen:

Code: [Select all] [Download] GeSHi © Codebox Plus

   ;diese Routine zeigt ein Ausfüllhinweis für die Angestellten an
;der muss natürlich geschlossen werden wenn das Fenster nicht mehr da ist
If WinExist("Cave! von") {
If (CTTExist = 0)
AlbisCaveVonToolTip(compname)
} Else {
If (CTTExist = 1) {
CTTExist := 0
ToolTip,,,, 10
}
}
User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

23 May 2018, 17:36

Ist jetzt einiges an Zeit vergangen und ich habe Deine Vorschläge umgesetzt. Es hat etwas gebracht. Ich liege circa bei 8-9% CPU Auslastung. Das ist aber immer noch zuviel. Ich habe mir jetzt allerdings auch nicht weiter den Kopf zerbrochen.
just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

24 May 2018, 01:18

Wenn Du Deinen aktuellen Code einstellst, würde ich mir den noch einmal intensiver anschauen. Eine CPU-Last von 0 % wird in diesem Fall aber eher nicht zu erreichen sein.
User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

24 May 2018, 14:38

Der aktuelle Code entspricht Deinen Änderungen. Hat doch aber auch was gebracht. Sieh mal was ich hier gerade aus einem anderen Thread von EvilC als Antwort gepostet gefunden haben.
https://autohotkey.com/boards/viewtopic.php?f=18&t=43060&hilit=Precise+sleep+time
while (A_TickCount < reopen)
{ ;do nothing
}

DO NOT do this. It will use LOTS of CPU time.
On my work PC, this code alone uses ~5% CPU

However, with MicroTimer, I can have a 1 MILLISECOND timer running and the CPU usage is like 0.1%


Diesen Teil mit A_Tickcount habe ich nicht gepostet. Ich bin zufrieden von 13-15% auf 8-9%. Ich habs jedoch in meiner vollen Blase, daß da noch irgendein anderer Grund da ist. Ich werde das Problem finden.
Ich möchte es jetzt auch allein finden. Neulich haperte es an meiner Konzentration und da habe ich halt gefragt weil es merkbar den Computer ausbremste und ich keine Lösung fand und das Problem weg musste.
Jetzt ist ein Ausbremsen nicht mehr zu merken und es hat deshalb Zeit.

Doch was denkst Du über obiges? Wie meint er das?
Meint er den Loop, den Variablenvergleich oder A_TickCount das CPU Zeit kostet oder die Kombination?
just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

25 May 2018, 03:01

Moin,

AHK führt den Skriptcode aus und braucht dafür Rechenleistung (CPU). Und weil es eine interpretierte Sprache ist, wird während der Ausführung ein Teil der Leistung nur für den Interpreter benötigt.

Code: [Select all] [Download] GeSHi © Codebox Plus

WaitUntil := A_TickCount + 60000
While (A_TickCount < WaitUntil) {
}
läuft auf meinem Rechner (4 Prozessorkerne - 2 echte + 2 logische) mit ~13 % CPU-Last. Das ist ungefähr ein halber Kern.
Wenn ich noch
einfüge, komme ich auf ~25 % CPU-Last. Das ist schon ein ganzer Kern. Es liegt daran, dass AHK die Skriptausführung dann nicht mehr regelmäßig intern unterbricht.

Für (A_TickCount < WaitUntil) muss AHK bei jedem Schleifendurchlauf
  • erst einmal den Ausdruck im Skriptcode parsen/auflösen,
  • dann den aktuellen Wert des Systemtimers TickCount per Aufruf der API-Funktion GetTickcount() abrufen,
  • dann den Wert der Variablen WaitUntil ermitteln
  • und schließlich beide Werte vergleichen.
Und wenn die Schleife nicht durch AHK selbst oder z.B. einen Timer unterbrochen wird, nimmt sich AHK dafür alle Rechenleistung, die zur Verfügung steht, maximal also einen kompletten CPU-Kern.

Die Schleife ist aber nicht nur ein 'CPU-Fresser', sie ist auch ein 'sinnloser' CPU-Fresser. Der Wert des Systemtimers TickCount wird auf normalen Rechnern nur alle 15 oder 16 (genauer ~15,625) Millisekunden verändert (es soll auch Systeme mit einem ~10 Millisekunden Intervall geben). In dieser Zeit wird die Schleife zig-mal durchlaufen und vergleicht 'sinnlos' immer wieder identische Werte. Und das bedeutet auch, dass AHK eine 'auf die Millisekunde genaue' Prüfung systembedingt nicht leisten kann. Es ist deshalb sinnvoll, in die Schleife ein Sleep Kommando einzufügen, das diesen sinnlosen Aktionismus abstellt. Das darf auch ein Sleep, 1 sein, weil auch die internen Prüfungen für den Ablauf der Sleep-Zeit auf den TickCount abgestellt sind. Ein Sleep, 1 wartet also darauf, dass der TickCount einen neuen Wert bekommt.

Deshalb:
Das reduziert die angezeigte CPU-Last hier auf 00 und reagiert mit einer Genauigkeit von 15,625 Millisekunden.

Als weiteres Beispiel:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

25 May 2018, 14:02

Grandios erklärt! Das sollte am besten in der Autohotkey Hilfe untergebracht werden. Jetzt verstehe ich warum es bei einem meiner anderen Skripte regelmässig zu CPU Auslastungspeaks kommt.
Gast

Re: neues Fenster automatisch erkennen

28 May 2018, 06:40

Ich möchte in diesem Zusammenhang noch einmal auf einen nicht ganz neuen Thread verweisen, der in der Google-Suche unter "[How to] Hook on to Shell to receive its messages?" zu finden ist. (https://goo.gl/cvHU1B)

Diese Methode führt nämlich zu überhaupt keiner relevanten Systemauslastung.

Bei mir läuft seit Jahren ständig ein Script mit ca. 1.400 Codezeilen im Hintergrund, was unter anderem sämtliche Fenster überwacht. Die Systemauslastung liegt dabei in Ruhe nie über 0,16%.

Der Ablauf sieht in etwa so aus, dass Windows ständig u.a. auch alle vorhandenen Fenster über gerade ablaufende Systemereignisse informiert.

Also erzeugt man ein Fake-Fenster und überwacht das Eintreffen dieser Messages.

Erhält das Fake-Fenster nun eine Benachrichtigung darüber, dass irgendwas mit einem anderen Fenster passiert, ruft der Befehl OnMessage die Funktion "ShellMessage" auf und man kann entsprechend auf das jeweilige Ereignis reagieren.

Meine Variante davon sieht so aus:
Am Anfang des Scriptes

Code: [Select all] [Download] GeSHi © Codebox Plus

	Gui, New, +HwndFakeWinHwnd
DllCall( "RegisterShellHookWindow", UInt, FakeWinHwnd)
OnMessage( DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ), "ShellMessage" )


Irgendwo unten dann die Funktion "ShellMessage", um die Message auszuwerten

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus



Allerdings werden nur "Elternfenster" erkannt. Erzeugen diese wiederum "Unterfenster" kann man von der Funktion aus z.B. einen Timer starten und über ein separates Label auf diese Fenster reagieren.

Kann z.B. so aussehen (wäre dann ein Teil des "weiteren beliebigen Codes" innerhalb der Funktion)

Code: [Select all] [Download] GeSHi © Codebox Plus

			;Automatisch einloggen wenn SFirm gestartet wird
If( ExePath = "c:\program files (x86)\sfirmv3\programm\sfmainprg.exe") {
SetTimer, WatchSFirmAnmeldung, 200 ; Label 'WatchSFirmAnmeldung' überprüft periodisch, ob das LogIn-Fenster vorhanden ist und trägt die LogIn-Daten ein
}


An beliebiger Stelle außerhalb der Funktion steht dann das Label

Code: [Select all] [Download] GeSHi © Codebox Plus

;	SFirm Passworteingabe
WatchSFirmAnmeldung:
IfWinActive, SFirm Anmeldung
{
Send, ********************{ENTER}
SetTimer, WatchSFirmAnmeldung, Off
}
Return
just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: neues Fenster automatisch erkennen

29 May 2018, 07:57

Ja, das ist eine gute Lösung. Sie verlangt vom Skriptschreiber aber mehr Kenntnisse, wenn er nicht einfach nur 'blind' Code kopieren will, den er dann möglicherweise nicht selbst warten kann. Wenn es geht, bevorzuge ich deshalb die eingebauten und dokumentierten AHK Anweisungen.
Gast

Re: neues Fenster automatisch erkennen

29 May 2018, 09:37

just me wrote:Ja, das ist eine gute Lösung. Sie verlangt vom Skriptschreiber aber mehr Kenntnisse, wenn er nicht einfach nur 'blind' Code kopieren will, den er dann möglicherweise nicht selbst warten kann. Wenn es geht, bevorzuge ich deshalb die eingebauten und dokumentierten AHK Anweisungen.

Wenn es um das grundlegende Verständnis für die in Windows ablaufenden Prozesse und für AHK geht, bist du hier vermutlich so etwas wie "das letzte Einhorn". Mit Glück gibt es hier noch 2 oder 3 weitere Leute mit Spezialwissen auf einzelnen Fachgebieten.
Irgendwie verstehe ich dann auch, dass man keine Lust hat, die Erklärung der Erklärung noch einmal erklären zu müssen und wie selbstverständlich davon ausgeht, dass tüfteln und nachdenken von den meisten Fragestellern nicht gewollt ist.

Anyway ... der Code enthält 6 Zeilen, die sich einem nicht wirklich von selbst erschließen. Der Rest ist frühe Kindersprache von AHK und in der Doc nachzulesen.

Wenn man bei AHK 3.0 dereinst nur noch durch Antippen von Kacheln fertige Codebausteine aneinanderfügen muss, werde ich glücklicherweise schon tot sein :offtopic:
User avatar
nnnik
Posts: 2905
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: neues Fenster automatisch erkennen

29 May 2018, 10:06

Entgegen aller deiner Unterstellungen hier dürften sich die meisten mit dem ShellHook auskennen und sich schon mal an einem ShellHook versucht haben.
Bei dem Versuch einen zu erzeugen wird einem dann doch relativ schnell klar wieso diese Technik nichts für Neulinge ist:
Sie ist sehr instabil. Für schon kleinere Verzögerungen schmeißt Windows dich aus der ShellHook raus - ohne Vorwarnung und ohne Hinweis.
Es gibt sehr viel was man beachten und wissen muss was einem auf Anhieb nicht direkt klar ist.
Für einen Neuling ist diese Technik nichts.
Recommends AHK Studio
User avatar
Frosti
Posts: 73
Joined: 27 Oct 2017, 14:30
Facebook: They have no decency!
Google: They have no decency!
GitHub: Ixiko
Location: Somwhere between Mars and Earth
Contact:

Re: neues Fenster automatisch erkennen

29 May 2018, 15:57

Ja als Neuling habe ich Shellhooks erstellt. Kein Ding. Das kapiert man schnell. Schwierig wurde es eben wenn wenn ChildWindows hinzu kommen. Mit der hier im Forum gefundenen Funktion IsBlocked() oder FindChildWindow oder noch einfacher (der Name fällt mir nicht ein gerade) einem einfachen DllCall einer WindowsRoutine mit der sich das zuletzt erstellte childwindow eines Prozesses ermitteln lässt , vereinfacht sich vieles. Letztere Funktion eignet sich hervorragend nach und nach alle blockierend ChildWindows zu schliessen um auf schnellem Wege auch ohne Enumerierung (so heisst das glaube ich) der Childs schnell weiter arbeiten zu können. Schwierig finde ich allerdings die Abarbeitung eingehender Messenges, wenn ich Subfunktionen aufrufe die langamer sind als die eintreffende Nachrichten. Mein Versuch zum zwischenpuffern der Messages (nennt man das Stack) hat mir zuviel Zeit gekostet und darum muss es über den die AHK internen Befehle erstmal reichen. Die Shellhooks laufen bei mir zu Hause bei meinem Scanprogramm. Ein Programm das manchmal Fenster nicht in der gleichen Reihenfolge öffnet. Auf Arbeit sind es gezählt 7 Programme die bearbeitet werden müssen. Wobei das Praxisprogramm manchmal childs öffnet manchmal eigene externe Prozesse mit eigenen Fenstern öffnet. Das Medikamentendatenbank nutzt 20 sichtbare Fenster und bei 200 (da habe ich aufgehört zu zählen) unsichtbare Fenster. So habt ihr beide durchaus recht. Ich schreibe meine Skripte so das interessierte Kollegen auch etwas damit anfangen können.
Try Ewig.langer().Objekt.Syntax.mit.(*Hashtag.enum.und."Sonstwas").bricht.mir.die.Augen.InsertAt(vorne):= Keine Ahnung.
Mehr versteh ich dann kaum und soll ja anpassbar bleiben und insbesondere für nicht Programmierer lesbar. Ansonsten bin ich ein Fan von Assembler! Der heutige Assemblercode ist allerdings nicht mehr so schön wie früher auf dem C64.

Anmerkung die wunderbare Funktion deren Namen ich nicht wußte ist diese hier:

Code: [Select all] [Download] (GetLastActivePopup.ahk)GeSHi © Codebox Plus

WinID:=WinExist("A")
popHwnd:= DLLCall("GetLastActivePopup", "uint", WinID)
Last edited by Frosti on 30 May 2018, 15:02, edited 1 time in total.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 2 guests