ListView und ContextMenu Problem

  • Hallo liebe AutoIt-Community,

    es ist mir schon voll peinlich, hier wieder nach Eurer Hilfe zu fragen ?( ...
    Ich hab jetz aber schon nen halben Tag gegoogelt, hab aber nichts wirklich befriedigendes gefunden.
    Mein Problem ist, dass ich ein Listview-Control hab, in das alle Dateien eines Ordners eingefügt werden. Jetzt brauche ich für jeden Eintrag ein eigenes ContextMenu, so wies auch im Explorer ist.
    Jedoch weiß ich nicht, wie ich das bewerkstelligen soll. Im Beispiel unten hab ich mal 2 Kontextmenüs, 1 für Ordner und eins für Dateien, jedoch wird nur manchmal das Richtige angezeigt.

    Ich steh grad voll aufm Schlauch und seh das Problem irgendwie nicht =O .
    Kann da jemand weiterhelfen?

  • Hallo @NO1 :-),

    Das Skript hat doch noch einige Schwächen. Ein paar Dinge haben mir gar nicht gefallen (Schreib z.B. mal ConsoleWrite(0) in die erste Zeile deiner _IsDir- Funktion und klicke ein Item an...). Ganz schlimm finde ich:

    AutoIt
    AdlibRegister("_ListviewDoubleclick", 100)

    Schmeiß das unbedingt raus! Das kann dir ständig in alles hineinhacken. Du wertest mit WM_NOTIFY doch schon Klicks aus. Mach das auch für Doppelklicks. Schau dir am Besten mal die Hilfe etwa zu "_GUICtrlListView_HitTest" an. Da findest du im Grunde eine fertige Lösung für dieses und andere Szenarien.

    So hab ich die WM_NOTIFY-Funktion für dein Skript genutzt. ($ListviewDoubleclicked ist dann überflüssig):

    (Hier lösche ich explizit das Control (GUICtrlDelete($ContextMenu)))!
    Darüber hinaus habe ich $ContextMenu zu einer globalen Variable gemacht.


    Einige Hinweise:
    - Statt: If StringInStr(FileGetAttrib($Path), "D") = True Then genügt If StringInStr(FileGetAttrib($Path), "D") Then

    (Das Auswerten ("= True") ist unnötig, wenn du schon die Lösung zurückgibst (True/False)).
    - Warum überhaupt eine StringInStr-Prüfung hier?

    - Alle Variablen, die du außerhalb von Funktionen deklarierst sind Global - auch wenn du sie Local deklarierst (Dim würde ich ganz weglassen).

    (Es wäre besser, das auch richtig zu benennen. Das diszipliniert mich wenigstens zu überlegen, ob ich das für die betreffende Variable wirklich brauche. Je größer ein Projekt, desto wahrscheinlicher wird es, dass du mal versehentlich in einer Funktion mit einer globalen Variable arbeitest..).

    - Darüber hinaus möchte ich dir raten Namenskonventionen einzuhalten, die klar machen, um welchen Datentyp es sich bei der Variable handelt. Das erleichtert dir im Nachhinein (und Fremden, die sich deinen Code ansehen sollen) das Zurechtfinden ungemein. Schau dir bei Interesse folgende Seite an: https://www.autoitscript.com/wiki/Best_coding_practices


    PS: Klingt jetzt alles sehr kritisch. Aber es ist nicht so böse gemeint und soll nicht heißen, dass das alles Mist wäre. :)

    Grüße autoiter

  • Dankeschön für deine Antworten!

    Wenn ich wieder daheim bin, werde ich deine neue Funktion sofort testen.

    Zu deiner Aussage "Warum StringInStr benutzen": Es kann ja sein, dass durch FileGetAttrib mehrere Attribute zurückgegeben werden in einem String und dann muss man ja überprüfen, ob das Attribut "D" in dem String vorhanden ist...

    Ich skripte jetzt schon ein ganzes Jahr in AutoIt und mir ist das mit = True und der Variablendelaration bewusst. Wenn ich jetzt ein Skript nicht als UDF oder nicht für die Community schreib, dann komm ich mit den Bezeichnungen aber ziemlich gut zurecht.

    Lg NO1 :)

  • Zu deiner Aussage "Warum StringInStr benutzen": Es kann ja sein, dass durch FileGetAttrib mehrere Attribute zurückgegeben werden in einem String und dann muss man ja überprüfen, ob das Attribut "D" in dem String vorhanden ist...

    Ah ja, ein Blick in die Hilfe hilft immer! :D

    Bei meinen Versuchen, kam immer nur ein Buchstabe und ich habe das nicht weiter hinterfragt. Ich hoffe meine anderen Anmerkungen bringen dir wirklich etwas. ;)

    Grüße autoiter

  • "Warum StringInStr benutzen"

    Er sprach nicht nur davon warum man StringInStr benutzt wird, sondern warum du die Abfrage = True dahinter noch hast.

    StringInStr gibt schon automatisch bei einem Fund True zurück, somit würdest du nur True = True oder False = True abfragen.
    Du kannst dir somit das = True sparen da der Ausdruck If StringInStr() Then die selbe Wahrheitstabelle hat wie If StringInStr() = True.

    Des Weiteren kann man es sich sparen um den Code leserlicher zu machen. Man verwendet auch oft nicht = False sondern negiert die Ausgabe der Abfrage um es "sprachlicher" zu formulieren.
    If StringInStr() Then Wenn String in String vorhanden, dann ...
    If StringInStr() = True Then  Wenn String in String = wahr ist, dann ...
    If Not StringInStr()Wenn nicht String in String, dann ...
    If StringInStr() = FalseWenn String in String = falsch ist, dann...

    Letzlich ist es eine Stilfrage, da jeder unterschiedlich programmiert.

  • Du solltest die Antworten nicht überfliegen. Er sprach nicht davon warum man StringInStr benutzt wird, sondern warum du die Abfrage = True dahinter noch hast.

    Das stimmt zu meiner Schande nicht ganz @alpines.
    Ich hatte StringInStr und das "= True" in Zweifel gezogen. StringInStr scheint schon richtig zu sein. Der "= True"-Vergleich ist aber wie du schreibst nicht falsch aber unnötig.

    Grüße autoiter

  • In Zukunft verwende ich dort kein true mehr..., is ja wie bei FileExists, aber ich denke auch, dass es die Sache des Programmierers ist, wie er es handhabt. Bei Weiterverbreitung des Codes ist es sicher sinvoll, den Code möglichst kurz und sauber zu halten :) .

  • In Zukunft verwende ich dort kein true mehr..., is ja wie bei FileExists, aber ich denke auch, dass es die Sache des Programmierers ist, wie er es handhabt.

    Es kommt auch auf die Funktionen an die du verwendest.

    Mit Sicherheit gibt es UDFs die inkonsistente Rückgabewerte haben und da kann so eine Abfrage schon richtig sein.
    AutoIt handhabt Strings, sofern sie nicht leer sind, und Alle Zahlen <> 0 als True.

    Verwendet man jedoch den Case-Sensitiven Vergleich (== True), so löst die Bedingung nur aus wenn sie wirklich nur True ist und kein "String" oder Zahlen <> 0.

  • Hey @NO1 :-),

    Ich skripte jetzt schon ein ganzes Jahr in AutoIt und mir ist das mit = True und der Variablendelaration bewusst. Wenn ich jetzt ein Skript nicht als UDF oder nicht für die Community schreib, dann komm ich mit den Bezeichnungen aber ziemlich gut zurecht.

    Ja, da verlangt einer von dir, überall nochmal nachzubessern. Geht's noch?!?

    Es könnte in künftigen Skripten wenigstens nicht schaden, sich bei der Variablenbenennung an nachvollziehbare Regeln zu halten.

    Grüße autoiter

    Einmal editiert, zuletzt von autoiter (10. April 2017 um 00:59) aus folgendem Grund: Text revidiert, weil einfach zu vorlaut.