来源(null)

Customizing the Open/Save As Dialog Boxes

定制 Open/Save As 对话框

By Eduard Koller

Introduction

你可以通过一个钩子进程、一个定制模板或者两者结合来定制Open或者Save As对话框。但是,新的IE模式和旧模式[Windows 3.1的通用对话框类型]在应用定制模板和钩子程序时是不同的。

通用对话框具有缺省的模板,该模板定义了对话框的个数、类型和标准控件的位置。除了IE类型的打开/另存为对话框外,对于所有的通用对话框,你都可以通过修改缺省的模板去创建定制的模板,该定制的模板将确定标准控件的类型和位置以及其它额外控件的类型和位置。

然而,IE类型的打开/另存为对话框的确省模板是不能修改的。取而代之的是另一个可以定制的模板,它定义了一个仅仅包含要添加在标准对话框中的控件的子对话框。

要定义添加在一个IE类型的打开/另存为对话框中的控件,必须使用OPENFILENAME结构去指定一个包含额外控件的子对话框的模板。如果你的这个子对话框模板是一个应用程序的资源或者是一个动态链接库,请设置OFN_ENABLETEMPLATE标志并且用该结构的hInstancelpTemplateName成员去指定模块和资源名。如果该模板已存在于内存中,请设置OFN_ENABLETEMPLATEHANDLE标志并且使用hInstance成员去指定包含该模板的内存对象。

当提供一个IE类型对话框的一个子对话框模板时,你必须设置OFN_EXPLORER标志;否则,系统将假设你提供的是一个取代旧模式的模板而不是一个包含添加控件的模板。典型地,如果你提供了额外的控件,你必须同时提供一个IE类型的钩子进程去处理针对于新控件的各种消息。

你可以象处理任何其它模板一样来创建你的子对话框模板;然而,你必须指定WS_CHILDWS_CLIPSIBLINGS风格,并且你还必须指定DS_3DLOOKDS_CONTROL风格。系统要求WS_CHILD风格因为你的模板定义的是一个缺省对话框的子对话框,并且WS_CLIPSIBLINGS风格确保了子对话框的绘制不会覆盖于缺省对话框的任何控件上。
定制的模板也可以定义一个静态文本控件来指定在子对话框中标准控件群的位置。缺省的,所有来自于定制对话框的控件将位于缺省对话框的控件的下方。然而,你可以通过在你的定制对话框模板中加入一个静态文本控件来改变其位置,你必须指定其ID值为stc32(这个值是在DLG.H头文件中定义的)。在这种情况下,系统将在决定如何定位新控件时将其作为参考点。例如,所有的新控件相对于stc32控件的上边和左边的距离将等同于相对缺省控件的上边和左边的距离。为了给新的控件腾出空间,系统在需要时将在缺省对话框的上边、右边、底下和顶上留出足够的空间。

为了得到更多的信息,请参阅Microsoft Platform SDK(包含在VC++ 5.0中) 文档中“定制通用对话框”一节。

使用 MFC

CFileDialog类封装了Windows公用文件对话框。公用文件对话框以Windows的标准格式实现了文件打开和另存为对话框(以及其它的文件选择对话框)的功能。

你可以使用CFileDialog,以及它的构造函数,然而,你也可以从它派生出你自己的对话框类并且写出适合你需要的构造函数。在这两种情况下,这些对话框都将具有标准MFC对话框的行为,因为他们都是从CCommonDialog类派生而来的。

要定制这个对话框,请从CFileDialog派生出一个类,然后提供一个定制对话框模板,最后添加一个消息映射去处理来自于扩展控件的通知消息。任何未被处理的消息都将传递给基类。

使用API调用,定制模板可以定义一个静态文本控件来指定在子对话框中标准控件的位置。

问题显而易见:上面描述的方法允许在IE类型的打开或另存为对话框中在标准控件周围放置其它控件,但是它不允许对标准控件进行改变大小、移动或是隐藏等操作。

众所周知,公用对话框的好处在于使各应用程序具有有统一的风格和功能。但是一个应用程序也许需要更多定制功能的打开对话框。例如,我要在一个wizard向导中的一个属性页中使用这样一个对话框,假设象图1所显示的一样:

1

创建一个这样的对话框从理论上来说是很简单的。首先,找到所有标准控件的句柄,然后移动、改变大小或是隐藏它们。而实际上,找到这些控件的句柄并且发现何时执行这些动作是困难的。

找到标准控件的句柄

当“探测”[Microsoft Spy++]定制的打开或另存为对话框时,请注意你创建的CFileDialog是屏幕上的对话框的一个子窗口。  (Figure 2):


2

其它的子窗口是打开/另存为对话框的标准控件。这些句柄可以通过调用::GetDlgItem()函数得到,CFileDialog父窗口的句柄作为第一个参数而某个标准控件的ID作为第二个:

CWnd* pCcommDlg->GetParent();  
  HWND hWndControl;  
  HwndControl = ::GetDlgItem(pCcommDlg->m_hWnd,1137);

为了方便你的观看,ID都列在下面了:


3

Link: http://www.asm32.net/article_details.aspx?id=79