首 页免费信息软件下载在线电视QQ空间克隆免费博客论 坛
您当前的位置:鸿飞官方免费资源网免费信息编程技术 → 文章内容 退出登录 用户管理
本类热门文章
相关文章
 
一步步教你如何编写Shell扩展
作者:鸿飞  来源:本站整理  发布时间:2007-11-22 22:00:48

减小字体 增大字体


Explorer 使用该方法传递给我们各种各样的信息.
PidlFolder是用户所选择操作的文件所在的文件夹的 PIDL 变量. (一个 PIDL [指向ID 列表的指针] 是一个数据结构,它唯一地标识了在Shell命名空间的任何对象, 一个Shell命名空间中的对象可以是也可以不是真实的文件系统中的对象.)
pDataObj 是一个 IDataObject 接口指针,通过它我们可以获取用户所选择操作的文件名。
hProgID 是一个HKEY 注册表键变量,可以用它获取我们的DLL的注册数据.
在这个简单的扩展例子中, 我们将只使用到 pDataObj 参数.

要添加这个接口进 COM 对象, 先打开SimpleShlExt.h 文件, 然后加入下列标红的代码:

#include "shlobj.h"
#include "comdef.h"

class ATL_NO_VTABLE CSimpleShlExt :
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl,
public IShellExtInit

BEGIN_COM_MAP(CSimpleShlExt)
COM_INTERFACE_ENTRY(ISimpleShlExt)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellExtInit)
END_COM_MAP()

COM_MAP是ATL实现 QueryInterface()机制的宏,它包含的列表告诉ATL其它外部程序用QueryInterface()能从我们的 COM对象获取哪些接口.
接着,在类声明里, 加入Initialize()的函数原型.
另外我们需要一个变量来保存文件名:

protected:
TCHAR m_szFile [MAX_PATH];
public:
// IShellExtInit
STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

然后, 在 SimpleShlExt.cpp 文件中, 加入该函数方法的实现定义:

HRESULT CSimpleShlExt::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID )

我们要做的是取得被右击选择的文件名,再把该文件名显示在弹出消息框中。
可能会有多个文件同时被选择右击, 你可以用pDataObj 接口指针获取所有的文件名, 但现在为简单起见, 我们只获取第一个文件名.

文件名的存放格式与你拖放文件到带WS_EX_ACCEPTFILES风格的窗口时使用的文件名格式是一样的。
这就是说我们可以使用同样的API来获取文件名: DragQueryFile().
首先我们先获取包含在IdataObject中的数据句柄:

{
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
HDROP hDrop;

// 在数据对象内查找 CF_HDROP 型数据.
if ( FAILED( pDataObj->GetData ( &fmt, &stg )))
{
// Nope! Return an "invalid argument" error back to Explorer.
return E_INVALIDARG;
}

// 获得指向实际数据的指针
hDrop = (HDROP) GlobalLock ( stg.hGlobal );

// 检查非NULL.
if ( NULL == hDrop )
{
return E_INVALIDARG;
}

请注意错误检查,特别是指针的检查。
由于我们的扩展运行在 Explorer 进程内, 要是我们的代码崩溃了, Explorer也会随之崩溃. 在Win 9x上, 这样的一个崩溃可能导致需要重启系统.

所以, 现在我们有了一个 HDROP 句柄, 我们就可以获取我们需要的文件名了:

// 有效性检查 – 保证最少有一个文件名.
UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
if ( 0 == uNumFiles )
{
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return E_INVALIDARG;
}
HRESULT hr = S_OK;

// 取得第一个文件名并把它保存在类成员m_szFile 中.
if ( 0 == DragQueryFile ( hDrop, 0, m_szFile, MAX_PATH ))
{
hr = E_INVALIDARG;
}
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return hr;
}


要是我们返回 E_INVALIDARG, Explorer 将不会继续调用以后的扩展代码.
要是返回 S_OK, Explorer 将再一次调用QueryInterface() 获取另一个我们下面就要添加的接口指针: IContextMenu.

与上下文菜单交互的接口

一旦 Explorer 初始化了扩展,它就会接着调用 IContextMenu 的方法让我们添加菜单项, 提供状态栏上的提示, 并响应执行用户的选择.

添加IContextMenu 接口到Shell扩展类似于上面IshellExtInit接口的添加 .打开 SimpleShlExt.h,添加下列标红的代码:

class ATL_NO_VTABLE CSimpleShlExt :
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl,
public IShellExtInit,

public IContextMenu

{
BEGIN_COM_MAP(CSimpleShlExt)
COM_INTERFACE_ENTRY(ISimpleShlExt)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellExtInit)

COM_INTERFACE_ENTRY(IContextMenu)

END_COM_MAP()


添加 IContextMenu 方法的函数原型:

public:
// IContextMenu
STDMETHOD(GetCommandString)(UINT, UINT, UINT*, LPSTR, UINT);
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO);
STDMETHOD(QueryContextMenu)(HMENU, UINT, UINT, UINT, UINT);

上一页  [1] [2] [3] [4]  下一页

推荐:本站站长(鸿飞)原创软件免费赠送

温馨提示:如果发现资源地址无效时,请在下面的评论上留言,我会及时处理!谢谢!

[] [返回上一页] [打 印]
文章评论 (评论内容只代表网友观点,与本站立场无关!)

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 0分

内 容:

         (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码

关于本站 - 网站帮助 - 广告合作 - 下载声明 - 有情连接 - 网站地图 - 发布信息

Copyright © 2007-2008 鸿飞免费资源网:www.fei2yu.com. All Rights Reserved

站 长:鸿飞    Q Q:250118591    蜀ICP备07502538号