[Programm] Bilder in Threads laden

Für allgemeine Fragen zur Programmierung mit PureBasic.
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

[Programm] Bilder in Threads laden

Beitrag von es_91 »

Hier geht es zwar um Grafik, der Inhalt ist aber ein Thread-Problem, deshalb kommt dies hier nicht in die Grafik- und Sound-Abteilung.

Ich versuche ein Programm zu schreiben, was Bilddateien, Bitmaps, einlädt. Die Besonderheit: das Laden soll als Thread ablaufen - jedes Bild ein einzelner Thread - damit das Programm sich entfalten kann, bevor die Bilder in dem MDIGadget angezeigt werden (jedes Bild ein MDIWindow).

Warum funktioniert mein Code nicht?

Code: Alles auswählen

  Structure IMAGE
    ID.i
  EndStructure
  
  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
  
  Global NewList Images.IMAGE()
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList ProgramParams$()
  Global NewList LoadingThreads()
  Global NewList ThreadEntriesToDelete()
  NewList ProgramParams$()
  
  Procedure LoadingThread(*FileName$)
    
    AddElement(Images())
    Images()\ID = LoadImage(#PB_Any, *FileName$)
    
  EndProcedure
  
  While ProgramParameter(x)
    AddElement(ProgramParams$())
    ProgramParams$() = ProgramParameter(x)
    x + 1
  Wend
  
  Window_Main_Title$ = "just a little test program..."
  
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
  
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
  
  HideWindow(Window_Main, #False)
  
  ForEach ProgramParams$()
    AddElement(LoadingThreads())
    LoadingThreads() = CreateThread(@LoadingThread(), @ProgramParams$())
  Next
  
  Repeat
    
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
    
    ForEach LoadingThreads()
      
      If Not IsThread(LoadingThreads())
        SelectElement(Images(), ListIndex(LoadingThreads()))
        AddElement(MDIWindows_Main())
        MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images()\ID))
        MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, WindowWidth(MDIWindows_Main()), WindowHeight(MDIWindows_Main()), Images()\ID)
        AddElement(ThreadEntriesToDelete())
        ThreadEntriesToDelete() = LoadingThreads()
      EndIf
      
    Next
    
    WindowEvent = WindowEvent()
    Select WindowEvent
      Case #PB_Event_SizeWindow
        ResizeGadget(MDIGadget_Main, 0, 0, WindowWidth(Window_Main), WindowHeight(Window_Main))
      
      Case #PB_Event_CloseWindow
        
        End
        
    EndSelect
    
    ForEach ThreadEntriesToDelete()
      ForEach LoadingThreads()
        If LoadingThreads() = ThreadEntriesToDelete()
          DeleteElement(LoadingThreads())
          Break
        EndIf
      Next
    Next
        
  ForEver
Die Images()\ID wird bei mir immer null sein. Warum? Was mache ich falsch?

Schönen Abend und Danke im Vorraus,

es_91.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: [Programm] Bilder in Threads laden

Beitrag von NicTheQuick »

Weil du falsch mit Pointern umgehst.
'*FileName$' sollte in PB verboten werden. :mrgreen:

Und weil deine LinkedList nicht threadsafe ist. Es kann nämlich durchaus passieren, dass der eine Thread 'AddElement()' macht und dann ein anderer auch nochmal ein 'AddElement()' macht. Wenn dann der erste wiederum 'Images()\ID = LoadImage(...)' ausführt, dann hat er ein Element übersprungen.
Du musst ein Array benutzen und jedem Thread sagen an welchem Index er die ImageID zu speichern hat. (Oder du nutzt komplizierte Lock/Semaphoren-Mechanismen) :wink:
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

Danke Dir. Das mit dem Array leuchtet mir ein, aber wie mache ich das mit dem Pointer?

/EDIT: Jetzt geht das mit den Images, aber sie werden nicht angezeigt ????? :?

Code: Alles auswählen

  Structure IMAGE
    ID.i
  EndStructure
  
  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
  
  Structure THREADINFO
    ID.i
    FileName$
  EndStructure
  
  Global NewList ProgramParams$()
  
  While ProgramParameter(x)
    AddElement(ProgramParams$())
    ProgramParams$() = ProgramParameter(x)
    x + 1
  Wend
  
  If x - 1 => 0
    Global Dim Images.IMAGE(x - 1)
  EndIf
  
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList LoadingThreads()
  Global NewList ThreadEntriesToDelete()
  Global NewList ThreadInfos.THREADINFO()
  
  Procedure LoadingThread(*ThreadInfo.THREADINFO)
    
    Images(*ThreadInfo\ID)\ID = LoadImage(#PB_Any, *ThreadInfo\FileName$)
    
  EndProcedure
  
  
  Window_Main_Title$ = "just a little test program..."
  
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
  
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
  
  HideWindow(Window_Main, #False)
  
  ForEach ProgramParams$()
    AddElement(LoadingThreads())
    AddElement(ThreadInfos())
    ThreadInfos()\ID = ListIndex(ProgramParams$())
    ThreadInfos()\FileName$ = ProgramParams$()
    LoadingThreads() = CreateThread(@LoadingThread(), @ThreadInfos())
  Next
  
  Repeat
    
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
    
    ForEach LoadingThreads()
      
      If Not IsThread(LoadingThreads())
        x = ListIndex(LoadingThreads())
        AddElement(MDIWindows_Main())
        MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images(x)\ID))
        ResizeWindow(MDIWindows_Main()\ID, 0, 0, 400, 200)
        MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, WindowWidth(MDIWindows_Main()\ID), WindowHeight(MDIWindows_Main()\ID), Images(x)\ID)
        AddElement(ThreadEntriesToDelete())
        ThreadEntriesToDelete() = LoadingThreads()
      EndIf
      
    Next
    
    WindowEvent = WindowEvent()
    Select WindowEvent
        
      Case #PB_Event_SizeWindow
        If IsToolBar(Toolbar_Main)
          ToolBarHeight_Main = ToolBarHeight(Toolbar_Main)
        EndIf
        If IsMenu(Menu_Main)
          MenuHeight_Main = MenuHeight()
        EndIf
        ResizeGadget(MDIGadget_Main, Const_ToolBarWidth, ToolBarHeight, WindowWidth(Window_Main) - Const_ToolBarWidth, WindowHeight(Window_Main) - ToolBarHeight - MenuHeight)
      
      Case #PB_Event_CloseWindow
        
        End
        
    EndSelect
    
    ForEach ThreadEntriesToDelete()
      ForEach LoadingThreads()
        If LoadingThreads() = ThreadEntriesToDelete()
          DeleteElement(LoadingThreads())
          Break
        EndIf
      Next
    Next
        
  ForEver
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: [Programm] Bilder in Threads laden

Beitrag von Bisonte »

Ehrlich gesagt, entzieht sich mir der Sinn, jedes Bild in einem eigenem Thread in eine Linklist einzulesen. Damit sich die Threads nicht gegenseitig verwirren, müsste man ja Locks usw nutzen und dadurch kann man dann gleich alles in einem Rutsch lesen ... ohne threads... Schneller wird das auch nicht dadurch....

Dann eher das Window erst anzeigen lassen, wenn alles soweit fertig ist...
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: [Programm] Bilder in Threads laden

Beitrag von NicTheQuick »

Du solltest mal konsequent überall Überprüfungen einbauen. Also wurde das Bild im Thread tatsächlich fehlerfrei geladen (Ist die ID ungleich 0 bzw. IsImage())? Wurde das Element korrekt zur Liste hinzugefügt (AddElement() ungleich 0)? ThreadSafe in den Compiler-Optionen aktiviert? Und was soll eigentlich dieses 'ThreadEntriesToDelete()'? Lösch' den Eintrag doch gleich in der ersten ForEach-Schleife, wo du die neuen MDI-Fenster erstellst. ;)
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

Überprüfungen einbauen ... mach ich!
NicTheQuick hat geschrieben:Und was soll eigentlich dieses 'ThreadEntriesToDelete()'? Lösch' den Eintrag doch gleich in der ersten ForEach-Schleife, wo du die neuen MDI-Fenster erstellst. ;)
Das würde die Zählschleife manipulieren und Elemente überspringen. Stell dir vor, du bist bei Element 2, löscht dieses ... welches Element kommt als nächstes? Die 3. Die war aber vorher die vier. Also wird die vorherige 3 übersprungen. Hoffe, das beschreibt es gut. [s]Und mit PreviousElement() kann ich da nicht ran gehen, weil ich ja nicht ausschließen kann, dass es sich nicht um das erste Element handelt.[/s]

/EDIT: Oh Mann, bin ich blöd, bin ich blöd, bin ich blöd, bin ich blöd ... Was habe ich vergessen ? Was hat mich 45 Minuten lang angestrengt suchen lassen ??? IMAGEID() hat gefehlt!

So geht der Text jetzt:

Code: Alles auswählen

  Structure IMAGE
    ID.i
  EndStructure
  
  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
  
  Structure THREADINFO
    ID.i
    FileName$
  EndStructure
  
  Global NewList ProgramParams$()
  
  While ProgramParameter(x)
    AddElement(ProgramParams$())
    ProgramParams$() = ProgramParameter(x)
    x + 1
  Wend
  
  If x - 1 => 0
    Global Dim Images.IMAGE(x - 1)
  EndIf
  
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList LoadingThreads()
  Global NewList ThreadEntriesToDelete()
  Global NewList ThreadInfos.THREADINFO()
  
  Procedure LoadingThread(*ThreadInfo.THREADINFO)
    
    Images(*ThreadInfo\ID)\ID = LoadImage(#PB_Any, *ThreadInfo\FileName$)
    
  EndProcedure
  
  
  Window_Main_Title$ = "just a little test program..."
  
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
  
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
  
  HideWindow(Window_Main, #False)
  
  ForEach ProgramParams$()
    AddElement(LoadingThreads())
    AddElement(ThreadInfos())
    ThreadInfos()\ID = ListIndex(ProgramParams$())
    ThreadInfos()\FileName$ = ProgramParams$()
    LoadingThreads() = CreateThread(@LoadingThread(), @ThreadInfos())
  Next
  
  Repeat
    
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
    
    ForEach LoadingThreads()
      
      If Not IsThread(LoadingThreads())
        x = ListIndex(LoadingThreads())
        AddElement(MDIWindows_Main())
        MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images(x)\ID))
        
        MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, 600, 300, ImageID(Images(x)\ID))
        AddElement(ThreadEntriesToDelete())
        ThreadEntriesToDelete() = LoadingThreads()
      EndIf
      
    Next
    
    WindowEvent = WindowEvent()
    Select WindowEvent
        
      Case #PB_Event_SizeWindow
        If IsToolBar(Toolbar_Main)
          ToolBarHeight_Main = ToolBarHeight(Toolbar_Main)
        EndIf
        If IsMenu(Menu_Main)
          MenuHeight_Main = MenuHeight()
        EndIf
        ResizeGadget(MDIGadget_Main, Const_ToolBarWidth, ToolBarHeight, WindowWidth(Window_Main) - Const_ToolBarWidth, WindowHeight(Window_Main) - ToolBarHeight - MenuHeight)
      
      Case #PB_Event_CloseWindow
        
        End
        
    EndSelect
    
    ForEach ThreadEntriesToDelete()
      ForEach LoadingThreads()
        If LoadingThreads() = ThreadEntriesToDelete()
          DeleteElement(LoadingThreads())
          Break
        EndIf
      Next
    Next
        
  ForEver
So, jetzt noch irgendwas falsch dran? Jetzt kann ich endlich weiterarbeiten. :bounce:
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

... will ich Bisontes Thread mal auseinander nehmen :mrgreen:
Bisonte hat geschrieben:Ehrlich gesagt, entzieht sich mir der Sinn, jedes Bild in einem eigenem Thread in eine Linklist einzulesen. Damit sich die Threads nicht gegenseitig verwirren, müsste man ja Locks usw nutzen
Wie Du an meinem letzten Code siehst geht es auch so. :)
Bisonte hat geschrieben:und dadurch kann man dann gleich alles in einem Rutsch lesen ... ohne threads... Schneller wird das auch nicht dadurch....
Schneller nicht, aber kontrollierbarer. Ich kann eine ProgressBar einbauen, die den Ladefortschritt anzeigt, deren Mutterfenster mit frischen WindowEvents() versorgt wird und nicht "abhängt" bis das Bild geladen ist. Außerdem - man stelle sich vor - es wird ein Image von 8192*8192 Pixeln auf einem uralt-Rechner geladen und der Anwender entscheidet sich, dass es ihm zu lange dauert => Klick auf Abbrechen und der Thread ist tot. Sonst müsste er warten, bis das Bild geladen ist.
Bisonte hat geschrieben:Dann eher das Window erst anzeigen lassen, wenn alles soweit fertig ist...
Nö. :D
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: [Programm] Bilder in Threads laden

Beitrag von NicTheQuick »

es_91 hat geschrieben:Überprüfungen einbauen ... mach ich!
NicTheQuick hat geschrieben:Und was soll eigentlich dieses 'ThreadEntriesToDelete()'? Lösch' den Eintrag doch gleich in der ersten ForEach-Schleife, wo du die neuen MDI-Fenster erstellst. ;)
Das würde die Zählschleife manipulieren und Elemente überspringen. Stell dir vor, du bist bei Element 2, löscht dieses ... welches Element kommt als nächstes? Die 3. Die war aber vorher die vier. Also wird die vorherige 3 übersprungen. Hoffe, das beschreibt es gut. [s]Und mit PreviousElement() kann ich da nicht ran gehen, weil ich ja nicht ausschließen kann, dass es sich nicht um das erste Element handelt.[/s]
Wenn du dir die Hilfe zu 'DeleteElement()' durchliest wirst du bemerken, dass nach einem 'DeleteElement()' standardmäßig das vorherige Element das neue wird. Existiert kein vorheriges Element, dann wird kein Element das neue sein. Demnach wird im nächsten Durchlauf der ForEach-Schleife immer das Element aktuell sein, was nach dem gelöschten kam.
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

Dann möchte ich mich gehörig entschuldigen. Ich versuche, das ThreadEntriesToDelete() auszubauen.

/EDIT: Irgendetwas mache ich falsch ... in meiner ProgramParams$()-Liste sind zwei Bilder, aber es wird zweimal das erste Bild angezeigt . . .

Code: Alles auswählen

  Structure IMAGE
    ID.i
  EndStructure
  
  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
  
  Structure THREADINFO
    ID.i
    FileName$
  EndStructure
  
  Global NewList ProgramParams$()
  
  While ProgramParameter(x)
    AddElement(ProgramParams$())
    ProgramParams$() = ProgramParameter(x)
    x + 1
  Wend
  
  If Not (x - 1) < 0
    Global Dim Images.IMAGE(x - 1)
  EndIf
  
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList LoadingThreads()
  Global NewList ThreadEntriesToDelete()
  Global NewList ThreadInfos.THREADINFO()
  
  Procedure LoadingThread(*ThreadInfo.THREADINFO)
    
    Images(*ThreadInfo\ID)\ID = LoadImage(#PB_Any, *ThreadInfo\FileName$)
    
  EndProcedure
  
  
  Window_Main_Title$ = "just a little test program . . ."
  
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
  
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
  
  HideWindow(Window_Main, #False)
  
  ForEach ProgramParams$()
    AddElement(LoadingThreads())
    AddElement(ThreadInfos())
    ThreadInfos()\ID = ListIndex(ProgramParams$())
    ThreadInfos()\FileName$ = ProgramParams$()
    LoadingThreads() = CreateThread(@LoadingThread(), @ThreadInfos())
  Next
  
  Repeat
    
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
    
    ForEach LoadingThreads()
      
      If Not IsThread(LoadingThreads())
        x = ListIndex(LoadingThreads())
        AddElement(MDIWindows_Main())
        MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images(x)\ID))
        
        MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, 600, 300, ImageID(Images(x)\ID))
        DeleteElement(LoadingThreads())
      EndIf
      
    Next
    
    WindowEvent = WindowEvent()
    Select EventWindow()
        Case Window_Main
          Select WindowEvent
              
            Case #PB_Event_SizeWindow
              If IsToolBar(Toolbar_Main)
                ToolBarHeight_Main = ToolBarHeight(Toolbar_Main)
              EndIf
              If IsMenu(Menu_Main)
                MenuHeight_Main = MenuHeight()
              EndIf
              ResizeGadget(MDIGadget_Main, Const_ToolBarWidth, ToolBarHeight, WindowWidth(Window_Main) - Const_ToolBarWidth, WindowHeight(Window_Main) - ToolBarHeight - MenuHeight)
            
            Case #PB_Event_CloseWindow
              
              End
              
          EndSelect
    EndSelect
  ForEver
Geändert wurde:


If Not IsThread(LoadingThreads())
x = ListIndex(LoadingThreads())
AddElement(MDIWindows_Main())
MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images(x)\ID))

MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, 600, 300, ImageID(Images(x)\ID))
DeleteElement(LoadingThreads())
EndIf

und es wurde die alte Löschungsabfrage gelöscht.
Benutzeravatar
CSHW89
Beiträge: 489
Registriert: 14.12.2008 12:22

Re: [Programm] Bilder in Threads laden

Beitrag von CSHW89 »

Es liegt nun daran, dass

Code: Alles auswählen

x = ListIndex(LoadingThreads())
nach dem Löschen ein falschen Index haben kann. Wenn du das 0te Element löscht, haben alle nachfolgenden einen um 1 kleineren Index.
Das mit einer zusätzlichen Liste zu bereinigen, halte ich aber für Falsch, oder zumindest für schlechten Stil. Du hast sowieso für mein Geschmack zu viele Listen. Denn die Werte in den einzelnen Listen korrespondieren ja. Also z.b. das zweite Element der Liste ThreadInfos() speichert den Index der Liste und den Dateinamen des zweiten Bildes. Das zweite Element der Liste ProgramParams$() speichert ebenfalls den Dateinamen. Und das zweite Element der Liste LoadingThreads() speichert von genau diesem Bild die Thread-Nummer.
Für solche Fälle sollte man nur eine Liste und eine Structure verwenden. Also ProgramParams$(), LoadingThreads() und TreahEntriesToDelete() rausschmeißen, und stattdessen in die Structure THREADINFO ein zusätzlichen Eintrag "thread.i" einfügen, der die Rückgabe von CreateThread speichert. Am Anfang wird dann nicht ProgramParams$ befüllt, sondern ThreadInfos() und beim Laden wird auch genau in dieser Liste geprüft, ob der Thread noch existiert. Dabei kann man dann x gleich den Index in ThreadInfo() setzen.
Das sähe dann so aus (ungetestet):

Code: Alles auswählen

  Structure IMAGE
    ID.i
  EndStructure
 
  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
 
  Structure THREADINFO
    ID.i
    Thread.i
    FileName$
  EndStructure
 
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList ThreadInfos.THREADINFO()
 
  While ProgramParameter(x)
    AddElement(ThreadInfos())
    ThreadInfos()\ID = ListIndex(ThreadInfos())
    ThreadInfos()\FileName$ = ProgramParameter(x)
    x + 1
  Wend
 
  If Not (x - 1) < 0
    Global Dim Images.IMAGE(x - 1)
  EndIf
 
  Procedure LoadingThread(*ThreadInfo.THREADINFO)
   
    Images(*ThreadInfo\ID)\ID = LoadImage(#PB_Any, *ThreadInfo\FileName$)
   
  EndProcedure
 
 
  Window_Main_Title$ = "just a little test program . . ."
 
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
 
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
 
  HideWindow(Window_Main, #False)
 
  ForEach ThreadInfos()
    ThreadInfos()\Thread = CreateThread(@LoadingThread(), @ThreadInfos())
  Next
 
  Repeat
   
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
   
    ForEach ThreadInfos()
     
      If Not IsThread(ThreadInfos()\Thread)
        x = ThreadInfos()\ID
        AddElement(MDIWindows_Main())
        MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, "", ImageID(Images(x)\ID))
       
        MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, 600, 300, ImageID(Images(x)\ID))
        DeleteElement(ThreadInfos())
      EndIf
     
    Next
   
    WindowEvent = WindowEvent()
    Select EventWindow()
        Case Window_Main
          Select WindowEvent
             
            Case #PB_Event_SizeWindow
              If IsToolBar(Toolbar_Main)
                ToolBarHeight_Main = ToolBarHeight(Toolbar_Main)
              EndIf
              If IsMenu(Menu_Main)
                MenuHeight_Main = MenuHeight()
              EndIf
              ResizeGadget(MDIGadget_Main, Const_ToolBarWidth, ToolBarHeight, WindowWidth(Window_Main) - Const_ToolBarWidth, WindowHeight(Window_Main) - ToolBarHeight - MenuHeight)
           
            Case #PB_Event_CloseWindow
             
              End
             
          EndSelect
    EndSelect
  ForEver
Bild Bild Bild
http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
Antworten