选择文件夹对话框 API 函数(SHBrowseForFolder)的一个小问题

kxgy 2002-07-03 05:33:20
我在程序中声明了 SHBrowseForFolder 函数:
<StructLayout(LayoutKind.Sequential)> _
Public Structure BROWSEINFO
Public hWndOwner As IntPtr
Public pidlRoot As ITEMIDLIST
<MarshalAs(UnmanagedType.LPTStr)> Public pszDisplayName As String
<MarshalAs(UnmanagedType.LPTStr)> Public lpszTitle As String
Public ulFlags As BrowsingForDirectory
Public lpfn As BFFCALLBACK
Public lParam As IntPtr
Public iImage As Integer
End Structure

Public Enum BrowsingForDirectory
BIF_RETURNONLYFSDIRS = &H1
BIF_DONTGOBELOWDOMAIN = &H2
BIF_STATUSTEXT = &H4
BIF_RETURNFSANCESTORS = &H8
BIF_EDITBOX = &H10
BIF_VALIDATE = &H20
BIF_NEWDIALOGSTYLE = &H40
BIF_USENEWUI = BIF_NEWDIALOGSTYLE Or BIF_EDITBOX
BIF_BROWSEINCLUDEURLS = &H80
BIF_UAHINT = &H100
BIF_NONEWFOLDERBUTTON = &H200
BIF_NOTRANSLATETARGETS = &H400
BIF_BROWSEFORCOMPUTER = &H1000
BIF_BROWSEFORPRINTER = &H2000
BIF_BROWSEINCLUDEFILES = &H4000
BIF_SHAREABLE = &H8000
End Enum

<StructLayout(LayoutKind.Sequential)> _
Public Class ITEMIDLIST
Public mkid As SHITEMID
End Class

<StructLayout(LayoutKind.Sequential)> _
Public Structure SHITEMID
Public cb As Short
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)> Public abID() As Byte
End Structure

Public Delegate Function BFFCALLBACK(ByVal hWnd As Integer, ByVal nMsg As Integer, ByVal lParam As IntPtr, ByVal lpData As IntPtr) As Integer

Public Declare Auto Function SHBrowseForFolder (Byref lpbi As BROWSEINFO) As <MarshalAs(UnmanagedType.LPStruct)> ITEMIDLIST

调用正常。

但我将返回值代入函数:
Public Declare Auto Function SHGetPathFromIDList Lib "shell32" (ByVal pidl As ITEMIDLIST, ByVal pszPath As String) As Boolean
时却始终得不到正确的 pszPath 值。

请问哪位大侠能帮帮我,是声明中有错,还是其它什么原因?……
...全文
1361 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
kxgy 2002-07-03
  • 打赏
  • 举报
回复
你的程序还勉强可以,不过也有些糟糕,知不知道只用 SHBrowseForFolder 和 SHGetPathFromIDList 两个 API 函数就够了,还用什么其它的 API 函数。

但是我在程序中还是需要得到 SHBrowseForFolder 返回的 ITEMIDLIST,怎样声明可以一步搞定,而且不影响 SHGetPathFromIDList 函数的调用。


给你加的分暂搁着,等我结贴的时候再给你。
proking 2002-07-03
  • 打赏
  • 举报
回复
大哥,我的定義好象同你不一樣哦

Declare Function SHGetPathFromIDList Lib "shell32" Alias "SHGetPathFromIDList" (ByVal pidList As IntPtr, ByVal lpBuffer As StringBuilder) As Integer

我的是沒問題的啊!

你可以試著把string改為StringBuilder
proking 2002-07-03
  • 打赏
  • 举报
回复
好吧,我把所有的源代碼發給你吧.150分就給我了吧(加上前面的100分)<:)有點像搶!

Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Public Class DirectoryDialog
Public Structure BROWSEINFO
Public hWndOwner As IntPtr
Public pIDLRoot As Integer
Public pszDisplayName As String
Public lpszTitle As String
Public ulFlags As Integer
Public lpfnCallback As Integer
Public lParam As Integer
Public iImage As Integer
End Structure

Const MAX_PATH As Integer = 260
Public Enum BrowseForTypes As Integer
Computers = 4096
Directories = 1
FilesAndDirectories = 16384
FileSystemAncestors = 8
End Enum
Declare Function CoTaskMemFree Lib "ole32" Alias "CoTaskMemFree" (ByVal hMem As IntPtr) As Integer
Declare Function lstrcat Lib "kernel32" Alias "lstrcat" (ByVal lpString1 As String, ByVal lpString2 As String) As IntPtr
Declare Function SHBrowseForFolder Lib "shell32" Alias "SHBrowseForFolder" (ByRef lpbi As BROWSEINFO) As IntPtr
Declare Function SHGetPathFromIDList Lib "shell32" Alias "SHGetPathFromIDList" (ByVal pidList As IntPtr, ByVal lpBuffer As StringBuilder) As Integer

Protected Function RunDialog(ByVal hWndOwner As IntPtr) As Boolean

Dim udtBI As BROWSEINFO = New BROWSEINFO()
Dim lpIDList As IntPtr
Dim hTitle As GCHandle = GCHandle.Alloc(Title, GCHandleType.Pinned)
udtBI.hWndOwner = hWndOwner
udtBI.lpszTitle = Title
udtBI.ulFlags = BrowseFor
Dim buffer As StringBuilder = New StringBuilder(MAX_PATH)
buffer.Length = MAX_PATH
udtBI.pszDisplayName = buffer.ToString()
lpIDList = SHBrowseForFolder(udtBI)
hTitle.Free()
If lpIDList.ToInt64() <> 0 Then
If BrowseFor = BrowseForTypes.Computers Then
m_Selected = udtBI.pszDisplayName.Trim()
Else

Dim path As StringBuilder = New StringBuilder(MAX_PATH)
SHGetPathFromIDList(lpIDList, path)
m_Selected = path.ToString()
End If
CoTaskMemFree(lpIDList)
Else
Return False
End If
Return True
End Function

Public Function ShowDialog() As DialogResult
Return ShowDialog(Nothing)
End Function

Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
Dim handle As IntPtr
If Not owner Is Nothing Then
handle = owner.Handle
Else
handle = IntPtr.Zero
End If
If RunDialog(handle) Then
Return DialogResult.OK
Else
Return DialogResult.Cancel
End If
End Function

Public Property Title() As String
Get
Return m_Title
End Get
Set(ByVal Value As String)
If Value Is DBNull.Value Then
Throw New ArgumentNullException()
End If
m_Title = Value
End Set
End Property
Public ReadOnly Property Selected() As String
Get
Return m_Selected
End Get
End Property
Public Property BrowseFor() As BrowseForTypes
Get
Return m_BrowseFor
End Get
Set(ByVal Value As BrowseForTypes)
m_BrowseFor = Value
End Set
End Property

Private m_BrowseFor As BrowseForTypes = BrowseForTypes.Directories
Private m_Title As String = ""
Private m_Selected As String = ""

Public Sub New()
End Sub
End Class


應用方法
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim frmd As DirectoryDialog = New DirectoryDialog()
'frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Directories
'frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Computers
frmd.BrowseFor = DirectoryDialog.BrowseForTypes.FilesAndDirectories
frmd.Title = "請選擇一個目錄"
'frmd.
'frmd.ShowDialog(Me)
If frmd.ShowDialog(Me) = DialogResult.OK Then
MsgBox(frmd.Selected)
End If
End Sub
kxgy 2002-07-03
  • 打赏
  • 举报
回复
但是我需要得到 SHBrowseForFolder 返回的 ITEMIDLIST 值,可我不想用 Marshal.Copy 函数。有没有其它办法?

16,553

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧