1. Artikel
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forum
  • Anmelden
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. Paules-PC-Forum.de
  2. Forum
  3. Programmierung
  4. XProfan
  5. Spezielles

UserMessages

  • H.Brill
  • 22. Mai 2021 um 19:47
  • H.Brill
    Stammuser
    Reaktionen
    508
    Beiträge
    1.192
    • 22. Mai 2021 um 19:47
    • #1

    Hallo,

    habe hier ein kleines Problem.

    Ziel ist es, viele Bilder in einem Prozess vorzuladen (Handle), um das Hauptprogramm zu entlasten

    bzw. daß es flüssiger läuft. Mit einer Message (SendMessage) soll der Prozess das Handle zum

    Hauptprogramm senden und wenn der Prozess fertig mit Laden ist, auch eine Message senden.

    Leider bekomme ich die Handles nicht ins Hauptprogramm, bzw. bewirkt die UserMessage nichts.

    Die Message, wenn der Prozess fertig ist, funktioniert dagegen.

    Hat jemand eine Idee, woran das hängen könnte ?

    Code
    Declare path$, pid&, ende&, Diashow%[], Handle btn1
    Window 1100, 800
    btn1 = Create("Button", %HWnd, "Ende", 10, 10, 60, 25)
    
    UserMessages 1000, 2000
    path$ = "F:\StarTreck\"  ' PFAD BITTE ANPASSEN !!!!!!!!!!!!!!!
    Setsize Diashow%[], 100
    
    pid& = pExec("|Bilder", %HWnd, path$)
    ende& = 0
    
    WhileNot ende&
      waitinput
      If %UMessage = 1000
         Diashow%[&ULPARAM] = &UWPARAM
         DrawPic Diashow%[&UWPARAM], 100, 20; 0
      ElseIf %UMessage = 2000
         Process("Kill", pid&, 0)
         MessageBox(Str$(&UWPARAM) + " Dateien geladen !", "Info", 0)
      ElseIf Clicked(btn1)
         ende& = 1
      EndIf
    EndWhile
    
    'Bildverzeichnis Initialisieren
    Proc Bilder
    Parameters win%, Pfad$
    Declare count%, handle%[]
    ClearList : ChDir Pfad$ : AddFiles "*.jpg"
    WhileLoop 0, GetCount(0) - 1
        count% = &LOOP
        handle%[&LOOP] = Create("hSizedPic", -1, Pfad$ + GetString$(0, &LOOP), 400, 200, 1)
        SendMessage(win%, 1000, handle%[&LOOP], count%)
        Sleep 500
    EndWhile
    SendMessage(win%, 2000, count% + 1, 0)
    EndProc
    
    End
    Alles anzeigen

    Im Prozess selber kann ich mit StartPaint...EndPaint auf das übergebene Fensterhandle zeichnen.

    Insofern sind die Bilder mit den richtigen Handles ja da.

    Ich möchte die Bilder aber gerne im Hauptprogamm anzeigen.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

  • Volkmar
    Moderator
    Reaktionen
    7.017
    Beiträge
    6.942
    • 22. Mai 2021 um 20:59
    • #2

    Die Usermessage 1000 will er wohl nicht. Wenn ich 1001 nehme, dann komme ich zu

    "Dieses Element gibt es nicht" in Zeile 16. Das muß wohl richtigerweise DrawPic Diashow%[&ULPARAM], 100, 20; 0 heißen. Aber dort erhalte ich dann "Falscher Parametertyp: 100 in Zeile 16" :?: Der Grund ist mir jetzt nicht klar,

    Gruß Volkmar

  • H.Brill
    Stammuser
    Reaktionen
    508
    Beiträge
    1.192
    • 23. Mai 2021 um 08:25
    • #3

    Hallo Volkmar,

    Die Werte der Usermessages hatte ich auch schon verändert und keinen Erfolg gehabt.

    Da Roland in seiner Hilfe auch von der UserMessage 1000 , 1001 Gebrauch macht, bin ich

    mal davon ausgegangen, daß man mit denen nicht ins Gehege mit anderen Messages kommt.

    Irgendwie scheinen die Handles im Hauptprogramm nicht mehr gültig zu sein. Die Meldung

    "Falscher Parametertyp: 100 kommt auch bei falschen oder mit 0 belegten Handles.

    Zuerst bekomme ich aber die Meldung, daß es dieses Element (Diashow%[&ULPARAM] nicht

    gibt, obwohl ich mit SetSize das Array groß genug erweitere.

    Aber bei UserMessages 2000, 3000 :

    If %UMessage = 2000

    Messagebox(Str$(&UWPARAM), Str$(&ULPARAM), 0)

    und das andere auskommentiert, zeigt mir, daß beide Werte ankommen. Bei 1000 geht es nicht.

    Die erste 0 bei &ULPARAM zeigt die Nummer (Index) des in das Array einzutragende Handle

    &UWPARAM. Und beim Index 0 fangen wir ja auch beim Array an.

    Wenn ich direkt mit

    DrawPic &UWPARAM, 100, 20; 0

    anzeigen will, kommt auch der falsche Parametertyp.

    Da muß der Fehler doch woanders stecken. Auch eine übergebene Variable an pExec() , die das Handle

    des Bildes aufnehmen soll, funktioniert nicht. Mit Handles von Fenstern etc. geht es ja auch. Scheint

    so zu sein, daß es sich verhält wie Bereiche und Arrays, die man auch nicht übergeben kann / sollte,

    Auszug aus der Hilfe :

    Zitat

    PExec - PExecWait

    Bei Arrays und Bereichen würden Referenzen auf Speicheradressen übergeben, die im neuen Prozess des Moduls keine Gültigkeit mehr hätten. Ein Programmabbruch wäre die Folge.

    Wird wohl umgekehrt auch so sein.


    Vielleicht kann Roland das mal anschauen.

    Erstens das mit der UserMessage 1000 und zweitens das mit den (falschen) Werten

    beim Array und DrawPic.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

    2 Mal editiert, zuletzt von H.Brill (23. Mai 2021 um 08:54)

  • Volkmar
    Moderator
    Reaktionen
    7.017
    Beiträge
    6.942
    • 23. Mai 2021 um 09:50
    • #4

    Nun wollte ich mir, etwas ausgeschlafen, das nochmal ansehen, aber Du hast schon vorweggenommen, was ich vor hatte :) Da muß mal jemand ran, der klüger ist 8)

    Gruß Volkmar

  • H.Brill
    Stammuser
    Reaktionen
    508
    Beiträge
    1.192
    • 23. Mai 2021 um 10:34
    • #5

    Ich nehme da an, daß das Bildhandle im Hauptprogramm nicht mehr

    gültig ist.

    Bloß die Sache mit dem Array müßte doch wenigstens funktionieren.

    Ich probiere mal Schritt für Schritt weiter. z.B. mit MAT mal das Array

    vorbelegen usw.

    Zitat von Volkmar

    Da muß mal jemand ran, der klüger ist 8)

    Das wird wohl nur Roland sein.

    Wir können nur durch Probieren und Hilfe lesen das eine oder andere herausfinden.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

  • p. specht
    Premium-Mitglied
    Reaktionen
    986
    Beiträge
    5.665
    • 13. Juni 2021 um 15:13
    • #6

    Jonathan lieferte - denke ich - einen Workaround:

    Orig.-Text:

    Wenn man in einem Programm viele Bilder zeichnet und diese nicht immer wieder von der Festplatte geladen werden sollten, man aber auch keine Lust hat, jedes Bild am Anfang ausdrücklich zu laden, kann man diese Routinen nehmen:

    Code
    'Zum Puffern von Bildern
    Declare BufferedImageFiles$'Liste der bereits gepufferten Bilder, getrennt durch "|"
    Declare hBufferedImages&[]'Handles der gepufferten Bilder
    
    SubProc Create.hPicBuffered
        Parameters Typ&, S$    Declare NewImg&
        If @Len(BufferedImageFiles$) = 0
            BufferedImageFiles$ = "|"
        EndIf
        If Typ& = -1
            IfNot @InStr("|" + @Upper$(S$) + "|", @Upper$(BufferedImageFiles$))
                BufferedImageFiles$ = BufferedImageFiles$ + S$ + "|"            hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))] = @Create("hPic", -1, S$)
            EndIf
            NewImg& = @Create("hPicCopy", hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))])
        Else
            NewImg& = @Create("hPic", Typ&, S$)
        EndIf
        Return NewImg&
    
    EndProc
    
    SubProc Create.hSizedPicBuffered
        Parameters Typ&, S$, X&, Y&, N&    Declare NewImg&, XN&, YN&, Faktor1!, Faktor2!
        If @Len(BufferedImageFiles$) = 0
            BufferedImageFiles$ = "|"
        EndIf
        If Typ& = -1
            IfNot @InStr("|" + @Upper$(S$) + "|", @Upper$(BufferedImageFiles$))
                BufferedImageFiles$ = BufferedImageFiles$ + S$ + "|"            hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))] = @Create("hPic", -1, S$)
            EndIf
            If N& = 1
                Faktor1! = X& / @Width(hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))])            Faktor2! = Y& / @Height(hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))])
                If Faktor1! < Faktor2!
                    XN& = X&                YN& = @Height(hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))]) * Faktor1!
                Else
                    XN& = @Width(hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))]) * Faktor2!                YN& = Y&
                EndIf
            Else
                XN& = X&            YN& = Y&
            EndIf
            NewImg& = @Create("hNewPic", XN&, YN&, 0)        StartPaint NewImg&        DrawSizedPic hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))], 0, 0 - XN&, YN&; 0        EndPaint
        Else
            NewImg& = @Create("hSizedPic", Typ&, S$, X&, Y&, N&)
        EndIf
        Return NewImg&
    
    EndProc
    
    Proc DrawSizedPicBuffered
        Parameters S$, X&, Y&, DX&, DY&, N&
        If @Len(BufferedImageFiles$) = 0
            BufferedImageFiles$ = "|"
        EndIf
        IfNot @InStr("|" + @Upper$(S$) + "|", @Upper$(BufferedImageFiles$))
            BufferedImageFiles$ = BufferedImageFiles$ + S$ + "|"        hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))] = @Create("hPic", -1, S$)
        EndIf
        DrawSizedPic hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))], X&, Y& - DX&, DY&; N&
    
    EndProc
    
    Proc DrawPicBuffered
        Parameters S$, X&, Y&, N&
        If @Len(BufferedImageFiles$) = 0
            BufferedImageFiles$ = "|"
        EndIf
        IfNot @InStr("|" + @Upper$(S$) + "|", @Upper$(BufferedImageFiles$))
            BufferedImageFiles$ = BufferedImageFiles$ + S$ + "|"        hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))] = @Create("hPic", -1, S$)
        EndIf
        DrawPic hBufferedImages&[@InStr('|' + @Upper$(S$) + '|', @Upper$(BufferedImageFiles$))], X&, Y&; N&
    
    EndProc
    
    Proc DeleteImageBuffer
        WhileLoop 0, @SizeOf(hBufferedImages&[]) - 1
            If hBufferedImages&[&loop]
                DeleteObject hBufferedImages&[&loop]
            EndIf
        EndWhile
    
    EndProc
    Alles anzeigen

    Die Procs ersetzen Create("hPic"), Create("hSizedPic"), DrawPic und DrawSizedPic in ihrer Form zum Laden von Bildern von der Festplatte. Wird ein Bild zum ersten Mal geladen, laden diese Routinen das Bild in den RAM und behalten dort eine Kopie davon. Wird das Bild erneut geladen, wird die Kopie im RAM benutzt und es nicht nochmal von der Festplatte geladen. Am Ende sollte man DeleteImageBuffer nicht vergessen, damit die ganzen Handles der Kopien wieder freigegeben werden.

    Gruß

    Jonathan

    HP255G7:Win10pro2.004,4*AMD Ryzen3200U@2.60GHz,6+2GB-RadeonVega/237GBSSD:intlDVDRW,3xUSB3 ext4TB-HDX,XProfanX3+Xasm/Xpse

  • H.Brill
    Stammuser
    Reaktionen
    508
    Beiträge
    1.192
    • 13. Juni 2021 um 18:35
    • #7

    Ob das mit sehr vielen Bildern viel schneller ist ?

    Immerhin müssen die Procs ja auch abgearbeitet werden

    und in dieser Zeit steht ja das Hauptprogramm.

    Es ging ja um flüssiges Arbeiten im Hauptprogramm und

    deshalb sollte das Laden im Hintergrund erfolgen.

    Da wäre halt das Multiprozessing das Mittel der Wahl

    gewesen.

    Vielleicht kann man auch mit einem Timer was machen.

    Der muß halt so kurz angepaßt werden, damit er das

    Arbeiten im Programm nicht stört. Die Timer-Proc müßte

    sich ja nur merken, wo sie in der Listboxliste beim Verlassen

    steht, um beim nächsten Timerüberlauf dort weiter zu machen.

    Eben halt bis zum Ende der Listboxliste.

    Die Zeit müßte man dann im Hauptprogramm ausbaldowern.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

  • p. specht
    Premium-Mitglied
    Reaktionen
    986
    Beiträge
    5.665
    • 14. Juni 2021 um 09:40
    • #8

    Verstehe ... manuelles polling, sozusagen... Aber das droht dann sehr PC- und Auslastungs-spezifisch zu werden.

    Wie wär´s mit XPSE-UserThreads? Seit iF den Workaround zu thread.is vorgestellt hat, klappt das recht gut! Und fände schon im Datenraum des Hauptprogramms statt, habe ich gelesen (Oder gilt das nur für Kernel-Threads?)

    HP255G7:Win10pro2.004,4*AMD Ryzen3200U@2.60GHz,6+2GB-RadeonVega/237GBSSD:intlDVDRW,3xUSB3 ext4TB-HDX,XProfanX3+Xasm/Xpse

    Einmal editiert, zuletzt von p. specht (14. Juni 2021 um 09:47)

  • Michael Wodrich
    Profi
    Reaktionen
    263
    Beiträge
    562
    • 14. Juni 2021 um 17:02
    • #9

    Ich glaube immer noch, das dies der falsche Weg ist.

    Im Internet stehen viele Lösungen, wie man Bilder schnell mit OpenGL anzeigt.

    Handles werden immer innerhalb eines Prozesses bleiben. Ruft man einen 2. Prozess auf kommen die Zugriffsgeister und der Spuk beginnt.

    Über "opengl viele bilder schnell laden" habe ich auf Anhieb Aussagen gefunden, die ein schnelles Laden als 'ganz normal' beschreiben.

    Hier wird aber dann ganz mit OpenGL gearbeitet.

    Mit XProfan müsste man dann tiefer in die OpenGL-Speicherstrukturen einsteigen.

    Vielleicht hilft auch: Eine Einführung in OpenGL - Universität Augsburg Informatik

    Dort wird auch auf schnell zu bearbeitende Texturen eingegangen.

    Programmieren, das spannendste Detektivspiel der Welt.

    Einmal editiert, zuletzt von Michael Wodrich (14. Juni 2021 um 17:09)

  • Jens-Arne
    Schüler
    Reaktionen
    99
    Beiträge
    124
    • 21. November 2022 um 20:44
    • #10

    Hallo,

    der Thread ist zwar schon alt, aber ich habe ihn jetzt erst gefunden. Michael hat Recht: Bild-Handles kann man nicht prozessübergreifend verwenden. Jeder Prozess hat seinen eigenen Speicherbereich für sowas, der nur für den jeweiligen Prozess gültig ist.

    Das ganze geht allerdings, wenn man einen Thread verwendet. Hauptprogramm und dessen Threads teilen sich einen Speicherbereich. Aber hier gleich eine Warnung: Thread-Programmierung ist extrem fehleranfällig und fast nicht debugfähig. Es gibt einfach immer irgendwelche Abstürze ohne jeden Anhaltspunkt, was eigentlich genau schiefgelaufen ist. Erfahrungsgemäß geht es einigermaßen, wenn man nur einen einzigen Thread benutzt (zusätzlich zum Hauptprogramm). Aber auch da darf es keine Zugriffsparallelitäten geben wie z.B. Thread lädt gerade Bild, Hauptprogramm versucht schon, Bild anzuzeigen. Wer da genauer einsteigen will, sollte zum Anfang nach "CreateThread" und "CreateMutexA" im MSDN suchen.

    Und: XProfan ist von Hause aus nicht multithreading-fähig. Das geht also nur mit einer DLL, die in einer anderen Sprache geschrieben wurde, in der die Thread-Proc steht, die man dann als Thread startet. Das geht z.B. mit Profan2Cpp, wenn man zu den Glücklichen zählt, die damals noch eine Lizenz ergattert haben, oder heute auch kostenlos mit fbProcs über JRPC3/FreeBasic. Das ist aber alles ziemlich aufwändig. Ob sich das für dieses spezielle Problem von Heinz lohnt, ist die Frage. Ich habe das mal für ein Bildanzeigeprogramm à la IrfanView programmiert, es hat aber Jahre (!) gedauert, bis ich das wirklich zum Laufen bekommen habe. Jetzt allerdings lädt das Programm über einen Thread immer schon das nächste Bild in einem Verzeichnis vor, während man sich das aktuelle noch anschaut. Das ist schon ziemlich praktisch.

    Gruß, Jens-Arne

  • Jens-Arne
    Schüler
    Reaktionen
    99
    Beiträge
    124
    • 21. November 2022 um 22:09
    • #11

    Das ganze sei an einem rudimentären Beispiel illustriert, das mit Profan2Cpp erstellt wird:

    Erst einmal das XProfan-Hauptprogramm:

    Code
    declare UebergabeString$,ThreadDone&,hImage&,fn$,hThread&,ThreadProcAddr&,hDLL&
    
    cls
    hDLL&=@usedll("ThreadLoadImageDLL.dll")
    'Thread vorbereiten und starten
    UebergabeString$=@str$(@addr(ThreadDone&))+"~" 'es kann nur ein Parameter an den Thread übergeben werden, daher benutzen wir einen String, um darin alle Parameter mit "~" getrennt unterzubringen
    UebergabeString$=UebergabeString$+@str$(@addr(hImage&))+"~"
    UebergabeString$=UebergabeString$+"test.bmp" 'muss existieren, bitte selbst erzeugen
    ThreadProcAddr&=@external("Kernel32.dll","GetProcAddress",hDLL&,"LoadImageThread")
    hThread&=@external("Kernel32.dll","CreateThread",0,0,ThreadProcAddr&,@addr(UebergabeString$),0,0)
    'auf Signal des Threads warten, dass er mit seiner Arbeit fertig ist und nun ein gültiges Bitmaphandle in hImage& steht
    while ThreadDone&=0 'braucht keinen Mutex zur Absicherung, weil ein LonInt 32bit umfasst und daher mit einem einzigen Assembler-Befehl gelesen und beschrieben werden kann (das ist also "atomar")
      sleep 25
    endwhile
    'Bild anzeigen
    drawpic hImage&,0,0;0
    waitinput
    deleteobject hImage&
    freedll hDLL&
    end
    Alles anzeigen

    Und nun der Code für die DLL, in der die Thread-Proc steht (muss mit Profan2Cpp übersetzt werden, die erzeugte DLL muss ins Verzeichnis des XProfan-Programms kopiert werden, Name der Quelldatei: ThreadLoadImageDLL.prf):

    Code
    $DLL
    
    DLLPROC LoadImageThread,1,"LoadImageThread"
      parameters p#
      declare UebergabeString$,ThreadDone#,hImage#,fn$,hPic&
      'Übergabestring auswerten
      UebergabeString$=@string$(p#,0)
      ThreadDone#=@val(@substr$(UebergabeString$,1,"~")) 'entspricht ThreadDone& im Hauptprogramm
      hImage#=@val(@substr$(UebergabeString$,2,"~")) 'entspricht himage& im Hauptprogramm
      fn$=@substr$(UebergabeString$,3,"~")
     'Bild laden
      hPic&=@create("hPic",-1,fn$)
      long hImage#,0=hPic&
      'Flag für Hauptprogramm setzen, dass der Thread fertig ist und sich beendet
      long ThreadDone#,0=1
      return 0
    ENDPROC
    Alles anzeigen

    Die Grafikdatei "test.bmp" muss natürlich existieren. Einfach irgendwas im bmp-Format erzeugen, das klein genug ist, um in einem mit cls erzeugten Fenster angezeigt zu werden und ins Verzeichnis des Hauptprogramms kopieren.

    2 Mal editiert, zuletzt von Jens-Arne (21. November 2022 um 22:19)

  • Jens-Arne
    Schüler
    Reaktionen
    99
    Beiträge
    124
    • 23. November 2022 um 23:10
    • #12

    Und hier das ganze noch einmal für XProfan mit JRPC3 und FreeBasic (man braucht dann keinen zweiten Quellcode mehr für die DLL und sich um deren Erstellung nicht zu sorgen):

    Code
    declare UebergabeString$,ThreadDone&,hImage&,fn$,hThread&,ThreadProcAddr&,hDLL&
    
    {$PUSHFBDLLGLOBALLINE #include "file.bi"}
    
    fbPROC SubStr(s As String,num As Integer,delim As String) As String 'SubStr gibt es in FreeBasic nicht, daher nachbauen
      Dim As Integer anz,aktpos,findpos,lastpos
      Dim As String erg
      anz=0
      aktpos=1
      lastpos=1
      erg=""
      while (anz<num) and (anz<>-1)
        findpos=instr(aktpos,s,delim)
        if findpos>0
          anz=anz+1
          if anz=num
            erg=mid(s,lastpos,findpos-lastpos)
          else
            lastpos=findpos+1
            aktpos=findpos+1
          endif
        else
          if (len(s)>lastpos) and (anz=num-1)
            erg=right(s,len(s)-lastpos+1)
          endif
          anz=-1 'raus, nichts (weiter) gefunden
        endif
      endwhile
      return erg
    ENDPROC 'SubStr
    
    fbPROC CatchBmp(MemPointer As Any Pointer) As HBITMAP
      Dim As Integer BMPInfo,init
      Dim As Any Pointer BITMAPFILEHEADER
      Dim As HBITMAP hImage
      Dim As HDC hDC
      hDC=GetDC(GetDesktopWindow())
      BITMAPFILEHEADER=MemPointer
      BMPInfo=cast(Integer,MemPointer)+14
      init=cast(Integer,MemPointer)+Peek(Integer,BITMAPFILEHEADER+10)
      hImage=CreateDIBitmap(hDC,cast(Any Pointer,BMPInfo),4,cast(Any Pointer,init),cast(Any Pointer,BMPInfo),0)
      ReleaseDC(GetDesktopWindow(),hDC)
      return hImage
    ENDPROC
    
    fbPROC LoadImageThread(p As ZString Pointer) As Integer Export
      Dim As String UebergabeString,fn
      Dim As Integer ThreadDone,hImage,nFile
      DIm As LongInt FileSize
      Dim As HBITMAP hPic
      Dim As Byte Pointer b
      'Übergabestring auswerten
      UebergabeString=Peek(ZString,p)
      ThreadDone=int(val(substr(UebergabeString,1,"~"))) 'entspricht ThreadDone& im Hauptprogramm
      hImage=int(val(substr(UebergabeString,2,"~"))) 'entspricht himage& im Hauptprogramm
      fn=substr(UebergabeString,3,"~")
      substr(UebergabeString,4,"~")
      'Bild laden
      FileSize=FileLen(fn)
      b=Allocate(FileSize)
      nFile=FreeFile()
      open fn For Binary Access Read As #nFile
      get #nFile,0,*b,FileSize
      close #nFile
      hPic=catchbmp(b)
      DeAllocate(b)
      Poke Integer,hImage,cast(Integer,hPic)
      'Flag für Hauptprogramm setzen, dass der Thread fertig ist und sich beendet
      Poke Integer,ThreadDone,1
      return 0
    ENDPROC
    
    cls
    hDll&=@usedll("ThreadLoadImageJRPC3_fbprocs.dll")
    'Thread vorbereiten und starten
    UebergabeString$=@str$(@addr(ThreadDone&))+"~" 'es kann nur ein Parameter an den Thread übergeben werden, daher benutzen wir einen String, um darin alle Parameter mit "~" getrennt unterzubringen
    UebergabeString$=UebergabeString$+@str$(@addr(hImage&))+"~"
    UebergabeString$=UebergabeString$+"test.bmp" 'muss existieren, bitte selbst erzeugen
    ThreadProcAddr&=@external("Kernel32.dll","GetProcAddress",hDLL&,"LOADIMAGETHREAD@4")
    hThread&=@external("Kernel32.dll","CreateThread",0,0,ThreadProcAddr&,@addr(UebergabeString$),0,0)
    'auf Signal des Threads warten, dass er mit seiner Arbeit fertig ist und nun ein gültiges Bitmaphandle in hImage& steht
    while ThreadDone&=0 'braucht keinen Mutex zur Absicherung, weil ein LonInt 32bit umfasst und daher mit einem einzigen Assembler-Befehl gelesen und beschrieben werden kann (das ist also "atomar")
      sleep 25
    endwhile
    'Bild anzeigen
    drawpic hImage&,0,0;0
    waitinput
    deleteobject hImage&
    freedll hDLL&
    end
    Alles anzeigen

    Die Grafikdatei "test.bmp" muss natürlich existieren. Einfach irgendwas im bmp-Format erzeugen, das klein genug ist, um in einem mit cls erzeugten Fenster angezeigt zu werden und ins Verzeichnis des Hauptprogramms kopieren.

    3 Mal editiert, zuletzt von Jens-Arne (23. November 2022 um 23:36)

Windows 11

  1. Datenschutzerklärung
  2. Impressum
Community-Software: WoltLab Suite™