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).

Était-ce utile?

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top