このスクリーンショットに示すように、選択したフォルダーはビューにありません。選択したフォルダーを表示するには、下にスクロールする必要があります。
同じダイアログで、選択したフォルダーが別のコンピューターに表示される
両方とも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 ();
}
}
基本的な問題は、FolderBrowserDialog
での不十分な設計決定です。まず、FolderBrowserDialog
は.NETコントロールではなく、Common Dialog
であり、Windowsの一部であることを認識する必要があります。このダイアログのデザイナーは、ダイアログが表示され、初期フォルダーが選択された後、TreeViewコントロールにTVM_ENSUREVISIBLE
メッセージを送信しないことを選択しました。このメッセージにより、TreeViewコントロールがスクロールされ、現在選択されているアイテムがウィンドウに表示されます。
したがって、これを修正するために必要なことは、FolderBrowserDialog
the TVM_ENSUREVISIBLE
メッセージの一部であるTreeViewを送信することだけです。右?まあ、それほど速くありません。これは確かに答えですが、私たちの邪魔になるものがいくつかあります。
まず、FolderBrowserDialog
は実際には.NETコントロールではないため、内部Controls
コレクションがありません。つまり、.NETからTreeView子コントロールを見つけてアクセスすることはできません。
次に、.NET FolderBrowserDialog
クラスの設計者は、このクラスをsealに決定しました。この不幸な決定により、そこから派生してウィンドウメッセージハンドラをオーバーライドすることができなくなります。これを行うことができた場合、メッセージハンドラでTVM_ENSUREVISIBLE
メッセージを取得したときに、WM_SHOWWINDOW
メッセージを投稿しようとした可能性があります。
3番目の問題は、ツリービューコントロールが実際のウィンドウとして実際に存在するまでTVM_ENSUREVISIBLE
メッセージを送信できず、ShowDialog
メソッドを呼び出すまで存在しないことです。ただし、このメソッドはブロックされるため、このメソッドが呼び出された後にメッセージを投稿する機会はありません。
これらの問題を回避するために、FolderBrowserDialog
を表示するために使用できる単一のメソッドを持つ静的ヘルパークラスを作成し、選択したフォルダーまでスクロールさせます。これを管理するには、ダイアログのTimer
メソッドを呼び出す直前に短いShowDialog
を開始し、TreeView
内のTimer
コントロールのハンドルを追跡します。ハンドラー(ダイアログが表示された後)およびTVM_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;
}
}
私はこのスレッドが非常に古いことを知っていますが、拡張メソッドを使用すると、これを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);
}
}
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を使用しています
vB.Netコードでは、ダイアログを表示する直前にこのコード行を置くだけです。
SendKeys.Send ("{TAB}{TAB}{RIGHT}")
SelectedPathとRootFolderは相互に排他的であるため、RootFolderが原因である可能性があることを別のフォーラムで読んでいます。つまり、両方は共存できませんが、デフォルトのRootFolder(。/folders)。
ただし、RootFolderをデスクトップ以外に変更すると、UNCパスに移動できなくなります。
Hans Passantへの回答:私はこのDialog Extensionを試しました。これにはTextBoxがありますが、運はありません。
私はそれを見つけました:
.SelectedPath
が「\」で終わる場合、ダイアログは下にスクロールしてパスを表示します。.SelectedPath
の末尾が「\」ではないため、パスは選択されたままですが、表示されているとは限りません。VB.NETで計算したので、C#に簡単に変換できます。私はフランス人で、VBの初心者です。とにかく、あなたは私の解決策を試すことができます。
私のアイデアは、folderBrowserDialog
を表示する直前に非同期タスクを起動することです。
私はこれを自分で見つけましたが、ブラッドの投稿に触発されました。私のコードは次のとおりです。
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#に翻訳できます。
C++/mfcでも同じ問題が発生します。 TVF_ENSUREVISIBLE msgを配置するために、BFFM_INITIALIZEDコールバックで:: SendMessageではなく:: PostMessageを使用することができました
case BFFM_INITIALIZED:
{
// select something
::SendMessage(m_hDialogBox, BFFM_SETSELECTION, TRUE, (LPARAM) pszSelection);
// find tree control
m_hTreeCtrl = 0;
HWND hchild = GetWindow(hWnd, GW_CHILD) ;
while (hchild != NULL)
{
VS_TChar classname[200] ;
GetClassName(hchild, classname, 200) ;
if (VS_strcmp(classname, _T("SHBrowseForFolder ShellNameSpace Control")) == 0)
{
HWND hlistctrl = GetWindow(hchild, GW_CHILD) ;
do
{
GetClassName(hlistctrl, classname, 200) ;
if (lstrcmp(classname, _T("SysTreeView32")) == 0)
{
m_hTreeCtrl = hlistctrl;
break ;
}
hlistctrl = GetWindow(hlistctrl, GW_HWNDNEXT) ;
} while (hlistctrl != NULL);
}
if (m_hTreeCtrl)
break;
hchild = GetWindow(hchild, GW_HWNDNEXT);
}
if (m_hTreeCtrl)
{
int item = ::SendMessage(m_hTreeCtrl, TVM_GETNEXTITEM, TVGN_CARET, 0);
if (item != 0)
::PostMessage(m_hTreeCtrl, TVM_ENSUREVISIBLE,0,item);
}
break;
}
上記の議論と解決策を読みました。特にBrat Oestreicherは私を正しい方向に導いた。本質的に、最初にSHBrowseForFolder
ダイアログでTreeViewコントロールを見つけ、そのウィンドウに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 に感謝します。
このリンクには簡単に答えられる答えがあります(Windowsがあります8.1
)
dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;
とは異なります
dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;
SpecialFolder.DesktopとSpecialFolder.DesktopDirectoryの違いは何ですか?
リンクされたスレッドは、パスとして同じ結果が得られることを示しています。ただし、1つは論理パスであり、もう1つは物理パスであるため、両者は同じではありません。
どちらかがフォルダーを開くダイアログのRootFolderに割り当てられている場合、結果の動作が異なることがあります。
.RootFolder割り当てとして、win7などの一部のバージョンのウィンドウは、どちらかを「デスクトップ」として扱います。つまり、「コンピューター」サブエントリを表示し、それを開いて個々のドライブ文字を表示できます。 .SelectedPathはどちらの方法でも選択されますが、選択されたパスは、デスクトップの論理パスが.RootFolderに割り当てられている場合にのみ表示されます。
さらに悪いことに、win10プレリリースでフォルダーの参照ダイアログを使用すると、「DesktopDirectory」がデスクトップディレクトリのコンテンツのみであり、論理デスクトップディレクトリへのリンクはまったくないように見えます。そして、その下のサブアイテムをリストしません。 win7用に作成されたアプリをwin10で使用しようとすると、非常にイライラします。
OPが抱えている問題は、論理デスクトップを使用すべきだったときに、ルートとして物理デスクトップを使用したことです。
OPの2つの異なるマシンが異なる応答をする理由については説明がありません。私は彼らがインストールされている.NETフレームワークの2つの異なるバージョンを持っていると推測します。
Win10プレリリースに[フォルダーの参照]ダイアログに「デスクトップでスタック」問題があるという事実は、win10プレリリースに同梱されている最新の.NETフレームワークが原因である可能性があります。残念ながら、私はまだ更新していないので、この(win10)ケースのすべての事実について無知のままです。
追伸win8でも「デスクトップでスタック」という症状が発生することがわかりました。
そこでの回避策は、win8で代替GUIを選択することでした。おそらく、win10プレリリースでも同様のことができます。
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を参照してください。
これは私のために働く
folderBrowserDialog1.Reset();
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = WorkingFolder;
ただし、ダイアログを2回使用した後のみ