- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试 p/调用 SHBrowseForFolder
API 以提示用户选择一个文件夹,我看到标题静态/标签字段 float 在树控件的顶部。
代码是从 article 下载的在网络上的多个位置引用并从 C# 转换为 VB.NET(它被放入现有应用程序中)。
如果有人对正确布局有任何提示,请赐教。
调用代码很简单:
Using getLocDialog As New FolderBrowserDialog()
getLocDialog.Description = "This is a test"
getLocDialog.ShowDialog()
End Using
接下来,这是代码的 VB.NET 版本:
Public Class FolderBrowserDialog
Inherits CommonDialog
'---------------------------------------------------------------------------
' instance
'---------------------------------------------------------------------------
Private info As BrowseInfo
Private folder As String = String.Empty
'---------------------------------------------------------------------------
' ctor
'---------------------------------------------------------------------------
Public Sub New()
info = New BrowseInfo()
info.Title = String.Empty
InitCommonControls()
End Sub
'---------------------------------------------------------------------------
' public
'---------------------------------------------------------------------------
Public Shadows Function ShowDialog() As DialogResult
Dim pitemidlist As IntPtr
Try
pitemidlist = SHBrowseForFolder(info.ToByteArray())
Catch mme As MissingMethodException
Throw New PlatformNotSupportedException("Your platform doesn't support the SHBrowseForFolder API", mme)
End Try
If pitemidlist = IntPtr.Zero Then
Return DialogResult.Cancel
End If
'//maxpath unicode chars
Dim buffer As Byte() = New Byte(519) {}
Dim success As Boolean = SHGetPathFromIDList(pitemidlist, buffer)
'//get string from buffer
If success Then
folder = System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length)
Dim nullindex As Integer = folder.IndexOf(Convert.ToChar(0))
If nullindex <> -1 Then
folder = folder.Substring(0, nullindex)
End If
End If
LocalFree(pitemidlist)
Return DialogResult.OK
End Function
Public ReadOnly Property SelectedPath() As String
Get
Return folder
End Get
End Property
Public Property Description() As String
Get
Return info.Title
End Get
Set(ByVal value As String)
info.Title = value
End Set
End Property
'---------------------------------------------------------------------------
' private
'---------------------------------------------------------------------------
<DllImport("commctrl", SetLastError:=True)> _
Private Shared Sub InitCommonControls()
End Sub
<DllImport("ceshell", SetLastError:=True)> _
Private Shared Function SHBrowseForFolder(ByVal lpbi As Byte()) As IntPtr
End Function
<DllImport("ceshell", SetLastError:=True)> _
Private Shared Function SHGetPathFromIDList(ByVal pidl As IntPtr, ByVal pszPath As Byte()) As Boolean
End Function
<DllImport("coredll", SetLastError:=True)> _
Private Shared Function LocalFree(ByVal ptr As IntPtr) As IntPtr
End Function
'---------------------------------------------------------------------------
' inner classes
'---------------------------------------------------------------------------
Private Class BrowseInfo
Private m_data As Byte()
Private m_displayname As Byte()
Private m_title As Byte()
Private namehandle As GCHandle
Private titlehandle As GCHandle
Public Sub New()
m_data = New Byte(31) {}
m_displayname = New Byte(511) {}
m_title = New Byte(127) {}
namehandle = GCHandle.Alloc(m_displayname, GCHandleType.Pinned)
titlehandle = GCHandle.Alloc(m_title, GCHandleType.Pinned)
BitConverter.GetBytes(namehandle.AddrOfPinnedObject().ToInt32 + 4).CopyTo(m_data, 8)
BitConverter.GetBytes(titlehandle.AddrOfPinnedObject().ToInt32 + 4).CopyTo(m_data, 12)
End Sub
Public Function ToByteArray() As Byte()
Return m_data
End Function
Protected Overrides Sub Finalize()
namehandle.Free()
titlehandle.Free()
MyBase.Finalize()
End Sub
Public Property Title() As String
Get
Dim ttl As String = System.Text.Encoding.Unicode.GetString(m_title, 0, m_title.Length)
Dim nullindex As Integer = ttl.IndexOf(Convert.ToChar(0))
If nullindex = -1 Then
Return ttl
End If
Return ttl.Substring(0, ttl.IndexOf(Convert.ToChar(0)))
End Get
Set(ByVal value As String)
Dim titlebytes As Byte() = System.Text.Encoding.Unicode.GetBytes(value & Convert.ToChar(0))
If titlebytes.Length > m_title.Length Then
Throw New ArgumentException("Description must be no longer than 64 characters")
End If
Try
Buffer.BlockCopy(titlebytes, 0, m_title, 0, titlebytes.Length)
Catch ex As Exception
End Try
End Set
End Property
Public Property FileName() As String
Get
Dim fn As String = System.Text.Encoding.Unicode.GetString(m_displayname, 0, m_displayname.Length)
Dim nullindex As Integer = fn.IndexOf(Convert.ToChar(0))
If nullindex = -1 Then
Return fn
End If
Return fn.Substring(0, fn.IndexOf(Convert.ToChar(0)))
End Get
Set(ByVal value As String)
Dim filenamebytes As Byte() = System.Text.Encoding.Unicode.GetBytes(value & Convert.ToChar(0))
If filenamebytes.Length > m_title.Length Then
Throw New ArgumentException("SelectedFolder must be no longer than 256 characters")
End If
Buffer.BlockCopy(filenamebytes, 0, m_displayname, 0, filenamebytes.Length)
End Set
End Property
'/*HWND hwndOwner;
'LPCITEMIDLIST pidlRoot;
'LPTSTR pszDisplayName;
'LPCTSTR lpszTitle;
'UINT ulFlags;
'BFFCALLBACK lpfn;
'LPARAM lParam;
'int iImage;*/
End Class
End Class
原来的 C# 是这样的:
public class FolderBrowserDialog : CommonDialog
{
private BrowseInfo info;
private string folder = string.Empty;
/// <summary>
/// Initializes a new instance of the FolderBrowserDialog class.
/// </summary>
public FolderBrowserDialog()
{
info = new BrowseInfo();
info.Title = string.Empty;
InitCommonControls();
}
/// <summary>
/// Runs a common dialog box with a default owner.
/// </summary>
/// <returns></returns>
public new DialogResult ShowDialog()
{
IntPtr pitemidlist;
try
{
pitemidlist = SHBrowseForFolder(info.ToByteArray());
}
catch(MissingMethodException mme)
{
throw new PlatformNotSupportedException("Your platform doesn't support the SHBrowseForFolder API",mme);
}
if(pitemidlist==IntPtr.Zero)
{
return DialogResult.Cancel;
}
//maxpath unicode chars
byte[] buffer = new byte[520];
bool success = SHGetPathFromIDList(pitemidlist, buffer);
//get string from buffer
if(success)
{
folder = System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length);
int nullindex = folder.IndexOf('\0');
if(nullindex!=-1)
{
folder = folder.Substring(0, nullindex);
}
}
LocalFree(pitemidlist);
return DialogResult.OK;
}
/// <summary>
/// Gets the path selected by the user.
/// </summary>
public string SelectedPath
{
get
{
return folder;
}
}
/// <summary>
/// Gets or sets the descriptive text displayed above the tree view control in the dialog box.
/// </summary>
public string Description
{
get
{
return info.Title;
}
set
{
info.Title = value;
}
}
#region P/Invokes
[DllImport("commctrl", SetLastError=true)]
private static extern void InitCommonControls();
[DllImport("ceshell", SetLastError=true)]
private static extern IntPtr SHBrowseForFolder(byte[] lpbi);
[DllImport("ceshell", SetLastError=true)]
private static extern bool SHGetPathFromIDList(IntPtr pidl, byte[] pszPath);
[DllImport("coredll", SetLastError=true)]
private static extern IntPtr LocalFree(IntPtr ptr);
#endregion
#region helper class for BROWSEINFO struct
private class BrowseInfo
{
private byte[] m_data;
private byte[] m_displayname;
private byte[] m_title;
private GCHandle namehandle;
private GCHandle titlehandle;
public BrowseInfo()
{
m_data = new byte[32];
m_displayname = new byte[512];
m_title = new byte[128];
namehandle = GCHandle.Alloc(m_displayname, GCHandleType.Pinned);
titlehandle = GCHandle.Alloc(m_title, GCHandleType.Pinned);
BitConverter.GetBytes((int)namehandle.AddrOfPinnedObject() + 4).CopyTo(m_data, 8);
BitConverter.GetBytes((int)titlehandle.AddrOfPinnedObject() + 4).CopyTo(m_data, 12);
}
public byte[] ToByteArray()
{
return m_data;
}
~BrowseInfo()
{
namehandle.Free();
titlehandle.Free();
}
public string Title
{
get
{
string title = System.Text.Encoding.Unicode.GetString(m_title, 0, m_title.Length);
int nullindex = title.IndexOf('\0');
if(nullindex==-1)
{
return title;
}
return title.Substring(0, title.IndexOf('\0'));
}
set
{
byte[] titlebytes = System.Text.Encoding.Unicode.GetBytes(value + '\0');
if(titlebytes.Length > m_title.Length)
{
throw new ArgumentException("Description must be no longer than 64 characters");
}
try
{
Buffer.BlockCopy(titlebytes, 0, m_title,0, titlebytes.Length);
}
catch
{
}
}
}
public string FileName
{
get
{
string filename = System.Text.Encoding.Unicode.GetString(m_displayname, 0, m_displayname.Length);
int nullindex = filename.IndexOf('\0');
if(nullindex==-1)
{
return filename;
}
return filename.Substring(0, filename.IndexOf('\0'));
}
set
{
byte[] filenamebytes = System.Text.Encoding.Unicode.GetBytes(value + '\0');
if(filenamebytes.Length > m_title.Length)
{
throw new ArgumentException("SelectedFolder must be no longer than 256 characters");
}
Buffer.BlockCopy(filenamebytes, 0, m_displayname,0, filenamebytes.Length);
}
}
/*HWND hwndOwner;
LPCITEMIDLIST pidlRoot;
LPTSTR pszDisplayName;
LPCTSTR lpszTitle;
UINT ulFlags;
BFFCALLBACK lpfn;
LPARAM lParam;
int iImage;*/
}
#endregion
}
其他详细信息:开发环境是 Visual Studio 2008,Compact Framework 3.5。该设备运行 Windows CE 4.2。
最佳答案
我对 SHBrowseForFolder
、FolderBrowserDialog
和 Windows CE 5.0 有同样的体验。
解决方法是为标志设置 BIF_STATUSTEXT
。这样布局就被置换了,标题出现在 TreeView 的上方。
为此,将数据成员 uint m_flags
添加到 BrowseInfo
类。在它的构造函数中添加:
const uint BIF_STATUSTEXT = 0x00000004;
m_flags |= BIF_STATUSTEXT;
并在 ToByteArray()
方法中添加:
BitConverter.GetBytes(m_flags).CopyTo(m_data, 16);
关于c# - WinCE 上的 SHBrowseForFolder 布局不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17684320/
我找到了使 SHBrowseForFolder 在我的应用程序中工作所需的所有代码。但我讨厌它迫使您在小文件夹窗口中执行所有操作,而没有文本框可通过键入进行导航。 在 Windows 中,我知道我经常
在我调用 SHBrowseForFloder 函数的代码中,现在我想让对话框始终位于顶部。但是我找不到可以做到这一点的参数。有人可以帮助我吗?或者我是否应该选择其他 API 来实现此功能? 最佳答案
我使用 SHBrowseForFolder在 Windows 中显示文件夹选择对话框的 API。我的应用程序支持基于最终用户选择的 UI 语言本地化。这是通过使用 FindResourceEx 加载所
我目前正在使用 SHBrowseForFolder() 打开浏览文件夹窗口,但是当取消/确定 被按下。我读到我应该在对话框关闭之前重新启用我的主窗口,但那到底在哪里?有什么想法吗? void butt
下面用于调用 ShBrowseForFolder 的包装器代码仅工作一次:如果我第二次调用 Execute 方法,则对话框不会出现在“PtrIDL := ShBrowseForFolder(Brows
当我用 SHBrowseForFolder 打开对话框时,我希望它也能浏览隐藏文件夹(隐藏文件夹出现在对话框中)。我该怎么做? 最佳答案 SHBrowseForFolder 不显示隐藏文件夹。您将需要
我已经在网上搜索并与这个东西抗争了一个多小时,但似乎仍然无法让它工作。当大多数人在论坛等上得到它时,他们似乎很满意,但我的仍然不起作用。我试图强制 SHBrowseForFolder() 函数在我选择
我正在使用 SHBrowseForFolder 和 SHGetPathFromIDList 函数来获取用户选择的文件夹路径。但是此方法不返回完整路径的驱动器路径。如何另外获取该信息? 最佳答案 取自该
我正在尝试 p/调用 SHBrowseForFolder API 以提示用户选择一个文件夹,我看到标题静态/标签字段 float 在树控件的顶部。 代码是从 article 下载的在网络上的多个位置引
我正在尝试修复 SHBrowseForFolder 对话框,因为它不会对文件夹重命名使用react(BFFM_SELCHANGED 未被发送并且无法确定路径现在是否正确) .我用谷歌搜索了一个解决方案
我在使用 Vcl.FileCtrl 函数 SelectDirectory(它是 ShBrowseForFolder Win32 API 的一个薄包装器)时遇到了一个非常奇怪的问题。 我使用以下代码来允
我有一个同时使用 SHBrowseForFolder 和 GetSaveFileName 的程序。 当我使用 GetSaveFileName 并且所选目录没有正确的权限时,它会自动显示错误,指出当前用
从昨天早上开始我就遇到了一个问题,现在已经快把我逼疯了。 问题是我想创建一个对话框来浏览文件夹。对于每一个早于 Vista 的操作系统,我都使用 SHBrowseForFolder() 方法,它工作正
我正在尝试使用 BIF_BROWSEFORCOMPUTER 让 SHBrowseForFolder 工作,以允许用户选择网络上的计算机。 我可以让对话框显示并允许选择网络计算机,启用“确定”按钮,但是
我正在维护一个使用 Win32 的 C++ 程序。它多年来一直运行良好,但现在我在两台运行 Windows 8 的计算机上遇到“选择文件”或“选择文件夹”功能的问题,但在另外两台运行 Windows
我是一名优秀的程序员,十分优秀!