代码之家  ›  专栏  ›  技术社区  ›  Michael Sorens

设置openfiledialog/savefiledialog的起始位置

  •  21
  • Michael Sorens  · 技术社区  · 16 年前

    对于WinForm应用程序中的任何自定义对话框(窗体),我可以在显示它之前设置其大小和位置:

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

    这在处理多个监视器时尤其重要。如果没有这些代码,当您从已拖动到第二个监视器的应用程序中打开一个对话框时,该对话框将显示在主监视器上。这会带来糟糕的用户体验。

    我想知道是否有钩子来设置标准.NET OpenFileDialog和SaveFileDialog(没有StartPosition属性)的位置。

    7 回复  |  直到 8 年前
        1
  •  4
  •   Marc Gravell    16 年前

    我怀疑你能做的最好是确保你使用 overload of ShowDialog 接受一个 IWin32Window 用作父级。这个 可以 帮助它选择合适的位置;最常见的是:

    using(var dlg = new OpenFileDialog()) {
        .... setup
        if(dlg.ShowDialog(this) == DialogResult.OK) {
            .... use
        }
    }
    
        2
  •  4
  •   Charlie    16 年前

    退房 this article 在代码项目上。Excerpt:

    这是当handy.net NativeWindow出现在图片中, NativeWindow是一个窗口包装器,其中 它处理由 与之关联的句柄。它创造了一个 NativeWindow和Associates 它的OpenFileWindow句柄。从这个 点,发送到的每条消息 OpenFileWindow将被重定向到 我们自己的wndproc方法 相反,我们可以 取消、修改或让他们通过 通过。

    在我们的wndproc中,我们处理消息 wm_windowposchanging.如果打开 对话正在打开,然后我们将更改 原始水平或垂直 大小取决于惊吓位置 由用户设置。它将增加 要创建的窗口的大小。这个 当控件为 开的。

    另外,我们将处理消息 显示窗口。这里,所有控件 原始OpenFileDialog中有 创建,我们将附加 打开文件对话框的控件。 这是通过调用Win32 API来完成的。 父母们。此API允许您更改 父窗口。那么,基本上 它的作用是附加我们的控制 到原始的OpenFileDialog 设置的位置,取决于 StartLocation属性的值。

    它的优点是我们仍然 完全控制 附加到的控件 OpenFileDialog窗口。这意味着我们 可以接收事件、调用方法和 我们想怎么做就怎么做 控制。

        3
  •  2
  •   trashr0x Pac0    8 年前

    我昨天大部分时间都有这个问题。鲍伯的回答对我帮助最大(谢谢鲍伯)。

    甚至可以创建一个私有方法,该方法创建一个窗口并在 dialog.ShowDialog() 方法调用,它仍将使 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;
    }
    

    然后在 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;
    }
    
        4
  •  1
  •   BobB    12 年前

    openfiledialog和savefiledialog将自己定位在 最近显示的窗口的工作区。所以在创建和显示对话框之前,只需创建一个新的不可见窗口,该窗口位于希望对话框出现的位置。

    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();
    
        5
  •  0
  •   andynormancx    16 年前

    有一个关于msdn方法的老例子。

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

    它包括实现您自己的OpenFileDialog类所需的所有代码,这些类允许扩展。

        6
  •  0
  •   shytikov Cascabel    10 年前

    非常感谢鲍伯对此事的答复。还有一些“gotchas”。调用OpenFileDialog1.ShowDialog(positionForm)时必须传递positionForm的句柄,否则Bobb的技术在所有情况下都不可靠。此外,现在W8.1启动了一个新的fileopen控件,其中包含SkyDrive,现在W8.1 fileopen控件中的documents文件夹位置已拧紧。因此,我通过设置showhelp=true将fileopen设置为使用旧的w7控件。

    下面是我最终使用的vb.net代码,我对社区的贡献,以防它有所帮助。

    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
    
        7
  •  0
  •   IAbstract    9 年前

    我是这样做的:

    要显示OpenFileDialog的点:

    Thread posThread = new Thread(positionOpenDialog);
    posThread.Start();
    
    DialogResult dr = ofd.ShowDialog();
    

    重新定位代码:

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

    我启动一个线程来查找一个标题为“open”的窗口。(通常在3次迭代或15毫秒内找到)然后我用获得的句柄设置它的位置。(有关位置/尺寸参数,请参阅setwindowpos文档。)

    笨拙的