[RESOLVED] Return Selected Filter with GetSaveFileName API
Ok, I have a File Save dialog for a while, through the GetSaveFileName API.
However, now I need to determine which Filter the user has selected.
i.e .jpeg, .bmp, .gif etc...
Code:
Private Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameW" (pOpenfilename As OPENFILENAME) As Long
Private Type OPENFILENAME
lStructSize As Long 'Length of structure, in bytes
hWndOwner As Long 'Window that owns the dialog, or NULL
hInstance As Long 'Handle of mem object containing template (not used)
lpstrFilter As Long 'File types/descriptions, delimited with vbnullchar, ends with 2xvbnullchar
lpstrCustomFilter As Long 'Filters typed in by user
nMaxCustFilter As Long 'Length of CustomFilter, min 40x chars
nFilterIndex As Long 'Filter Index to use (1,2,etc) or 0 for custom
lpstrFile As Long 'Initial file/returned file(s), delimited with vbnullchar for multi files
nMaxFile As Long 'Size of Initial File long , min 256
lpstrFileTitle As Long 'File.ext excluding path
nMaxFileTitle As Long 'Length of FileTitle
lpstrInitialDir As Long 'Initial file dir, null for current dir
lpstrTitle As Long 'Title bar of dialog
flags As Long 'See OFN_Flags
nFileOffset As Integer 'Offset to file name in full path, 0-based
nFileExtension As Integer 'Offset to file ext in full path, 0-based (excl '.')
lpstrDefExt As Long 'Default ext appended, excl '.', max 3 chars
lCustData As Long 'Appl defined data for lpfnHook
lpfnHook As Long 'Pointer to hook procedure
lpTemplateName As Long 'Template Name (not used)
pvReserved As Long 'new Win2000 / WinXP members
dwReserved As Long 'new Win2000 / WinXP members
FlagsEx As Long 'new Win2000 / WinXP members
End Type
Public Function cFileSave(ByVal InitialDir As String, _
ByVal DialogTitle As String, ByVal Filter As String, _
ByVal FrmhWnd As Long, Optional FileTitle As String = vbNullString, _
Optional ByRef rtnFilter As Long) As String
Dim OpenFile As OPENFILENAME
Dim lReturn As Long
Dim FileFilter As String
Dim strFile As String
strFile = String$(512, 0)
If Not FileTitle = vbNullString Then
strFile = FileTitle & strFile
End If
OpenFile.lStructSize = Len(OpenFile)
OpenFile.hWndOwner = FrmhWnd
OpenFile.hInstance = App.hInstance
FileFilter = Replace$(Filter, "|", vbNullChar)
If AscW(Right$(FileFilter, 1)) <> 0& Then FileFilter = FileFilter & vbNullChar
OpenFile.lpstrFilter = StrPtr(FileFilter)
OpenFile.nFilterIndex = 1
OpenFile.lpstrFile = StrPtr(strFile)
OpenFile.nMaxFile = Len(strFile) - 1
OpenFile.lpstrFileTitle = StrPtr(OpenFile.lpstrFile)
OpenFile.nMaxFileTitle = StrPtr(OpenFile.nMaxFile)
OpenFile.lpstrInitialDir = StrPtr(InitialDir)
OpenFile.lpstrTitle = StrPtr(DialogTitle)
OpenFile.flags = 0
lReturn = GetSaveFileName(OpenFile)
If lReturn = 0 Then
'Cancel Button Pressed
Else
cFileSave = Left$(strFile, InStr(strFile, vbNullChar) - 1)
rtnFilter = OpenFile.lpstrFile
End If
End Function
Currently it returns a LONG number,
How do i convert this to the relevant String format ?
Re: Return Selected Filter with GetSaveFileName API
Curious. You want the filter index, by you are looking at the .lpstrFile which is a Long string pointer. Wouldn't you want to look .nFilterIndex? Not sure if it gets updated, but easy enough to check.
Edited: I checked, it does get updated. So: rtnFilter = OpenFile.nFilterIndex
Re: Return Selected Filter with GetSaveFileName API
the simple method is to change the type of the filter member of the type to string and remove the strptr when assigning the value
lpstrFilter As String 'File types/descriptions, delimited with vbnullchar, ends with 2xvbnullchar
OpenFile.lpstrFilter = FileFilter
same applies to other members of the type
an alternative
Code:
Private Type OPENFILENAME
lStructSize As Long ' Filled with UDT size
hwndOwner As Long ' Tied to Owner
hInstance As Long ' Ignored (used only by templates)
lpstrFilter As String ' Tied to Filter
lpstrCustomFilter As String ' Ignored
nMaxCustFilter As Long ' Ignored
nFilterIndex As Long ' Tied to FilterIndex
lpstrFile As String ' Tied to FileName
nMaxFile As Long ' Handled internally
lpstrFileTitle As String ' Tied to FileTitle
nMaxFileTitle As Long ' Handled internally
lpstrInitialDir As String ' Tied to InitDir
lpstrTitle As String ' Tied to DlgTitle
Flags As Long ' Tied to Flags
nFileOffset As Integer ' Ignored
nFileExtension As Integer ' Ignored
lpstrDefExt As String ' Tied to DefaultExt
lCustData As Long ' Ignored (needed for hooks)
lpfnHook As Long ' Ignored (good luck with hooks)
lpTemplateName As Long ' Ignored (good luck with templates)
End Type
Re: Return Selected Filter with GetSaveFileName API
westconn1, one of the advantages of using StrPtr is that some1uk03 is supporting unicode filenames via the W API version. But using strings works as well, the only difference is that they need to be converted to unicode, i.e., StrConv(), or other workarounds, else VB will convert the strings to ANSI when it passes the UDT.
Edited: However, his code will fail on non-unicode systems (possibly WinME and below). But that may not be an issue?
Edited yet again. Personal preferences of mine are to use strings as you are describing and changing the declaration depending on whether A or W version API is called:
Code:
Private Declare Function GetSaveFileNameUnicode Lib "comdlg32.dll" Alias "GetSaveFileNameW" (ByVal pOpenfilename As Long) As Long
' ^^ sample call: lReturn = GetSaveFileNameUnicode(VarPtr(OPENFILE))
Private Declare Function GetSaveFileNameANSI Lib "comdlg32.dll" Alias "GetSaveFileNameA" (ByRef pOpenfilename As OPENFILENAME) As Long
' ^^ sample call: lReturn = GetSaveFileNameANSI(OPENFILE)
Re: Return Selected Filter with GetSaveFileName API
Quote:
Originally Posted by
LaVolpe
Curious. You want the filter index, by you are looking at the .lpstrFile which is a Long string pointer. Wouldn't you want to look .nFilterIndex? Not sure if it gets updated, but easy enough to check.
Edited: I checked, it does get updated. So: rtnFilter = OpenFile.nFilterIndex
You've spotted it well LaVolpe... Nice 1..
I think haven't been careful with the spelling there and typed OpenFile.lpstrFile instead. :rolleyes:
Also with the UniCode version, yes I'm not supporting WinME and below, so that isn't an issue.
Thanks Guys