PropertySheet外壳扩展AppWizard

  • 下载source files - 39 Kb
  • 下载Wizard - 17 Kb

本文旨在简化属性表外壳扩展的实现。它紧接我的第一篇文章 处理上下文菜单壳扩展和灵感 由Michael Dunn最优秀的系列教程 关于编写shell扩展。我强烈建议你们通读一下,以便更好地理解 下面。 这一次,我们将处理一个实现属性表外壳扩展的解决方案。我们会重复使用材料 在我的前一篇文章中找到,并添加了几行代码。所有这些都打包在一个整洁的PropertySheet外壳扩展中 AppWizard。 安装并运行向导 属性表外壳扩展向导包含在一个自包含的propsheetapp中。awx文件 需要复制到您的模板文件夹中。模板文件夹可以在主Microsoft Visual中找到 Studio安装文件夹,位于\通用\MSDev98\模板文件夹下。 使用File|New菜单项激活向导,该菜单项会触发一个New Projects对话框。 选择属性表外壳扩展项将出现以下向导对话框。这一步可以让 指定shell扩展要注册的文件类型,以及它的c++类名 将由向导生成。 巫师给了你什么? 该向导将生成一个与ATL/COM应用向导创建的项目类似的Visual Studio项目。 主要区别在于,项目已经包含了实现属性表骨架的类 外壳扩展。 回想一下Michael Dunn的教程,属性表外壳扩展是一个应该实现的COM对象 IShellExtInit和IShellPropSheetExt接口。向导生成的类 已经以头文件atlshellexh的形式提供了支持这些实现所需的所有内容 它与我上一篇文章中使用的相同,只是经过了更新,而且增加了几行代码 输出IShellPropSheetExt接口的实现。 向导生成的代码使用了ATL的WTL扩展。这些真的很方便 没有明显的理由不使用它们。这些扩展简化了对属性页本身和对话框的编程 控制。向导已经生成了初始的属性页类。它已经知道如何对WM_INITDIALOG作出反应 和PSM_APPLY消息。 让我们从一个示例开始 让我们尝试编写一个类似于本教程中描述的shell扩展。这可不那么容易 时间,因为属性表有点复杂,你必须自己做大部分工作。然而, 向导已经生成了实际创建和显示属性页的所有工作。 从上面的屏幕快照中可以注意到,我们选择将shell扩展挂钩到. txt文件,就像Michael的一样。 还要注意,在我们的示例中实现扩展的类名为CShellExt。 如果查看CShellExt中AddPages()方法的实现,就会发现 看到这些线: 隐藏,复制Code

STDMETHODIMP CShellExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
{
	CSamplePropPage* m_pPage;

	m_pPage = new CSamplePropPage;
	m_pPage->SetTitle(_T("Sample"));
	m_pPage->SetFile(m_files[0]);

	HPROPSHEETPAGE hPage = m_pPage->Create();
	if (!lpfnAddPage(hPage, lParam)) delete m_pPage;
	return S_OK;
}

这段由向导生成的代码实际上创建了一个属性页的实例,并为它分配了一个假标题 根据您的项目名称。它还将第一个选定文件的名称传递给属性表,并调用 shell的回调函数,执行向属性表添加页面的操作。请注意这个属性 page类名是基于您的项目名合成的,在我们的例子中,项目是Sample,因此 CSamplePropPage类。 如果我们需要添加更多的页面,就像Michael在他的例子中所做的那样,那就是放置它们的地方。我不会做 我举个例子。只需对m_files数组和进行迭代就足够了 为每个属性页创建其他实例。 令人惊讶的是,属性页的WTL实现没有提供在其中设置小图标的方法 属性页选项卡。所以我们需要自己添加它。此外,我们希望文件名显示 也在选项卡中。需要作出的改变概述如下: 隐藏,复制Code

#include "shlwapi.h"
...
STDMETHODIMP CShellExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
{
	CSamplePropPage* m_pPage;
	m_pPage = new CSamplePropPage;

	// Add a small icon (assuming a resource identifier IDI_ICON)
	m_pPage->m_psp.pszIcon = MAKEINTRESOURCE(IDI_ICON);
	m_pPage->m_psp.dwFlags |= PSP_USEICONID;

	// Use the file name as the title
	TCHAR szFile[_MAX_FNAME];
	lstrcpy(szFile, m_files[0]);
	::PathStripPath(szFile);	

	m_pPage->SetTitle(szFile);
	m_pPage->SetFile(m_files[0]);

	HPROPSHEETPAGE hPage = m_pPage->Create();
	if (!lpfnAddPage(hPage, lParam)) delete m_pPage;
	return S_OK;
}

一定要添加shlwapi。将库设置为项目设置中的库列表。 现在我们已经建立并运行了属性表的基础知识,我们需要添加更多有趣的特性 CSamplePropPage类。我们将在对话框模板中添加五个日期和时间选择器控件 order用来显示各种日期和时间,以及额外的静态控件来显示完整的文件路径。 为了简化我们的工作,我们将使用SetCombinedDatetime()和GetCombinedDateTime() 帮助函数,分别从两个日期和时间选择器中设置和获取日期和时间部分 控制。这些函数的代码改编自Michael的项目: 隐藏,收缩,复制Code

void GetCombinedDateTime ( HWND hwnd, UINT idcDatePicker, UINT idcTimePicker,
                           FILETIME* pFiletime )
{
	SYSTEMTIME st = {0}, stDate = {0}, stTime = {0};
	FILETIME   ftLocal;

	CDateTimePickerCtrl dtControl;
	dtControl.Attach(::GetDlgItem(hwnd, idcDatePicker));
	dtControl.GetSystemTime(&stDate);

	if (idcTimePicker != 0) {
		dtControl.Attach(::GetDlgItem(hwnd, idcTimePicker));
		dtControl.GetSystemTime(&stTime);
	}

	st.wMonth  = stDate.wMonth;
	st.wDay    = stDate.wDay;
	st.wYear   = stDate.wYear;
	st.wHour   = stTime.wHour;
	st.wMinute = stTime.wMinute;
	st.wSecond = stTime.wSecond;

	::SystemTimeToFileTime (&st, &ftLocal);
	::LocalFileTimeToFileTime (&ftLocal, pFiletime);

	dtControl.Detach();
}

隐藏,复制Code

void SetCombinedDateTime ( HWND hwnd, UINT idcDatePicker, UINT idcTimePicker,
                           const FILETIME* pFiletime )
{
	SYSTEMTIME st;
	FILETIME   ftLocal;

	::FileTimeToLocalFileTime (pFiletime, &ftLocal);
	::FileTimeToSystemTime (&ftLocal, &st);

	CDateTimePickerCtrl dtControl;
	dtControl.Attach(::GetDlgItem(hwnd, idcDatePicker));
	dtControl.SetSystemTime(GDT_VALID, &st);

	if (idcTimePicker != 0) {
		dtControl.Attach(::GetDlgItem(hwnd, idcTimePicker));
		dtControl.SetSystemTime(GDT_VALID, &st);
	}

	dtControl.Detach();
}

更新这些控件的代码是相当标准的WTL控件编程n OnInitDialog () 函数。这个函数是由向导生成的,所以这里是你需要添加的行: 隐藏,收缩,复制Code

LRESULT CSamplePropPage::OnInitDialog(HWND /*hWnd*/, LPARAM /*lParam*/)
{
	// Display the full path
	CStatic sPath;
	sPath.Attach(::GetDlgItem(m_hWnd, IDC_FILE));
	sPath.SetWindowText(m_file);
	sPath.Detach();

	// Get the file dates and times

	FILETIME creationTime;
	FILETIME accessTime;
	FILETIME modificationTime;

	HANDLE hFile;

	hFile = ::CreateFile(m_file, GENERIC_READ,
					FILE_SHARE_READ, 0,
					OPEN_EXISTING, 0, 0);
	ATLASSERT(hFile != INVALID_HANDLE_VALUE);

	::GetFileTime(hFile, &creationTime, &accessTime, &modificationTime);
	::CloseHandle(hFile);

	// Display the creation/modification/access date and time

	SetCombinedDateTime(m_hWnd, IDC_CREATIONDATE, IDC_CREATIONTIME, &creationTime);
	SetCombinedDateTime(m_hWnd, IDC_MODIFICATIONDATE, IDC_MODIFICATIONTIME, &modificationTime);
	SetCombinedDateTime(m_hWnd, IDC_ACCESSDATE, 0, &accessTime);

	return 0L;
}

要启用Apply按钮,我们需要捕获日期和时间选择器控件发送的通知。 它们向属性表发送一个DTN_DATETIMECHANGE通知。我们只需要添加一个宏 我们的消息映射和类中相应的消息处理程序来完成任务。注意,因为我们是 在使用WTL时,我使用了_EX版本的消息映射宏来执行消息破解,但是你没有 如果您愿意,可以随时使用ATL提供的一个。 隐藏,复制Code

class CSamplePropPage : public CPropertyPageImpl
{
...
	LRESULT OnDateTimeChanged(LPNMHDR lpnmhdr);
...
// Message map
public:
BEGIN_MSG_MAP_EX(CSamplePropPage)
	CHAIN_MSG_MAP(CPropertyPageImpll)
	MSG_WM_INITDIALOG(OnInitDialog)
	NOTIFY_RANGE_CODE_HANDLER_EX(IDC_CREATIONDATE, IDC_ACCESSDATE, DTN_DATETIMECHANGE, OnDateTimeChanged)
END_MSG_MAP()
};

我假设日期和时间选择器控件的资源标识符是顺序的,因此我可以 使用范围处理程序将所有这些控件的通知路由到一个消息处理程序。实现 OnDateTimeChanged()函数很简单。只要启用Apply按钮… 隐藏,复制Code

LRESULT CSamplePropPage::OnDateTimeChanged(LPNMHDR /*lpnmhdr*/)
{
	SetModified(TRUE);
	return 0L;
}

点击Apply按钮将触发向导生成的OnApply()函数。 这是一个被覆盖的函数,每当用户点击OK或Apply按钮时就会调用它。我们需要申请 返回到文件的日期和时间修改。 隐藏,复制Code

BOOL CSamplePropPage::OnApply(void)
{
	FILETIME creationTime;
	FILETIME accessTime;
	FILETIME modificationTime;

	// Get the new creation/modification/access date and time

	GetCombinedDateTime(m_hWnd, IDC_CREATIONDATE, IDC_CREATIONTIME, &creationTime);
	GetCombinedDateTime(m_hWnd, IDC_MODIFICATIONDATE, IDC_MODIFICATIONTIME, &modificationTime);
	GetCombinedDateTime(m_hWnd, IDC_ACCESSDATE, 0, &accessTime);

	// Set the file dates and times
	HANDLE hFile;

	hFile = ::CreateFile(m_file, GENERIC_WRITE,
					0, 0, OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL, 0);
	ATLASSERT(hFile != INVALID_HANDLE_VALUE);

	::SetFileTime(hFile, &creationTime, &accessTime, &modificationTime);
	::CloseHandle(hFile);

	return TRUE;
}

就是这样!这个项目现在完成了。 结论 如您所见,实现上下文菜单扩展现在更快更容易了。此外,你可以重复使用 在您自己的项目中提供了atlshellexh文件。这个文件,atlshellexh实现的 IShellExtInit接口在某种程度上也与实现上下文菜单Shell直接相关 我在上一篇文章中概述的扩展。 我希望这篇文章足够清楚。如果你有什么问题,请告诉我。 本文转载于:http://www.diyabc.com/frontweb/news30106.html

你可能感兴趣的:(PropertySheet外壳扩展AppWizard)