24

WinFormアプリケーションのカスタムダイアログ(フォーム)の場合、次のコマンドで表示する前に、そのサイズと位置を設定できます。

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

これは、複数のモニターを扱う場合に特に重要です。このようなコードがないと、2番目のモニターにドラッグしたアプリケーションからダイアログを開くと、そのダイアログがプライマリモニターに表示されます。これにより、ユーザーエクスペリエンスが低下します。

標準の.NETOpenFileDialogおよびSaveFileDialog(StartPositionプロパティがない)の位置を設定するためのフックがあるかどうか疑問に思っています。

4

8 に答える 8

5

あなたができる最善のことは、親として使用することを受け入れるのオーバーロードを使用することを確認することだと思います。ShowDialogIWin32Windowこれ、適切な場所を選択するのに役立つ場合があります。最も一般的に:

using(var dlg = new OpenFileDialog()) {
    .... setup
    if(dlg.ShowDialog(this) == DialogResult.OK) {
        .... use
    }
}
于 2009-08-10T18:30:46.967 に答える
4

CodeProjectに関するこの記事をチェックしてください。抜粋:

便利な.NETNativeWindowが登場したとき、NativeWindowは、関連付けられたハンドルによって送信されたメッセージを処理するウィンドウラッパーです。NativeWindowを作成し、OpenFileWindowハンドルをそれに関連付けます。この時点から、OpenFileWindowに送信されたすべてのメッセージは、代わりにNativeWindowの独自のWndProcメソッドにリダイレクトされ、キャンセル、変更、または通過させることができます。

WndProcでは、メッセージWM_WINDOWPOSCHANGINGを処理します。開いているダイアログが開いている場合は、ユーザーが設定したStartLocationに応じて、元の水平または垂直のサイズを変更します。作成するウィンドウのサイズが増加します。これは、コントロールが開かれたときに1回だけ発生します。

また、メッセージWM_SHOWWINDOWを処理します。ここでは、元のOpenFileDialog内のすべてのコントロールが作成され、ファイルを開くダイアログにコントロールを追加します。これは、Win32APISetParentを呼び出すことによって行われます。このAPIを使用すると、親ウィンドウを変更できます。次に、基本的には、StartLocationプロパティの値に応じて、設定した場所にある元のOpenFileDialogにコントロールをアタッチします。

これの利点は、OpenFileDialogウィンドウに接続されているコントロールを完全に制御できることです。これは、イベントを受信したり、メソッドを呼び出したり、それらのコントロールを使用して必要なことを実行したりできることを意味します。

于 2009-08-10T18:44:46.547 に答える
3

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();
于 2013-06-30T13:33:10.843 に答える
2

私は昨日のほとんどの間この問題を抱えていました。BobBの答えは、私を最も助けてくれたものでした(BobBに感謝します)。

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;
}
于 2016-11-16T11:40:48.197 に答える
1

これが私がそれをした方法です:

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

「開く」というタイトルのウィンドウを探すスレッドを開始します。(通常、3回の反復または15ミリ秒で検出されます。)次に、取得したハンドルを使用してその位置を設定します。(位置/サイズのパラメーターについては、SetWindowPosのドキュメントを参照してください。)

Kludgy。

于 2012-05-07T21:51:03.783 に答える
0

MSDNには1つのアプローチのかなり古い例があります。

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

これには、拡張性を可能にする独自のOpenFileDialogクラスを実装するために必要なすべてのコードが含まれています。

于 2009-08-10T18:52:44.597 に答える
0

これに関するBobBの返信に非常に感謝しています。さらにいくつかの「落とし穴」があります。OpenFileDialog1.ShowDialog(PositionForm)を呼び出すときは、PositionFormのハンドルを渡す必要があります。そうしないと、BobBの手法がすべての場合に信頼できるとは限りません。また、W8.1がSkyDriveを含む新しいfileopenコントロールを起動するようになったため、W8.1fileopenコントロールの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
于 2014-01-22T20:13:00.517 に答える
0

2014年1月22日のRobSherritの応答をインスピレーションとして使用して、新しいモジュールを作成し、次のコードを含むCKRFileDialog(必要なものと呼びます)と呼びました。

Public Function Show(fd As Object, CoveredForm As Form, Optional bShowHelp As Boolean = False) As DialogResult

    Dim oDR As DialogResult

    'The .Net FileDialogs open in the last Form that was created. 
    'To ensure they appear in the area of the current Form, we create a new HIDDEN PositionForm and then 
    'delete it afterwards.

    Dim PositionForm As New Form With {
      .StartPosition = FormStartPosition.Manual,
      .Left = CoveredForm.Left + CInt(CoveredForm.Width / 8),  'adjust as required
      .Top = CoveredForm.Top + CInt(CoveredForm.Height / 8),   'adjust as required
      .Width = 0,
      .Height = 0,
      .FormBorderStyle = Windows.Forms.FormBorderStyle.None,
      .Visible = False
    }
    PositionForm.Show()

    'If you use SkyDrive you need to ensure that "bShowHelp" is set to True in the passed parameters.
    'This is a workaround for a problem on W8.1 machines with SkyDrive installed.
    'Setting it to "true" causes the "old" W7 control to be used which avoids a pointing to SkyDrive error.
    'If you do not use SkyDrive then simply do not pass the last parameter (defaults to "False")
    fd.ShowHelp = bShowHelp

    'store whether the form calling this routine is set as "topmost"
    Dim oldTopMost As Integer = CoveredForm.TopMost
    'set the calling form's topmost setting to "False" (else the dialogue will be "buried"
    CoveredForm.TopMost = False

    oDR = fd.ShowDialog(PositionForm)

    'set the "topmost" setting of the calling form back to what it was.
    CoveredForm.TopMost = oldTopMost
    PositionForm.Close()
    PositionForm.Dispose()
    Return oDR

End Function

次に、さまざまなモジュールでこのコードを次のように呼び出します。

「FileOpen」を実行する場合は、フォームまたはコードにFileOpenDialogコンポーネントが追加されていることを確認し、必要に応じてコンポーネントのプロパティを調整します(InitDirectory、Multiselectなど)。

FileSaveDialogコンポーネントを使用する場合も同じようにします(FileOpenDialogコンポーネントとは異なるプロパティが適用される場合があります)。

ダイアログコンポーネントを「表示」するには、次のコード行を使用して、2つのパラメーターを渡します。最初のパラメーターは使用しているFileDialog(「開く」または「保存」)で、2番目のパラメーターはダイアログをオーバーレイするフォームです。

CKRFileDialog.Show(saveFileDialog1、CoveredForm)またはCKRFileDialog.Show(openFileDialog1、CoveredForm)

SkyDriveを使用している場合は、3番目のパラメーターとして「True」を渡す必要があることに注意してください。

CKRFileDialog.Show(saveFileDialog1、CoveredForm、True)またはCKRFileDialog.Show(openFileDialog1、CoveredForm、True)

ダイアログの「オフセット」をフォーム「CoveredForm」の上下に1/8に設定しましたが、1/2(Rob Sherretのコードのように)または任意の値に戻すことができます。

これは最も簡単なアプローチのようでした

ありがとうロブ!:-)

于 2020-06-14T10:42:48.883 に答える