neues Fenster automatisch erkennen
Moderator: jNizM
neues Fenster automatisch erkennen
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!
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!
Re: neues Fenster automatisch erkennen
Welche art von anwendungsfenster soll denn erfasst werden?
Re: neues Fenster automatisch erkennen
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.
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.
Re: neues Fenster automatisch erkennen
Zum beispiel Excel, Word, Internet Explorer, Firefox, etc.BoBo wrote:Welche art von anwendungsfenster soll denn erfasst werden?
Re: neues Fenster automatisch erkennen
Also in der regel Windows konforme standard applications (nix JAVA ) was es vereinfacht.TVTomy wrote:Zum beispiel Excel, Word, Internet Explorer, Firefox, etc.BoBo wrote:Welche art von anwendungsfenster soll denn erfasst werden?
just me's vorschlag sollte da schon passen
Re: neues Fenster automatisch erkennen
Oder mehrere WinWait?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!
Re: neues Fenster automatisch erkennen
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?
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?
Re: neues Fenster automatisch erkennen
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 %.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.
Re: neues Fenster automatisch erkennen
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. ( )
Und einen Tip könnte ich auch gebrauchen. Möglicherweise lerne ich noch was dazu. ( )
Code: Select all
compname:= A_ComputerName
;Clientabhängige Rechnerroutinen - wird nur alle 200ms ausgeführt
;nur die Kontrolle auf diese Fenster macht im Schnitt 15,7%
;mehr Timer oder irgendein Hook sind nicht an - einzig der Stundentimer
SetTimer, nopopup_%compname%, 200
;Errinnerungsfenster für die Schwestern, Kontrolle von Wochentag und Uhrzeit finden stündlich statt
If Instr("SP1 AnmeldungPC FUNKTION", compname) {
SetTimer, seldom_%compname%, 3600000
}
;wenn ein Rechner unbenutzt ist (Idle Zustand), werden bestimmte Routinen angehalten
SetTimer, UserAway, 30000
.
.
.
nopopup_AnmeldungPC: ;{
;drückt ein Fenster weg
ChipKartenNachfrage()
;schließt Teamviewer Hinweisfenster
TeamViewerGSClose()
;korrigiert die Fensterposition bei Veränderung der Position
If (WinActive("Telegram") or WinActive("Claws Mail")) {
MailAndTelegramWindow()
}
;HELP Taskbar für Praxomat
IfWinActive, ALBIS ahk_class OptoAppClass
AlbisHotKeyHilfe(AddendumHelp, PraxomatHelp)
;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") And CTTExist=0) {
AlbisCaveVonToolTip(compname)
} else If (!WinExist("Cave! von") And CTTExist=1) {
CTTExist=0
ToolTip,,,, 10
}
return
;diese wird nur einmal pro Stunde aufgerufen
seldom_AnmeldungPC:
If ( (A_WDay = Donnerstag) AND (A_HOUR > 10) AND (AuffuellFlag = 0) ) {
Auffuellflag = 1
IniWrite, 1, %AddendumDir%\Praxomat.ini, Anmeldung-PC, Auffuellflag
SprechzimmerAuffuellen("1")
}
If ( (Auffuellflag = 1) AND (!A_WDay = Donnerstag) ) {
Auffuellflag = 0
IniWrite, 0, %AddendumDir%\Praxomat.ini, Anmeldung-PC, Auffuellflag
}
return
;Funktionen -----
ChipKartenNachfrage() { ;automatisches Schließen des Fensters - der Patient hat in diesem Quartal seine Chipkarte noch nicht vorgelegt
SetTitleMatchMode, 2
CoordMode, ToolTip, Window
If WinExist("ALBIS", "Patient hat in diesem Quartal") {
ControlGet, BHwnd, Hwnd, , Button1, ALBIS
ToolTip, Chipkartennachfrage Fenster wurde gefunden`nEs wird geschlossen. Button "Ja" Hwnd ist: %BHwnd%, 100,2, 19
WinActivate, ALBIS ahk_class #32770, Patient hat in diesem Quartal
ControlFocus, Button1, ALBIS ahk_class #32770, Patient hat in diesem Quartal
ControlClick, Button1, ALBIS ahk_class #32770, Patient hat in diesem Quartal, LEFT, NA
sleep, 1000
ToolTip,,,,19
}
CoordMode, ToolTip, Screen
SetTitleMatchMode, Slow
}
TeamViewerGSClose() { ;schließt das Teamviewer Fenster automatisch
;schließen des gesponserte Sitzung Fenster von Teamviewer
If WinExist("Gesponserte Sitzung ahk_exe TeamViewer.exe") or WinExist("Verbindungs Timeout! ahk_exe TeamViewer.exe")
ControlClick, Button4, ahk_exe TeamViewer.exe ahk_class #32770
return
}
MailAndTelegramWindow() { ;fixieren der Positionen von ClawsMail und Telegramfenster am AnmeldungsPC
;ClawsMailFenster
ClawsID:= WinExist("Claws Mail ahk_class gdkWindowToplevel")
If (ClawsID) {
WinGet, minmax, minmax, ahk_id %ClawsID%
if (minmax<>0) {
WinRestore, ahk_id %ClawsID%
}
Claws_RecPointer:= GetWindowPos(ClawsID, ClawsX, ClawsY, ClawsW, ClawsH)
WinGet, Claws_Style, Style, ahk_id %ClawsID%
WinGet, Claws_ExStyle, ExStyle, ahk_id %ClawsID%
if (ClawsX<>1686 OR ClawsY<>12 OR ClawsW<>605 OR ClawsH<>1031) {
WinMove, ahk_id %ClawsID%,, 1686, 12, 605, 1031
}
if ((ClawsStyle<> 0x160F0000) OR (ClawsExStyle<> 0x00000110)) {
WinSet, Style, 0x160F0000, ahk_id %ClawsID% ; Entfernt die Titelleiste des aktiven Fensters (WS_CAPTION).
WinSet, ExStyle, 0x0000011, ahk_id %ClawsID%
}
}
;Telegram Fenster
TGramID:= WinExist("Telegram ahk_class Qt5QWindowIcon")
If (TGramID) {
WinGet, minmax, minmax, ahk_id %TGramID%
if (minmax<>0) {
WinRestore, ahk_id %TGramID%
}
TGram_RecPointer:= GetWindowPos(TGramID, TGramX, TGramY, TGramW, TGramH)
;WinGet, TGram_Style, Style, ahk_id %TGramID%
;WinGet, TGram_ExStyle, ExStyle, ahk_id %TGramID%
if (TGramX<>2302 OR TGramY<>13 OR TGramW<>654 OR TGramH<>1024) {
WinMove, ahk_id %TGramID%,, 2302, 13, 654, 1024
}
}
}
Re: neues Fenster automatisch erkennen
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 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):
Es könnte auch noch ewas bringen, MailAndTelegramWindow() und die zugehörige Abfrage
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:
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
Code: Select all
#NoEnv
SetBatchLines, ...
SetWinDelay, ...
SetControlDelay, ...
SetTitleMatchMode, ...
DetectHiddenWindows, ...
Code: Select all
If WinExist("ALBIS", "Patient hat in diesem Quartal") {
Als Beispiel für mögliche Verbesserungen mal ChipKartenNachfrage() und TeamViewerGSClose() (ungetestet):
Code: Select all
ChipKartenNachfrage() { ;automatisches Schließen des Fensters - der Patient hat in diesem Quartal seine Chipkarte noch nicht vorgelegt
SetTitleMatchMode, 2 ; Muss das hier geändert werden?
CoordMode, ToolTip, Window ; Warum? Es wird kein Tooltip angezeigt!
If WinExist("ALBIS ahk_class #32770", "Patient hat in diesem Quartal") { ; falls ahk_class #32770 benötigt wird
ControlGet, BHwnd, Hwnd, , Button1 ; last-found window
ToolTip, Chipkartennachfrage Fenster wurde gefunden`nEs wird geschlossen. Button "Ja" Hwnd ist: %BHwnd%, 100,2, 19
WinActivate ; last-found window
ControlFocus, , ahk_id %BHwnd% ; BHwnd benutzen
ControlClick, , ahk_id %BHwnd%, , LEFT, NA ; BHwnd benutzen
sleep, 1000
ToolTip,,,,19
}
CoordMode, ToolTip, Screen ; Warum? Siehe oben!
SetTitleMatchMode, Slow ; Ist das notwendig?
}
TeamViewerGSClose() { ;schließt das Teamviewer Fenster automatisch
;schließen des gesponserte Sitzung Fenster von Teamviewer
If WinExist("Gesponserte Sitzung ahk_class #32770 ahk_exe TeamViewer.exe") or WinExist("Verbindungs Timeout! ahk_class #32770 ahk_exe TeamViewer.exe")
ControlClick, Button4 ; last-found window
return
}
Code: Select all
;korrigiert die Fensterposition bei Veränderung der Position
If (WinActive("Telegram") or WinActive("Claws Mail")) {
MailAndTelegramWindow()
}
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
Code: Select all
If (ActiveID := WinExist("A")
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
;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
}
}
Re: neues Fenster automatisch erkennen
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.
Re: neues Fenster automatisch erkennen
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.
Re: neues Fenster automatisch erkennen
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 ... sleep+time
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?
https://autohotkey.com/boards/viewtopic ... sleep+time
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.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%
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?
Re: neues Fenster automatisch erkennen
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.läuft auf meinem Rechner (4 Prozessorkerne - 2 echte + 2 logische) mit ~13 % CPU-Last. Das ist ungefähr ein halber Kern.
Wenn ich nocheinfü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
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:
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
WaitUntil := A_TickCount + 60000
While (A_TickCount < WaitUntil) {
}
Wenn ich noch
Code: Select all
SetBatchLines, -1
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.
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:
Code: Select all
#NoEnv
SetBatchLines, -1
WaitUntil := A_TickCount + 1000
While (A_TickCount < WaitUntil) {
Sleep, 1
}
Als weiteres Beispiel:
Code: Select all
#NoEnv
SetBatchLines, -1
Iterations1 := 0
Iterations2 := 0
Sleep, 1 ; A_TickCount synchronisieren
WaitUntil := A_TickCount + 1000
While (A_TickCount < WaitUntil) {
Iterations1++
}
Sleep, 1 ; A_TickCount synchronisieren
WaitUntil := A_TickCount + 1000
While (A_TickCount < WaitUntil) {
Iterations2++
Sleep, 1
}
MsgBox, 0, Schleifendurchläufe, Ohne Sleep: %Iterations1%`nMit Sleep: %Iterations2%
Re: neues Fenster automatisch erkennen
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.
Re: neues Fenster automatisch erkennen
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
Irgendwo unten dann die Funktion "ShellMessage", um die Message auszuwerten
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)
An beliebiger Stelle außerhalb der Funktion steht dann das Label
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
Gui, New, +HwndFakeWinHwnd
DllCall( "RegisterShellHookWindow", UInt, FakeWinHwnd)
OnMessage( DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ), "ShellMessage" )
Code: Select all
ShellMessage(wParam,lParam) {
If ( wParam = 1 ) { ; HSHELL_WINDOWCREATED
; Ausgangszustand feststellen und versteckte Fenster für AHK sichtbar machen
HiddenWinState := A_DetectHiddenWindows
HiddenTextState := A_DetectHiddenText
DetectHiddenText, On
DetectHiddenWindows, On
; Infos über das neue Fenster abfragen
WinHWND := lParam ; Windows-Handle
WinGetPos , WinX, WinY, WinWidth, WinHeight, ahk_id %WinHWND% ; Koordinaten, Höhe und Breite
WinGetTitle, WinTitle, ahk_id %WinHWND% ; Fenstertitel
WinGetText, WinText, ahk_id %WinHWND% ; Textinhalt
WinGetClass, WinClass, ahk_id %WinHWND% ; Klasse (ahk_class)
WinGet, WinControlList, ControlList, ahk_id %WinHWND% ; Liste der Controls
WinGet, WinStyle, Style, ahk_id %WinHWND% ; Style
WinGet, WinExStyle, ExStyle, ahk_id %WinHWND% ; Extended Style
WinGet, WinPID, PID, ahk_id %WinHWND% ; Prozess-ID
For Process In ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where Handle=" . WinPID) { ; Infos über den Prozess holen
Commandline := Process.CommandLine ; Kommandozeilenaufruf
ExePath := Process.ExecutablePath ; Pfad zur EXE
}
;... weiterer beliebiger Code zur Auswertung der erhaltenen Informationen über das neue Fenster...
} ;# Ende der Funktion ShellMessage()
Kann z.B. so aussehen (wäre dann ein Teil des "weiteren beliebigen Codes" innerhalb der Funktion)
Code: Select all
;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
}
Code: Select all
; SFirm Passworteingabe
WatchSFirmAnmeldung:
IfWinActive, SFirm Anmeldung
{
Send, ********************{ENTER}
SetTimer, WatchSFirmAnmeldung, Off
}
Return
Re: neues Fenster automatisch erkennen
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.
Re: neues Fenster automatisch erkennen
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.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.
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
Re: neues Fenster automatisch erkennen
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.
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
Re: neues Fenster automatisch erkennen
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:
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
WinID:=WinExist("A")
popHwnd:= DLLCall("GetLastActivePopup", "uint", WinID)
Last edited by Frosti on 30 May 2018, 15:02, edited 1 time in total.
Who is online
Users browsing this forum: No registered users and 31 guests