[VB6] Unicode File Open/Save Dialog-VBForums
Results 1 to 24 of 24

Thread: [VB6] Unicode File Open/Save Dialog

  1. #1

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    [VB6] Unicode File Open/Save Dialog

    Edited: 6 Jan 2012. Added a unicode capable Browse for Folder dialog class

    I have seen recent posts asking how to support selection of unicode filenames with the common dialog. The common dialog control offered by VB does not support unicode, but the APIs do. This class is also ANSI compatible.

    The attached class wraps the Open and Save dialog and includes all of the properties offered by VB's Open/Save common dialog, along with a couple more. The additional methods/properties are:
    - Clear: resets all properties to default values
    - CustomFilterSize: returns/sets size of buffer for user-defined filters
    - CustomHookProc: returns/sets the hook procedure for the dialog
    - CustomHookData: returns/sets coder-defined value associated with the hook
    - FileExtension: returns the extension of a selected file
    - FilePath: returns just the path of a selected file
    - FlagsEx: returns/sets additional flags for Win2K+
    - MaxFileTitleSize: returns/sets buffer size for the FileTitle property
    - MinimumBufferSizeRequired: returns required buffer size if multiselecting files and dialog errors with "buffer to small"

    I have not included other dialogs (i.e., color, printer, font, etc). Here is another class that you can use to combine codes as needed. That class has all the dialogs but does not support unicode as written. If I knew it was there before I wrote this one, I would have simply modified it instead with the author's permission.

    Of course getting a unicode path/file name doesn't do you much good unless you can use it. So I assume anyone that downloads and uses this class can process the file using W-version (unicode) APIs. Trying to use LoadPicture, for example, on a unicode path/file name will generate an error on non-unicode OEM machines, but using the API LoadImageW, passing the StrPtr of the filename, will not.

    Using APIs means you have to do most of the work yourself, here is a unicode-capable API-version example of loading a bitmap, gif, jpg, icon, cursor, wmf, emf to a picturebox. Somewhat simple example follows, not 100% fool-proof
    Code:
    ' Add a picturebox and command button to a form; then:
    Option Explicit
    
    Private Type PictDesc
        Size As Long
        Type As Long
        hHandle As Long
        hPal As Long
    End Type
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long
    Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
    Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
    Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
    Private Declare Function OleLoadPicture Lib "olepro32" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj As Any) As Long
    Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (lpPictDesc As PictDesc, riid As Any, ByVal fPictureOwnsHandle As Long, iPic As IPicture) As Long
    
    Private Declare Function LoadImageW Lib "user32.dll" (ByVal hInst As Long, ByVal lpsz As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
    Private Const IMAGE_BITMAP As Long = 0
    Private Const LR_LOADFROMFILE As Long = &H10
    
    Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function GetFileSize Lib "kernel32.dll" (ByVal hFile As Long, ByRef lpFileSizeHigh As Long) As Long
    Private Declare Function ReadFile Lib "kernel32.dll" (ByVal hFile As Long, ByRef lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByRef lpOverlapped As Any) As Long
    Private Const INVALID_HANDLE_VALUE = -1&
    
    Private Sub Command1_Click()
        Dim hImage As Long, tmpPic As StdPicture
        Dim hHandle As Long, imageData() As Byte, bytesRead As Long
        
        Dim cBrowser As cOpenSaveDialog
        Set cBrowser = New cOpenSaveDialog
        With cBrowser
            .CancelError = True
            .Filter = "Bitmaps|*.bmp|JPEGs|*.jpg;*jpeg|GIFs|*.gif|Meta Files|*.wmf;*.emf|Icons/Cursors|*.ico;*.cur"
            .Flags = OFN_FILEMUSTEXIST
            .DialogTitle = "Select Image"
        End With
        On Error GoTo EH
        cBrowser.ShowOpen Me.hWnd
        On Error GoTo 0
        
        ' Note: You don't need to load bitmaps separately as done in this example.
        ' The LoadImageW call is shown only to let you see that we can pass a unicode filename
        '   to an API.  The API declaration must be tweaked to look for a Long vs String
        If cBrowser.FilterIndex = 1 Then ' loaded a .bmp file?
            hImage = LoadImageW(0&, StrPtr(cBrowser.FileName), IMAGE_BITMAP, 0&, 0&, LR_LOADFROMFILE)
            If hImage Then Set tmpPic = HandleToStdPicture(hImage, vbPicTypeBitmap)
        Else ' loaded a gif, jpg or possibly something else?
            hHandle = GetFileHandle(cBrowser.FileName)
            If hHandle <> INVALID_HANDLE_VALUE Then
                If hHandle Then
                    bytesRead = GetFileSize(hHandle, ByVal 0&)
                    If bytesRead Then
                        ReDim imageData(0 To bytesRead - 1)
                        ReadFile hHandle, imageData(0), bytesRead, bytesRead, ByVal 0&
                        If bytesRead > UBound(imageData) Then
                            Set tmpPic = ArrayToPicture(imageData(), 0, bytesRead)
                        End If
                    End If
                    CloseHandle hHandle
                End If
            End If
        End If
        If tmpPic Is Nothing Then
            MsgBox "Error loading that file", vbOKOnly + vbExclamation
        Else
            Set Picture1.Picture = tmpPic
        End If
    EH:
        If Err Then
            If Err.Number <> CommonDialogErrorsEnum.CDERR_CANCELED Then
                MsgBox Err.Description, vbOKOnly, "Error Encountered"
            End If
            Err.Clear
        End If
    End Sub
    
    Private Function HandleToStdPicture(ByVal hImage As Long, ByVal imgType As Long) As IPicture
    
        ' function creates a stdPicture object from an image handle (bitmap or icon)
        
        Dim lpPictDesc As PictDesc, aGUID(0 To 3) As Long
        With lpPictDesc
            .Size = Len(lpPictDesc)
            .Type = imgType
            .hHandle = hImage
            .hPal = 0
        End With
        ' IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}
        aGUID(0) = &H7BF80980
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        ' create stdPicture
        Call OleCreatePictureIndirect(lpPictDesc, aGUID(0), True, HandleToStdPicture)
        
    End Function
    
    Private Function ArrayToPicture(inArray() As Byte, Offset As Long, Size As Long) As IPicture
        
        ' function creates a stdPicture from the passed array
        ' Note: The array was already validated as not empty when calling class' LoadStream was called
        
        Dim o_hMem  As Long
        Dim o_lpMem  As Long
        Dim aGUID(0 To 3) As Long
        Dim IIStream As IUnknown
        
        aGUID(0) = &H7BF80980    ' GUID for stdPicture
        aGUID(1) = &H101ABF32
        aGUID(2) = &HAA00BB8B
        aGUID(3) = &HAB0C3000
        
        o_hMem = GlobalAlloc(&H2&, Size)
        If Not o_hMem = 0& Then
            o_lpMem = GlobalLock(o_hMem)
            If Not o_lpMem = 0& Then
                CopyMemory ByVal o_lpMem, inArray(Offset), Size
                Call GlobalUnlock(o_hMem)
                If CreateStreamOnHGlobal(o_hMem, 1&, IIStream) = 0& Then
                      Call OleLoadPicture(ByVal ObjPtr(IIStream), 0&, 0&, aGUID(0), ArrayToPicture)
                End If
            End If
        End If
    
    End Function
    
    Private Function GetFileHandle(ByVal FileName As String) As Long
    
        ' Function uses APIs to read/create files with unicode support
    
        Const GENERIC_READ As Long = &H80000000
        Const OPEN_EXISTING = &H3
        Const FILE_SHARE_READ = &H1
        Const FILE_ATTRIBUTE_ARCHIVE As Long = &H20
        Const FILE_ATTRIBUTE_HIDDEN As Long = &H2
        Const FILE_ATTRIBUTE_READONLY As Long = &H1
        Const FILE_ATTRIBUTE_SYSTEM As Long = &H4
        Const FILE_ATTRIBUTE_NORMAL = &H80&
        
        Dim Flags As Long, Access As Long
        Dim Disposition As Long, Share As Long
        
        Access = GENERIC_READ
        Share = FILE_SHARE_READ
        Disposition = OPEN_EXISTING
        Flags = FILE_ATTRIBUTE_ARCHIVE Or FILE_ATTRIBUTE_HIDDEN Or FILE_ATTRIBUTE_NORMAL _
                Or FILE_ATTRIBUTE_READONLY Or FILE_ATTRIBUTE_SYSTEM
        GetFileHandle = CreateFileW(StrPtr(FileName), Access, Share, ByVal 0&, Disposition, Flags, 0&)
    
    End Function
    
    Private Sub Form_Load()
        Picture1.AutoSize = True
    End Sub
    Example of using the folder browser and setting an initial directory.
    Code:
     ' in a module add these lines of code
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
    Private Const WM_USER = &H400
    Private Const BFFM_SETSELECTION = (WM_USER + 102)
    Private Const BFFM_INITIALIZED = 1
    
    Public Function BrowseCallbackProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal lp As Long, ByVal lParam As Long) As Long
        Select Case uMsg
           Case BFFM_INITIALIZED
                ' http://msdn.microsoft.com/en-us/library/aa452875.aspx
                ' the 3rd parameter of SendMessage is either zero or non-zero
                '   zero :: lParam is a PIDL (as used below)
                '   non-zero :: lParam is yourDesiredInitialDirectoryPath string
    
                Call SendMessage(hWnd, BFFM_SETSELECTION, 0&, ByVal lParam)
    
            ' other Case BFFM_xxxx messages as desired
    
       End Select
       BrowseCallbackProc = 0&
    End Function
    Public Function GetAddressofFunction(addr As Long) As Long
        GetAddressofFunction = addr
    End Function
    
    ' how to call the class & set the initial directory from within your form
    Private Sub Command1_Click()
        Dim cBrowser As cBrowseFolders, tPIDL As Long
        Set cBrowser = New cBrowseFolders
    
        On Error GoTo ExitRoutine
        tPIDL = cBrowser.CreatePIDLfromFolder("C:\Program Files\Realtek\Audio")
        cBrowser.CustomHookProc = GetAddressofFunction(AddressOf BrowseCallbackProc)
        cBrowser.CustomHookData = tPIDL
        cBrowser.ShowBrowseForFolder Me.hWnd, True 
             ' ^^ if you need the return PIDL; don't set final parameter to True, but do destroy it at some point
    
         ' if user selected non-virtual folder then cBrowser.SelectedItem contains path
    
    ExitRoutine:
        cBrowser.DestroyPIDL tPIDL ' destroy PIDL you created
    End Sub
    Since this is a class and errors are raised if the CancelError property is set to true, VB may stop in the class when the error is raised. If VB does stop, it is due to your VB settings. If you have error trapping option to "Break in Class Modules", change it to "Break on Unhandled Errors". That error is required in order to mimic common dialog's CancelError property. The VB stopping applies only to IDE not if project is compiled.
    Attached Files Attached Files
    Last edited by LaVolpe; Apr 9th, 2012 at 08:52 AM. Reason: Added a unicode capable Browse for Folder dialog class
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  2. #2
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,469

    Re: [VB6] Unicode File Open/Save Dialog

    I'm actually just using this for a replacement to the CommonDialog control, but supporting Unicode is definitely a big plus.

    Thanks.

  3. #3

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    You're welcome. I should have mentioned that the class is also ANSI compatible.
    However, the sample unicode routine I posted above is not ANSI compatible.

    I think the class code is well commented and easy to follow. Any minor bug reports, feel free to mention them.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Minor logic error.
    In the FileName Property Let routine, change
    Code:
    from:
        If fTitle = vbNullString Then
            Mid$(ofn.lpstrFile, 1, 1) = vbNullChar
        Else
            Mid$(ofn.lpstrFile, 1, Len(fTitle)) = fTitle
        End If
    to:
        If fTitle = vbNullString Then
            Mid$(ofn.lpstrFile, 1, 1) = vbNullChar
        ElseIf ofn.nMaxFile = Len(fTitle) Then
            ofn.lpstrFile = fTitle
        Else
            Mid$(ofn.lpstrFile, 1, Len(fTitle) + 1) = fTitle & vbNullChar
        End If
    Without change it is possible that running class multiple times, you could get the new file name you are supplying suffixed with the currently existing filename. The null character appended after the supplied value will prevent that.

    Same applies to the FileTitle property, change appropriately.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    Lively Member
    Join Date
    Jan 2010
    Posts
    94

    Re: [VB6] Unicode File Open/Save Dialog

    Note: you will not get a nice looking dialog box if you use OFN_ENABLEHOOK flag under Vista or Win7.

  6. #6

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Quote Originally Posted by riov View Post
    Note: you will not get a nice looking dialog box if you use OFN_ENABLEHOOK flag under Vista or Win7.
    That is very true. Vista+ uses a new interface and will only apply the Vista+ look if the dialog is not subclassed/hooked. The other solution is to stop using the common dialog and use the new interface, which I think would require a TLB to use it in VB.

    Edited: I have an update to post to this and completely forgot. Thanx for bringing this post back to my attention.
    Last edited by LaVolpe; Jan 22nd, 2010 at 11:57 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7
    Hyperactive Member
    Join Date
    Jun 2009
    Posts
    437

    Re: [VB6] Unicode File Open/Save Dialog

    LaVolpe, Each time i ask a question, i discover you already worked On that lol ,
    thanks for the information, i will check what you said once am home and i will let you know if i could make it works.
    In general should i make a kind of mix between your code to get the file name with Unicode and Jonney's code to rename a file UNICODE ?
    Still also need to know please ow can i also Read/Write into a file using unicode ?
    So that if a user entered in the textbox an arabic (or other Unicode langage), i can save it into a file ?

  8. #8

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    The class I provided in this thread returns a string containing the file name. That string may or may not contain unicode characters. However that string can be used with APIs that read/write files. In my signature, you'll see the XP/Vista Manifest Creator. In that project is a short example on reading/writing files using APIs. In the sample code in post #1 above is an example of reading an array using APIs.

    Bottom line, if you are going to use APIs, the routine is basically this:
    1. Use CreateFile API (A or W version) to create a file handle for a new file or existing file
    -- If using W version, pass filename with StrPtr, else just pass the string
    2. Use ReadFile & WriteFile APIs to read/write files
    3. Use SetFilePointer to move within the file if needed
    4. Use other APIs to get file details: GetFileSize, Get/SetFileAttributes and others as needed
    5. Always close an opened file with CloseHandle API

    Once you start playing with the APIs, you'll quickly appreciate how easy VB made it for us and wish VB just had the foresight to handle unicode files too.
    Please post follow-up questions regarding this topic to the VB6 forum. If you have questions about the open/save dialog class, post it here. Thanx.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #9
    Hyperactive Member
    Join Date
    Jul 2010
    Posts
    273

    Re: [VB6] Unicode File Open/Save Dialog

    Good code, and it is so nice of La Volpe to help people here.

    I became involved in Unicode because very occasionally a Chinese friend would send me a DVD containing photos under various folder names. To view those photos I cannot use my own paint program, nor a third party program such as PhotoShop (v 7.0.0), as folder names are in Chinese, which hinders the access of the files. So I had to make a simple program in order to Open the files and/or to browser them one by one through Next/Previous buttons. Since some photos were vertically taken, I had to provide "turn left" and "turn right" buttons as well. To gain an acceptable speed for the said rotation operations, I used DIB to contain the source image, before projecting it to a full-screen-sized PictureBox (keeping aspect ratio). It is through this kind of exercise that I've acquired some Unicode knowledge.

    A few notes of observation:

    (a) I normally have the returned type as IPicture or StdPicture interchangeably. However, in the case of OleLoadPicture, I must use IPicture, otherwise GetObjectType would err.

    (b) I use both Open and CreateFile depending on circumstances. The file pointer in the case of Open is 1-based, but 0-based if CreateFile.

    (c) I don't favor the idea of setting to "Break On Unhandled Errors". I detect whether user had clicked Cancel, and whether any error had occurred, in the following manner:
    vb Code:
    1. Function ShowOpenW(Optional Owner As Long = 0&, Optional inFilter As String = "All (*.*)| *.*") As String
    2.  
    3.     ........
    4.     ........
    5.  
    6.     mFileSpec = ""
    7.     m_FileExtIndexOnOpen = -1
    8.     If mResult = 1 Then
    9.          If typOpenFile.nFileOffset Then
    10.              i = InStr(typOpenFile.nFileOffset, typOpenFile.lpstrFile, vbNullChar) - 1&
    11.              If i = 0 Then
    12.                  i = Len(typOpenFile.lpstrFile)
    13.              End If
    14.          Else
    15.              i = Len(typOpenFile.lpstrFile))
    16.          End If
    17.          
    18.            'Fill in mFileSpec
    19.          If i > 0 Then
    20.                mFileSpec = Left$(typOpenFile.lpstrFile, i)
    21.                  ' Note down for possible use of calling program, e.g. to set file pattern
    22.                  ' "*.*" when a certain nFilterIndex has been selected.
    23.                m_FileExtIndexOnOpen = typOpenFile.nFilterIndex
    24.          End If
    25.     Else
    26.          If mResult <> 0 Then              ' 0 is Cancel, else extended error
    27.               m_lExtendedError = CommDlgExtendedError()
    28.          End If
    29.     End If
    30.       ' Return file spec
    31.     ShowOpenW = mFileSpec
    32. End Function

    Remarks: If ShowOpenW returns "", then it is assumed user must have Cancelled. If one wants to ensure, then just add something like this:

    vb Code:
    1. If returnedFileSpec = "" then
    2.     If cUniDialog.ExtendedErrorNum <> 0 then
    3.             'Flag what is the error description
    4.         cUniDialog.FlagErrMsg cUniDialog.ExtendedErrorNum
    5.     End If
    6. End if

    This way, no run-time error would ever occur in IDE.


    BTW, I have uploaded a Unicode Textbox User Control, please see http://www.vbforums.com/showthread.p...07#post3836607
    Last edited by petersen; Jul 4th, 2010 at 09:54 PM. Reason: Add last paragraph

  10. #10
    Hyperactive Member
    Join Date
    Jun 2009
    Posts
    437

    Re: [VB6] Unicode File Open/Save Dialog

    petersen, thanks for this reply, but can you explain what does your code ?
    I am a bit lost, as i understood above that i can't use the UNICODE except with special controls and that normal textbox and listbox won't show the names of the arabic and chinese files ... you said that you used to work with UNICODE, any way or suggestion to help me to show a dialog box that can select any file name (including chinese and arabic), and to show in a listbox And textbox the name of the selected file and to allow me to rename this file or copy it using the Name AS function for expl ?

  11. #11

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    justgreat, please PM Petersen or post questions on his linked thread. I would appreciate not using my thread to discuss stuff not related to what I posted. Thank you
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  12. #12
    Hyperactive Member
    Join Date
    Jul 2010
    Posts
    273

    Re: [VB6] Unicode File Open/Save Dialog

    For clarity purposes, I jot down the following points:

    (1) Since this thread is on "Unicode File Open/Save Dialog", we take the VB-supplied Common Dialog Control for example. For certain reasons you cannot use it to "Open" a file which file specification has some Chinese characters in it (here Chinese characters are just as an example). Therefore, La Volpe posts his "class", to be used to invoke an Open dialog which is capable of showing the said file and enabling access to it.

    (2) I bumped into the above said "class", hence entered into the forum to share a few points of my observation on the related issues.

    (3) I briefly explained how I had become involved in Unicode stuff. As you can see, my knowledge in Unicode is only skin deep. As the problem mentioned in "1" also exists in the VB-supplied TextBox control, i.e. incapable of accepting / displaying Chinese characters, and it happends I have a Unicode TextBox User Control in hand, so I made a mention of it and posted it in the hope that it might be of use to some readers.

    (4) The subject of Unicode and associated issues are rather wide and complicated, for an adequate explanation, perhaps you should visit:

    http://www.cyberactivex.com/UnicodeTutorialVb.htm

    (5) Apart from the "class" mentioned in "1" above, La Volpe also posts the source code to demonstrate how to render the image of a BMP and JPG etc file. So all you have to do is download the "class", copy and paste the source code for the Form (shown in Forum panel), read the comments of La Volpe's, and run the code.

    (6) In IDE, if you click Cancel button in the Open dialog, a runtime error might occur. Don't worry about it, just re-run the program.

  13. #13
    Lively Member
    Join Date
    Feb 2009
    Posts
    72

    Re: [VB6] Unicode File Open/Save Dialog

    Hi LaVolpe,

    Thank for class.

    I have one question. How can I change the button "Open", "Cancel" or Title to Unicode.

    Thanks,

    LVD

  14. #14

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Quote Originally Posted by levanduyet View Post
    I have one question. How can I change the button "Open", "Cancel" or Title to Unicode.
    The class has a DialogTitle property that you can change. Simply give the property your unicode title

    As for the button captions, you can find examples of subclassing/hooking the dialog window on the net. There are even examples on how to add your own buttons, like a preview button. Search for keywords: OPENFILENAME hook

    But note that in Vista & above, setting the HookProc of the class will cause the dialog to loose any theming. For XP and below, this is not the case.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #15
    Lively Member
    Join Date
    Feb 2009
    Posts
    72

    Re: [VB6] Unicode File Open/Save Dialog

    Hi Lavolpe,
    Thanks for your reply. I mean that if you can combine in your class, it will be better. The user can do everything with your class.

    Thanks,

    Lvd

  16. #16

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Added a unicode capable Browse for Folder dialog class. See 1st post above
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  17. #17

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Added example, in post #1 above, of using the folder browser to set the initial display/selected path
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  18. #18
    Hyperactive Member
    Join Date
    Jan 2010
    Posts
    268

    Re: [VB6] Unicode File Open/Save Dialog

    Quote Originally Posted by LaVolpe View Post
    Added example, in post #1 above, of using the folder browser to set the initial display/selected path
    You could add some more codes in demo:

    cBrowser.DialogTitle = ChrW$(&H6B22) & ChrW$(&H8FCE) & " to choose a folder ..."

    If we set some flags to show TextBox (e.g. Folder) or Buttons (e.g. Make new Folder), the focus in Folder Treeview will lost. Any way to be initially focused on treeview items and .EnsureVisible at Dialog showing up?
    cBrowser.flags = BIF_DONTGOBELOWDOMAIN + BIF_USENEWUI + BIF_NEWDIALOGSTYLE
    Attached Images Attached Images  
    Last edited by Jonney; Apr 8th, 2012 at 07:23 PM.

  19. #19

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    One thing first. You should not ADD flag values together; they should be OR'd together. The following results in 2 different values:
    Code:
    MsgBox BIF_DONTGOBELOWDOMAIN Or BIF_USENEWUI Or BIF_NEWDIALOGSTYLE & vbCrLf & _
          BIF_DONTGOBELOWDOMAIN + BIF_USENEWUI + BIF_NEWDIALOGSTYLE
    From experience, I've found that most things you want to do with the browser window should be done via subclassing. The browser callback messages are very few and most occur before the window is even displayed. A workaround to your scenario is shown below.

    1. Add these declarations to your module, as needed, to allow subclassing
    Code:
    Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
    Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SetFocusAPI Lib "user32.dll" Alias "SetFocus" (ByVal hWnd As Long) As Long
    Private Declare Function DefWindowProc Lib "user32.dll" Alias "DefWindowProcA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Const WM_SHOWWINDOW As Long = &H18
    Private Const GWL_WNDPROC As Long = -4
    
    Private m_WndProc As Long
    2. Add a subclass procedure to your module
    Code:
    Private Function BrowserWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    
        If m_WndProc = 0& Then
            BrowserWndProc = DefWindowProc(hWnd, uMsg, wParam, lParam)
        Else
            BrowserWndProc = CallWindowProc(m_WndProc, hWnd, uMsg, wParam, lParam)
            If uMsg = WM_SHOWWINDOW Then
                Dim cWnd As Long, pWnd As Long
                SetWindowLong hWnd, GWL_WNDPROC, m_WndProc
                m_WndProc = 0&
                Do ' find the treeview
                    pWnd = FindWindowEx(hWnd, pWnd, vbNullString, vbNullString)
                    Debug.Print "checking child window: " & Hex(pWnd)
                    If pWnd = 0& Then Exit Do
                    cWnd = FindWindowEx(pWnd, 0&, "SysTreeView32", vbNullString)
                    If cWnd Then
                        Debug.Print "treeview found as: " & Hex(cWnd)
                        SetFocusAPI cWnd
                        Exit Do
                    End If
                Loop
                Debug.Print "unsubclassed"
            End If
        End If
        
    End Function
    3. Modify the BrowseCallbackProc function to start subclassing during initialization, i.e.,
    Code:
    Case BFFM_INITIALIZED
        If m_WndProc = 0& Then
            Call SendMessage(hWnd, BFFM_SETSELECTION, 0&, ByVal lParam)
            m_WndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf BrowserWndProc)
        End If
    Edited: Note that the assumption is the treeview will be a grandchild of the main dialog. I would think a more robust/recursive search should be created should previous/future versions of Windows place the treeview higher/deeper in the hierarchy.
    Last edited by LaVolpe; Apr 9th, 2012 at 09:44 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  20. #20
    Hyperactive Member
    Join Date
    Jan 2010
    Posts
    268

    Re: [VB6] Unicode File Open/Save Dialog

    Quote Originally Posted by LaVolpe View Post
    Edited: Note that the assumption is the treeview will be a grandchild of the main dialog. I would think a more robust/recursive search should be created should previous/future versions of Windows place the treeview higher/deeper in the hierarchy.
    Suclassing is a good way to set the focus. But .EnsureVisible is bit of complicated.
    Call SendMessageLong(m_hTreeView, TVM_ENSUREVISIBLE, 0&, hNode),but how to obtain the hNode (I forgot treeview knowledge)?

    Never mind, just curious, I seldom used this feature.

  21. #21
    PowerPoster
    Join Date
    Feb 2006
    Posts
    10,453

    Re: [VB6] Unicode File Open/Save Dialog

    The main point of this thread can be important because in VB6 we don't otherwise have a Unicode Open/Save dialog.

    But a folder browsing dialog doesn't need this pile of code since the Shell COM object exposed by Shell32.dll already has the simple BrowseForFolder method available.
    Code:
    Option Explicit
    '
    'Late-Binds Microsoft Shell Controls and Automation because Microsoft
    'did not maintain binary compatibility in all versions and service
    'packs of Windows after XP.
    '
    'Uses RTBEx.bas for some Unicode operations on RichTextBox controls.
    '
    
    Private Enum BIF_OPTIONS_ENUM
        'Some options require later shell32.dll versions than 4.71
        BIF_RETURNONLYFSDIRS = &H1&
        BIF_DONTGOBELOWDOMAIN = &H2&
        BIF_RETURNFSANCESTORS = &H8&
        BIF_EDITBOX = &H10&
        BIF_VALIDATE = &H11&
        BIF_NEWDIALOGSTYLE = &H40&
        BIF_BROWSEINCLUDEURLS = &H80&
        BIF_USENEWUI = BIF_EDITBOX Or BIF_NEWDIALOGSTYLE
        BIF_UAHINT = &H100&
        BIF_NONEWFOLDERBUTTON = &H200&
        BIF_NOTRANSLATETARGETS = &H400&
        BIF_BROWSEFORCOMPUTER = &H1000&
        BIF_BROWSEFORPRINTER = &H2000&
        BIF_BROWSEINCLUDEFILES = &H4000&
        BIF_SHAREABLE = &H8000&
    End Enum
    
    Private Sub Command1_Click()
        Dim Folder2 As Object
        
        With CreateObject("Shell.Application")
            Set Folder2 = .BrowseForFolder(hWnd, _
                                           "Choose a folder:", _
                                           BIF_USENEWUI _
                                        Or BIF_SHAREABLE _
                                        Or BIF_DONTGOBELOWDOMAIN _
                                        Or BIF_RETURNONLYFSDIRS, _
                                           RTBReadUnicode(RTB1))
        End With
        If Not (Folder2 Is Nothing) Then
            RTBWriteUnicode RTB2, Folder2.Self.Path
        End If
    End Sub
    Note that no special Unicode handling is required since Unicode is natively supported. The only bow to Unicode here is for entry of the RootFolder and displaying the Path of the resulting Folder2 object.

    In many cases the Folder/Folder2 result can be directly used (via .CopyHere, .MoveHere, etc.) making this especially convenient for folder operations.
    Attached Files Attached Files

  22. #22

    Thread Starter
    VBaholic & Loving It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    GetWindowRect()
    Posts
    11,938

    Re: [VB6] Unicode File Open/Save Dialog

    Though the shell's BrowseForFolder method is nice and clean, requires little knowledge to use, it does have limitations by not exposing a callback for those that want that option. My class may have a few limitations too, but they should be able to be resolved via additional code as needed.

    In your example, the path you pass as the final parameter is not the same as setting the desired initial directory to be displayed. That final parameter defines the root of the browser; thereby, restricting selection of anything above that folder in the directory structure. This option is included with that class: SetRootFolder

    Not saying my class is better or worse. Different scenarios will dictate usage of either. Good to know of a more generic, suitable substitute. Thanx

    Edited: I think a separate thread on many of the shell methods, a coder would use in common projects, could be a really good thing.

    P.S. Maybe I did something wrong with the shell version, I get errors whenever I try to use BIF_BROWSEINCLUDEFILES. The dialog displays as intended, but errors if a file is selected (IShellDispatch4 failed).
    Code:
        With CreateObject("Shell.Application")
            Call .BrowseForFolder(hWnd, _
                                           "Choose a folder:", _
                                           BIF_USENEWUI _
                                        Or BIF_SHAREABLE _
                                        Or BIF_DONTGOBELOWDOMAIN _
                                        Or BIF_BROWSEINCLUDEFILES)
        End With
    Last edited by LaVolpe; Apr 9th, 2012 at 01:25 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts


    {Alpha Image Control} {Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VBA Control Arrays} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  23. #23
    PowerPoster
    Join Date
    Feb 2006
    Posts
    10,453

    Re: [VB6] Unicode File Open/Save Dialog

    Valid points of course, and some people may need just that level of flexibility.

    I only wanted to point out that in simple cases a simple solution already exists, unlike when you need a Unicode Open/Save dialog.

  24. #24
    New Member
    Join Date
    Mar 2013
    Posts
    1

    Re: [VB6] Unicode File Open/Save Dialog

    That's how you maybe add Support for
    Multi File Selection

    That's how the 'client part' may look like
    vb Code:
    1. Public Sub Form_Load()
    2.   With New cOpenSaveDialog
    3.    .Flags = OFN_ALLOWMULTISELECT ' + OFN_EXPLORER
    4.    .DialogTitle = "Select one (or more) files"
    5.    .Filter = "All Files|*.*|" & _
    6.              "Sibelius scorch Files|*.sco"
    7.       If .ShowOpen(hWnd) Then
    8.  
    9.          Dim item
    10.          For Each item In .FileNames
    11.             AddFile item
    12.          Next
    13.          
    14.          
    15.          Timer_TriggerLoad_OLEDrag.Enabled = True
    16.          
    17.       End If
    18.      
    19.    End With
    20. End Sub
    21.  
    22. Public Sub AddFile(FileName$)
    23.    cb_ScoFiles.AddItem FileName
    24.    cb_ScoFiles.ListIndex = cb_ScoFiles.ListCount - 1
    25. End Sub

    Note: To get that sample fully working.
    Add a new Form and place there a comboBox and name [it B]cb_ScoFiles[/B].
    Na who cares - for sure ya've your own code. Just read over it to grab some Inspirations


    So that's how the 'server part' will look like:
    Code:
    ' returns the filenames the dialog starts with or returns
    
    Public Property Get FileNames()
    
      'OFN_ALLOWMULTISELECT _
       without OFN_EXPLORER
       If ( _
               (ofn.Flags And OFN_ALLOWMULTISELECT) And _
              ((ofn.Flags And OFN_EXPLORER) = False) _
           ) Then
           
          Dim splitchar$
          splitchar = " "
         
          Dim FilenameRaw$
          FilenameRaw = FileName()
          
       Else
       
          splitchar = vbNullChar
          FilenameRaw = ofn.lpstrFile
    
       End If
                    
       
        
     ' Split FileNames
       Dim pFileNames
       pFileNames = Split(FilenameRaw, splitchar)
       
       
       Dim item, i&:   i = 0
       For Each item In pFileNames
       
        ' Cut Array at first empty FileName
          If item = "" Then
             Exit For
          End If
          
        ' First is the FilePath (without Filename attached)
          If i = 0 Then
             Dim pathName$
             pathName = pFileNames(0)
          Else
           ' Make full path ( ... and store it in previous array element)
             pFileNames(i - 1) = pathName & "\" & pFileNames(i)
          End If
        
          i = i + 1
          
       Next
    ' Rewind/cut empty element
      i = i - 1
    
       
     ' Rewind/cut last element
     ' ... but only if there are more than one File
     ' since if FilesCount=1 => first element is already fullpath
       If i >= 1 Then i = i - 1
       
       ReDim Preserve pFileNames(i)
    
       FileNames = pFileNames
    
    End Property
    (I left out vb-highlight here for easier Copy&Paste. So these LineNumber will not come into ya way. )
    so add this Property Get FileNames() to cOpenSaveDialog.cls
    or
    Download the attached cOpenSaveDialog.cls
    cOpenSaveDialog.cls
    Last edited by cw2k; Mar 25th, 2013 at 09:18 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.