FileRequester über API (wer's eben braucht...)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
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

FileRequester über API (wer's eben braucht...)

Beitrag von NicTheQuick »

Mit dem folgenden Code kann man den Open- und SaveFileRequester
öffnen.
Dazu gibt es 5 Flags, deren Beschreibung sich im Quellcode befindet.

Für MultiSelection gibt es eine extra Procedure, die alle ausgewählten
Dateien in einer LinkedList ausgibt.

Ein Beispiel ist dabei.

Code: Alles auswählen

#FR_Save = 1
#FR_Save = 1 ;Öffnet den SaveFileRequester
#FR_Open = 2 ;Öffnet den OpenFileRequester
#FR_OverwritePrompt = 4 ;Frägt bei Wahl einer existierenden Datei nach, ob sie überschrieben werden soll (nur bei #FR_Save)
#FR_FileMustExist = 8 ;Lässt nur existierende Dateien zu (nur bei #FR_Open)
#FR_DontAddToRecent = 16 ;Fügt die ausgewählte Datei nicht zu den zuletzt verwendeten Dateien hinzu
#OFN_DONTADDTORECENT = $02000000
Procedure.s FileRequester(Title.s, DefaultFile.s, Pattern.s, *PatternPosition.Long, hParent.l = 0, flags.l = 0)
  Protected of.OPENFILENAME, *lpstrFilter, *c.Byte, a.l, Size.l, DefaultPath.s, Result.s
  
  of\lStructSize = SizeOf(OPENFILENAME)
  of\hwndOwner = hParent
  of\flags = 0
  If Pattern <> ""
    Size = Len(Pattern) + 2
    of\lpstrFilter = AllocateMemory(Size)
    If of\lpstrFilter
      PokeS(of\lpstrFilter, Pattern)
      *c = of\lpstrFilter
      For a = 1 To Size
        If *c\b = '|' : *c\b = 0 : EndIf
        *c + 1
      Next
    EndIf
  Else
    of\lpstrFilter = 0
  EndIf
  of\lpstrCustomFilter = 0
  of\nMaxCustFilter = 0
  If *PatternPosition
    of\nFilterIndex = *PatternPosition\l
  Else
    of\nFilterIndex = 0
  EndIf
  of\lpstrFile = AllocateMemory(100 * 1024 + 1)
  If GetFilePart(DefaultFile) <> "" And of\lpstrFile
    PokeS(of\lpstrFile, DefaultFile)
  EndIf
  of\nMaxFile = 100 * 1024
  of\lpstrFileTitle = 0
  of\nMaxFileTitle = 0
  
  DefaultPath = GetPathPart(DefaultFile)
  If Right(DefaultPath, 1) <> "\" : DefaultPath + "\" : EndIf
  of\lpstrInitialDir = AllocateMemory(Len(DefaultPath) + 1)
  If of\lpstrInitialDir : PokeS(of\lpstrInitialDir, DefaultPath) : EndIf
  
  of\lpstrTitle = @Title
  
  of\flags = #OFN_EXPLORER | #OFN_DONTADDTORECENT
  of\flags | #OFN_HIDEREADONLY | #OFN_NODEREFERENCELINKS
  ;If flags & #FR_MultiSelection : of\flags | #OFN_ALLOWMULTISELECT : EndIf
  If flags & #FR_FileMustExist : of\flags | #OFN_FILEMUSTEXIST : EndIf
  If flags & #FR_OverwritePrompt : of\flags | #OFN_OVERWRITEPROMPT : EndIf
  If flags & #FR_DontAddToRecent : of\flags | #OFN_DONTADDTORECENT : EndIf
  
  of\lpstrDefExt = 0
  of\lCustData = 0
  of\lpfnHook = 0
  of\lpTemplateName = 0
  
  If flags & #FR_Open
    GetOpenFileName_(of)
  ElseIf flags & #FR_Save
    GetSaveFileName_(of)
  EndIf
  
  Result = PeekS(of\lpstrFile)
  
  If of\lpstrInitialDir : FreeMemory(of\lpstrInitialDir) : EndIf
  If of\lpstrFile : FreeMemory(of\lpstrFile) : EndIf
  If of\lpstrFilter : FreeMemory(of\lpstrFilter) : EndIf
  
  If *PatternPosition
    *PatternPosition\l = of\nFilterIndex
  EndIf
  
  ProcedureReturn Result
EndProcedure
Procedure.l FileRequesterMulti(Title.s, DefaultPath.s, Pattern.s, *PatternPosition.Long, Files.s(), hParent.l = 0, flags.l = 0)
  Protected of.OPENFILENAME, *lpstrFilter, *c.Byte, a.l, Size.l, Result.s, Path.s, File.s
  
  of\lStructSize = SizeOf(OPENFILENAME)
  of\hwndOwner = hParent
  of\flags = 0
  If Pattern <> ""
    Size = Len(Pattern) + 2
    of\lpstrFilter = AllocateMemory(Size)
    If of\lpstrFilter
      PokeS(of\lpstrFilter, Pattern)
      *c = of\lpstrFilter
      For a = 1 To Size
        If *c\b = '|' : *c\b = 0 : EndIf
        *c + 1
      Next
    EndIf
  Else
    of\lpstrFilter = 0
  EndIf
  of\lpstrCustomFilter = 0
  of\nMaxCustFilter = 0
  If *PatternPosition
    of\nFilterIndex = *PatternPosition\l
  Else
    of\nFilterIndex = 0
  EndIf
  of\lpstrFile = AllocateMemory(100 * 1024 + 1)
  of\nMaxFile = 100 * 1024
  of\lpstrFileTitle = 0
  of\nMaxFileTitle = 0
  
  If Right(DefaultPath, 1) <> "\" : DefaultPath + "\" : EndIf
  of\lpstrInitialDir = AllocateMemory(Len(DefaultPath) + 1)
  If of\lpstrInitialDir : PokeS(of\lpstrInitialDir, DefaultPath) : EndIf
  
  of\lpstrTitle = @Title
  
  of\flags = #OFN_EXPLORER | #OFN_DONTADDTORECENT | #OFN_ALLOWMULTISELECT
  of\flags | #OFN_HIDEREADONLY | #OFN_NODEREFERENCELINKS
  If flags & #FR_FileMustExist : of\flags | #OFN_FILEMUSTEXIST : EndIf
  If flags & #FR_OverwritePrompt : of\flags | #OFN_OVERWRITEPROMPT : EndIf
  If flags & #FR_DontAddToRecent : of\flags | #OFN_DONTADDTORECENT : EndIf
  
  of\lpstrDefExt = 0
  of\lCustData = 0
  of\lpfnHook = 0
  of\lpTemplateName = 0
  
  If flags & #FR_Open
    GetOpenFileName_(of)
  ElseIf flags & #FR_Save
    GetSaveFileName_(of)
  EndIf
  
  Path = PeekS(of\lpstrFile)
  
  *c = of\lpstrFile + of\nFileOffset
  Repeat
    File = PeekS(*c)
    If File <> ""
      If AddElement(Files())
        Files() = Path + File
      EndIf
      *c + Len(File) + 1
    EndIf
  Until File = ""
  
  If of\lpstrInitialDir : FreeMemory(of\lpstrInitialDir) : EndIf
  If of\lpstrFile : FreeMemory(of\lpstrFile) : EndIf
  If of\lpstrFilter : FreeMemory(of\lpstrFilter) : EndIf
  
  If *PatternPosition
    *PatternPosition\l = of\nFilterIndex
  EndIf
  
  If Path <> ""
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

PatternPosition = 1
Debug FileRequester("Wählen sie eine Datei aus", "c:\", "Alle Dateien (*.*)|*.*|Text-Dateien (*.txt;*.ini)|*.txt;*.ini", @PatternPosition, 0, #FR_Save)
Debug PatternPosition

NewList Files.s()
Debug FileRequesterMulti("Wählen sie mehrere Dateien aus", "c:\", "Alle Dateien (*.*)|*.*|Text-Dateien (*.txt;*.ini)|*.txt;*.ini", @PatternPosition, Files(), 0, #FR_Open)
ForEach Files()
  Debug Files()
Next
Debug PatternPosition
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Hatten wir das nicht gearde?
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Fluid Byte hat geschrieben:Hatten wir das nicht gearde?
Ja, aber diesmal ohne Memoryleak und in nützlicher form :mrgreen:

:allright:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
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

Beitrag von NicTheQuick »

Wenn dann richtig! :mrgreen:

Mir gings eigentlich nur darum, dass ich das Parent-Window selbst bestimmen
kann oder einfach gar keins angeben muss. Ich hatte das Problem, dass ich
nicht mehrere FileRequester() gleichzeitig in versch. Threads öffnen konnte.
Mit dieser Version funktioniert alles und ich hab die selben Möglichkeiten wie
bei den nativ von PB bereitgestellten Requestern. Bloß funktioniert der Code
nicht auf Linux, dem Mac und mit Unicode.

Außerdem finde ich die Möglichkeit bei MultiSelection alle Dateien in eine
LinkedList zu verfrachten, wesentlich angenehmer. Das hat übrigens auch
wieder seine Vorteile bei prozessinternem Multithreading.
'NextSelectedFileName()' könnte man da vergessen.

PS.: Hab wirklich nicht darauf geachtet, dass es einen ähnlichen Thread
schon einmal gab. :oops:
Benutzeravatar
kayfr72
Beiträge: 130
Registriert: 12.09.2004 19:13
Wohnort: Lehrberg

Beitrag von kayfr72 »

Also mir geht das hier nicht weit genug! :lol:

Nur mal ne Frage. Hab aus der Beschreibung von "OPENFILENAME Structure" glaub ich raus gelesen zu haben,das man über "lpstrCustomFilter" einstellen kann,welcher Fileendung automatisch bei umstellen bei des lpstrFilter" im Textfenster angezeigt wird. z.B Text.txt oder beim umstellen dann Text.doc

Wenn das so wäre oder auch nicht. wie funktioniert so was richtig?
Andesdaf
Moderator
Beiträge: 2671
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

danke für den Code :D
Win11 x64 | PB 6.20
Antworten