It is currently Wed Sep 18, 2019 10:52 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: [Done]error: Invalid memory access
PostPosted: Mon Jun 25, 2012 5:14 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Aug 03, 2011 4:52 am
Posts: 215
Location: Beirut, Lebanon
Hello:
I asked in "Coding questions" about new look openfilerequester, and I get answered the following, which is working very well:
Code:
; skywalk
; Since the built-in PureBasic OFN Requester does not allow Details View!
; Fill the OFN structure and use a OFNHook Procedure.
; Portions modified from Sparkie's code:
; http://www.purebasic.fr/english/viewtopic.php?p=133878#p133878
EnableExplicit
#sNull$ = "-999"
Structure ScanPBDataTypes
  ; These take up no memory and are allowed to grow without redim
  ; when the structure is pointed at a memory buffer.
  ; ex. *buf\d[i] ; 'i' being incremented in a loop
  ; Essentially, this is 1 big StructureUnion.
  b.b[0]  ; byte
  w.w[0]  ; word
  l.l[0]  ; long
  i.i[0]  ; integer
  q.q[0]  ; quad
  f.f[0]  ; float
  d.d[0]  ; double
  a.a[0]  ; ascii
  c.c[0]  ; character
  u.u[0]  ; unicode
  ;s.s{Use 1-MAX String Length expected 255}  ; string
  s.s[0]  ; This supports 1 String scan. *p\s = @x$, *p\s[1] does not work.
EndStructure

Macro FL_FileExists(Fname)
  ;  0 = File or Folder does not exist
  ;  1 = File Exists
  ; -1 = Folder Exists
  ; Since FileSize() returns:
  ;       -1 = File Not found.
  ;       -2 = File is a directory.
  ;        0 = Empty File, > 1 = File Exists
  ;        FileSize() respects '*' wildcards and reports results accordingly.
  FileSize(Fname) + 1
EndMacro

Procedure.i SF_CharReplace(*p.ScanPBDataTypes, StrFrom$="|", StrTo$=#NULL$)
  ; REV:  111227, skywalk
  ; SYNTAX:   nNulls = SF_CharReplace(@x$,"|",#Null$,0)
  ; DEFAULT:  Edit a string in memory to embed null char's = Chr(0)
  ; RETURN:   # of char replacements made.
  ; If StrFrom$=#Null$, then buffer end is assumed to be double null position.
  ; Accepts multiple chars, but only works with the 1st char.
  ; Works with unicode or ascii.
  Protected.i i, msLen, nChars
  Protected.i CharFrom = Asc(StrFrom$)
  Protected.i CharTo = Asc(StrTo$)
  ; Determine msLen
  If CharFrom = #Null   ; Search memory for double nulls = end of string buffer
    While msLen < 64000
      If *p\c[msLen] = 0 And *p\c[msLen+1] = 0
        Break
      EndIf
      msLen + 1
    Wend
    msLen - 1  ; Ignore the final #Null later in code
  Else
    msLen = MemoryStringLength(*p) - 1  ; Get Len in characters, not bytes.
   ; StringByteLength(PeekS(*p))        ; Returns nBytes and depends on ascii/unicode switch!
  EndIf
  For i = 0 To msLen   ; Since walking through String by Character, no need to count bytes/char.
    If *p\c[i] = CharFrom
      *p\c[i] = CharTo
      nChars + 1
    EndIf
  Next i
  ;ShowMemoryViewer(@*p,msLen+32)
  ProcedureReturn nChars
EndProcedure

Procedure.i Split(s$, Delm$, Array sA.s(1), trimsp.i=0, UseCase.i=#PB_String_CaseSensitive)
  ; REV:  100405, skywalk
  ;       modified from Trond PB forum code
  ;       www.purebasic.fr/english/viewtopic.php?f=13&t=26738
  ; REV:  111227, skywalk
  ;       removed ReSize parameter. sA() adjusts to size required = nStrings-1
  ;       added multi-char delimiter, case sensitivity, and unicode.
  ;       UseCase = 0-#PB_String_CaseSensitive or 1-#PB_String_NoCase
  ; Return: Count of elements or nStrings found.
  ;         If none, then entire string is assigned to sA(0)
  ; s$ = normal null terminated string
  ; VB6 syntax -> sA() = Split(expression[, delimiter[, count[, compare]]])
  ; SizeOf(Character) is converted to a constant by compiler so no speed hit for multiple use
  Protected.i i, nStrings
  Protected.i sLen = Len(s$)
  Protected.i DelmLen = Len(Delm$)
  Protected *s.Character = @s$  ; Character Structure points to s$ contents, not its address
  Protected.i lastp = *s
  Protected Delmc.c
  If DelmLen = 0  ; "" or empty
    ReDim sA(0)
    sA(0) = s$
    nStrings = 1
  ElseIf sLen = 0 ; s$ = ""
    ReDim sA(0)
    sA(0) = #NULL$
    nStrings = 0
  Else            ; OK to Split
    Dim sA(sLen/DelmLen+1)    ; Start array at worst case estimate
    If UseCase = #PB_String_CaseSensitive And (DelmLen = 1 Or Delm$ = #CRLF$) ; use faster single character split routine
      If DelmLen = 1
        Delmc = Asc(Delm$)
      Else            ; Delm$ = #CRLF$
        Delmc = #LF   ; use the 2nd char, then trim trailing #CR$ from elements
      EndIf
      While *s\c      ; > 0 means valid Character, = 0 means String terminated.
        If *s\c <> Delmc
          *s + SizeOf(Character)
        Else
          *s\c = 0    ; Terminate string with Chr(0) here
          sA(nStrings) = PeekS(lastp)
          lastp = *s + SizeOf(Character)  ; remember last pointer
          nStrings + 1
          *s + (DelmLen) * SizeOf(Character)
        EndIf
      Wend
    Else              ; use slower multi-char split routine
      While *s\c      ; > 0 means valid Character, = 0 means String terminated.
        If CompareMemoryString(*s, @Delm$, UseCase, DelmLen) ; <> 0 means different memory
          *s + SizeOf(Character)
        Else                                                 ; = 0  means identical memory
          *s\c = 0    ; Terminate string with Chr(0) here
          sA(nStrings) = PeekS(lastp)
          lastp = *s + (DelmLen) * SizeOf(Character)  ; remember last pointer
          nStrings + 1
          *s + (DelmLen) * SizeOf(Character)
        EndIf
      Wend
    EndIf
    If *s <> lastp    ; reached last valid element
      sA(nStrings) = PeekS(lastp)
    EndIf
    ReDim sA(nStrings)
    If trimsp
      For i = 0 To nStrings
        sa(i) = Trim(sa(i))
      Next i
      If trimsp = 9
        For i = 0 To nStrings
          sa(i) = Trim(sa(i), #TAB$)
        Next i
      EndIf
    EndIf
    If delm$ = #CRLF$
      For i = 0 To nStrings
        sa(i) = RTrim(sa(i),#CR$)
      Next i
    EndIf
    nStrings + 1      ; Catch #Null$ due to dangling Delm$, "1,2,"
  EndIf
  ProcedureReturn nStrings
EndProcedure
;-{ GUI FILE STUFF
#OSVEX_LENGTH           = 88  ; If > Win2K = 88 Else = 76
#CDN_INITDONE           = #CDN_FIRST - 0
#CDN_SELCHANGE          = #CDN_FIRST - 1
#CDN_FOLDERCHANGE       = #CDN_FIRST - 2
#OFN_VIEW_REPORT        = $702C
#OFN_VIEW_LIST          = $702B
#OFN_VIEW_LARGEICON     = $7029
#OFN_VIEW_SMALLICON     = $702A
#OFN_VIEW_THUMBNAIL     = $702D
#OFN_VIEW_THUMBNAIL_2K  = $7031
#OFN_VIEW_TILE          = $702E
#OFN_ENABLESIZING       = $800000
#OFS_FILE_OPEN_FLAGS    = #OFN_EXPLORER | #OFN_LONGNAMES | #OFN_CREATEPROMPT
#OFS_FILE_SAVE_FLAGS    = #OFN_EXPLORER | #OFN_LONGNAMES | #OFN_OVERWRITEPROMPT | #OFN_HIDEREADONLY
Structure OFNdata
  Title$
  DefFilePath$
  Pattern$
  PatternPos.i
  MultiSelect.i
  Array Files$(0)
  nFiles.i
EndStructure
Structure OFNgui Extends OFNdata  ; Used by OFN Dialog gui
  guiX.i
  guiY.i
  guiWd.i
  guiHt.i
EndStructure
Global OFNreq.OFNgui, OFNres.OFNdata

; Custom message for move/resize OpenFileRequester
Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")
Procedure gui_OFN_HookProc(hW, msg, wP, lP)
  Protected.i hParent, hLV, ri
  Select msg
  Case #WM_INITDIALOG
    ;                                 wd,           ht
    PostMessage_(hW, gui_OFN_MoveDlg, OFNreq\guiWd, OFNreq\guiHt)
  Case gui_OFN_MoveDlg
    ; Reposition @ resize dialog window
    hParent = GetParent_(hW)
    MoveWindow_(hParent, OFNreq\guiX, OFNreq\guiY, wP, lP, 1)
  Case #WM_NOTIFY
    ; hW is the handle to the dialog
    ; hParent is the handle to the common control
    ; hLV is the handle to the listview itself
    hParent = GetParent_(hW)
    hLV = FindWindowEx_(hParent, 0, "SHELLDLL_DefView", #NULL$)
    If hLV
      ri = SendMessage_(hLV, #WM_COMMAND, #OFN_VIEW_REPORT, #Null)
    EndIf
  EndSelect
  ProcedureReturn 0
EndProcedure

Procedure.i gui_PathRequester(*pReq.OFNgui, *pRes.OFNdata)
  ; REV:  120322, skywalk
  ; Process user response to OpenPathRequester Directory Selection(s)
  ; Results go in structure OFNres
  ; If MultiSelect=1,  then OFNres\File$(nFiles-1) contains the list of directories
  ;               =0,  then OFNres\File$(0)        contains 1 selected directory
  ; SYNTAX: nPaths = gui_PathRequester(hW, @myOFNreq, @myOFNres)
  ;p$ = PathRequester("Select path(s) to Pack...", "C:\") ; ONLY SUPPORTS 1 PATH SELECTION
  Protected.i i, k, wID, xlID, buID, wW, wH
  *pRes\nFiles = 0
  wID = OpenWindow(#PB_Any, *pReq\guiX, *pReq\guiY, *pReq\guiWd, *pReq\guiHt, *pReq\Title$, #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
  If wID
    StickyWindow(wID, 1)
    xlID = ExplorerListGadget(#PB_Any, 10, 10, *pReq\guiWd-20, *pReq\guiHt-50, *pReq\DefFilePath$, #PB_Explorer_NoFiles|#PB_Explorer_MultiSelect|#PB_Explorer_GridLines|#PB_Explorer_FullRowSelect)
    buID = ButtonGadget(#PB_Any, *pReq\guiWd/2-40, *pReq\guiHt-GadgetHeight(xlID)-10, 80, 30, "Done")
    Repeat
      Select WaitWindowEvent()
      Case #PB_Event_Gadget
        If EventGadget() = buID
          *pRes\nFiles = CountGadgetItems(xlID)
          ReDim *pRes\Files$(*pRes\nFiles-1)
          For i = 0 To *pRes\nFiles - 1
            If GetGadgetItemState(xlID, i) & #PB_Explorer_Selected
              *pRes\Files$(k) = GetGadgetText(xlID) + GetGadgetItemText(xlID, i)
              k + 1
            EndIf
          Next
          *pRes\nFiles = k
          If k
            ReDim *pRes\Files$(k-1)
            *pRes\DefFilePath$ = GetPathPart(*pRes\Files$(0))
          Else
            ReDim *pRes\Files$(0)
            *pRes\DefFilePath$ = *pReq\DefFilePath$
          EndIf
          Break
        EndIf
      Case #PB_Event_SizeWindow
        wW = WindowWidth(wID)
        wH = WindowHeight(wID)
        ResizeGadget(xlID, #PB_Ignore, #PB_Ignore, wW-20, wH-50)
        ResizeGadget(buID, wW/2-40, GadgetY(xlID)+GadgetHeight(xlID)+5, #PB_Ignore, #PB_Ignore)
      Case #PB_Event_CloseWindow
        Break
      EndSelect
    ForEver
  EndIf
  StickyWindow(wID, 0)
  CloseWindow(wID)
  ProcedureReturn *pRes\nFiles
EndProcedure

Procedure.i gui_FileRequester(hW.i, *pReq.OFNgui, *pRes.OFNdata)
  ; REV:  120106, skywalk
  ; Process user response to OpenFileRequester File Selection(s)
  ; Results go in structure OFNres
  ; If MultiSelect=1,  then OFNres\File$(nFiles-1) contains the list of files
  ;               =0,  then OFNres\File$(0)        contains the 1 selected file
  ; SYNTAX: nFiles = gui_FileRequester(hW, @myOFNreq, @myOFNres)
  Protected.i i, j, *selectedFile, bufferSize
  Protected.s folder$, nextFile$
  ; For Filter to function properly, replace "|" with null Chr(0) directly in memory
  ; Filter must end with 2 null chars
  If Right(*pReq\Pattern$,2) <> "||"
    *pReq\Pattern$ + "||"
  EndIf
  SF_CharReplace(@*pReq\Pattern$)
  If *pReq\MultiSelect
    bufferSize = 32000
  Else
    bufferSize = 512
  EndIf
  ; Buffer to hold selected file name(s)
  *selectedFile = AllocateMemory(bufferSize)
  If Len(GetFilePart(*pReq\DefFilePath$))
    PokeS(*selectedFile,*pReq\DefFilePath$)
  Else
    PokeB(*selectedFile, 0)   ; 1st byte must be null if no initial file name is to be displayed
  EndIf
  ;ShowMemoryViewer(*selectedFile,750)
  Protected myOFN.OPENFILENAME
  myOFN\hwndOwner         = hW
  myOFN\lStructSize       = SizeOf(OPENFILENAME) + 12 ; #OSVEX_LENGTH = 88
  myOFN\hInstance         = #Null
  myOFN\lpstrFilter       = @*pReq\Pattern$
  myOFN\lpstrCustomFilter = #Null
  myOFN\nMaxCustFilter    = #Null
  myOFN\nFilterIndex      = *pReq\patternPos
  myOFN\lpstrFile         = *selectedFile
  myOFN\nMaxFile          = bufferSize
  myOFN\lpstrFileTitle    = #Null
  myOFN\nMaxFileTitle     = #Null
  myOFN\lpstrInitialDir   = @*pReq\DefFilePath$
  myOFN\lpstrTitle        = @*pReq\Title$
  myOFN\flags             = #OFS_FILE_OPEN_FLAGS | #OFN_ENABLEHOOK | #OFN_ENABLESIZING  ;| #OFN_NOCHANGEDIR
  myOFN\lpfnHook          = @gui_OFN_HookProc()
  If *pReq\multiSelect
    myOFN\flags | #OFN_ALLOWMULTISELECT
  EndIf
  GetOpenFileName_(@myOFN)
  ; Deal with multi selections which are null terminated within *selectedFile
  ; With multi selections, the buffer null terminates folder and files
  ; If 1st string ends with the folder, we know we have multiple selections
  ;ShowMemoryViewer(*selectedFile,750)
  folder$ = PeekS(*selectedFile)
  If *pReq\MultiSelect And FileSize(GetFilePart(folder$)) = -1
    *pRes\nFiles = SF_CharReplace(*selectedFile,#NULL$,",")
    nextFile$ = PeekS(*selectedFile)
    nextFile$ = Mid(nextFile$,FindString(nextFile$,",")+1)
    *pRes\nFiles = Split(nextFile$,",",*pRes\Files$())
    *pRes\DefFilePath$ = folder$
    If Right(*pRes\DefFilePath$,1) <> "\"
      *pRes\DefFilePath$ + "\"
    EndIf
    If *pRes\nFiles = 0
      ReDim *pRes\Files$(0)
      *pRes\Files$(0) = #sNull$
    EndIf
  Else    ; 1 file selected
    If FL_FileExists(folder$) > 0
      *pRes\nFiles = 1
      *pRes\Files$(0) = GetFilePart(Folder$)
      *pRes\DefFilePath$ = GetPathPart(Folder$)
    Else
      *pRes\nFiles = 0
      *pRes\Files$(0) = #sNull$
    EndIf
  EndIf
  FreeMemory(*selectedFile)
  ProcedureReturn *pRes\nFiles
EndProcedure
;-}
Enumeration
  #gadResults
  #gadBrowseFiles
  #gadBrowsePaths
  #gadClear
EndEnumeration
Define.i i,evG
Define.s s$
If #PB_Compiler_Unicode
  s$ = "Get Files w/Details View in Unicode"
Else
  s$ = "Get Files w/Details View in Ascii"
EndIf
If OpenWindow(0,0,0,440,340,s$,#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  EditorGadget(#gadResults,20,40,400,300)
  ButtonGadget(#gadBrowseFiles,20,0,100,20,"Browse For File(s)...")
  ButtonGadget(#gadBrowsePaths,130,0,100,20,"Browse For Path(s)...")
  ButtonGadget(#gadClear,390,0,30,20,"Clear")
  Repeat
    Select WaitWindowEvent(5)
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      evG = EventGadget()
      Select evG
      Case #gadClear
        ClearGadgetItems(#gadResults)
      Case #gadBrowseFiles
        OFNreq\guiX         = 20
        OFNreq\guiY         = 20
        OFNreq\guiWd        = 300
        OFNreq\guiHt        = 300
        OFNreq\Title$       = "Select File(s)"
        OFNreq\DefFilePath$ = "d:\"
        OFNreq\MultiSelect  = 1
        OFNreq\PatternPos   = 1
        OFNreq\Pattern$     = "All Files (*.*)|*.*|CSV Files (*.csv)|*.csv|Text Files (*.txt)|*.txt||"
        If gui_FileRequester(WindowID(0), @OFNreq, @OFNres)
          AddGadgetItem(#gadResults,-1, Str(OFNres\nFiles) + " File(s) From '" + OFNres\DefFilePath$ + "' =")
          For i = 0  To OFNres\nFiles - 1
            AddGadgetItem(#gadResults,#PB_Any,OFNres\Files$(i))
          Next i
        EndIf
      Case #gadBrowsePaths
        OFNreq\guiX         = 20
        OFNreq\guiY         = 20
        OFNreq\guiWd        = 300
        OFNreq\guiHt        = 300
        OFNreq\Title$       = "Select Path(s)..."
        OFNreq\DefFilePath$ = "c:\"
        OFNreq\MultiSelect  = 1
        OFNreq\PatternPos   = 1
        OFNreq\Pattern$     = "All Files (*.*)|*.*|CSV Files (*.csv)|*.csv|Text Files (*.txt)|*.txt||"
        If gui_PathRequester(@OFNreq,@OFNres)
          AddGadgetItem(#gadResults,-1, Str(OFNres\nFiles) + " Path(s) From '" + OFNres\DefFilePath$ + "' =")
          For i = 0  To OFNres\nFiles - 1
            AddGadgetItem(#gadResults,#PB_Any,OFNres\Files$(i))
          Next i
        EndIf
      EndSelect
    EndSelect
  ForEver
EndIf


Now I liked to add this new file requester to my personal library, so I create the following lib:
Code:
Global resultsdll.s

; skywalk
; Since the built-in PureBasic OFN Requester does not allow Details View!
; Fill the OFN structure and use a OFNHook Procedure.
; Portions modified from Sparkie's code:
; http://www.purebasic.fr/english/viewtopic.php?p=133878#p133878
EnableExplicit
#sNull$ = "-999"
Structure ScanPBDataTypes
  ; These take up no memory and are allowed to grow without redim
  ; when the structure is pointed at a memory buffer.
  ; ex. *buf\d[i] ; 'i' being incremented in a loop
  ; Essentially, this is 1 big StructureUnion.
  b.b[0]  ; byte
  w.w[0]  ; word
  l.l[0]  ; long
  i.i[0]  ; integer
  q.q[0]  ; quad
  f.f[0]  ; float
  d.d[0]  ; double
  a.a[0]  ; ascii
  c.c[0]  ; character
  u.u[0]  ; unicode
  ;s.s{Use 1-MAX String Length expected 255}  ; string
  s.s[0]  ; This supports 1 String scan. *p\s = @x$, *p\s[1] does not work.
EndStructure

Macro FL_FileExists(Fname)
  ;  0 = File or Folder does not exist
  ;  1 = File Exists
  ; -1 = Folder Exists
  ; Since FileSize() returns:
  ;       -1 = File Not found.
  ;       -2 = File is a directory.
  ;        0 = Empty File, > 1 = File Exists
  ;        FileSize() respects '*' wildcards and reports results accordingly.
  FileSize(Fname) + 1
EndMacro

Procedure.i SF_CharReplace(*p.ScanPBDataTypes, StrFrom$="|", StrTo$=#NULL$)
  ; REV:  111227, skywalk
  ; SYNTAX:   nNulls = SF_CharReplace(@x$,"|",#Null$,0)
  ; DEFAULT:  Edit a string in memory to embed null char's = Chr(0)
  ; RETURN:   # of char replacements made.
  ; If StrFrom$=#Null$, then buffer end is assumed to be double null position.
  ; Accepts multiple chars, but only works with the 1st char.
  ; Works with unicode or ascii.
  Protected.i i, msLen, nChars
  Protected.i CharFrom = Asc(StrFrom$)
  Protected.i CharTo = Asc(StrTo$)
  ; Determine msLen
  If CharFrom = #Null   ; Search memory for double nulls = end of string buffer
    While msLen < 64000
      If *p\c[msLen] = 0 And *p\c[msLen+1] = 0
        Break
      EndIf
      msLen + 1
    Wend
    msLen - 1  ; Ignore the final #Null later in code
  Else
    msLen = MemoryStringLength(*p) - 1  ; Get Len in characters, not bytes.
   ; StringByteLength(PeekS(*p))        ; Returns nBytes and depends on ascii/unicode switch!
  EndIf
  For i = 0 To msLen   ; Since walking through String by Character, no need to count bytes/char.
    If *p\c[i] = CharFrom
      *p\c[i] = CharTo
      nChars + 1
    EndIf
  Next i
  ;ShowMemoryViewer(@*p,msLen+32)
  ProcedureReturn nChars
EndProcedure

Procedure.i Split(s$, Delm$, Array sA.s(1), trimsp.i=0, UseCase.i=#PB_String_CaseSensitive)
  ; REV:  100405, skywalk
  ;       modified from Trond PB forum code
  ;       www.purebasic.fr/english/viewtopic.php?f=13&t=26738
  ; REV:  111227, skywalk
  ;       removed ReSize parameter. sA() adjusts to size required = nStrings-1
  ;       added multi-char delimiter, case sensitivity, and unicode.
  ;       UseCase = 0-#PB_String_CaseSensitive or 1-#PB_String_NoCase
  ; Return: Count of elements or nStrings found.
  ;         If none, then entire string is assigned to sA(0)
  ; s$ = normal null terminated string
  ; VB6 syntax -> sA() = Split(expression[, delimiter[, count[, compare]]])
  ; SizeOf(Character) is converted to a constant by compiler so no speed hit for multiple use
  Protected.i i, nStrings
  Protected.i sLen = Len(s$)
  Protected.i DelmLen = Len(Delm$)
  Protected *s.Character = @s$  ; Character Structure points to s$ contents, not its address
  Protected.i lastp = *s
  Protected Delmc.c
  If DelmLen = 0  ; "" or empty
    ReDim sA(0)
    sA(0) = s$
    nStrings = 1
  ElseIf sLen = 0 ; s$ = ""
    ReDim sA(0)
    sA(0) = #NULL$
    nStrings = 0
  Else            ; OK to Split
    Dim sA(sLen/DelmLen+1)    ; Start array at worst case estimate
    If UseCase = #PB_String_CaseSensitive And (DelmLen = 1 Or Delm$ = #CRLF$) ; use faster single character split routine
      If DelmLen = 1
        Delmc = Asc(Delm$)
      Else            ; Delm$ = #CRLF$
        Delmc = #LF   ; use the 2nd char, then trim trailing #CR$ from elements
      EndIf
      While *s\c      ; > 0 means valid Character, = 0 means String terminated.
        If *s\c <> Delmc
          *s + SizeOf(Character)
        Else
          *s\c = 0    ; Terminate string with Chr(0) here
          sA(nStrings) = PeekS(lastp)
          lastp = *s + SizeOf(Character)  ; remember last pointer
          nStrings + 1
          *s + (DelmLen) * SizeOf(Character)
        EndIf
      Wend
    Else              ; use slower multi-char split routine
      While *s\c      ; > 0 means valid Character, = 0 means String terminated.
        If CompareMemoryString(*s, @Delm$, UseCase, DelmLen) ; <> 0 means different memory
          *s + SizeOf(Character)
        Else                                                 ; = 0  means identical memory
          *s\c = 0    ; Terminate string with Chr(0) here
          sA(nStrings) = PeekS(lastp)
          lastp = *s + (DelmLen) * SizeOf(Character)  ; remember last pointer
          nStrings + 1
          *s + (DelmLen) * SizeOf(Character)
        EndIf
      Wend
    EndIf
    If *s <> lastp    ; reached last valid element
      sA(nStrings) = PeekS(lastp)
    EndIf
    ReDim sA(nStrings)
    If trimsp
      For i = 0 To nStrings
        sa(i) = Trim(sa(i))
      Next i
      If trimsp = 9
        For i = 0 To nStrings
          sa(i) = Trim(sa(i), #TAB$)
        Next i
      EndIf
    EndIf
    If delm$ = #CRLF$
      For i = 0 To nStrings
        sa(i) = RTrim(sa(i),#CR$)
      Next i
    EndIf
    nStrings + 1      ; Catch #Null$ due to dangling Delm$, "1,2,"
  EndIf
  ProcedureReturn nStrings
EndProcedure
;-{ GUI FILE STUFF
#OSVEX_LENGTH           = 88  ; If > Win2K = 88 Else = 76
#CDN_INITDONE           = #CDN_FIRST - 0
#CDN_SELCHANGE          = #CDN_FIRST - 1
#CDN_FOLDERCHANGE       = #CDN_FIRST - 2
#OFN_VIEW_REPORT        = $702C
#OFN_VIEW_LIST          = $702B
#OFN_VIEW_LARGEICON     = $7029
#OFN_VIEW_SMALLICON     = $702A
#OFN_VIEW_THUMBNAIL     = $702D
#OFN_VIEW_THUMBNAIL_2K  = $7031
#OFN_VIEW_TILE          = $702E
#OFN_ENABLESIZING       = $800000
#OFS_FILE_OPEN_FLAGS    = #OFN_EXPLORER | #OFN_LONGNAMES | #OFN_CREATEPROMPT
#OFS_FILE_SAVE_FLAGS    = #OFN_EXPLORER | #OFN_LONGNAMES | #OFN_OVERWRITEPROMPT | #OFN_HIDEREADONLY
Structure OFNdata
  Title$
  DefFilePath$
  Pattern$
  PatternPos.i
  MultiSelect.i
  Array Files$(0)
  nFiles.i
EndStructure
Structure OFNgui Extends OFNdata  ; Used by OFN Dialog gui
  guiX.i
  guiY.i
  guiWd.i
  guiHt.i
EndStructure
Global OFNreq.OFNgui, OFNres.OFNdata

; Custom message for move/resize OpenFileRequester
Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")
Procedure gui_OFN_HookProc(hW, msg, wP, lP)
  Protected.i hParent, hLV, ri
  Select msg
  Case #WM_INITDIALOG
    ;                                 wd,           ht
    PostMessage_(hW, gui_OFN_MoveDlg, OFNreq\guiWd, OFNreq\guiHt)
  Case gui_OFN_MoveDlg
    ; Reposition @ resize dialog window
    hParent = GetParent_(hW)
    MoveWindow_(hParent, OFNreq\guiX, OFNreq\guiY, wP, lP, 1)
  Case #WM_NOTIFY
    ; hW is the handle to the dialog
    ; hParent is the handle to the common control
    ; hLV is the handle to the listview itself
    hParent = GetParent_(hW)
    hLV = FindWindowEx_(hParent, 0, "SHELLDLL_DefView", #NULL$)
    If hLV
      ri = SendMessage_(hLV, #WM_COMMAND, #OFN_VIEW_REPORT, #Null)
    EndIf
  EndSelect
  ProcedureReturn 0
EndProcedure

Procedure.i gui_FileRequester(hW.i, *pReq.OFNgui, *pRes.OFNdata)
  ; REV:  120106, skywalk
  ; Process user response to OpenFileRequester File Selection(s)
  ; Results go in structure OFNres
  ; If MultiSelect=1,  then OFNres\File$(nFiles-1) contains the list of files
  ;               =0,  then OFNres\File$(0)        contains the 1 selected file
  ; SYNTAX: nFiles = gui_FileRequester(hW, @myOFNreq, @myOFNres)
  Protected.i i, j, *selectedFile, bufferSize
  Protected.s folder$, nextFile$
  ; For Filter to function properly, replace "|" with null Chr(0) directly in memory
  ; Filter must end with 2 null chars
  If Right(*pReq\Pattern$,2) <> "||"
    *pReq\Pattern$ + "||"
  EndIf
  SF_CharReplace(@*pReq\Pattern$)
  If *pReq\MultiSelect
    bufferSize = 32000
  Else
    bufferSize = 512
  EndIf
  ; Buffer to hold selected file name(s)
  *selectedFile = AllocateMemory(bufferSize)
  If Len(GetFilePart(*pReq\DefFilePath$))
    PokeS(*selectedFile,*pReq\DefFilePath$)
  Else
    PokeB(*selectedFile, 0)   ; 1st byte must be null if no initial file name is to be displayed
  EndIf
  ;ShowMemoryViewer(*selectedFile,750)
  Protected myOFN.OPENFILENAME
  myOFN\hwndOwner         = hW
  myOFN\lStructSize       = SizeOf(OPENFILENAME) + 12 ; #OSVEX_LENGTH = 88
  myOFN\hInstance         = #Null
  myOFN\lpstrFilter       = @*pReq\Pattern$
  myOFN\lpstrCustomFilter = #Null
  myOFN\nMaxCustFilter    = #Null
  myOFN\nFilterIndex      = *pReq\patternPos
  myOFN\lpstrFile         = *selectedFile
  myOFN\nMaxFile          = bufferSize
  myOFN\lpstrFileTitle    = #Null
  myOFN\nMaxFileTitle     = #Null
  myOFN\lpstrInitialDir   = @*pReq\DefFilePath$
  myOFN\lpstrTitle        = @*pReq\Title$
  myOFN\flags             = #OFS_FILE_OPEN_FLAGS | #OFN_ENABLEHOOK | #OFN_ENABLESIZING  ;| #OFN_NOCHANGEDIR
  myOFN\lpfnHook          = @gui_OFN_HookProc()
  If *pReq\multiSelect
    myOFN\flags | #OFN_ALLOWMULTISELECT
  EndIf
  GetOpenFileName_(@myOFN)
  ; Deal with multi selections which are null terminated within *selectedFile
  ; With multi selections, the buffer null terminates folder and files
  ; If 1st string ends with the folder, we know we have multiple selections
  ;ShowMemoryViewer(*selectedFile,750)
  folder$ = PeekS(*selectedFile)
  If *pReq\MultiSelect And FileSize(GetFilePart(folder$)) = -1
    *pRes\nFiles = SF_CharReplace(*selectedFile,#NULL$,",")
    nextFile$ = PeekS(*selectedFile)
    nextFile$ = Mid(nextFile$,FindString(nextFile$,",")+1)
    *pRes\nFiles = Split(nextFile$,",",*pRes\Files$())
    *pRes\DefFilePath$ = folder$
    If Right(*pRes\DefFilePath$,1) <> "\"
      *pRes\DefFilePath$ + "\"
    EndIf
    If *pRes\nFiles = 0
      ReDim *pRes\Files$(0)
      *pRes\Files$(0) = #sNull$
    EndIf
  Else    ; 1 file selected
    If FL_FileExists(folder$) > 0
      *pRes\nFiles = 1
      *pRes\Files$(0) = GetFilePart(Folder$)
      *pRes\DefFilePath$ = GetPathPart(Folder$)
    Else
      *pRes\nFiles = 0
      *pRes\Files$(0) = #sNull$
    EndIf
  EndIf
  FreeMemory(*selectedFile)
  ProcedureReturn *pRes\nFiles
EndProcedure

 ProcedureDLL.s OpenFileRequester4(title.s,Path1.s, Filtre.s)
 Protected  i.a
  resultsdll=""
  OFNreq\guiX         = 20
  OFNreq\guiY         = 20
  OFNreq\guiWd        = 300
  OFNreq\guiHt        = 300
  OFNreq\Title$       = title
  OFNreq\DefFilePath$ = Path1
  OFNreq\MultiSelect  = 1
  OFNreq\PatternPos   = 1
  OFNreq\Pattern$     = Filtre
  If gui_FileRequester(WindowID(0), @OFNreq, @OFNres)
    For i = 0  To OFNres\nFiles - 1
      resultsdll+OFNres\Files$(i)
      Debug OFNres\Files$(i)
   Next i
  EndIf
  ProcedureReturn resultsdll
EndProcedure


then I compile it to lib using TailBite, result OK, then restart compiler

then I tried to test it with the following small program:
Code:
OpenWindow(0,0,0,440,340,"hello",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
 
Path1.s = "C:\" 
Filtre1.s = "Text (*.txt)|*.txt;*.bat|PureBasic (*.pb)|*.pb|All Files (*.*)|*.*"
tmp.s= OpenFileRequester4("title",Path1, Filtre1)

Debug tmp


when I run it, the requester starts, I can select files, then
I had error at the line: tmp.s= OpenFileRequester4("title",Path1, Filtre1)
Invalid memory access.

what's wrong??
any help is appreciated

thank you

_________________
PureBasic: Surprisingly simple, diabolically powerful


Top
 Profile  
Reply with quote  
 Post subject: Re: error: Invalid memory access
PostPosted: Mon Jun 25, 2012 9:16 pm 
Offline
Addict
Addict

Joined: Sat Apr 10, 2004 1:20 pm
Posts: 1143
Location: Germany
Most likely you have code outside of procedures.

And i did not see any Init() procedures.

Try moving this line :
Code:
Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")

into this:
Code:
ProcedureDll GUI_OFN_Init()
  Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: error: Invalid memory access
PostPosted: Tue Jun 26, 2012 7:00 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Aug 03, 2011 4:52 am
Posts: 215
Location: Beirut, Lebanon
thanks fro reply!

I created :
Code:
ProcedureDll GUI_OFN_Init()
  Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")
EndProcedure


then I call it from OpenFileRequester4(title.s,Path1.s, Filtre1.s) like the following:
Code:
ProcedureDLL.s OpenFileRequester4(title.s,Path1.s, Filtre1.s)
   Protected  i.a
   GUI_OFN_Init()

  resultsdll=""
  OFNreq\guiX         = 20
  OFNreq\guiY         = 20
  OFNreq\guiWd        = 300
  OFNreq\guiHt        = 300
  OFNreq\Title$       = title
  OFNreq\DefFilePath$ = Path1
  OFNreq\MultiSelect  = 1
  OFNreq\PatternPos   = 1
  OFNreq\Pattern$     = Filtre1
  If gui_FileRequester(WindowID(0), @OFNreq, @OFNres)
    For i = 0  To OFNres\nFiles - 1
      resultsdll+OFNres\Files$(i)
      Debug OFNres\Files$(i)
    Next i
  EndIf
  ProcedureReturn resultsdll
EndProcedure


then tools --> TailBite --> OK --> Restart compiler
then i've gone to my previous program:
Code:
OpenWindow(0,0,0,440,340,"hello",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
 
Path1.s = "C:\" 
Filtre1.s = "Text (*.txt)|*.txt;*.bat|PureBasic (*.pb)|*.pb|All Files (*.*)|*.*"

tmp.s= OpenFileRequester4("title",Path1, Filtre1)

Debug tmp


Nothing changed, always "Invalid memory access, (read error at address 0)" :(

_________________
PureBasic: Surprisingly simple, diabolically powerful


Top
 Profile  
Reply with quote  
 Post subject: Re: error: Invalid memory access
PostPosted: Tue Jun 26, 2012 10:05 pm 
Offline
Addict
Addict

Joined: Sat Apr 10, 2004 1:20 pm
Posts: 1143
Location: Germany
The problem is only when the array in the structure isn´t dimensioned, here´s a fixed version :

PS : in your library-code there is a hardcoded WindowID(0) :mrgreen:

Code:
ProcedureDLL GUI_OFN_Init()
  ; Custom message for move/resize OpenFileRequester
  Global gui_OFN_MoveDlg = RegisterWindowMessage_(@"gui_OFN_MoveDlg")
  Global OFNreq.OFNgui, OFNres.OFNdata
  Dim OFNreq\Files$(1)
  Dim OFNres\Files$(1)
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: error: Invalid memory access
PostPosted: Wed Jun 27, 2012 9:14 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Aug 03, 2011 4:52 am
Posts: 215
Location: Beirut, Lebanon
Thanks a lot!! now it's working :D

about WindowID(0), I changed it to a parameter
Code:
ProcedureDLL.s OpenFileRequester4(wid.l,title.s,Path1.s, Filtre1.s)
   Protected  i.a
   GUI_OFN_Init()

  resultsdll=""
  OFNreq\guiX         = 20
  OFNreq\guiY         = 20
  OFNreq\guiWd        = 300
  OFNreq\guiHt        = 300
  OFNreq\Title$       = title
  OFNreq\DefFilePath$ = Path1
  OFNreq\MultiSelect  = 1
  OFNreq\PatternPos   = 1
  OFNreq\Pattern$     = Filtre1
  If gui_FileRequester(wid, @OFNreq, @OFNres)
    For i = 0  To OFNres\nFiles - 1
      resultsdll+OFNres\Files$(i)
      Debug OFNres\Files$(i)
    Next i
  EndIf
  ProcedureReturn resultsdll
EndProcedure


Have a nice day

_________________
PureBasic: Surprisingly simple, diabolically powerful


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye