net - openfiledialog c#
¿Por qué el cuadro de diálogo FolderBrowserDialog no se desplaza a la carpeta seleccionada? (14)
Calculé algo en VB.NET, por lo que sería fácil transformarlo en C #. Soy francés y soy principiante en VB. De todos modos, puedes probar mi solución.
Mi idea es lanzar una tarea asincrónica justo antes de mostrar la folderBrowserDialog
.
Lo encontré yo mismo, pero me inspiré en la publicación de Brad. Aquí está mi código:
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
Estoy esperando tus sugerencias Y alguien puede traducirlo a C # porque no sé C #.
Como se muestra en esta captura de pantalla, la carpeta seleccionada no está en la vista. Necesita desplazarse hacia abajo para ver la carpeta seleccionada.
El mismo cuadro de diálogo muestra la carpeta seleccionada visible en una computadora diferente
Lo ejecuté en dos computadoras que tienen Windows 7. Funciona correctamente en una, pero no en la 2da. ¿Se ve algo con el entorno de Windows en lugar de un problema de código? ¿Alguien puede sugerir alguna solución?
No hay cambio en el código. Utilicé rutas más largas desde diferentes unidades, pero los resultados son los mismos.
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 ();
}
}
El mejor enfoque, al menos el más confiable es crear su propio cuadro de diálogo de clase del navegador. El problema del desplazamiento de árboles ha sido un problema durante muchos años: ¡nunca se solucionará!
Si sabes cómo renderizar en pintura, no hay mucho que no puedas hacer ... rápido en pintura, esa es otra historia.
El primer lugar que buscaría es el código fuente .Net de código abierto en GitHub, en su versión de .Net preferida, para la clase de diálogo que le interesa mejorar. Es posible que se sorprenda de lo que puede lograr con un poco de esfuerzo y siga adelante. Simplemente duplique el control y la depuración hasta el punto donde ocurre el error y el parche: eso es lo que hace Microsoft, ¡y usted también!
Debido a que este es un hilo antiguo, es posible que nunca se lean las muestras. Haría más desde la publicación si se le pregunta.
Sin embargo, para alguien que busca resolver un problema como el desplazamiento en árbol al directorio "esperado", aquí hay algunos consejos sólidos. Si existe un problema con un control o una biblioteca que no tiene una solución inmediata, cree su propia versión, cuando sea posible, extienda el original y solucione el problema. He mejorado todo, desde la clase Windows.Form.Control hasta las bibliotecas de Win32 con el único propósito de obtener resultados predecibles y precisos.
La buena noticia es que con C # hay mucho control de bajo nivel disponible para lograr casi cualquier objetivo razonable y el es C también.
En el pasado, pasé demasiadas horas buscando una solución a un problema donde si hubiera recreado lo que no funcionaba, habría ahorrado mucho tiempo.
El problema fundamental es una decisión de diseño deficiente en el FolderBrowserDialog
. Primero, debemos darnos cuenta de que el FolderBrowserDialog
no es un control .NET, sino más bien el Common Dialog
y es parte de Windows. El diseñador de este cuadro de diálogo eligió no enviar el control TreeView un mensaje TVM_ENSUREVISIBLE
después de que se muestre el cuadro de diálogo y se seleccione una carpeta inicial. Este mensaje hace que un control TreeView se desplace para que el elemento seleccionado actualmente sea visible en la ventana.
Entonces, todo lo que tenemos que hacer para solucionar esto es enviar el TreeView que es parte del FolderBrowserDialog
el mensaje TVM_ENSUREVISIBLE
y todo será genial. ¿Derecha? Bueno, no tan rápido. Esta es de hecho la respuesta, pero hay algunas cosas que se interponen en nuestro camino.
En primer lugar, porque
FolderBrowserDialog
no es realmente un control .NET, no tiene una colección deControls
internos. Esto significa que no podemos simplemente encontrar y acceder al control secundario TreeView desde .NET.En segundo lugar, los diseñadores de la clase .NET
FolderBrowserDialog
decidieron sellar esta clase. Esta desafortunada decisión nos impide derivar de ella y anular el manejador de mensajes de ventana. Si hubiéramos podido hacer esto, podríamos haber intentado publicar el mensajeTVM_ENSUREVISIBLE
cuando recibimos el mensajeWM_SHOWWINDOW
en el controlador de mensajes.El tercer problema es que no podemos enviar el mensaje
TVM_ENSUREVISIBLE
hasta que el control Tree View realmente exista como una ventana real, y no existe hasta que no llamemos al métodoShowDialog
. Sin embargo, este método bloquea, por lo que no tendremos la oportunidad de publicar nuestro mensaje una vez que se llame a este método.
Para evitar estos problemas, creé una clase auxiliar estática con un único método que se puede utilizar para mostrar un FolderBrowserDialog
, y hará que se desplace a la carpeta seleccionada. Administro esto iniciando un Timer
corto justo antes de llamar al método ShowDialog
del diálogo, y luego rastreando el control TreeView
en el controlador Timer
(es decir, después de que se muestra el diálogo) y enviando nuestro mensaje TVM_ENSUREVISIBLE
.
Esta solución no es perfecta porque depende de algunos conocimientos previos sobre el FolderBrowserDialog
. Específicamente, encuentro el diálogo usando su título de ventana. Esto se romperá con instalaciones que no sean en inglés. Localizo los controles secundarios en el diálogo usando sus Id. De artículo de diálogo, en lugar de título o nombre de clase, porque sentí que esto sería más confiable con el tiempo.
Este código ha sido probado en Windows 7 (64 bit) y Windows XP.
Aquí está el código: (Puede necesitar: 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;
}
}
En respuesta a la publicación de Marc F, convertí VB.Net a 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.
}
}
Probó esto y funciona bien. Asegúrese de hacer referencia a System.Runtime.InteropServices, System.Threading, System.Threading.Tasks
Este enlace tiene una respuesta simple que funcionó bien para mí (tengo Windows 8.1
)
He encontrado eso:
- Si
.SelectedPath
termina con "/", el.SelectedPath
diálogo se desplazará hacia abajo para hacer que la ruta sea visible. - Si
.SelectedPath
no termina con "/", la ruta todavía está seleccionada, pero no está asegurada.
He leído la discusión y las soluciones anteriores. Particularmente Brat Oestreicher me puso en la dirección correcta. En esencia, primero debemos encontrar el control TreeView en el SHBrowseForFolder
diálogo SHBrowseForFolder
y enviar esa ventana al mensaje TVM_ENSUREVISIBLE
. Lo siguiente hace esto en 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);
}
Muchas gracias a Gary Beene .
He usado una solución de 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 ();
No es la mejor manera, pero funciona para mí.
Sin RootFolder
NO funciona en la primera llamada, sino en la segunda y siguientes. Con eso, funciona siempre.
Como otros han observado que esta falla depende del sistema operativo:
Estoy usando Win 7 Pro x64 SP1
Leí en diferentes foros que podría deberse a RootFolder porque SelectedPath y RootFolder son mutuamente excluyentes, eso significa que ambos no pueden coexistir, pero con RootFolder (.Desktop) predeterminado, permite, al menos, escalar el árbol (navegar por el disco) / carpetas).
Sin embargo, si RootFolder se cambia a otro que no sea Desktop, no podrá navegar a las rutas UNC.
Respuesta a Hans Passant: Intenté esta extensión de diálogo, que tiene TextBox, pero no tuve suerte.
Personalizar el cuadro de diálogo buscar carpeta para mostrar la ruta
Me encuentro con el mismo problema en c ++ / mfc. Me resultó útil utilizar :: PostMessage en lugar de :: SendMessage en la devolución de llamada BFFM_INITIALIZED para colocar el mensaje TVM_ENSUREVISIBLE
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;
}
Sé que este hilo es WAY viejo, pero con los métodos de extensión, esto se puede agregar al método FolderBrowserDialog.ShowDialog, y luego se usa repetidamente cuando sea necesario.
La muestra (a continuación) solo está utilizando el método fácil SendKeys (que odio hacer, pero en este caso, funciona bien). Al utilizar el método SendKeys para saltar a la carpeta seleccionada en el cuadro de diálogo, si está depurando esto en Visual Studio, la llamada SendKeys se aplica a la ventana actual, que sería la ventana VS activa. Para ser más infalible y evitar que la ventana incorrecta reciba el mensaje SendKeys, el método de extensión contendría las llamadas al método externo para enviar mensajes a la ventana específica similar a lo que publicó Marc F, pero traducido a 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);
}
}
dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;
no es lo mismo que
dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;
¿Cuál es la diferencia entre SpecialFolder.Desktop y SpecialFolder.DesktopDirectory?
El hilo vinculado indica que, como ruta, obtienen el mismo resultado. Pero no son lo mismo, ya que uno es un camino lógico y el otro es un camino físico.
He encontrado que cuando se asigna uno al RootFolder del diálogo de la carpeta abierta, el comportamiento resultante puede ser diferente.
Como asignación de .RootFolder, algunas versiones de Windows, como win7, tratan cualquiera de las dos como "Escritorio". Es decir, puede ver la subentrada "Ordenador" y abrirla para ver las letras de unidad individuales. El .SelectedPath se selecciona de cualquier manera, pero la ruta seleccionada solo se hace visible cuando la ruta lógica del escritorio se asigna a .RootFolder.
Peor aún, al usar el diálogo de la carpeta de exploración en Win10 prelanzamiento, parece que "DesktopDirectory" es solo eso, el contenido del Directorio de escritorio solamente, sin ningún vínculo con el directorio de escritorio lógico. Y no enumerar ningún subtema debajo de él. Muy frustrante si una aplicación escrita para win7 está intentando ser utilizada con win10.
Creo que el problema que tiene el OP es que emplearon el escritorio físico como raíz, cuando deberían haber empleado el escritorio lógico.
No tengo una explicación de por qué las dos máquinas diferentes de OP responden de manera diferente. Me gustaría especular que tienen dos versiones diferentes de .NET Framework instalado.
El hecho de que la presentación previa de win10 tenga el problema "Atascado en el escritorio" con el diálogo de la carpeta de navegación puede deberse al más reciente marco de .NET incluido con la presentación preliminar de win10. Desafortunadamente, sigo ignorando todos los hechos en este caso (win10), ya que aún no lo he actualizado.
PD: encontré que win8 también experimenta el síntoma "Atascado en el escritorio":
La solución alternativa era seleccionar la GUI alternativa en win8. Quizás algo similar se puede hacer en la presentación previa de win10.
en el código VB.Net, simplemente ponga esta línea de código justo antes de mostrar el diálogo.
SendKeys.Send ("{TAB}{TAB}{RIGHT}")
esto funciona para mí
folderBrowserDialog1.Reset();
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = WorkingFolder;
pero solo después del segundo uso del diálogo