OpenFileDialog / SaveFileDialogの開始位置を設定します
-
12-09-2019 - |
質問
任意のカスタムダイアログ(フォーム)用のWinFormアプリケーションで私がそれを表示する前に、私はそのサイズと位置を設定することができます:
form.StartPosition = FormStartPosition.Manual;
form.DesktopBounds = MyWindowPosition;
複数のモニタを扱うときにこのことは特に重要です。あなたはセカンドモニタにドラッグしているアプリケーションからダイアログを開いたときに、このようなコードがないと、ダイアログがプライマリモニタに表示されます。これは、貧弱なユーザーエクスペリエンスを提供します。
(開始位置のプロパティを持っていない)標準の.NET OpenFileDialogとSaveFileDialogのための位置を設定する任意のフックがある場合、私は疑問に思ってます。
解決
私はあなたができる最善のは、あなたがオーバーロードを使用してくださいがあると思われます親として使用するShowDialog
を受け入れIWin32Window
するの。この はそれが適切な場所を選択するに役立つかもしれません。最も一般ます:
using(var dlg = new OpenFileDialog()) {
.... setup
if(dlg.ShowDialog(this) == DialogResult.OK) {
.... use
}
}
他のヒント
CodeProjectの上この記事をチェックしてください。抜粋ます:
ここでは、ときに便利です.NET NativeWindowのは、A、画像に入ってきます NativeWindowのはどこの窓ラッパーです それはによって送信されたメッセージを処理します それに関連付けられたハンドル。それが作成されます NativeWindowの仲間と それに対処OpenFileWindow。これから に送信された時点、すべてのメッセージ OpenFileWindowはにリダイレクトされます で私たち自身のWndProcメソッド NativeWindowの代わりに、私たちはすることができます キャンセル、変更、またはそれらを通過させます 通じています。
私たちのWndProcメソッドでは、メッセージを処理します WM_WINDOWPOSCHANGING。オープンの場合 ダイアログが開いている、我々は変更されます 元の水平または垂直 StartLocationに依存サイズ ユーザによって設定されました。それが増分します ウィンドウのサイズを作成します。この コントロールがあるときに一度だけ起こります オープンします。
また、私たちはメッセージを処理します WM_SHOWWINDOW。ここでは、すべてのコントロール 元OpenFileDialogの内側にあります 作成した、と私たちは、追加しようとしています オープンファイルダイアログに私たちのコントロール。 これは、Win32のAPIを呼び出すことによって行われ SetParent関数。このAPIを使用すると、変更することができます 親ウィンドウ。次に、基本的に 何それがないと、私たちのコントロールを添付してあります の元OpenFileDialogへ 応じて、それが設定された場所、 StartLocationプロパティの値ます。
これの利点は、我々はまだです 完全に制御を持っています コントロールに添付 OpenFileDialogウィンドウ。これは、私たちを意味します 、イベントを受け取るメソッドを呼び出すと、することができます 私たちはそれらとやりたいです コントロールます。
私は昨日のほとんどのために、この問題を抱えていました。 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;
}
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();
ここで私はそれをやった方法は次のとおりです。
私は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のドキュメントを参照してください。)
クルージます。
MSDN上の一つのアプローチのかなり古い例があります。
http://msdn.microsoft.com/en-us/library /ms996463.aspxする
これは、拡張性を可能にする独自のOpenFileDialogクラスを実装するために必要なすべてのコードが含まれます。
この1にBobBの返信のために非常に感謝。さらにいくつかの「落とし穴」があります。あなたはOpenFileDialog1.ShowDialog(PositionForm)を呼び出すときにPositionFormのハンドルを渡す必要がありそうBobBの技術は、すべてのケースで信頼できるものではありません。また、今ではW8.1はそれでSkyDriveの持つ新しいFILEOPENコントロールを起動し、W8.1のFILEOPENコントロールのドキュメントフォルダの場所は現在、ネジ止めされています。だから私は、真のShowHelp =を設定することにより、古いW7コントロールを使用するFILEOPEN frig。
ここに私が使用して終了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