我想在附加到SaveFileDialog
事件的事件处理程序中更改FileOk
的文件名,以便将用户输入的文件名替换为另一个文件名。在某些情况下,保持对话框打开:
var dialog = new SaveFileDialog();
...
dialog.FileOk +=
delegate (object sender, CancelEventArgs e)
{
if (dialog.FileName.EndsWith (".foo"))
{
dialog.FileName = "xyz.bar";
e.Cancel = true;
}
};
单步执行代码显示FileName
确实已正确更新,但当事件处理程序返回时,对话框中显示的文件名不会更改。我已经看到理论上我可以使用如下的Win32代码来更改对话框本身的文件名:
class Win32
{
[DllImport("User32")]
public static extern IntPtr GetParent(IntPtr);
[DllImport("User32")]
public static extern int SetDlgItemText(IntPtr, int string, int);
public const int FileTitleCntrlID = 0x47c;
}
void SetFileName(IntPtr hdlg, string name)
{
Win32.SetDlgItemText (Win32.GetParent (hdlg), Win32.FileTitleCntrlID, name);
}
但是,我不知道从哪里可以获得与HDLG
实例关联的SaveFileDialog
。我知道我可以自己重写整个SaveFileDialog
包装器(或使用code like NuffSaveFileDialog或CodeProject extension of SaveFileDialog),但出于技术原因,我更倾向于使用标准的WinForms类。
答案 0 :(得分:2)
获取对话框句柄我使用了反射,然后使用该句柄调用SetFileName
:
dialog.FileOk +=
delegate (object sender, CancelEventArgs e)
{
if (dialog.FileName.EndsWith (".foo"))
{
Type type = typeof(FileDialog);
FieldInfo info = type.GetField("dialogHWnd", BindingFlags.NonPublic
| BindingFlags.Instance);
IntPtr fileDialogHandle = (IntPtr)info.GetValue(dialog);
SetFileName(fileDialogHandle, "xyz.bar");
e.Cancel = true;
}
};
N.B。:在你的Win32类中,你只需要定义SetDlgItemText函数(不需要GetParent
)并将对话句柄传递给它:
[DllImport("User32")]
public static extern int SetDlgItemText(IntPtr hwnd, int id, string title);
public const int FileTitleCntrlID = 0x47c;
void SetFileName(IntPtr hdlg, string name)
{
SetDlgItemText(hdlg, FileTitleCntrlID, name);
}
要让以前的代码在Windows 7上工作(我认为Vista也是如此?),请将对话框的属性ShowHelp
设置为true
:
dialog.ShowHelp = true;
外观会有所改变,但我认为这不是什么大问题。