gpt4 book ai didi

c# - WinCE 上的 SHBrowseForFolder 布局不正确

转载 作者:太空宇宙 更新时间:2023-11-03 13:39:20 30 4
gpt4 key购买 nike

我正在尝试 p/调用 SHBrowseForFolder API 以提示用户选择一个文件夹,我看到标题静态/标签字段 float 在树控件的顶部。

Folder browse with bad layout

代码是从 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。

最佳答案

我对 SHBrowseForFolderFolderBrowserDialog 和 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/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com