Domanda

Per ogni finestra di dialogo personalizzata (form) in un'applicazione WinForm posso impostare la sua dimensione e la posizione prima che io lo mostro con:

form.StartPosition = FormStartPosition.Manual;
form.DesktopBounds = MyWindowPosition;

Ciò è particolarmente importante quando si tratta di più monitor. Senza tale codice, quando si apre una finestra di dialogo da un'applicazione che si è trascinato per un secondo monitor, viene visualizzata la finestra sul monitor principale. Questo presenta una scarsa esperienza utente.

Mi chiedo se ci sono dei ganci per impostare la posizione per l'OpenFileDialog .NET standard ed SaveFileDialog (che non hanno una proprietà StartPosition).

È stato utile?

Soluzione

Ho il sospetto che la cosa migliore che puoi fare è assicurarsi di utilizzare la sovraccarico di ShowDialog che accetta un IWin32Window da utilizzare come genitore. Questo potrebbe aiutarla a scegliere un luogo adatto; più comunemente:

using(var dlg = new OpenFileDialog()) {
    .... setup
    if(dlg.ShowDialog(this) == DialogResult.OK) {
        .... use
    }
}

Altri suggerimenti

questo articolo su CodeProject. Estratto:

  

Qui è quando il pratico .NET   NativeWindow entra in scena, un   NativeWindow è un wrapper finestra in cui   elabora i messaggi inviati dal   maniglia associata ad esso. Esso crea un   NativeWindow e associa i   OpenFileWindow gestire ad esso. Da questo   punto, ogni messaggio inviato a   OpenFileWindow verrà reindirizzati alla   il nostro metodo di WndProc nella   NativeWindow invece, e siamo in grado di   annullare, modificare, o farli passare   attraverso.

     

Nel nostro WndProc, elaboriamo il messaggio   WM_WINDOWPOSCHANGING. Se il aperta   finestra di dialogo si apre, quindi cambieremo   orizzontale o verticale originale   dimensioni a seconda della StartLocation   impostato dall'utente. Si incrementa il   dimensione della finestra da creare. Questo   accade solo una volta quando il controllo è   aperto.

     

Inoltre, provvederemo a elaborare il messaggio   WM_SHOWWINDOW. Qui, tutti i controlli   all'interno del OpenFileDialog originale sono   creato, e stiamo per accodare   il nostro controllo alla finestra di dialogo file aperto.   Questo viene fatto chiamando l'API Win32   SetParent. Questa API consente di cambiare   la finestra padre. Poi, in fondo   ciò che fa è collegare il nostro controllo   all'originale OpenFileDialog in   posizione ha fissato, a seconda della   valore della proprietà StartLocation.

     

Il vantaggio di questo è che abbiamo ancora   avere il controllo completo sul   controlli attaccato al   finestra OpenFileDialog. Ciò significa che   può ricevere eventi, chiamare i metodi, e   fare quello che vogliamo con quelli   controlli.

Ho avuto questo problema per la maggior parte di ieri. La risposta di Bobb è stato quello che mi ha aiutato di più (Grazie Bobb).

Si può anche andare fino al punto di rendere un metodo privato che crea una finestra e la chiude prima della chiamata al metodo dialog.ShowDialog() e sarà ancora centrare il 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;
}

Poi chiamare in qualsiasi metodo prima del metodo 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 e SaveFileDialog posizionarsi nell'angolo superiore sinistro l'area client della finestra visualizzata più di recente. Quindi, basta creare una nuova finestra invisibile posizionato dove si desidera che la finestra di dialogo per comparire prima di creare e mostrando che dialogo.

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();

Ecco come ho fatto:

Il punto in cui voglio visualizzare l'OpenFileDialog:

Thread posThread = new Thread(positionOpenDialog);
posThread.Start();

DialogResult dr = ofd.ShowDialog();

Il codice di riposizionamento:

[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);
}

I avviare un thread che cerca una finestra con il titolo "Open". (Tipicamente trovati in 3 iterazioni o 15 millisecondi). Poi ho impostato la sua posizione con la maniglia ricavata. (Vedere la documentazione SetWindowPos per i parametri di posizione / dimensioni.)

kludgy.

C'è piuttosto un vecchio esempio di un approccio su MSDN.

http://msdn.microsoft.com/en-us/library /ms996463.aspx

Esso include tutto il codice necessario per implementare la propria classe OpenFileDialog che permette di estensibilità.

Molto grato per la risposta di Bobb su questo. Ci sono un paio di "trucchi". Devi passare il manico di PositionForm quando si chiama OpenFileDialog1.ShowDialog (PositionForm) altrimenti la tecnica di Bobb non è affidabile in tutti i casi. Inoltre, ora che W8.1 lancia un nuovo controllo FileOpen con SkyDrive in esso, la posizione della cartella Documenti nel controllo W8.1 FileOpen è ormai avvitata. Così ho FRIG FileOpen ad usare il vecchio controllo W7 impostando ShowHelp = True.

Ecco il codice VB.NET ho finito per usare, il mio contributo alla comunità in caso aiuta.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top