65.9K
CodeProject 正在变化。 阅读更多。
Home

FileDialogExtender

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (35投票s)

2004年12月4日

CPOL

3分钟阅读

viewsIcon

194348

downloadIcon

1829

描述了一种简单的方法来更改 Open/SaveFileDialog 中列表视图的初始状态。

Sample Image - article.jpg

引言

我认为 .NET 框架是一个令人印象深刻的、具有许多有用类的作品。但我想每个开发人员都至少遇到过一次一个类或函数不能完全满足他的需求的问题。通常,人们会从它派生并扩展功能。 OpenFileDialogSaveFileDialog 是密封的,因此没有直接的方法可以扩展它们。 本文解释了如何以任何方式扩展它们,而无需自己完成所有操作。

背景

很久很久以前,在一个遥远的国家...

...一位客户提出了一个请求,即在 OpenFileDialog(他可以在其中打开图像)中,所包含列表视图的默认视图状态应该是缩略图视图。 我们公司没有人真正考虑过这个问题,所以我们只是说:“没问题!”。

在查看了给定的对话框类之后,我意识到这并不像仅仅设置适当的属性那么简单。 我搜索了论坛和几个搜索引擎,但我能找到的只是显示如何通过 Windows API 直接创建对话框的列表,这需要几十个带有几十个字段和神秘常量的 struct。 这对于仅仅更改初始视图状态来说太多的开销了。 所以我开始考虑其他解决方案。

我想到的想法是,父窗体必须以某种方式知道何时显示哪个模态对话框。 所以我编写了一个覆盖 WndProc 的窗体,并跟踪了打开文件对话框时传来的消息。 几分钟后,我得到了我需要的消息。 它编号为 289,并在模态对话框的消息循环中触发。 此消息还包含对话框的句柄。 重要的是此时对话框已完全创建,否则后续步骤将不起作用。

哎呀! 不,我有了对话框的句柄,并且知道它已显示(我只需看看屏幕就能意识到这一点)。 现在,我需要一种方法来更改列表视图的样式。 所以我启动了 Spy++ 并搜索了对话框(手头有句柄,这很容易),并很快找到了包含列表视图的子窗口。

SampleImage - spy1.jpg

我打开了 Spy++ 的消息对话框,开始更改列表视图的视图状态,经过一些筛选后,我得到了更改样式的消息。 Spy++ 也显示了视图类型的适当参数。

SampleImage - spy2.jpg

现在,我只需要添加两个小的 API 调用来更改我的对话框。 我使用了 FindWindowEx 来搜索持有列表视图的窗口的句柄。 在检索到它之后,我调用了 SendMessage 将 Spy++ 传递的消息发送到窗口。

使用代码

我尝试将所有内容放入一个组件中。 问题是,唯一有权访问 System.Windows.FormWndProc 的是窗体本身。 因此,将显示文件对话框的窗体需要覆盖 WndProc 并调用此组件。 显示扩展对话框的最小代码将是

public class TestForm : System.Windows.Forms.Form
{
    private System.Windows.Forms.Button _btnOpen;
    private FileDialogExtender _extender = 
        new FileDialogExtender();

    public TestForm()
    {
        this._btnOpen = 
            new System.Windows.Forms.Button();
        this._btnOpen.Location = 
            new System.Drawing.Point(8, 8);
        this._btnOpen.Name = "_btnOpen";
        this._btnOpen.Size = 
            new System.Drawing.Size(96, 23);
        this._btnOpen.Text = "Open";
        this._btnOpen.Click += 
            new System.EventHandler(this.ShowOpenDialog);
        this.Controls.Add(this._btnOpen);
        this.FormBorderStyle = 
            FormBorderStyle.FixedDialog;
        this.MaximizeBox = false;
        this.MinimizeBox = false;
        this.Name = "TestForm";
        this.Text = "Test";
    }

    [STAThread]
    static void Main() 
    {
        Application.Run(new TestForm());
    }

    private void ShowOpenDialog(object sender, 
        System.EventArgs e)
    {
        new OpenFileDialog().ShowDialog();
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        _extender.WndProc(ref m);
    }
}

更好的示例项目包含在其中一个下载链接中。

关注点

我希望我能向您展示如何通过找到所需的句柄来扩展系统对话框,以远程控制它们的行为。

人们可以通过这种方式做更多的事情,而不会放弃使用托管对话框类的优势。 由于我不再需要扩展,我现在将其保留在此阶段。

如果有人有关于如何在不覆盖 WndProc 或添加其他 API 调用或钩子的情况下实现此功能的想法,请告诉我。

历史

  • 2004-12-04 - 初始发布。
© . All rights reserved.