GuiCtrlBusy - wie ToolTip, nur anders ;-) - Final [v1.0]

  • Hi,

    Mehrere Busy's offen zu haben kann die Geschwindigkeit (zumindest bei mir) drastisch reduzieren (Ergebiss variiert stark bei jedem Durchlauf):

    Spoiler anzeigen

    Busy: 0 - ( 278.89ms )

    Busy: 1 - ( 380.03ms )

    Busy: 2 - ( 393.87ms )

    Busy: 3 - ( 540.40ms )

    Busy: 4 - ( 626.66ms )

    Busy: 5 - ( 1233.96ms )

    Busy: 6 - ( 3582.21ms )

    Busy: 7 - ( 8110.07ms )

    @OSVersion: WIN_10

    @AutoItVersion: 3.3.15.0

    >Exit code: 0 Time: 15.66

    Scheint nur bei $_iTimeCounter = 2 so extrem aufzutreten.

    (PC war recht ausgelastet wärend des Tests, unausgelastet kommt der Effekt vermutlich etwas später)

    AutoIt
    ; The default font size value needs to calculate for using in API funcs
    Global Const $giCALCFONTFACTOR = 1.67

    Gibt es dafür nicht _GDIPlus_FontGetHeight?

    mfg,

    Zeitriss

    Einmal editiert, zuletzt von Zeitriss (20. Oktober 2017 um 15:37) aus folgendem Grund: Falsche Varriable benützt, hatte aber keinen Einfluss aufs Ergebniss :-)

    • Offizieller Beitrag

    Gibt es dafür nicht _GDIPlus_FontGetHeight?

    Da ich den formatierten Text ausmesse mit _GDIPlus_GraphicsMeasureString sollte das eigentlich dieselben Werte zurück geben. Aber die Werte sind für WinAPI-Funktionen unbrauchbar. Mit dem Faktor kann ich das zumindest ausgleichen, indem ich vor dem Messen die logische Größe damit multipliziere. Bei exotischen Fonts (z.B. Deja Vu) geht das aber daneben.

    Falls du also eine Methode findest, wie man die Schriftgrößen für

    - native AutoIt Funktionen

    - GDI Funktionen

    - WinAPI Funktion

    hin- und her verrechnen kann, wäre das sehr hilfreich.

    • Offizieller Beitrag

    Scheint nur bei $_iTimeCounter = 2 so extrem aufzutreten.

    DANKE, das war der goldene Hinweis. Habe die entsprechende Abfrage zum Neuzeichnen angepasst und schon geht die CPU-Last auf < 10.

    Ich stelle Version v0.10 in Post #1 ein.

  • Schriftart: "Consolas"

    Links: _WinAPI_DrawText

    Rechts: _GDIPlus_GraphicsDrawString

    Ich habe willkürlich ein paar Schriftarten getestet, das Ergebniss von FontGetHeight schien eigentlich immer zu stimmen.

    mfg

    Zeitriss

    • Offizieller Beitrag

    Finale Version v1.0 im Startpost

    NEU

    - für jedes Ctrl eigenes Callback Intervall möglich

    - Ansicht des Ctrl kann zur Laufzeit geändert werden (nur Titel / Titel+Uhrzeit/Titel+Countdown)

    - Countdown (Timeout) ist mit jeder Ansicht verwendbar, Restlaufzeit über Platzhalter im Text anzeigbar

    - Icon aus allen *.dll und *.ico verwendbar

  • Super! :)

    Hier noch ein paar Dinge, die mir aufgefallen sind:

    Wenn für ein BusyCtrl ein Icon gesetzt wurde, wird es - auch wenn es nicht geändert wurde - bei jedem CallBackInterval neu geladen.

    Du prüfst in deinen Funktionen nicht, ob ein gültiges Window-Handle übergeben wurde... was z. B. dazu führt, dass nachdem $hBusy7 (in deinem Example) durch mein hinzugefügtes Event (s. w. unten) geschlossen wurde, durch einen Klick auf den Button $bt4 zwei neue BusyCtrl's erzeugt werden. 8|

    Icons auch aus 'exe' und 'icl' extrahieren...

    Code
    ;~             Case 'dll'
                Case 'dll', 'icl', 'exe'

    __WinAPI_IconFromDll

    Hier solltest du den Pointer für Large Icons setzen...

    Code
    ;~ Local $iIcons = _WinAPI_ExtractIconEx($_sDll, $_iIconID, $tIcons, 0, 1) ; Small Icons
    Local $iIcons = _WinAPI_ExtractIconEx($_sDll, $_iIconID, 0, $tIcons, 1) ; Large Icons


    Und eine Frage hätte ich noch... testweise habe ich mal für das Busy7 ein Event gesetzt.

    Code
    $hBusy7 = _GuiCtrlBusy_Create('Nr 7', 'Titel && Zeit\nScheme: Orange\nund eine Zeile #3\nund auch noch eine Zeile #4', -1, 100, 550, 0, 2, 'orange', True)
    GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, '_CloseBusy')
    
    Func _CloseBusy()
        _GuiCtrlBusy_Close(@GUI_WinHandle)
    EndFunc

    Ist es "normal", dass ich die Maustaste ca. 1 Sekunde lang drücken, damit dieses Event ausgelöst wird?

    • Offizieller Beitrag

    Du prüfst in deinen Funktionen nicht, ob ein gültiges Window-Handle übergeben wurde... was z. B. dazu führt, dass nachdem $hBusy7 (in deinem Example) durch mein hinzugefügtes Event (s. w. unten) geschlossen wurde, durch einen Klick auf den Button $bt4 zwei neue BusyCtrl's erzeugt werden.

    Ha-Ha, da habe ich mir ja ein Ei gelegt. Manchmal scheitert man an der eigenen Logik. Um die Überprüfung schlank zu halten, war mein Gedanke: Index vorbelegen mit "-1" und als hWnd "Null" übergeben um Neuerstellung zu bewirken, denn hWnd "Null" gibt es nicht also bleibt Index -1 == Neu. Dass der Index auch -1 bleibt, wenn ich ein falsches Fenster übergebe und somit auch Neu ausgelöst wird, kam mir irgendwie nicht in den Sinn X/. Da werde ich etwas umbauen.

    Icons auch aus 'exe' und 'icl' extrahieren...

    Hier solltest du den Pointer für Large Icons setzen...

    Danke für die Hinweise, werde ich übernehmen.

    Ist es "normal", dass ich die Maustaste ca. 1 Sekunde lang drücken, damit dieses Event ausgelöst wird?

    Ich könnte ja sagen, es ist ein Feature, aber tatsächlich habe ich adhoc keine Erklärung. Das werde ich mal genauer unter die Lupe nehmen.

    Nochmals Danke fürs Testen. Ist schon komisch, dass man bei eigenen Werken eine Art Betriebsblindheit hat und bei Fremdprodukten auf einen Blick die Schwachstellen sieht. Das ist halt auch das Gute am Forum, der Blick aus einem anderen Winkel.


    EDIT:

    Mir ist gerade noch etwas aufgefallen. Nach Auslösen des Events $GUI_EVENT_PRIMARYDOWN (also Aufruf von _GuiCtrlBusy_Close) funktioniert mein Dummy nicht mehr, das heißt ab diesem Zeitpunkt schlägt das Senden der Closed-Msg fehl (GUICtrlSendToDummy wird ausgeführt, gibt aber 0 zurück = Fehler). (neue Baustelle)

    Das ist dann gültig für alle noch existierenden Ctrl. - Kannst du das verifizieren?

    EDIT-2:

    Das macht mich konfus. Mit _GuiCtrlBusy_Close wird im Parameterarray des Ctrl der Wert [$__gbBrake] auf True gesetzt. Im Callback prüft ein If-Statement ob dieser Wert True ist oder die Zeit abgelaufen ist. Bei abgelaufener Zeit funktioniert der Closed-Dummy, bei Setzen von True für [$__gbBrake] aber nicht, obwohl beide Abfragen im selben Statement sind!

    AutoIt
    ; brake by script OR timeout/safety timeout ended
    If $gaGCB_CTRL[$idxCtrl][$__gbBreak] Or _
       $iTime - $gaGCB_CTRL[$idxCtrl][$__giTimestamp] >= ($gaGCB_CTRL[$idxCtrl][$__giTimeOut] = 0 ? $GCB_U_TIMEOUT_ZERO : $gaGCB_CTRL[$idxCtrl][$__giTimeOut])*1000 Then

    Jetzt wollte ich tricksen und statt [$__gbBrake] = True, einen Fantasie Timestamp und Timeout setzen, sodass dieser Abfragezweig zum Beenden des Ctrl führt. Das klappt auch, aber auch mit dem Effekt, dass der Dummy nicht mehr angesprochen werden kann.

    Ich habe dafür keine Erklärung. Das entzieht sich meinem Verständnis.

    Vielleicht hat jemand eine zündende Idee?

    EDIT-3:

    Manchmal bleiben nur Umwege. Ich habe versucht GUICtrlSendToDummy auszulagern, aber der Fehler trat immer weiter auf.

    Jetzt werde ich wieder auf die anfangs verwendete Variante mit _SendMessage zurückgreifen. Im ersten Versuch gab es damals ein Problem, dass beim letzten Ctrl, dessen Closed-Msg 'verloren' ging. Ich nehme jetzt ein unsichtbares Fenster zum Aufnehmen der Closed-Msg. (wird mit _GuiCtrlBusy_GetClosed erstellt). Außerdem puffere ich die Nachrichten intern, sodass keine Nachricht verloren gehen kann. - Das ist erstmal der Plan.

    Bleibt nur noch das Problem, der Zeitverzögerung beim Auslösen des Event. Da habe ich noch keinen Lösungsansatz.

  • Wenn in allen relevanten Funktionen überprüft wird, ob ein gültiges Window-Handle übergeben wurde und andernfalls direkt wieder mit Return SetError(1, ...) rausgesprungen wird, können alle BusyCtrl's in beliebiger Reihenfolge mit einem Linksklick geschlossen werden, insofern sie nicht bereits durch ein gesetztes TimeOut gekillt wurden. Nachdem alle BusyCtrl's geschlossen wurden (das letzte mit Linksklick), werden zwei weitere BusyCtrl's erstellt... die sich dann auch wieder mit Linksklick schließen lassen... oder via TimeOut... bis der Arzt kommt.

    :rock:

    Kurz:

    Code
    ConsoleWrite(StringSplit("Alles funktioniert wie erwartet!|Kann keinen Fehler mehr entdecken.", '|', 2)[Random(0, 1, 1)] & @CRLF)
    • Offizieller Beitrag

    Ich habe jetzt eine Lösung, die alle (bisher bekannten) Macken fixen sollte. Den Dummy habe ich rausgeworfen, dafür gibt es $WM_COMMAND zum Auswerten. Damit die Zeitverzögerung beim Mausklick eleminiert werden kann, habe ich die Maus gehookt und Events für Klick links/rechts auf das Ctrl eingebaut.

    Probiere mal, ob du da noch Fehler entdecken kannst.

    Ich schaue mir derweil mal deinen Code an.

    P.S. Habe deine Variante gerade ausgeführt - das Dummyproblem lässt sich damit auch nicht beheben. Finde diese Dummy-Lösungen eigentlich recht elegant, da man einfach nur eine ID abfragen muss. Warum die Funktion in diesem Kontext aussteigt, ist mir nicht plausibel. Ich werde bei Gelegenheit mal probieren, das Problem auf Minimalcode runterzubrechen, vielleicht findet man dann die Ursache (oder einen Bug).