如何在SaveFileDialog.FileOk事件处理程序中替换FileName

时间:2009-10-21 08:46:05

标签: c# winforms interop savefiledialog

我想在附加到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 NuffSaveFileDialogCodeProject extension of SaveFileDialog),但出于技术原因,我更倾向于使用标准的WinForms类。

1 个答案:

答案 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;

外观会有所改变,但我认为这不是什么大问题。