Ajuste de la posición de inicio de OpenFileDialog / SaveFileDialog
-
12-09-2019 - |
Pregunta
Para cualquier diálogo personalizado (forma) en una aplicación WinForm puedo fijar su tamaño y posición antes de que exhibo con:
form.StartPosition = FormStartPosition.Manual;
form.DesktopBounds = MyWindowPosition;
Esto es particularmente importante cuando se trata de múltiples monitores. Sin ese código, cuando se abre un cuadro de diálogo desde una aplicación que ha arrastrado a un segundo monitor, aparece el cuadro de diálogo en el monitor principal. Esto presenta una experiencia de usuario pobre.
Me gustaría saber si hay algún ganchos para fijar la posición de la norma .NET OpenFileDialog y SaveFileDialog (que no tienen una propiedad StartPosition).
Solución
Sospecho que lo mejor que puede hacer es asegurarse de que utiliza la sobrecarga de ShowDialog
que acepta un IWin32Window
utilizar como padre. Este podría ayudarla a elegir un lugar apropiado; más comúnmente:
using(var dlg = new OpenFileDialog()) {
.... setup
if(dlg.ShowDialog(this) == DialogResult.OK) {
.... use
}
}
Otros consejos
este artículo en CodeProject. Extracto:
Aquí es cuando la mano .NET NativeWindow entra en la imagen, una NativeWindow es un envoltorio ventana donde que procesa los mensajes enviados por el identificador asociado a la misma. Se crea una NativeWindow y asocia las OpenFileWindow manejar a ella. De esto punto, cada mensaje enviado a OpenFileWindow será redirigido a nuestro propio método WndProc en el NativeWindow lugar, y podemos cancelar, modificar, o dejarlos pasar a través.
En nuestro WndProc, se procesa el mensaje WM_WINDOWPOSCHANGING. Si la apertura de diálogo se abre, entonces cambiaremos la horizontal original o vertical tamaño dependiendo de la StartLocation establecido por el usuario. Se incrementará el tamaño de la ventana que se creará. Esta ocurre sólo una vez cuando el control está abierto.
Además, vamos a procesar el mensaje WM_SHOWWINDOW. En este caso, todos los controles dentro del OpenFileDialog originales se creamos, y vamos a añadir nuestro control del diálogo de archivos abiertos. Esto se hace llamando a una API de Win32 SetParent. Esta API permite cambiar la ventana padre. Entonces, básicamente lo que hace es conectar nuestro control OpenFileDialog a la original en el ubicación se establece en función de la valor de la propiedad StartLocation.
La ventaja de ello es que todavía tener un control completo sobre el controles unido a la OpenFileDialog ventana. Esto significa que puede recibir eventos, llamar a los métodos y hacer lo que queramos con las controles.
he tenido este problema durante la mayor parte del día de ayer. La respuesta de Bobb fue la que me ayudó a cabo la mayor parte (Gracias Bobb).
Usted puede incluso ir tan lejos como para hacer un método privado que crea una ventana y se cierra antes de la llamada al método dialog.ShowDialog()
y todavía centrará el OpenFileDialog
.
private void openFileDialogWindow()
{
Window openFileDialogWindow = new Window();
openFileDialogWindow.Left = this.Left;
openFileDialogWindow.Top = this.Top;
openFileDialogWindow.Width = 0;
openFileDialogWindow.Height = 0;
openFileDialogWindow.WindowStyle = WindowStyle.None;
openFileDialogWindow.ResizeMode = ResizeMode.NoResize;
openFileDialogWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
openFileDialogWindow.Show();
openFileDialogWindow.Close();
openFileDialogWindow = null;
}
A continuación, llamar en cualquier método antes del método ShowDialog()
.
public string SelectWebFolder()
{
string WebFoldersDestPath = null;
CommonOpenFileDialog filePickerDialog = new CommonOpenFileDialog();
// OpenFileDialog Parameters..
openFileDialogWindow();
if (filePickerDialog.ShowDialog() == CommonFileDialogResult.Ok)
{
WebFoldersDestPath = filePickerDialog.FileName + "\\";
}
filePickerDialog = null;
return WebFoldersDestPath;
}
OpenFileDialog y SaveFileDialog posicionarse en la esquina superior izquierda de el área de cliente de la ventana que se muestra más recientemente. Así que simplemente crear una nueva ventana invisible colocado donde desea que el cuadro de diálogo que aparezca antes de crear y mostrar ese diálogo.
Window dialogPositioningWindow = new Window();
dialogPositioningWindow.Left = MainWindow.Left + <left position within main window>;
dialogPositioningWindow.Top = MainWindow.Top + <top position within main window>;
dialogPositioningWindow.Width = 0;
dialogPositioningWindow.Height = 0;
dialogPositioningWindow.WindowStyle = WindowStyle.None;
dialogPositioningWindow.ResizeMode = ResizeMode.NoResize;
dialogPositioningWindow.Show();// OpenFileDialog is positioned in the upper-left corner
// of the last shown window (dialogPositioningWindow)
Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
...
if ((bool)dialog.ShowDialog()){
...
}
dialogPositioningWindow.Close();
Así es como lo hice:
El punto en el que desea mostrar el OpenFileDialog:
Thread posThread = new Thread(positionOpenDialog);
posThread.Start();
DialogResult dr = ofd.ShowDialog();
El código de reposicionamiento:
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
/// <summary>
/// Find the OpenFileDialog window when it appears, and position it so
/// that we can see both dialogs at once. There is no easier way to
/// do this (&^%$! Microsoft!).
/// </summary>
private void positionOpenDialog ()
{
int count = 0;
IntPtr zero = (IntPtr)0;
const int SWP_NOSIZE = 0x0001;
IntPtr wind;
while ((wind = FindWindowByCaption(zero, "Open")) == (IntPtr)0)
if (++count > 100)
return; // Find window failed.
else
Thread.Sleep(5);
SetWindowPos(wind, 0, Right, Top, 0, 0, SWP_NOSIZE);
}
inicio un hilo que busca una ventana con el título "abierto". (Se encuentran típicamente en 3 iteraciones o 15 milisegundos.) Entonces me puse su posición con el mango obtenido. (Consulte la documentación SetWindowPos para los parámetros de posición / tamaño.)
kludgy.
Hay bastante un viejo ejemplo de un enfoque en MSDN.
http://msdn.microsoft.com/en-us/library /ms996463.aspx
Incluye todo el código necesario para implementar su propia clase OpenFileDialog que permite la extensibilidad.
Muy agradecido por la respuesta de Bobb en este caso. Hay algunas "trampas" más. Usted tiene que pasar el mango de PositionForm al llamar OpenFileDialog1.ShowDialog (PositionForm) de lo contrario la técnica de Bobb no es fiable en todos los casos. Además, ahora que W8.1 lanza un nuevo control FileOpen con SkyDrive en ella, la ubicación de la carpeta Documentos en el control W8.1 FileOpen está atornillado. Así que Frig FILEOPEN utilizar el viejo sistema de control mediante el establecimiento de W7 ShowHelp = True.
Este es el código VB.NET que terminé usando, mi contribución a la comunidad en caso de que ayuda.
Private Function Get_FileName() As String
' Gets an Input File Name from the user, works with multi-monitors
Dim OpenFileDialog1 As New OpenFileDialog
Dim PositionForm As New Form
Dim MyInputFile As String
' The FileDialog() opens in the last Form that was created. It's buggy! To ensure it appears in the
' area of the current Form, we create a new hidden PositionForm and then delete it afterwards.
PositionForm.StartPosition = FormStartPosition.Manual
PositionForm.Left = Me.Left + CInt(Me.Width / 2)
PositionForm.Top = Me.Top + CInt(Me.Height / 2)
PositionForm.Width = 0
PositionForm.Height = 0
PositionForm.FormBorderStyle = Forms.FormBorderStyle.None
PositionForm.Visible = False
PositionForm.Show()
' Added the statement "ShowHelp = True" to workaround a problem on W8.1 machines with SkyDrive installed.
' It causes the "old" W7 control to be used that does not point to SkyDrive in error.
OpenFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
OpenFileDialog1.Filter = "Excel files (*.xls*)|*.xls*|CSV Files (*.csv)|*.csv"
OpenFileDialog1.FilterIndex = 1
OpenFileDialog1.RestoreDirectory = True
OpenFileDialog1.AutoUpgradeEnabled = False
OpenFileDialog1.ShowHelp = True
OpenFileDialog1.FileName = ""
OpenFileDialog1.SupportMultiDottedExtensions = False
OpenFileDialog1.Title = "Select an Excel or .csv file containing patent data or list of Publication Numbers for your project."
If OpenFileDialog1.ShowDialog(PositionForm) <> System.Windows.Forms.DialogResult.OK Then
Console.WriteLine("No file was selected. Please try again!")
PositionForm.Close()
PositionForm.Dispose()
OpenFileDialog1.Dispose()
Return ""
End If
PositionForm.Close()
PositionForm.Dispose()
MyInputFile = OpenFileDialog1.FileName
OpenFileDialog1.Dispose()
Return MyInputFile
End Function