1

我想更改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);
}

但是,我不知道从哪里可以获得HDLGSaveFileDialog实例相关联的信息。我知道我可以自己重写整个SaveFileDialog包装器(或使用NuffSaveFileDialog 之类的代码或 SaveFileDialog的CodeProject 扩展),但出于技术原因,我更喜欢使用标准的 WinForms 类。

4

1 回答 1

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

注意:在您的 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?),请将对话框的属性设置ShowHelptrue

dialog.ShowHelp = true;

外观会有一点点变化,但我觉得没什么大不了的。

于 2009-10-21T09:00:39.640 回答