79

このスクリーン ショットに示すように、選択したフォルダはビューにありません。選択したフォルダを表示するには、下にスクロールする必要があります。

ここに画像の説明を入力

同じダイアログで、選択したフォルダが別のコンピュータに表示される

ここに画像の説明を入力

どちらもWindows 7を搭載した2台のコンピューターで実行しました。1台では正しく動作しますが、2台目では動作しません。コードの問題ではなく、Windows環境で何か見えますか?誰でも修正を提案できますか?

コードに変更はありません。異なるドライブからの長いパスを使用しましたが、結果は同じです。

private void TestDialog_Click ( object sender, EventArgs e )
        {
            //Last path store the selected path, to show the same directory as selected on next application launch.
            //Properties.Settings.Default.LastPath

            FolderBrowserDialog dlgFolder = new FolderBrowserDialog ();

            dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

            dlgFolder.SelectedPath = Properties.Settings.Default.LastPath;

            if (dlgFolder.ShowDialog () == System.Windows.Forms.DialogResult.OK)
            {

                Properties.Settings.Default.LastPath = dlgFolder.SelectedPath;               

                Properties.Settings.Default.Save ();
            }

        }
4

14 に答える 14

89

根本的な問題は、 の設計上の決定の誤りFolderBrowserDialogです。まず、 はFolderBrowserDialog.NET コントロールではなく、Common DialogWindows の一部であることを理解する必要があります。TVM_ENSUREVISIBLEこのダイアログの設計者は、ダイアログが表示されて最初のフォルダが選択された後、TreeView コントロールにメッセージを送信しないことを選択しました。このメッセージにより、現在選択されている項目がウィンドウに表示されるように TreeView コントロールがスクロールされます。

したがって、これを修正するために必要なことはFolderBrowserDialogTVM_ENSUREVISIBLEメッセージの一部である TreeView を送信することだけで、すべてがうまくいきます。右?まあ、それほど速くはありません。これが確かに答えですが、私たちの前に立ちはだかるものがいくつかあります。

  • まず、FolderBrowserDialogは実際には .NET コントロールではないため、内部Controlsコレクションがありません。これは、.NET から TreeView 子コントロールを見つけてアクセスすることはできないことを意味します。

  • 次に、.NETFolderBrowserDialogクラスの設計者は、このクラスを封印することにしました。この残念な決定により、そこから派生してウィンドウ メッセージ ハンドラをオーバーライドすることができなくなります。これができていれば、メッセージ ハンドラーでメッセージTVM_ENSUREVISIBLEを取得したときに、メッセージを投稿しようとした可能性があります。WM_SHOWWINDOW

  • 3 つ目の問題は、ツリー ビュー コントロールが実際のウィンドウとして実際に存在するまでメッセージを送信できず、メソッドTVM_ENSUREVISIBLEを呼び出すまで存在しないことです。ShowDialogただし、このメソッドはブロックするため、このメソッドが呼び出されるとメッセージを投稿する機会がありません。

これらの問題を回避するために、単一のメソッドを使用して静的ヘルパー クラスを作成しました。このメソッドを使用しFolderBrowserDialogて、選択したフォルダーにスクロールすることができます。Timerこれを管理するには、ダイアログのメソッドを呼び出す直前にショートを開始し、ハンドラーで (つまり、ダイアログが表示された後)コントロールShowDialogのハンドルを追跡し、メッセージを送信します。TreeViewTimerTVM_ENSUREVISIBLE

このソリューションは、 についての予備知識に依存するため、完全ではありませんFolderBrowserDialog。具体的には、ウィンドウ タイトルを使用してダイアログを見つけます。これは、英語以外のインストールでは壊れます。タイトル テキストやクラス名ではなく、ダイアログ アイテム ID を使用してダイアログ内の子コントロールを追跡します。

このコードは、Windows 7 (64 ビット) および Windows XP でテストされています。

コードは次のとおりです: (必要な場合があります: using System.Runtime.InteropServices;)

public static class FolderBrowserLauncher
{
    /// <summary>
    /// Using title text to look for the top level dialog window is fragile.
    /// In particular, this will fail in non-English applications.
    /// </summary>
    const string _topLevelSearchString = "Browse For Folder";

    /// <summary>
    /// These should be more robust.  We find the correct child controls in the dialog
    /// by using the GetDlgItem method, rather than the FindWindow(Ex) method,
    /// because the dialog item IDs should be constant.
    /// </summary>
    const int _dlgItemBrowseControl = 0;
    const int _dlgItemTreeView = 100;

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// Some of the messages that the Tree View control will respond to
    /// </summary>
    private const int TV_FIRST = 0x1100;
    private const int TVM_SELECTITEM = (TV_FIRST + 11);
    private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
    private const int TVM_GETITEM = (TV_FIRST + 12);
    private const int TVM_ENSUREVISIBLE = (TV_FIRST + 20);

    /// <summary>
    /// Constants used to identity specific items in the Tree View control
    /// </summary>
    private const int TVGN_ROOT = 0x0;
    private const int TVGN_NEXT = 0x1;
    private const int TVGN_CHILD = 0x4;
    private const int TVGN_FIRSTVISIBLE = 0x5;
    private const int TVGN_NEXTVISIBLE = 0x6;
    private const int TVGN_CARET = 0x9;


    /// <summary>
    /// Calling this method is identical to calling the ShowDialog method of the provided
    /// FolderBrowserDialog, except that an attempt will be made to scroll the Tree View
    /// to make the currently selected folder visible in the dialog window.
    /// </summary>
    /// <param name="dlg"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    public static DialogResult ShowFolderBrowser( FolderBrowserDialog dlg, IWin32Window parent = null )
    {
        DialogResult result = DialogResult.Cancel;
        int retries = 10;

        using (Timer t = new Timer())
        {
            t.Tick += (s, a) =>
            {
                if (retries > 0)
                {
                    --retries;
                    IntPtr hwndDlg = FindWindow((string)null, _topLevelSearchString);
                    if (hwndDlg != IntPtr.Zero)
                    {
                        IntPtr hwndFolderCtrl = GetDlgItem(hwndDlg, _dlgItemBrowseControl);
                        if (hwndFolderCtrl != IntPtr.Zero)
                        {
                            IntPtr hwndTV = GetDlgItem(hwndFolderCtrl, _dlgItemTreeView);

                            if (hwndTV != IntPtr.Zero)
                            {
                                IntPtr item = SendMessage(hwndTV, (uint)TVM_GETNEXTITEM, new IntPtr(TVGN_CARET), IntPtr.Zero);
                                if (item != IntPtr.Zero)
                                {
                                    SendMessage(hwndTV, TVM_ENSUREVISIBLE, IntPtr.Zero, item);
                                    retries = 0;
                                    t.Stop();
                                }
                            }
                        }
                    }
                }

                else
                {
                    //
                    //  We failed to find the Tree View control.
                    //
                    //  As a fall back (and this is an UberUgly hack), we will send
                    //  some fake keystrokes to the application in an attempt to force
                    //  the Tree View to scroll to the selected item.
                    //
                    t.Stop();
                    SendKeys.Send("{TAB}{TAB}{DOWN}{DOWN}{UP}{UP}");
                }
            };

            t.Interval = 10;
            t.Start();

            result = dlg.ShowDialog( parent );
        }

        return result;
    }
}
于 2013-03-15T19:46:30.557 に答える
11

このスレッドがかなり古いことは知っていますが、拡張メソッドを使用すると、これを FolderBrowserDialog.ShowDialog メソッドに追加して、必要に応じて繰り返し使用できます。

サンプル (以下) は、簡単な SendKeys メソッドを使用しているだけです (これは嫌いですが、この場合はうまく機能します)。SendKeys メソッドを使用してダイアログで選択したフォルダーにジャンプする場合、これを Visual Studio でデバッグしている場合、SendKeys 呼び出しは現在のウィンドウ (アクティブな VS ウィンドウ) に適用されます。確実性を高め、間違ったウィンドウが SendKeys メッセージを取得するのを避けるために、拡張メソッドには、Marc F が投稿したものと同様の特定のウィンドウにメッセージを送信するための外部メソッド呼び出しが含まれますが、C# に変換されます。

internal static class FolderBrowserDialogExtension
{
    public static DialogResult ShowDialog(this FolderBrowserDialog dialog, bool scrollIntoView)
    {
        return ShowDialog(dialog, null, scrollIntoView);
    }

    public static DialogResult ShowDialog(this FolderBrowserDialog dialog, IWin32Window owner, bool scrollIntoView)
    {
        if (scrollIntoView)
        {
            SendKeys.Send("{TAB}{TAB}{RIGHT}");
        }

        return dialog.ShowDialog(owner);
    }
}
于 2016-09-10T04:07:21.227 に答える
9

https://www.daniweb.com/software-development/csharp/threads/300578/folderbrowserdialog-expanding-the-selected-directory-の回避策を使用しました

FolderBrowserDialog^ oFBD = gcnew FolderBrowserDialog;
oFBD->RootFolder = Environment::SpecialFolder::MyComputer;
oFBD->SelectedPath = i_sPathImport;
oFBD->ShowNewFolderButton = false;     // use if appropriate in your application
SendKeys::Send ("{TAB}{TAB}{RIGHT}");  // <<-- Workaround
::DialogResult oResult = oFBD->ShowDialog ();

それは最も良い方法ではありませんが、私にとってはうまくいきます。
がないRootFolderと、最初の呼び出しでは機能しませんが、2 回目以降は機能しません。それで、それは常に動作します。

この失敗はオペレーティング システムに依存していることを他の人が観察しているように:
私は Win 7 Pro x64 SP1 を使用しています。

于 2015-04-17T06:25:41.463 に答える
8

VB.Net コードでは、ダイアログを表示する直前にこのコード行を配置してください。

SendKeys.Send ("{TAB}{TAB}{RIGHT}")
于 2016-08-08T18:21:39.970 に答える
3

別のフォーラムで、SelectedPath と RootFolder は相互に排他的であるため、RootFolder が原因である可能性があることを読みました。つまり、両方が共存できないことを意味しますが、デフォルトの RootFolder(.Desktop) では、少なくともツリーを登ることができます (ドライブをナビゲートします)。 /フォルダ)。

ただし、RootFolder を Desktop 以外に変更すると、UNC パスに移動できなくなります。

Hans Passant への回答: TextBox を備えたこのダイアログ拡張機能を試しましたが、うまくいきませんでした。

フォルダの参照ダイアログをカスタマイズしてパスを表示する

于 2011-08-05T06:25:31.890 に答える
3

私はそれを発見しました:

  1. .SelectedPath「\」で終わる場合、ダイアログは下にスクロールしてパスを表示します。
  2. 「\」で終わらない場合.SelectedPath、パスは選択されたままですが、確実に表示されるわけではありません。
于 2015-01-12T09:44:13.927 に答える
2

VB.NET で何かを計算したので、C# に変換するのは簡単です。私はフランス人で、VB の初心者です。とにかく、あなたは私の解決策を試すことができます。

私の考えは、を表示する直前に非同期タスクを起動すること folderBrowserDialogです。

私はこれを自分で見つけましたが、Brad の投稿に触発されました。これが私のコードです:

Imports System.Threading.Tasks
Imports Microsoft.VisualBasic.FileIO.FileSystem

Public Enum GW
    HWNDFIRST = 0
    HWNDLAST = 1
    HWNDNEXT = 2
    HWNDPREV = 3
    OWNER = 4
    CHILD = 5
    ENABLEDPOPUP = 6
End Enum

Public Declare Function SendMessageW Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As UInteger, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As IntPtr
Public Declare Function FindWindowExW Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal wCmd As Long) As Long
Public Declare Function GetDesktopWindow Lib "user32" () As IntPtr
Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer

Private Sub FolderBrowserDialog_EnsureVisible(FB As FolderBrowserDialog, _Owner As IntPtr)
    Dim hwnd As IntPtr
    Dim sClassname As New System.Text.StringBuilder(256)
    Thread.Sleep(50)                                     'necessary to let FolderBrowserDialog construct its window
    hwnd = GetDesktopWindow()                            'Desktop window handle.
    hwnd = GetWindow(hwnd, GW.CHILD)                     'We will find all children.
    Do Until hwnd = 0
        If GetWindow(hwnd, GW.OWNER) = _Owner Then       'If one window is owned by our main window...
            GetClassName(hwnd, sClassname, 255)
            If sClassname.ToString = "#32770" Then       'Check if the class is FolderBrowserDialog.
                Exit Do                                  'Then we found it.
            End If
        End If
        hwnd = GetWindow(hwnd, GW.HWNDNEXT)              'Next window.
    Loop                                                 'If no found then exit.
    If hwnd = 0 Then Exit Sub
    Dim hChild As IntPtr = 0
    Dim hTreeView As IntPtr = 0
    Dim i As Integer = 0
    Do
        i += 1
        If i > 1000 Then Exit Sub                                       'Security to avoid infinite loop.
        hChild = FindWindowExW(hwnd, hChild, Nothing, Nothing)          'Look for children windows of FolderBrowserDialog.
        hTreeView = FindWindowExW(hChild, 0, "SysTreeView32", Nothing)  'Look for treeview of FolderBrowserDialog.
        Thread.Sleep(5)                                                 'delay necessary because FolderBrowserDialog is in construction, then treeview maybe not yet exist.
    Loop While hTreeView = 0
    If SendMessageW(hwnd, &H46A, 1, FB.SelectedPath) = 0 Then           'Send message BFFM_SETEXPANDED to FolderBrowserDialog.
        SendMessageW(hTreeView, &H7, 0, Nothing)                        'Send message WM_SETFOCUS to the treeeview.
    End If
End Sub


Dim My_save_dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "\My-Saves"

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim FolderBrowserDialog1 As New FolderBrowserDialog
    FolderBrowserDialog1.Description = "Choose your save files path."
    If Directory.Exists(My_save_dir) Then
        FolderBrowserDialog1.SelectedPath = My_save_dir
    Else
        FolderBrowserDialog1.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    End If

    Dim Me_handle = Me.Handle         'Store the main handle to compare after with each windows owner.
    Task.Run(Sub() FolderBrowserDialog_EnsureVisible(FolderBrowserDialog1, Me_handle))      'Here's the trick, run an asynchronous task to modify the folderdialog.
    If FolderBrowserDialog1.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then
        My_save_dir = FolderBrowserDialog1.SelectedPath
    End If
End Sub

あなたの提案を待っています。私は C# を知らないので、誰かがそれを C# に翻訳できます。

于 2015-07-11T19:50:30.033 に答える
1

上記の議論と解決策を読みました。特に Brat Oestreicher は私を正しい方向に導いてくれました。本質的には、最初にダイアログで TreeView コントロールを見つけ、SHBrowseForFolderそのウィンドウにTVM_ENSUREVISIBLEメッセージを送信する必要があります。以下は C でこれを行います。

#include <windows.h>
#include <objbase.h>
#include <objidl.h>
#include <Shlobj.h>
#include <Dsclient.h>
#include <wchar.h>
// 
//  EnumCallback - Callback function for EnumWindows 
// 
static BOOL CALLBACK EnumCallback(HWND hWndChild, LPARAM lParam)
{
   char szClass[MAX_PATH];
   HTREEITEM hNode;
   if (GetClassName(hWndChild, szClass, sizeof(szClass))
   &&  strcmp(szClass,"SysTreeView32")==0) {
      hNode = TreeView_GetSelection(hWndChild);    // found the tree view window
      TreeView_EnsureVisible (hWndChild, hNode);   // ensure its selection is visible
      return(FALSE);   // done; stop enumerating
   }
   return(TRUE);       // continue enumerating
}
// 
//  BrowseCallbackProc - Callback function for SHBrowseForFolder 
// 
static INT CALLBACK BrowseCallbackProc (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 
{
    switch (uMsg) 
    { 
        case BFFM_INITIALIZED:
            SendMessage (hWnd, BFFM_SETEXPANDED, TRUE, lpData);    // expand the tree view
            SendMessage (hWnd, BFFM_SETSELECTION, TRUE, lpData);   // select the item
            break;
        case BFFM_SELCHANGED:
            EnumChildWindows(hWnd, EnumCallback,0);
            break;
    } 
    return 0; 
} 
// 
//  SelectDirectory - User callable entry point 
// 
int SelectDirectory (HWND hWndParent, char *path, int pathSize) 
{ 
    BROWSEINFO bi = {0};
    LPITEMIDLIST pidl = NULL;
    wchar_t ws[MAX_PATH];

    CoInitialize(0);
    if (pathSize < MAX_PATH) return(FALSE);

    swprintf(ws, MAX_PATH, L"%hs", path);

    bi.hwndOwner = hWndParent; 
    bi.lpszTitle = "Select Directory"; 
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
    bi.lpfn = BrowseCallbackProc;
    bi.lParam = (LPARAM) ws;

    pidl = SHBrowseForFolder (&bi); 
    if (pidl != NULL) 
    { 
        LPMALLOC pMalloc = NULL; 
        SHGetPathFromIDList (pidl, path);
        path[pathSize-1]= '\0';

        SHGetMalloc(&pMalloc);
        pMalloc->lpVtbl->Free(pMalloc,pidl);    // deallocate item 
        pMalloc->lpVtbl->Release(pMalloc);

        return (TRUE);
    } 
    return (FALSE);
} 

Gary Beeneに感謝します。

于 2018-01-18T16:56:45.777 に答える
0

このリンクには、私にとってはうまくいった簡単な答えがあります(私は窓を持っています8.1

FolderBrowserDialog: 選択したディレクトリの展開

于 2014-03-18T00:08:44.813 に答える
0

dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

と同じではありません

dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;

SpecialFolder.Desktop と SpecialFolder.DesktopDirectory の違いは何ですか?

リンクされたスレッドは、パスとして同じ結果が得られることを示しています。ただし、1 つは論理パスで、もう 1 つは物理パスであるため、同じではありません。

いずれかがフォルダーを開くダイアログの RootFolder に割り当てられている場合、結果の動作が異なる可能性があることがわかりました。

.RootFolder の割り当てとして、win7 などの一部のバージョンの Windows は、いずれかを「デスクトップ」として扱います。つまり、「コンピュータ」サブエントリが表示され、それを開いて個々のドライブ文字を表示できます。.SelectedPath はいずれかの方法で選択されますが、選択されたパスは、デスクトップの論理パスが .RootFolder に割り当てられている場合にのみ表示されます。

さらに悪いことに、win10 プレリリースでフォルダーの参照ダイアログを使用すると、「DesktopDirectory」はデスクトップ ディレクトリの内容のみであり、論理デスクトップ ディレクトリへのリンクはまったくないように見えます。その下にサブアイテムをリストしません。win7 用に作成されたアプリを win10 で使用しようとすると、非常にイライラします。

OPが抱えている問題は、論理デスクトップを使用する必要があるときに、物理デスクトップをルートとして使用したことだと思います。

OPの2つの異なるマシンの応答が異なる理由については説明がありません。2 つの異なるバージョンの .NET フレームワークがインストールされていると推測できます。

win10 プレリリースでフォルダーの参照ダイアログが「デスクトップにスタックする」問題があるのは、win10 プレリリースに同梱されている最新の .NET フレームワークが原因である可能性があります。残念ながら、私はまだ更新していないため、この (win10) ケースのすべての事実を知らないままです。

PS win8でも「デスクトップで立ち往生」の症状が発生することがわかりました。

https://superuser.com/questions/869928/windows-8-1-folder-selection-dialog-missing-my-computer-and-sub-items

そこでの回避策は、win8 で代替 GUI を選択することでした。おそらく、win10プレリリースでも同様のことができるでしょう。

于 2015-06-27T18:31:39.587 に答える
0

Marc F の投稿に応えて - VB.Net を C# に変換しました

    public enum GW
    {
        HWNDFIRST = 0,
        HWNDLAST = 1,
        HWNDNEXT = 2,
        HWNDPREV = 3,
        OWNER = 4,
        CHILD = 5,
        ENABLEDPOPUP = 6
    }

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessageW", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr SendMessageW(IntPtr hWnd, uint msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindowExW", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr FindWindowExW(IntPtr hWndParent, IntPtr hWndChildAfter, [MarshalAs(UnmanagedType.LPWStr)] string lpszClass, [MarshalAs(UnmanagedType.LPWStr)] string lpszWindow);
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetWindow", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern UInt32 GetWindow(IntPtr hwnd, UInt32 wCmd);
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetDesktopWindow", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetDesktopWindow();
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetClassNameA", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int GetClassName(IntPtr hwnd, System.Text.StringBuilder lpClassName, int nMaxCount);

    private void FolderBrowserDialog_EnsureVisible(FolderBrowserDialog FB, IntPtr _Owner)
    {
        IntPtr hwnd = System.IntPtr.Zero;
        System.Text.StringBuilder sClassname = new System.Text.StringBuilder(256);
        Thread.Sleep(50); //necessary to let FolderBrowserDialog construct its window
        hwnd = GetDesktopWindow(); //Desktop window handle.
        hwnd = (System.IntPtr)GetWindow(hwnd, (UInt32)GW.CHILD); //We will find all children.
        while (!(hwnd == (System.IntPtr)0))
        {
            if (GetWindow(hwnd, (UInt32)GW.OWNER) == (UInt32)_Owner) //If one window is owned by our main window...
            {
                GetClassName(hwnd, sClassname, 255);
                if (sClassname.ToString() == "#32770") //Check if the class is FolderBrowserDialog.
                {
                    break; //Then we found it.
                }
            }
            hwnd = (System.IntPtr)GetWindow(hwnd, (UInt32)GW.HWNDNEXT); //Next window.
        } //If no found then exit.
        if (hwnd == (System.IntPtr)0)
        {
            return;
        }
        IntPtr hChild = (System.IntPtr)0;
        IntPtr hTreeView = (System.IntPtr)0;
        int i = 0;
        do
        {
            i += 1;
            if (i > 1000) //Security to avoid infinite loop.
            {
                return;
            }
            hChild = FindWindowExW(hwnd, hChild, null, null); //Look for children windows of FolderBrowserDialog.
            hTreeView = FindWindowExW(hChild, (System.IntPtr)0, "SysTreeView32", null); //Look for treeview of FolderBrowserDialog.
            Thread.Sleep(5); //delay necessary because FolderBrowserDialog is in construction, then treeview maybe not yet exist.
        } while (hTreeView == (System.IntPtr)0);
        if (SendMessageW(hwnd, 0x46A, 1, FB.SelectedPath) == (System.IntPtr)0) //Send message BFFM_SETEXPANDED to FolderBrowserDialog.
        {
            SendMessageW(hTreeView, 0x7, 0, null); //Send message WM_SETFOCUS to the treeeview.
        }
    }

これをテストし、正常に動作します。System.Runtime.InteropServices、System.Threading、System.Threading.Tasks を必ず参照してください。

于 2018-03-13T02:33:51.390 に答える