GUICtrlCreateListViewItem ist zu langsam? -> Problem gelöst, aber Warum ist das so?

  • Hallo liebe Community,


    ich habe mich entschlossen, diese Zeilen hier zu schreiben, weil ich Stunden auf der Suche nach einem Fehler verbracht habe und davon gerne erzählen möchte. ^^

    Das allseits beliebte GUICtrlCreateListViewItem!

    Ich habe einige Zeit in Foren verbracht, in denen verschiedenste Methoden ausdiskutiert wurden, wie man nun "GUICtrlCreateListViewItem" schneller hinbekommt. Oft genug wurde es mir zu kompliziert und womöglich war es auch gar nicht das Problem das ich hatte.

    Mein Problem war eine Datenbank mit etwa 4400 Einträgen in einem Listview, erstellt mit GUICtrlCreateListViewItem in einer FOR-Schleife. Sobald in einem Input-Feld ein Buchstabe eingegeben wurde, wurde mit einer gleichen FOR-Schleife das Listview geleert und neu befüllt in dem das Item erstellt wird, wenn die Bedingung erfüllt ist (Update-Funktion).

    Das Eingeben eines Buchstaben reduzierte die Datenbankausgabe auf 3200 Einträge und dauerte 6000ms. 6 Sekunden waren mir zu lang. Daraufhin Foren durchgestöbert und einige Varianten getestet: _GUICtrlListView_AddItem und _GUICtrlListView_AddArray, beides mit Geschwindigkeitserfolg, auch $SW_HIDE und _GUICtrlListView_BeginUpdate haben zum Erfolg geführt, aber waren immer noch viel zu langsam.
    Denn beim Testen ist dann aufgefallen: beim Starten meines Programms wird das Listview auch schon gefüllt und es dauerte nur 70ms (!) mit mehr Einträgen.
    Daraufhin habe ich die Update-Funktion mal an anderen Stellen gepackt und dabei entdeckt: NACH GuiSetState() (also nach dem ganze GUI) 6000ms -> VOR GuiSetState 70ms !!!

    Mit anderen Worten der Geschwindigkeitsverlust kommt NUR durch das GUI. Selbst wenn ich die Liste vor dem Updaten nicht gelöscht habe ist es etwas über 6000ms gegangen (knapp doppelte Menge, also knapp 70ms mehr als vorher).

    Und jetzt kommt es. Der Hauptübeltäter war ein GUICtrlCreateGroup das den Listview einrahmte.

    mit GUICtrlCreateGroup = 6000ms
    ohne GUICtrlCreateGroup = 1400ms

    Daraufhin jedes GUICtrlCreateGroup rausgenommen: trotzdem nur 1400ms

    GUICtrlCreateGroup wieder hinzugenommen:
    1. Start 4300ms
    2. Start 5000ms
    danach wieder 6000ms nach jedem Start.

    Und nu würde ich gerne von den Profis wissen, WARUM ist das so?

    Ich habe versucht es in einem Testprogramm zu reproduzieren, aber es reicht nicht nur eine Group hinzuzufügen, es müssen wohl weit mehr Elemente sein. Denn auch die 1400ms sind ja nicht das Beste.


    Für die, die sich durch die Textwüste gekämpft haben:
    um auf die 70ms wiederzukommen muss man das GUI-Listview Element löschen und wieder neu erstellen. Natürlich sind die 70ms nur das Füllen vom Listview....löschen vom GUI-Element oder das Leeren vom Listview kostet natürlich auch Zeit.

    Vielen Dank fürs Durchlesen. :D

  • Hi,
    altbekanntes "Problem", denn lt. Windowsparadigma hat sich jedes Programm selbst um seine Fenster(-inhalte) zu kümmern!
    Da wird dann bspw. "nur um ein Item einer Listview hinzuzufügen" eine unglaubliche Menge Messages abgefeuert, und so gut wie sämtliche Funktionen, welche das BS zur Verfügung stellt, abgeklappert. Und natürlich wird bei jedem deiner 4000 Items nachgeschaut, ob dieses jetzt gerade nicht zufällig doch dargestellt werden soll....

    Abhilfe schafft, die Darstellung bei bestimmten Operationen einfach abzuschalten. Damit wird verhindert, dass der gesamte Rattenschwanz an Funktionen zur Fensterdarstellung (da reicht eine Mausbewegung im Fenster! ) ausgeführt wird.
    Windows ist idR so clever, bei bspw. einem WinSetState() (in anderen Programmiersprachen heisst die Bildschirmaktualisierung anders) nur den zzt. im Fenster sichtbaren Bereich upzudaten. Das geht auch Ruckzuck!
    In VBA wird per ScreenUpdating = False bei so manchem Script der Turbo eingeschaltet. Faktor 10 und schneller sind da keine Seltenheit!
    Würde mich wundern, wenn man in AutoIt so nicht auch zum Erfolg kommen könnte....

    • Offizieller Beitrag

    Hey,

    Wenn du _BeginUpdate und _EndUpdate richtig benutzt sollte das auch ein massiven Geschwindigkeitsboost hervor rufen. Zu den Gruppen kann ich nichts sagen. Aber zum Löschen gibt's noch ein Tipp von mir:

    Ich habe letztens auch festgestellt, dass das leeren eines ListViews unglaublich lange dauert und habe mir dann mal die Funktion _GuiCtrlListView_DeleteAllItems angesehen. Dort sieht man: Wenn es ein AutoIt control (GuiCtrlCreateListView) ist wird jedes einzelne Element von "Hand" gelöscht, wenn es ein WinApi control ist (_GuiCtrlListView_Create) dann wird einfach nur eine Message abgefeuert; das sollte sehr fix gehen. Leider gibt es in der aktuellen UDF (GuiListView.au3, sowohl Stable als auch Beta) einen bösen Bug.

    Genaueres findest du hier: http://www.autoitscript.com/forum/topic/16…istview-create/ so klappt das mit dem Löschen des ListViews auch super schnell. Allerdings musst du aufpassen: Die WM MEssage Funktioniert zwar auch mit GuiCtrlListViewCreate, allerdings gibt es dann hier ein Speicherleck, weil die Controls zwar aus dem ListView entfernt werden, aber trotzdem AutoIt intern immer noch existieren. Das heißt die Funktion solltest du nur bei _GuiCtrlListView_Create benutzten. Die ist sowieso schneller als GuiCtrlCreateListView, deswegen würde ich dir empfehlen nur _GuiCtrlListView_Create zu benutzten.

    Gruß,
    Spider

  • Morgen,

    habe meine Datenbank einfach auf 13000 Einträge erweitert

    mit GUICtrlCreateGroup = 18000ms
    ohne GUICtrlCreateGroup = 4000ms
    direkt nach GUI-Erstellung = 200ms


    Mein Listview fülle ich, in dem ich es erst verstecke (hide) -> _BeginUpdate -> Füllen -> _EndUpdate -> sichtbar machen (show).
    Möglichweise bringt das _BeginnUpdate bei 2d-Arrays, mehr Bedingungen oder viel größeren Datenbanken mehr. Bei mir aber war es recht wenig.


    Was weit mehr bringt ist das Verstecken des Listview, was sich ja mit der Erkenntnis, dass das GUI schuld hat ja deckt.
    Sobald man etwas flackern sieht, ist es langsam.

    Im übrigen , wenn ohne hide und _BeginUpdate arbeite sieht man ja das Befüllen des Listviews.
    Und ich erinnere mich an ein früheres, sehr spartanischen mit GUI ausgestatteten Projekt, dort konnte ich das Befüllen sehr gut verfolgen (in der rechten Leiste wurde der Schiebebalken immer kleiner). Beim jetzigen Programm sieht man nur Flackern, erst wenn man das Listview löscht und neu befüllt und dabei mal nicht versteckt kann man das Füllen wieder beobachten.


    Das mit dem _GuiCtrlListView_DeleteAllItems werde ich mir noch anschauen, obwohl ich ja eh das GUI komplett löschen muss, um volle Geschwindigkeit zu bekommen.
    Daher wäre das GuiDelete wichtiger.
    Ich muss aber gestehen, dass ich eigentlich es lieber hätte, wenn ich mein erstelltes GUI nicht mehr anfassen müsste.

    Aso, gerade noch getestet, wenn ich bei mir nicht nur das Listview verstecke, sondern auch GUICtrlCreateGroup, dann verschwindet auch die Leistungsbremse, als wenn es nicht da wäre.

    Aber was heißt dass nun, um max. Geschwindigkeit zu erhalten?
    Nach meiner Erkenntnis:

    Vor jeder Befüllung GUI-Element löschen, versteckt erstellen und befüllen!
    (Habe listbox und Edit Elemente nicht getestet)

    Aber was wenn man diese Elemente aber nicht löschen kann, aus welchen Gründen auch immer?

    Wie kann man Leistungsbremsen, wie ein GUICtrlCreateGroup (das nichts weiter als ein kleiner Rahmen ist, nichts bedeutendes) ausfindig machen (es ist ja nicht jedes, sondern nur das eine um das zu befüllende Element)?

    Will man bei bestimmten Aktionen, wie von Andy vorgeschlagen, alles verstecken? Sieht sicher komisch aus, schon nur ein GUICtrlCreateGroup zu verstecken bei Befüllen von einem Listview wirkt eigenartig (aber um 4 Sekunden zu sparen bzw im oberen Beispiel 14 Sekunden wäre es es sicher wert).
    Soll ich alle GUI Elemente durchtesten bis ich den Übeltäter habe oder gibt es vielleicht etwas worauf man achten kann? Z.B. erstelle ein Tab mit einem Listview immer zuerst oder schreibe GUI-Anweisungen immer nur mit der Nasenspitze, statt mit den Fingern. :)

    Ach...für mich alles ein Rätsel.

  • Ach...für mich alles ein Rätsel.

    Willkommen in der Welt der Programmierung! :rock:

    Will man bei bestimmten Aktionen, wie von Andy vorgeschlagen, alles verstecken? Sieht sicher komisch aus, schon nur ein GUICtrlCreateGroup zu verstecken bei Befüllen von einem Listview wirkt eigenartig (aber um 4 Sekunden zu sparen bzw im oberen Beispiel 14 Sekunden wäre es es sicher wert).


    Wen interessiert, was "merkwürdig" aussieht, wenn man dadurch massiv Zeit spart?!

    Mich würde in diesem Zusammenhang auch interessieren, wieviel Zeit und somit auch Geld die berühmte "Sanduhr" täglich kostet. Ich schätze mal niedrig einige Milliarden Euros. Windows-Nutzer haben die Sanduhr aber inzwischen dermaßen verinnerlicht, da fällt schon auf, wenn man sie einige Minuten NICHT sieht!

  • Damit das ganze nicht so "merkwürdig" aussieht, könnte man ja vorher ein Screencapture der Form machen und als Hintergrund setzen oder die versteckten Steuerelemente kurzzeitig durch neu erstellte Steuerelement-Attrappen ersetzen.

  • @habenureinproblem: Ich denke, du solltest ein extra Skript für die GUI erstellen und ein extra Skript für deine Datenverwaltung und dann lässt du beide Skripte untereinander kommunizieren. Dann sollte dein Speed Problem bezüglich GUI gelöst sein?!

    Eine Kommunikation von Skripten untereinander hat 'Andy' ja perfekt gelöst!
    -> https://autoit.de/index.php/Thre…-untereinander/


    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Ich denke, du solltest ein extra Skript für die GUI erstellen und ein extra Skript für deine Datenverwaltung und dann lässt du beide Skripte untereinander kommunizieren. Dann sollte dein Speed Problem bezüglich GUI gelöst sein?!


    Offensichtlich hast du das Problem nicht nachvollzogen.
    Das Problem befindet sich in der Darstellung der Liste, also ein reines GUI-Problem. Die Datenverwaltung ist davon völlig losgelöst. Daher besteht auch keine Veranlassung, das Script zu teilen!

    "In grauer Vorzeit", als es noch gar kein Windows gab, hatte man trotzdem schon Listendarstellungen. Da war man so clever und hat ausschliesslich den sichtbaren Teil der Liste ausgelesen und dargestellt. Beim Scrollen wurden einfach die oberen Zeilen "abgeschnitten" und die neuen Zeilen unten angehängt, also immer nur ein kleiner Teil der Liste angezeigt.
    Ich vermute mal, ähnlich funktioniert das heute auch noch, ausser dass in irgendeiner "klickibunti"-Funktion wieder mal mehr Wert auf optischen Schnickschnack (Aero) gelegt wurde, als auf Geschwindigkeit.
    Btw, AERO abschalten lässt einige Programme wesentlich schneller laufen! Leider kein Witz!

  • Zitat

    Offensichtlich hast du das Problem nicht nachvollzogen

    Das habe ich wohl falsch verstanden - Sorry!

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Guten Morgen,

    vielen Dank für euren Beitrag.

    Ich war ja nun der Meinung, dass Löschen das Maß aller Dinge ist. Musste aber feststellen, dass es Komplikationen gibt, wenn das neu erstellte Element in einem anderen Tab ist.
    Plötzlich hatte das Listview alle anderen Elemente von den anderen Tabs überdeckt.

    Ärgerlich, da ich aber einfach zu faul war, jetzt auch noch Lösungen zu finden wie man das Listview wieder nur in Tab 3 bekommt, habe ich das guictrlcreategroup gelöscht und lebe zufrieden.

    Für meine Zwecke reicht es ja, ABER es läßt mich nicht los. Irgendwann kann ich vielleicht nicht mehr mit paar Sekunden mehr leben und stehe vor dem selben Problem.

    Daher KloMeister:

    Ich denke, dieser Ansatz ist super, wenn man sehr viele Elemente im Bild hat.
    Und bringt mich auf die Idee: macht es einen Unterschied, ob beim Listview füllen, die sich im Bild befindenen Elemente, kurz vorher oder viel früher erstellt wurden? (Z.B. eine vor, das andere nach GuiSetState)

    In meinem speziellen Fall wüßte ich nicht, wie ich mit Screencapture ein GuiCtrlCreateGroup "emuliere". Nebenbei würde es das GuiCtrlCreateGroup ad absurdum führen.
    Wenn ich meine zwei Buttons entferne die sich unter dem Listview befinden, ändert sich nichts. Ein ScreenCapture über die Listview, wäre ja wie ein GuiCtrlCreateGroup über dem Listview, also das gleiche Ergebnis?
    Probieren werde ich es aber auf jeden Fall.

    Andy:
    Es gibt ja schon die Variante bei PHP und HTML, dass man mit Seiten arbeitet, um nur einen kleinen Bereich und nicht alles anzuzeigen.
    Würde ich das auch machen mit meinem Listview, müsste aber theoretisch immer noch das Problem GuiCtrlCreateGroup bestehen. Zwar zeitmäßig uninteressant, aber vorhanden.
    Theoretisches Beispiel:
    mit GuiCtrlCreateGroup: 60ms
    ohne GuiCtrlCreateGroup: 20ms

    Ich werde nochmal testen, alle Elemente die sichtbaren wie unsichtbaren, die sich aber theoretisch hinter oder vor dem Listview befinden zu entfernen. (Beispiel: mein Listview ist in Tab3 in Tab 2 und 4 befinden sich auf Höhe des Listview Buttons oder Text u.ä.)
    Mal sehen, ob die nicht auch Geschwindigkeit klauen.

    Viele Grüße

  • @BugFix

    Test:

    mit Standard GuiCtrlCreateGroup: 4400ms
    mit deiner _GuiCtrlGroup_Create: 1600ms
    ohne alles: 1200ms

    Super, wie auch immer das möglich ist. :)
    Ich schaue mir deine groupex mal genauer an.

    Ahh, wahrscheinlich wird mit deinem _GuiCtrlGroup_Create UM mein Listview gezeichnet (gelabeled :) ), während GuiCtrlCreateGroup (weshalb auch immer) auch den Bereich innen ändert.

  • Morgen,

    Da BugFix groupex schon einiges geholfen hat, aber noch entfernt von der Erstellgeschwindigkeit ist, wollte ich weiter testen.

    Deshalb habe ich gestern mal ein neues GUI erstellt mit 3 Listviews, Zeit gemessen und GuiCtrlCreateGroup rum gemacht. Ergebnis: keine Änderungen.
    Da dachte ich mir, dass es also im Zusammenhang mit anderen Elementen oder aber an meine Programmierung liegt.

    Nun werde ich nach und nach mein GUI entschlacken und immer mal testen.

    Dabei ist mir aber der Gedanke von Andy gekommen. Was wenn es am System selber liegt?

    Daher habe ich mein Programm alle relevanten Teile rausgenommen und nur das GUI drin gelassen (aber die Grundstruktur dringelassen). Wer möchte kann es ja mal auf seinem Rechner starten lassen und 4 Varianten testen.


    Spoiler anzeigen


    Immer die gleiche Vorgehensweise
    einige Zeilen auskommentieren, dann Programm starten, in Tab3 gehen, ins Inputfeld eine 1 tippen, warten und in die Console schauen.

    Um diese Zeilen geht es (einfach per STRG+Q auskommentieren bzw. wieder reinbringen):
    Zeile 152: _GuiCtrlGroup_Create
    Zeile 153: GuiCtrlCreateGroup
    Zeile 308-312: Listview leeren bzw. löschen

    Variante1 (normale GuiCtrlCreateGroup,Listview leeren):

    Ersterstellung 71.1722469699422
    nur löschen: 2034.77237302716
    (342) : nur hinzufügen $insg = 6335.95952541161
    insgesamt: 8487.79612799918

    Variante2 (komplett ohne GuiCtrlCreateGroup,Listview leeren):

    Ersterstellung 77.6267173166847
    nur löschen: 2255.17422300204
    (342) : nur hinzufügen $insg = 1346.96704625789
    insgesamt: 3706.29178839422

    Variante 3 (normale GuiCtrlCreateGroup,Listview löschen):
    Zeile 153
    Zeilen 308 bis 312 strg+q

    Ersterstellung 78.545572240156
    nur löschen: 524.298210498522
    (342) : nur hinzufügen $insg = 29.5134020969787
    insgesamt: 675.303176130895

    Variante 4 für die, die BugFix groupex benutzen (mit _GuiCtrlGroup_Create,Listview leeren):
    Zeilen 308 bis 312 Strg+q
    Zeile 152 und 153 Strg+q
    Zeile 9 strg+q

    Ersterstellung 79.0579778037085
    nur löschen: 1973.03465721805
    (342) : nur hinzufügen $insg = 1791.06015825291
    insgesamt: 3871.39438023286


    EDIT: Spoiler hinzugefügt

  • Spoiler anzeigen
    [autoit]

    $timer3 = TimerInit()
    ;-----------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------
    _GUICtrlListView_BeginUpdate($hLVHandle)
    ;~ _GUICtrlListView_DeleteAllItems($hLVHandle)

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlDelete($hListView)
    Global $hListView = GUICtrlCreateListView($sHeader, $x_datenbank + 22, $y_datenbank + 80, 490, 230, $LVS_SHOWSELALWAYS)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumn($hLVHandle, 0, "Test2", 420, 0) ; 1. Spalte = 120 Px breit, rechts ausgerichtet

    [/autoit] [autoit][/autoit] [autoit]

    ;-----------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('nur löschen: ' & TimerDiff($timer3) & @CRLF ) ;### Debug Console

    [/autoit]

    damit füllen sich auf meinem Laptop in maximal 2 Sekunden 10000 Einträge!
    nur löschen/erstellen in 1.8 Sekunden (warum ist GuiControlDelete() so langsam? ), füllen in 0.2 Sekunden.
    Damit habe ich ehrlich gesagt absolut kein Problem, imho ist das HÖLLISCH schnell für eine "Scriptsprache"!

  • @Andy:
    Ja klar ist das schnell, deswegen auch meine favorisierte Lösung. Wie aber sogt man dafür, dass das neu erstellte Listview in Tab3 bleibt?

    Aber wozu leert man dann Listview? Kann man doch immer löschen.
    Ich antworte mal selber :) : Weil es nur bei diesem speziellen GUI Geschwindigkeitsverluste gibt. Bei einem z.B. ohne Tabs und ohne anderen Kram bremst ein GuiCtrlCreateGroup um ein Listview gar nichts aus.

    Leider ist Zeit bei mir so ein kleines Problem, aber ich denke mal heute Abend werde ich mein GUI entschlacken.

  • Abend,


    das ging schneller als erwartet, ich habe den Übeltäter.

    Wieso GuiCtrlCreateGroup vorher etwas bewirkt hat ist mir schleierhaft, aber diese Zeile:

    $tab1 = GUICtrlCreateTab(0, 0, 550, 600)

    war der Auslöser.
    Sobald keine Tabs genutzt werden füllt sich das Listview genau so wie wenn es gelöscht wurde.

    Ich habe alle Inhalte der anderen Tabs entfernt = keine Verbesserung
    andere Tabs entfernt = keine Verbesserung
    Tabs ganz weggemacht bzw. nur diese oben genannte Zeile auskommentiert = full speed

    MEINE geliebten TABS !!! Ich werde irre, was mache ich denn nun?


    Kleine Randbemerkung:
    Ich hatte in der Zwischenzeit ein Geschwindigkeitsproblem beim Imagesearch und hatte wegen einem Hinweis Aero ausgeschaltet (von Win7 Aero zu Win7 klassisch).
    Prompt waren es keine 6 Sekunden sondern nur noch 2,5 Sekunden, mehr als doppelter Geschwindigkeitsgewinn.

    Somit bleiben nur noch 2 Fragen offen.

    Welche Alternativen, die genauso schön aussehen, gibt es für Tabs?
    Wenn man die Tabs weiter benutzen möchte und full speed braucht, muss man das listview löschen, wie bekomme ich es in Tab3 und nur dort wieder hin?

    Vielen Dank für eure Hilfe, wir nähern uns dem Ende ;)


    kleines EDIT:

    gerade ein
    GUICtrlCreateTab und GUICtrlCreateTabItem in mein Testprogramm, in dem nur Listviews drinnen sind eingefügt und sofort 3fache Füllzeit erreicht.

    • Offizieller Beitrag

    Hier mal ein Zitat aus der Hilfe zu GuiSwitch:

    Zitat

    Using the tabitemID allow to create new control in the specified tabitem control. Don't forget to close tabitem definition GUICtrlCreateTabItem("")


    Und hier ein Beispielscript:

    Spoiler anzeigen
    [autoit]


    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("My GUI Tab", 400, 300)

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlCreateTab(10, 10, 380, 280)
    $idTab0 = GUICtrlCreateTabItem("tab0")
    $idTab1 = GUICtrlCreateTabItem("tab1")
    GUICtrlCreateLabel("label1", 30, 80, 50, 20)
    $idTab2 = GUICtrlCreateTabItem("tab2")
    GUICtrlSetState(-1, $GUI_SHOW)
    $idListView = GUICtrlCreateListView("1|2", 20, 50, 160, 140)
    GUICtrlCreateTabItem("")
    GUISetState(@SW_SHOW)
    Sleep(2000)
    GUICtrlDelete($idListView)

    [/autoit] [autoit][/autoit] [autoit]

    GUISwitch($hGui, $idTab2)
    $idListView = GUICtrlCreateListView("A|B", 20, 50, 160, 140)
    GUICtrlCreateTabItem("")

    [/autoit] [autoit][/autoit] [autoit]

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    [/autoit]
  • @Oscar
    Ahh vielen Dank.

    Gleich getestet und festgestellt, dass das Erstellen vom neuen Listview direkt wieder üüber 3 Sekunden statt 30ms dauert.

    Ich glaube wir können somit festlegen:

    Tabs dürfen nicht mit Listview benutzt werden für volle Geschwindigkeit.

    Benutzt jemand Alternativen? Z.B. für Einstellungen 2. Gui erstellen o.ä.?

  • Du könntest deine Tabs nachbauen. Als Beispiel:

    Spoiler anzeigen
    [autoit]


    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    $hGui=GUICreate("",400,300)
    $Button1=GUICtrlCreateButton("Tab1",10,10,41)
    $Button2=GUICtrlCreateButton("Tab2",50,10,40)
    GUISetState(@SW_SHOW)
    $TabListView=_guiCtrlTabListview_create($hGui,"Spalte1|Spalte2",10,40,380,255)
    for $i=0 to 10 step 1
    GUICtrlCreateListViewItem($i&" 1|"&$i&" 2",_guiCtrlTabListview_getListviewHandle($TabListView))
    next
    while Sleep(10)
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    exit
    Case $Button1
    GUISetState(@SW_SHOW,_guiCtrlTabListview_getGuiHandle($TabListView))
    Case $Button2
    GUISetState(@SW_HIDE,_guiCtrlTabListview_getGuiHandle($TabListView))
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_create($hGui,$text,$x,$y,$width,$height,$style=-1,$exstyle=-1)
    $struct=DllStructCreate("HWND;int")
    DllStructSetData($struct,1,GUICreate("",$width,$height,$x,$y,$WS_POPUP,$WS_EX_MDICHILD,$hGui))
    GUISetState(@SW_SHOW,DllStructGetData($struct,1))
    DllStructSetData($struct,2,GUICtrlCreateListView($text,0,0,$width,$height,$style,$exstyle))
    GUISwitch($hGui)
    return $struct
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_getGuiHandle($struct)
    return DllStructGetData($struct,1)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_getListviewHandle($struct)
    return DllStructGetData($struct,2)
    EndFunc

    [/autoit]

    Wenn du dann noch die Buttons, etc. manuell erstellst (und Buttons und Rahmen optisch anpasst) könnte man es so machen :)
    Ansonsten kann man bestimmt auch vom Tab die Message abfragen, ob ein Tab-Item gedrückt wurde, sodass du dann das leere Tab mit der Gui überdeckst :)
    MfG Kanashius

    Edit: Ich hab das ganze mal für die normalen Tabs umgebastelt:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    $hGui=GUICreate("",400,300)
    $Tab=GUICtrlCreateTab(10,10,380,280)
    $Tab1=GUICtrlCreateTabItem("Tab 1")
    GUISetState(@SW_SHOW)
    $Tab2=GUICtrlCreateTabItem("Tab 2")
    $TabListView=_guiCtrlTabListview_create($hGui,"Spalte1|Spalte2",10,10+20,380-2,280-20)
    GUICtrlCreateTabItem("")
    for $i=0 to 10 step 1
    GUICtrlCreateListViewItem($i&" 1|"&$i&" 2",_guiCtrlTabListview_getListviewHandle($TabListView))
    next
    while Sleep(10)
    $msg=GUIGetMsg(1)
    Switch $msg[0]
    Case $GUI_EVENT_CLOSE
    exit
    Case $Tab
    if GUICtrlRead($Tab)=0 then
    GUISetState(@SW_SHOW,_guiCtrlTabListview_getGuiHandle($TabListView))
    else
    GUISetState(@SW_HIDE,_guiCtrlTabListview_getGuiHandle($TabListView))
    endif
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_create($hGui,$text,$x,$y,$width,$height,$style=-1,$exstyle=-1)
    $struct=DllStructCreate("HWND;int")
    DllStructSetData($struct,1,GUICreate("",$width,$height,$x,$y,$WS_POPUP,$WS_EX_MDICHILD,$hGui))
    GUISetState(@SW_HIDE,DllStructGetData($struct,1))
    DllStructSetData($struct,2,GUICtrlCreateListView($text,0,0,$width,$height,$style,$exstyle))
    GUISwitch($hGui)
    return $struct
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_getGuiHandle($struct)
    return DllStructGetData($struct,1)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _guiCtrlTabListview_getListviewHandle($struct)
    return DllStructGetData($struct,2)
    EndFunc

    [/autoit]


    Damit wird ein GUI "in" das Tab gelegt (oder man merkt zumindest keinen unterschied :)) und angezeigt oder versteckt. Jenachdem, welches Tab angezeigt wird :)

  • Ich wollte mich nochmal bedanken für euren Einsatz.

    Habe den Thread nun auf gelöst gesetzt, da ja das Problem an sich gefunden wurde.

    nur noch zum Schluss:
    @Kanashius - Super Idee mit dem neuen GUI hatte aber einige Schwierigkeiten da etwas hinzuzufügen, auch wird das eine GUI mit blauen Balken gezeigt, das andere sieht wie nicht angewählt aus.

    Aber wenn dann würde ich dafür einen neuen Thread erstellen.


    Bis dann