Seite 1 von 1

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

Verfasst: 14.08.2007 21:56
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

Verfasst: 14.08.2007 22:42
von Fluid Byte
Hatten wir das nicht gearde?

Verfasst: 14.08.2007 22:47
von ts-soft
Fluid Byte hat geschrieben:Hatten wir das nicht gearde?
Ja, aber diesmal ohne Memoryleak und in nützlicher form :mrgreen:

:allright:

Verfasst: 14.08.2007 23:12
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:

Verfasst: 28.01.2009 03:21
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?

Verfasst: 29.01.2009 13:13
von Andesdaf
danke für den Code :D