tags:

views:

692

answers:

4

My Google-Fu is weak today, hopefully this is a simple thing.

I need to set the InitDir property of a VB6 CommonDialog control to start at [My] Computer. If I set InitDir to an empty string, it just defaults to the current directory from the last open dialog.

My code:

With MyCommonDialogControl
    .DialogTitle = "Choose Import File"
    .Filter = "Import Files|*.dbf"
    .InitDir = Environ("HOMEDRIVE") //Needs to be "My Computer"
    .CancelError = False
    .ShowOpen
    If Len(.Filename) = 0 Then Exit Sub
    InputFile = .Filename
End With

Thank you in advance for any assistance.

+1  A: 

I've come across a couple of ways to do it - one is through the Environ method which appears to work in both VB6 and VBA - although I've never used this method, the other is through p/Invoke referencing: SHGetSpecialFolderLocation and SHGetPathFromIDList in the shell32.dll.

I didn't have the code to hand, so I've copied and pasted from another site http://en.kioskea.net/faq/sujet-951-vba-vb6-my-documents-environment-variables

I can't guarantee the correctness, but it looks very similar to code I've used in the past, so it should work with minimal debugging... anyway, at least it points you in the right direction.

Option Explicit
Private Type SHITEMID
    cb As Long
    abID As Byte
End Type
Private Type ITEMIDLIST
    mkid As SHITEMID
End Type
Private Const CSIDL_PERSONAL As Long = &H5
Private Declare Function SHGetSpecialFolderLocation Lib "shell32.dll" _
                        (ByVal hwndOwner As Long, ByVal nFolder As Long, _
                         pidl As ITEMIDLIST) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _
                        (ByVal pidl As Long, ByVal pszPath As String) As Long


Public Function Rep_Documents() As String
    Dim lRet As Long, IDL As ITEMIDLIST, sPath As String
    lRet = SHGetSpecialFolderLocation(100&, CSIDL_PERSONAL, IDL)
    If lRet = 0 Then
        sPath = String$(512, Chr$(0))
        lRet = SHGetPathFromIDList(ByVal IDL.mkid.cb, ByVal sPath)
        Rep_Documents = Left$(sPath, InStr(sPath, Chr$(0)) - 1)
    Else
        Rep_Documents = vbNullString
    End If
End Function

Referencing Rep_Documents() will give you a string holding the path name of the My Documents folder. It's just a case of assigning it to the file dialog's InitDir property.

BenAlabaster
This works great for any special folder that has a definitive path, but when you try to execute SHGetPathFromIDList after using SHGetSpecialFolderLocation using CSIDL_DRIVES it returns an empty string. It doesn't appear there is a path equivalent for "My Computer".I've instead routed the InitDir to the desktop, but I'm still curious if this can be done through either the OCX or the API. +1 for helping. :)
Heather
Heather "My Computer" is not really a directory but a logical grouping of drives and virtual paths - i.e. it includes the recycle bin. I'm not sure of a way to get that "path", I've never needed to. Sorry, I misread your question as wanting "My Documents", instead of "My Computer" - my fault.
BenAlabaster
Can I recommend Karl Peterson's code for wrapping SHGetSpecialFolderLocation etc? His code is always very high quality. balabaster, sounds like you've Googled and the resulting code may not necessarily be reliable? http://visualstudiomagazine.com/articles/2009/01/19/lemme-tell-ya-where-to-stick-it.aspx
MarkJ
I didn't have my old code to hand as I mentioned and I said that this "looks sufficiently similar" that it should point the OP in the right direction. I didn't state that it would work in it's present state.
BenAlabaster
This information was useful in pointing InitDir to My Documents, which the customer in question settled on. Thanks for the help!
Heather
+1  A: 

The problem is that My Computer is a virtual folder which doesn't have an equivalent physical directory path. Googling turned up this below which works for me on Windows XP.

  CommonDialog1.InitDir = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
  CommonDialog1.ShowOpen

Apparently this is using the CLSID for the My Computer namespace. Anyone out there who can explain this stuff? I'm just posting Google results that I don't really understand :)

MarkJ
This one doesn't seem to work for me, but works for other virtual folders. I've already given up on it and told my customer they will just have to just have to live with the control starting at their My Documents folder.
Heather
A: 

Back in the day a group of programmers founded the now defunct CCRP project. However, among the free downloads they have the Extended File Dialogs OCX/DLL, that give you what you want, plus one hell of a lot more.

http://ccrp.mvps.org/download/ccrpdownloads.htm">http://ccrp.mvps.org/index.html?http://ccrp.mvps.org/download/ccrpdownloads.htm

AngryHacker
A: 

Works well, THANKS! (WinXP SP3)

Option Explicit '

    Private getdir As String
    '

    '

    Private Sub Command1_Click()

      Dim strFilter As String
    Dim lngFlags As Long
    strFilter = thAddFilterItem(strFilter, "Excel Files (*.xls)", "*.XLS")
    'strFilter = thAddFilterItem(strFilter, "Text Files(*.txt)", "*.TXT")
    'strFilter = thAddFilterItem(strFilter, "All Files (*.*)", "*.*")
 ' MsgBox thCommonFileOpenSave(InitialDir:=App.Path, Filter:=strFilter, FilterIndex:=3, Flags:=lngFlags, DialogTitle:="File Browser")
   MsgBox thCommonFileOpenSave(InitialDir:="::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", Filter:=strFilter, FilterIndex:=3, Flags:=lngFlags, DialogTitle:="File Browser")

   Debug.Print Hex(lngFlags)
End Sub

Option Explicit

Type thOPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    strFilter As String
    strCustomFilter As String
    nMaxCustFilter As String
    nFilterIndex As Long
    strFile As String
    nMaxFile As Long
    strFileTitle As String
    nMaxFileTitle As Long
    strInitialDir As String
    strTitle As String
    Flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    strDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

Declare Function th_apiGetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (OFN As thOPENFILENAME) As Boolean
Declare Function th_apiGetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (OFN As thOPENFILENAME) As Boolean
Declare Function CommDlgExtendetError Lib "commdlg32.dll" () As Long

Private Const thOFN_READONLY = &H1
Private Const thOFN_OVERWRITEPROMPT = &H2
Private Const thOFN_HIDEREADONLY = &H4
Private Const thOFN_NOCHANGEDIR = &H8
Private Const thOFN_SHOWHELP = &H10
Private Const thOFN_NOVALIDATE = &H100
Private Const thOFN_ALLOWMULTISELECT = &H200
Private Const thOFN_EXTENSIONDIFFERENT = &H400
Private Const thOFN_PATHMUSTEXIST = &H800
Private Const thOFN_FILEMUSTEXIST = &H1000
Private Const thOFN_CREATEPROMPT = &H2000
Private Const thOFN_SHAREWARE = &H4000
Private Const thOFN_NOREADONLYRETURN = &H8000
Private Const thOFN_NOTESTFILECREATE = &H10000
Private Const thOFN_NONETWORKBUTTON = &H20000
Private Const thOFN_NOLONGGAMES = &H40000
Private Const thOFN_EXPLORER = &H80000
Private Const thOFN_NODEREFERENCELINKS = &H100000
Private Const thOFN_LONGNAMES = &H200000

Function StartIt()
    Dim strFilter As String
    Dim lngFlags As Long
    strFilter = thAddFilterItem(strFilter, "Excel Files (*.xls)", "*.XLS")
    strFilter = thAddFilterItem(strFilter, "Text Files(*.txt)", "*.TXT")
    strFilter = thAddFilterItem(strFilter, "All Files (*.*)", "*.*")
    Startform.filenameinput.Value = thCommonFileOpenSave(InitialDir:="x:\Anlagen_PG80", Filter:=strFilter, FilterIndex:=3, Flags:=lngFlags, DialogTitle:="File Browser")
    Debug.Print Hex(lngFlags)
End Function

Function GetOpenFile(Optional varDirectory As Variant, Optional varTitleForDialog As Variant) As Variant
    Dim strFilter As String
    Dim lngFlags As Long
    Dim varFileName As Variant
    lngFlags = thOFN_FILEMUSTEXIST Or thOFN_HIDEREADONLY Or thOFN_NOCHANGEDIR

    If IsMissing(varDirectory) Then varDirectory = ""
    End If

    If IsMissing(varTitleForDialog) Then varTitleForDialog = ""
    End If

    strFilter = thAddFilterItem(strFilter, "Excel (*.xls)", "*.XLS")
    varFileName = thCommonFileOpenSave(OpenFile:=True, InitialDir:=varDirectory, Filter:=strFilter, Flags:=lngFlags, DialogTitle:=varTitleForDialog)

    If Not IsNull(varFileName) Then varFileName = TrimNull(varFileName)
    End If

    GetOpenFile = varFileName

End Function

Function thCommonFileOpenSave(Optional ByRef Flags As Variant, Optional ByVal InitialDir As Variant, Optional ByVal Filter As Variant, _
                               Optional ByVal FilterIndex As Variant, Optional ByVal DefaultEx As Variant, Optional ByVal fileName As Variant, _
                               Optional ByVal DialogTitle As Variant, Optional ByVal hwnd As Variant, Optional ByVal OpenFile As Variant) As Variant

    Dim OFN As thOPENFILENAME
    Dim strFileName As String
    Dim FileTitle As String
    Dim fResult As Boolean

    If IsMissing(InitialDir) Then InitialDir = CurDir
    If IsMissing(Filter) Then Filter = ""
    If IsMissing(FilterIndex) Then FilterIndex = 1
    If IsMissing(Flags) Then Flags = 0&
    If IsMissing(DefaultEx) Then DefaultEx = ""
    If IsMissing(fileName) Then fileName = ""
    If IsMissing(DialogTitle) Then DialogTitle = ""
    If IsMissing(hwnd) Then hwnd = 0
    If IsMissing(OpenFile) Then OpenFile = True

    strFileName = Left(fileName & String(256, 0), 256)
    FileTitle = String(256, 0)

    With OFN
        .lStructSize = Len(OFN)
        .hwndOwner = hwnd
        .strFilter = Filter
        .nFilterIndex = FilterIndex
        .strFile = strFileName
        .nMaxFile = Len(strFileName)
        .strFileTitle = FileTitle
        .nMaxFileTitle = Len(FileTitle)
        .strTitle = DialogTitle
        .Flags = Flags
        .strDefExt = DefaultEx
        .strInitialDir = InitialDir
        .hInstance = 0
        .lpfnHook = 0
        .strCustomFilter = String(255, 0)
        .nMaxCustFilter = 255
    End With

    If OpenFile Then fResult = th_apiGetOpenFileName(OFN) Else fResult = th_apiGetSaveFileName(OFN)


    If fResult Then
        If Not IsMissing(Flags) Then Flags = OFN.Flags
        thCommonFileOpenSave = TrimNull(OFN.strFile)
        Else
        thCommonFileOpenSave = vbNullString
    End If

End Function

Function thAddFilterItem(strFilter As String, strDescription As String, Optional varItem As Variant) As String

    If IsMissing(varItem) Then varItem = "*.*"
    thAddFilterItem = strFilter & strDescription & vbNullChar & varItem & vbNullChar

End Function

Private Function TrimNull(ByVal strItem As String) As String
    Dim intPos As Integer
    intPos = InStr(strItem, vbNullChar)
    If intPos > 0 Then
        TrimNull = Left(strItem, intPos - 1)
        Else
        TrimNull = strItem
    End If

End Function
fotonut