Réglage de la position de départ pour OpenFileDialog / SaveFileDialog
-
12-09-2019 - |
Question
Pour tout dialogue personnalisé (formulaire) dans une application WinForm je peux définir sa taille et la position avant de l'afficher avec:
form.StartPosition = FormStartPosition.Manual;
form.DesktopBounds = MyWindowPosition;
Ceci est particulièrement important quand vous utilisez plusieurs moniteurs. Sans un tel code, lorsque vous ouvrez une boîte de dialogue à partir d'une application que vous avez traîné à un second moniteur, la boîte de dialogue apparaît sur le moniteur principal. Cela présente une expérience utilisateur médiocre.
Je me demande s'il y a des crochets pour définir la position de l'OpenFileDialog norme .NET et SaveFileDialog (qui ne dispose pas d'une propriété StartPosition).
La solution
Je pense que le mieux que vous pouvez faire est de vous assurer que vous utilisez le surcharge de ShowDialog
qui accepte un IWin32Window
à utiliser comme parent. Cette peut l'aider à choisir un endroit approprié; le plus souvent:
using(var dlg = new OpenFileDialog()) {
.... setup
if(dlg.ShowDialog(this) == DialogResult.OK) {
.... use
}
}
Autres conseils
Consultez cet article sur CodeProject. Extrait:
Voici quand le .NET pratique NativeWindow est dans l'image, un NativeWindow est une enveloppe de fenêtre où il traite les messages envoyés par le poignée qui lui est associée. Il crée un NativeWindow et associe les OpenFileWindow gérer à elle. de cette le point, chaque message envoyé à OpenFileWindow seront redirigés vers notre propre méthode WndProc dans la NativeWindow à la place, et nous pouvons annuler, de modifier, ou les laisser passer à travers.
Dans notre WndProc, nous traitons le message WM_WINDOWPOSCHANGING. Si l'ouverture dialogue ouvre, nous allons changer l'horizontale ou verticale d'origine taille en fonction de la StartLocation défini par l'utilisateur. Il incrémenter la taille de la fenêtre à créer. Cette il arrive qu'une seule fois lorsque le contrôle est ouvert.
En outre, nous traiterons le message WM_SHOWWINDOW. Ici, tous les contrôles à l'intérieur du OpenFileDialog d'origine sont créé, et nous allons ajouter notre contrôle à la boîte de dialogue de fichier ouvert. Cela se fait en appelant une API Win32 SetParent. Cette API vous permet de changer la fenêtre parent. Puis, au fond ce qu'il fait est attacher notre contrôle à l'origine dans le OpenFileDialog emplacement il se couche, selon la valeur de la propriété StartLocation.
L'avantage de ce que nous avons encore ont un contrôle complet sur la contrôle attaché à la fenêtre OpenFileDialog. Cela signifie que nous peuvent recevoir des événements, appeler des méthodes et faisons tout ce que nous voulons avec les commandes.
J'ai eu ce problème pour la plupart d'hier. La réponse de Bobb a été celui qui m'a aidé le plus (Merci Bobb).
Vous pouvez même aller aussi loin que de faire une méthode privée qui crée une fenêtre et il se ferme avant que la méthode dialog.ShowDialog()
appel et il sera toujours le centre 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;
}
Ensuite, appelez dans toute méthode avant que la méthode 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 et SaveFileDialog se positionner dans le coin supérieur gauche de la zone client de la fenêtre la plus récente affichée. Il suffit donc de créer une nouvelle fenêtre invisible repositionnés vous voulez que la boîte de dialogue apparaisse avant de créer et de montrer cette boîte de dialogue.
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();
Voici comment je l'ai fait:
Le point où je veux afficher le OpenFileDialog:
Thread posThread = new Thread(positionOpenDialog);
posThread.Start();
DialogResult dr = ofd.ShowDialog();
Le code de repositionnement:
[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);
}
Je commence un thread qui recherche une fenêtre avec le titre « Open ». (En général trouvé en 3 itérations ou 15 millisecondes.) Ensuite, je définir sa position avec le manche obtenu. (Voir la documentation SetWindowPos pour les paramètres de position / taille.)
kludgy.
Il est tout à fait un vieil exemple d'approche sur MSDN.
http://msdn.microsoft.com/en-us/library /ms996463.aspx
Il comprend tout le code nécessaire pour implémenter votre propre classe OpenFileDialog qui permet l'extensibilité.
Très reconnaissant pour la réponse de Bobb sur celui-ci. Il y a quelques « trucs ». Vous devez passer la poignée de PositionForm lorsque vous appelez OpenFileDialog1.ShowDialog (PositionForm), sinon la technique de Bobb n'est pas fiable dans tous les cas. En outre, maintenant que W8.1 lance un nouveau contrôle fileopen avec SkyDrive en elle, l'emplacement du dossier Documents dans le contrôle W8.1 de fileopen est maintenant vissé. Donc, je branler fileOpen d'utiliser l'ancien contrôle W7 en réglant ShowHelp = True.
Voici le code VB.NET je fini par utiliser, ma contribution à la communauté au cas où il aide.
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