2013-07-16 1 views
2

SHBrowseForFolder API를 호출/호출하여 사용자에게 폴더 선택을 요청하고 트리 컨트롤 상단에 제목/정적/플로팅 필드 플로팅이 표시됩니다. WinCE의 SHBrowseForFolder가 올바르게 레이아웃되지 않았습니다.

Folder browse with bad layout

코드

그물에 여러 곳에서 참조 대상의 article에서 다운로드하고 (이것은 기존 앱 삭제되고 있었다) VB.NET에 C#을 변환.

아무에게도 올바르게 레이아웃을 지정하는 데 도움이되는 정보가 있으면 제게 알려주십시오.

호출 코드가 간단

Using getLocDialog As New FolderBrowserDialog() 

    getLocDialog.Description = "This is a test" 
    getLocDialog.ShowDialog() 

    End Using 

다음, 여기에 부호의 VB.NET 버전이다

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 
    } 

:

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 번호이되었다 추가 세부 정보 : Dev 환경은 Visual Studio 2008, Compact Framework 3.5입니다. 장치는 Windows CE 4.2를 실행합니다.

답변

1

나는 SHBrowseForFolder, 그 FolderBrowserDialog 및 Windows CE 5.0에서 동일한 경험을했습니다.

플래그에 BIF_STATUSTEXT을 설정하면 문제를 해결할 수 있습니다. 이렇게하면 레이아웃이 옮겨지고 제목이 TreeView 위에 나타납니다.

이렇게하려면 데이터 멤버 uint m_flagsBrowseInfo 클래스에 추가하십시오. 그것의 생성자에서 추가

const uint BIF_STATUSTEXT = 0x00000004; 
m_flags |= BIF_STATUSTEXT; 

그리고 ToByteArray() 방법 담기를 :

BitConverter.GetBytes(m_flags).CopyTo(m_data, 16); 
+0

내가 제공해야합니다 시도하는, 팁을위한 감사합니다. – tcarvin

+0

잘 작동하지 않았습니까? 제목 레이블이 무시되는 동안 대화 상자의 상위 30 %가 비어 있도록 트리 뷰의 맨 위가 아래로 내려갔습니다. – tcarvin