Labelaktualisierung will wieder mal nicht

  • Hallo liebe Forengemeinde,

    ich habe mal wieder ein fachliches Problem. Ich habe ein kleines Druckermodul gescriptet, welches mir getrennt nach Netzwerk/lokal die installieten Drucker anzeigt, und vorhandene Netzwerkdrucker zum einbinden bereit hält. Soweit klappt schon alles prima, eigentlich dachte ich ich hätte den schwierigsten Teil hinter mir, jetzt bekomme ich es ums Verrecken wiede nicht hin, das Label $Standardpronter zu aktualisieren bei Case = default. Vielleicht kann mir ja einer auf die Spünge helfen. Mein kleines DruckerScript schaut so aus:

  • jo danke erstmal, das habe ich schon alles vesucht, mit und ohne -1, zuletzt sag die Case Anweisung, wo er ja dann aktualisieren soll, so aus:

  • versuch mal

    edit :

    jetzt sehe ich wo dein problem ist.


    Einmal editiert, zuletzt von MojoeB (28. April 2023 um 19:01)

  • Wow, dass war es ja, ich musste das CreateLable extra als Variable einführen, hatte ich ganz verpeilt, hoffe ich merk mir das jetzt endlich,

    Recht herzlichen Dank noch mal und ein schönes Wocheende

  • Vielleicht darf ich in diesem Zusammenhang noch eine Frage stellen, vielleicht etwas kniffliger. Eigentlich wollte ich der Übersichtlichheit die lokalen und die verbundenen Drucker getrennt darstellen, wahrscheinlich macht das das Problem. Ich habe nämlich versucht die Button nicht nur auf das obere Fenster anzuwenden, sondern auch auf das untere, aber dass wird wohl nicht so einfach gehen oder? , schon weil wenn man einmal im oberen Fenster was ausgewählt hat diese Markierung nicht mehr gelöscht kriegt, bzw dann 2 hat, eine im oberen, eine im unteren Fenster. Ich hoffe ihr versteht was ich meine.

    lg und schönen Abend noch mal

  • kannst du bitte mal dein komplettes Skript posten mit includes ?
    weil ohne diese kann man das Skript nicht mal starten deshalb weiß ich auch nicht was du damit meinst :

    'Eigentlich wollte ich der Übersichtlichheit die lokalen und die verbundenen Drucker getrennt darstellen, wahrscheinlich macht das das Problem. Ich habe nämlich versucht die Button nicht nur auf das obere Fenster anzuwenden'

    ^^

  • Hi, ich hab den ganzen Code mal umstrukturiert. Dazu kommen dann ein paar Hinweise, was ich geändert hab. Ich hab dabei auch umgesetzt, was du am Ende erfragt hast: Aus den beiden Listen kann immer nur ein Eintrag gleichzeitig ausgewählt werden und der ausgewählte Drucker wird verwendet, egal aus welcher Liste.

    Also, fangen wir mal an:

    1. Ich würde dir empfehlen beim programmieren mehr auf sauberen Code zu achten. Bei deinem Code ist die Einrückung das reinste Chaos, Deutsche/Englische Variablen sind gemischt,... Sauberer Code ist das wichtigste um effektiv zu programmieren und Fehler schnell zu erkennen/finden.

    2. Du verwendest das ganze in einem größeren Script (vermute ich mal, weil du statt exit nen anderes Fenster einblendest, alles in einer Funktion ist,...). Dabei würde ich dir den GuiOnEventMode empfehlen. Dann bleibt das Hauptfenster responsive, auch wenn du das extra Fenster öffnest, weil du nicht die While-Schleife des zweiten Fensters hast, was verhindert, dass die Schleife des ersten Fensters abgearbeitet wird. Kann man zwar auch mit GuiGetMsg lösen, das wird dann aber komplizierter. Dabei kann ich auch gleich erwähnen, dass ich WinOnTop rausgenommen hab und dadurch ersetzt habe, dass das Printer-Fenster das Hauptfenster als Parent bekommen hat. Dadurch ist es automatisch über dem Parent-Fenster, ohne dass es global über allen Fenstern (inkl. der Drucker Einstellungsfenster,...) ist.

    3. Vermeide doppelten/mehrfach gleichen Code. DruckerFenster, DruckerEigenschaft, DruckerEinstellung und Testdruck haben quasi immer den gleichen Code, das einzige was sich ändert ist der Parameter bei dem Command der mit RunWait ausgeführt wird (/o /p /e /k). Also einfach ne Funktion schreiben, wo das übergeben wird und schon hast du den Code nur an einer Stelle.

    Ähnliches hab ich für das Füllen der Listen/Combos gemacht. Ich hab eine Update-Funktion für jedes Control erstellt, welche die Liste leert und neu befüllt. Deshalb kann ich mit einem Funktionsaufruf alles aktualisieren, wenn das Fenster erneut angezeigt wird.

    Selbiges habe ich auch für die Abfrage des ausgewählten Druckers implementiert. Und ebenso für die Adresse des Druckservers.

    4. Beim erstellen des Fensters habe ich wie immer alle Pixeleinheiten in Variablen verlagert. Dadurch kannst du die Variablen am Anfang der Funktion ändern und alle Controls passen sich automatisch an. Macht das Designen deutlich einfacher, weil nur an einer Stelle z.B. die Breite der rechten Buttons geändert werden muss und sich alle anderen Controls automatisch daran anpassen.

    5. Error Handling: Immer wenn es eine Möglichkeit gibt, dass eine Funktion schiefgehen kann sollte man Fehler hinzufügen, die man beim Aufruf der Funktion dann prüfen kann. Wenn dann später was schief geht bekommt man direkt eine Fehlermeldung mit der passenden Nummer und weiß wo das Problem ist.

    6. Ich hab die Combobox für Netzwerkdrucker ausgeblendet, wenn der Server nicht erreichbar ist und stattdessen ein Label dort angezeigt. Ist etwas übersichtlicher und man kann nicht ausversehen "Kein Printserver" als Drucker auswählen. Da kommen nen paar nette Fehlermeldungen ;)

    Ich hoffe die Tipps helfen dir weiter :)

    MfG, Kanashius.

  • klar kann ich machen, schaut so aus:

    ein schönes WE

  • na umstrukturiert ist gut, hast wohl eher komplett neu geschrieben;) Auf jeden Fall kann ich schon mal sagen, dass es nicht funktioniert, es kommt ein Fehler in Zeile 234 (If UBound...) Error: Array variable has incorrect number of subscript .... Mit Deinen Kritikpunkten hast Du natürlich voll und ganz recht, auch wenn ich nicht ganz nachvozziehen kann, was an meinen Einrückungen zu bemeckern ist, ich wills halt gern nachvollziehen können;)

    So melde mich später wieder

  • Eine sehr interessante Art und Weise die Buttons zu erzeugen (mit Arrays), wusste ich gar nicht dass das geht, wobei ich mir trotzdem die Frage stelle, ob dass irgendwie einen Geschwindigkeitsvorteil oder so am Ende mitbringt.. Was sich da erst mal mitnehme, ist wohl die Empfehlung, für jede Anweisung eine ID zu vergeben, man weiss ja nie in welcher Form man damit hinterher noch operieren muss. Dass ich das nicht getan habe lag wohl eher daran, dass dieses Modul, und ja es ist Teil eines großen Ganzens, am Anfang nicht so groß gedacht war, und dann natürlich Etrawünsche im Laufe der Zeit dazu kommen.

    Warum dein Code bei mir nicht läuft ist mir aber schleierhaft, dass gab es ja schön öfter hier, vielleicht fehlt mir ja auch eine UDF. Noch eine Interessante Einlassung fand ich deine Bemerkung, dass ich mit GUISetOnEvent eine existierende Haupt Gui weiter bedienbar halte, ist das wirklich so, bisher habe ich immer gelsen, dass Autoi eine solche Multitaskingfähigkeit wohl eher nicht hätte, aber vielleicht war das ja Unsinn, ich lasse mich gerne eines besseren belehren.

    Nachtrag

    Soweit hab ich dein Vorgehen jetzt erst mal verstanden, dass ich um die anderen Sachen am Ende auch noch zu aktualisieren, noch einige Sachen als Funktion auslagern muss war mir schon irgendwie klar, wie gesagt, soweit hate ich am Anfang nicht gedacht. Um Deinen Code mal lauffähig zu machen habe ich den Inhalt deiner Rsestfunktion mal stumpf auskommentiert. Nun bekomm ich Deine GUI geladen, nun fällt auf, dass das Feld mit den verbundenen Druckern schon mal leer bleibt, bei mir sollten hier jedoch 2 vorhanden sein. Möglicherweise hast du win11 (habe noch 10) und du besitzt diesen Key gar nicht mehr. Eine Combo unten taucht gar nicht auf. Somit kann ich natürlich auch nicht testen, ob das mit den Buttons und der unabhängigen Auswahl aus den Listenfeldern wirklich funktioniert, zumal hier noch zu beachten ist, dasbei den Verbundenen Rechnern der Printserver und nicht @local vorangestellt werden muss.

    Nachtrag2

    Ich habe die Funktion _updateConnectedPrinters wieder vollständig drin aber habe die zeile mit dem Ubound nun leicht verändert:

    If UBound($arPrinter)>1 Then _GUICtrlListBox_AddString($idList, $arPrinter[2])

    Dieses führte jetzt zumindest zur Anzeige eines der beiden bei mir verbundenen Druckern, zuätzlich wurden 2 Zahlen im List2 Feld gezeigt. Ein ComboFeld erscheint bei mir aber weiterhin nicht

    Nachtrag3:

    Ok Zeile 232 muss doch heissen Local $arPrinter = StringSplit($sPrinterName, ",", 1+2), jetzt stehen nur die Rechnernamen drin. Haste wahrscheinlich extra reingemacht, damit ich was zum tüfteln habe lach. So mit dem Abwählen der Selektion funktioniert jetzt super, wie gesagt ich muss nun noch irgendwie entscheiden, ob es ein Lokaler Drucker ist oder nicht, da sonst der Druckerstring nur bei den lokalen geht. Warum die Combo nicht will ist mir immer noch rätselhaft

    Btw: Wie kommt man eigentlich darauf, also als mit durchschnittlichr Fantasie ausgestatteter Mensch auf die Idee, dass es eine Funktion Namens _GUICtrlListBox_SetCurSel gibt? Das ist ja wohl hier die eigentliche Lösung meines Problems. Gibbet da irgendwo ein Buch wo sowas drin steht, oder muss man dazu sämtliche UDFs die es so gibbt auswendig kennen lach?

    lg und schönen Abend noch

    PS Ich sehe gerade Deinen Code durch und weiss jetzt wass du mit Einrückungen meintest, ich habe Dir wohl zu viele gemacht, hat etwas gedauert;) Du hast ja so gut wie gar keine. schein wohl Geschmackssache zu sein, mach ich keine, bekomm ich auf den Deckel, mach ich welche krieg ich auch;)

    10 Mal editiert, zuletzt von casi4712 (29. April 2023 um 23:42)

  • Gibbet da irgendwo ein Buch wo sowas drin steht, oder muss man dazu sämtliche UDFs die es so gibbt auswendig kennen lach?

    Moin,

    das 'Buch' ist die AutoIt-Hilfe-Datei. In diesem Fall reicht es wohl, wenn man prüft, ob es im Abschnitt User Defined Functions Reference bei den Gui UDFs auch eine für ListBoxen gibt. Wenn ja, sollte ein Blick auf die Funktionskiste ausreichen. ;)

    Es ist auch immer wieder nützlich, sich die Microsoft Dokumentation der Windows Controls anzuschauen, wenn man wissen will, was theoretisch alles so geht.

  • Zitat

    Eine sehr interessante Art und Weise die Buttons zu erzeugen (mit Arrays), wusste ich gar nicht dass das geht, wobei ich mir trotzdem die Frage stelle, ob dass irgendwie einen Geschwindigkeitsvorteil oder so am Ende mitbringt..

    Ich nutze das gerne, um die Controls einfacher zu generieren. Es sorgt dafür, dass ich die Controls in einer Schleife generieren kann und somit deutlich weniger Zeilen Code habe, gerade wenn man noch Schriftgröße, Farbe,... ändern will oder so, dann kommen schnell >4 Zeilen pro Control. Ist für mich übersichtlicher und schneller zu erweitern. Außerdem ist es einfacher, die Position der Controls anzugeben, weil man einfach mit START+(CONTROLHEIGHT+SPACE)*$i die Höhe berechnet und dann nur an der Stelle was ändern muss, wenn man alle Controls z.B. 20px höher haben will.

    Zitat

    Noch eine Interessante Einlassung fand ich deine Bemerkung, dass ich mit GUISetOnEvent eine existierende Haupt Gui weiter bedienbar halte, ist das wirklich so, bisher habe ich immer gelsen, dass Autoi eine solche Multitaskingfähigkeit wohl eher nicht hätte, aber vielleicht war das ja Unsinn, ich lasse mich gerne eines besseren belehren.

    AutoIt hat nicht wirklich Multitasking, es hat aber begrenzt Asynchrone Fähigkeiten. Windows-Events (wie z.B. Mausklicks, Tastatur,...) unterbrechen quasi das eigentliche Programm und werden zuerst ausgeführt. Du kannst dir das so vorstellen, dass normalerweise, wenn du auf ein Control klickst, AutoIt im Hintergrund den klick wahrnimmt und in einem Array speichert. Wenn du dann GuiGetMsg aufrufst schaust du in dem Array nach, was denn in der Zwischenzeit an Events passiert ist. Beim GuiOnEventMode wird statt das Event in dem Array zu speichern, direkt die angegebene Funktion aufgerufen und ausgeführt. Deshalb wird quasi der eigentliche Code unterbrochen, die Methode ausgeführt und dann wird der Code an der Vorherigen Stelle weiter ausgeführt. Beim GuiOnEventMode hat man deshalb quasi eine leere While-Schleife, die dann bei jedem Event unterbrochen wird und danach weiter läuft. Selbiges passiert übrigens auch bei AdlibRegister. Du kannst also AdlibRegister nutzen um Dinge "nebenbei" auszuführen.

    Zitat

    Warum dein Code bei mir nicht läuft ist mir aber schleierhaft, dass gab es ja schön öfter hier, vielleicht fehlt mir ja auch eine UDF.

    Ich hab nur die UDFs genutzt, die AutoIt mitliefert. Ggf. kann es sein, dass du eine ältere Version nutzt. Ich habe v3.3.16.1 als Basis genommen.

    Zitat

    Haste wahrscheinlich extra reingemacht, damit ich was zum tüfteln habe lach.

    Ne, ich nutze das tatsächlich immer. Ich bin der Meinung, dass man Daten und Programmier-Informationen strikt trennen sollte und es ein unding ist, in nem Array die Größe vorne reinzuschreiben.

    Ich hatte schon oft das Problem, dass man beim Programmieren kurz nicht dran denkt (AutoIt ist da nämlich nicht mal konsistent; es ist mal so mal so) und dann länger sucht, bis man den Fehler findet.

    Fehlerquellen sollten so oft wie möglich vermieden werden.

    Zitat

    Warum die Combo nicht will ist mir immer noch rätselhaft

    Schau mal, ob es auftaucht, wenn du das Fenster größer machst (in der Höhe).

    Zitat

    irgendwie entscheiden, ob es ein Lokaler Drucker ist oder nicht, da sonst der Druckerstring nur bei den lokalen geht.

    Schau mal in _getSelectedPrinter Zeile 183/184. Dort wird rausgefunden, ob ein Lokal installierter oder ein Verbundener (?Netzwerk) Drucker ausgewählt ist.

    Zitat

    Wie kommt man eigentlich darauf, also als mit durchschnittlichr Fantasie ausgestatteter Mensch auf die Idee, dass es eine Funktion Namens _GUICtrlListBox_SetCurSel gibt?

    Die Namensgebung in AutoIt ist meiner Meinung nach etwas gewöhnungsbedürftig. Ich hab selbst zum Beispiel nen Moment gebraucht um _GUICtrlListBox_ResetContent zu finden, weil ich nach sowas wie _GUICtrlListBox_Clear gesucht habe. Generell würd ich sagen: Wenn du irgendwas mit nem Control machen willst, schau mal die User definied funktions zu dem Control in der Hilfe durch, welche Funktionen es alles gibt. Für die meisten Controls sind sie ähnlich und man wird schneller, die passenden Funktionen zu finden.

    Zitat

    Ich sehe gerade Deinen Code durch und weiss jetzt wass du mit Einrückungen meintest, ich habe Dir wohl zu viele gemacht, hat etwas gedauert;) Du hast ja so gut wie gar keine. schein wohl Geschmackssache zu sein, mach ich keine, bekomm ich auf den Deckel, mach ich welche krieg ich auch;)

    Ne, ich meinte tatsächlich die Tabs/Leerzeichen am Anfang einer Zeile. Jeder macht unterschiedlich viele Leerzeilen. Ich bin eher Sparsammer damit, weil es für mich nicht übersichtlicher ist, nach fast jeder Zeile ne Leerzeile zu haben und ich lieber mehr Zeilen auf einmal sehen will. Ist aber natürlich Geschmackssache.

    Ich dachte z.B. an Zeile 49-59 in deinem Original geposteten Script und daran, dass die Funktion,... nicht passend (mit Tabs/Leerzeichen) eingrückt sind. Passiert auch manchmal auf der Webseite hier, weil Leerzeichen/Tabs Probleme machen,... Bei der Einrückung gibts bei mir keine Geschmackssache, die muss korrekt sein, weil man nur dadurch gut/schnell sehen kann, wo Funktionen/Schleifen/Ifs anfangen/enden... Das gehört zu sauberen Code dazu. Es hat nen Moment gedauert, bis ich gesehen habe, wo z.B. deine erste Funktion (_form2) endet.

    Lg, Kanashius :)

  • Hallo Kanashius,

    recht herzlichen Dank dafür, dass Du Dir die Zeit genommen hast auf meine vielen Fragen zu antworten, ist ja nicht selbstverständlich. Wie gesagt Deine Technik mit der Erstellung der GUI Elemente mittels Array ist durchaus interessant und werde ich mir sicher in meinen nächsten Projekten zu Herzen nehmen. Ausch dass mit der Trennung von Daten und Programminfos ist sicher ein wichtiger Aspekt.

    Ok bei den Enrückungen weiss ich jetzt auch Bescheid, ich will immer alles ganz genau wissen.

    Im Übrigen nutze ich die gleiche AutoIt Version wie Du, ich habe sie extra noch mal neu installiert, um auszuschliessen dass mit den UDFs irgendetwas passiert ist, trotzdem kommt bei mir das Combo Feld nicht, wahrscheinlich mag mein Autoit diese Technik bei diesem Feld wohl doch nicht so ganz ;) Hast du vielleicht an deinen Udfs irgendwas verändert, ich würde gerne Deinen Ansatz übernehmen, wäre aber schade wenn ich dann wireder mischen müsste und das Element herkömlich einfügen müsste.

    Nachtrag: Jetzt ist die Combo da hat geholfen. Nur einen Schönheitsfehler hat das ganze jetzt bei Auswahl eines Netzwerkdruckers aus der Combo wird leider nicht mehr verbunden.

    Du sagst er merkt das, ob ein Drucker aus der "Verbundenen" Liste gewählt wird, wenn man bswpw. Eigenschaften klickt, aber anscheinend sucht er ihn dann doch lokal, dass sieht man am Requester: Auf den Drucker\\N2121\Drucker kann nicht zugegriffen werden, wobei N2121 mein lokales Gerät ist


    Recht schönen Dank noch mal und eine schöne Restwoche

    2 Mal editiert, zuletzt von casi4712 (2. Mai 2023 um 14:56)

  • So hallo noch mal,

    also irgendwie habe ich Deine Technik wohl noch nicht so ganz verstanden, denn so bekomme ich leider meine Hauptfunktionalität , einen Drucker aus der Combo zu verbinden nicht mehr hin, habe hier alle möglichen Variablenkombinationen versucht, aber angeblich nicht deklariert (neue Funktion), hier ist noch mal mein leicht modifizierter Code:

    Würde mich noch mal über entsprechenden Input freuen

    ein schönes WE noch unbd Danke

  • Hi,

    In Zeile 24 wird die Variable deklariert, die du nutzen musst.

    Also statt $mPrinterGuiData.idNetworkPrinters musst du $mPrinter.idNetworkPrinters nutzen.

    $mPrinterGuiData ist nur Lokal in der Funktion _createPrinterGui vorhanden.

    Dadurch kannst du theoretisch beliebig viele Druck-Fenster erstellen und verwalten.

    Dazu müsstest du nur alle erstellten Gui-Handle mit $mPrinterGuiData beim erstellen in der _createPrinterGui in eine Map werfen und dann entsprechend bei allen Button,... (GuiOnEventMode)-Funktionen mit dem Makro @GUI_WinHandle die Variable zu der GUI aus der Map holen.

    Das ganze würde dann so aussehen:

    Ich hab auch das globale $sText entfernt... global wird NUR im Notfall genutzt, wenn man Daten über mehrere Funktionen austauschen muss. Versuch das so oft wie möglich zu vermeiden, indem Funktionen Werte zurückgeben oder als Parameter übergeben bekommen. Das ist auch der Grund, warum ich die Map mit den $mPrinterGuiData.Gui, $mPrinterGuiData.idDefaultPrinter,... nutze. Die müsste sonst alle global sein und würden verhindern, dass mehrere Fenster gleichzeitig erstellt werden können und machen den Code allgemein unübersichtlich, wenn auf einmal Globale Variablen überall in Funktionen auftauchen wird das schnell unübersichtlich. Besonders wenn es nichtssagende namen wie $sText sind. Was für ein Text, woher, wo wird er verwendet,...

    $mPrinterGuis z.B. sagt eindeutig: Es ist eine Map mit mehreren Printer-Guis. => Eindeutig, was es ist. Selbiges beim $sPrintServer: Es ist der server unter dem die Drucker erreichbar sind.

    $sText: Ist ein Text, der ? ist und wo verwendet wird?

    Das birgt auch die Gefahr, dass du $sText noch woanders nutzt und dann ausversehen die eine Variable die andere Überschreibt, wenn das nicht beabsichtigt ist,... Viel Spaß beim Fehler finden :D

    MfG, Kanashius

  • JO hallo erst mal, und recht schönen Dank für Deine erneute ausführliche Antwort.

    global wird NUR im Notfall genutzt

    ok dass habe ich jetzt verinnerlicht, versucht auch in meinen letzten Scripten zu beherzigen, wenn hier und da doch noch mal was reingeflogen war oder ist, lag das zumeist daran dass erst etwas nicht funktionierte und nachdem ich es dann global gestzt hatte, es dann funktionierte. Aber grundsätzlich noch mal danke für den Hinweis.

    In Zeile 24 wird die Variable deklariert, die du nutzen musst.

    Also statt $mPrinterGuiData.idNetworkPrinters musst du $mPrinter.idNetworkPrinters nutzen.

    Das klingt auch durchaus logisch. Ich kann jetzt jedenfalls nicht 100 prozentig sagen ob ich dises schon versucht hatte, aber wenn doch, dann hat es leider auch nicht funktioniert, wie auch jetzt nicht. Hattest du dir mein Eingangsscript mal angesehen bzw es getestet, ich weiss ja nicht ob Du da zum Testen einen Druckserver zur Verfügung hattest. Beim Klicken auf einen Drucker in der Combo wird der Drucker eintsprechend verbunden, das Windowsfenster mit dem üblichen Treiber werden isntalliert erscheint und der Drucker wird gleich auf Standard gesetzt.

    Das Was er jetzt macht ist folgendes: Er bringt lediglich ein Fenster das er was getan hat, aber ein Drucker wird nicht verbunden, also landet demzufolge auch kein Eintrag in der Registry im Connections Zweig.

    Keine Ahnung was hier wieder schiefläuft, ich gehe schon davon aus dass mein Anliegen klar rüber gekommen war, und die gleiche Version haben wir ja auch. Ist schon manchmal echt verhext.

    Auf jeden Fall noch mal ein riesiges Dankeschön, vielleicht findest Du ja noch einen Hinweis der diese Hauptfunktion hier entsprechend wieder zurückbringt


    lg und deine schöne Restwoche noch

    PS und ja ich habe die entsprechenden Rundll Zeilen wieder einkommentiert!!

    Einmal editiert, zuletzt von casi4712 (9. Mai 2023 um 16:25)