最近开始用VS2003学习Windows Shell扩展编程,主要参考pudn的几个经典例子,这几个经典例子以前都是在vc6的环境下跑的,后来作者更新到vc7,网上还有好多教程是老版本的基于vc6环境的教程。现在把这两天学习的内容列下来,仅供参考。
1、按照方法生成项目,系统会自动生成两个项目SimpleExt和SimpleExtPS,SimpleExtPS项目可以整个删掉,对结果没有什么影响。
2、按照方法拷贝代码过来时,记得将教程中的GUID修改为自己的GUID,就是中括号中包含好多字符的那个。这个GUID可以在idl文件的“library SimpleExtLib”项下面找到。
3、编译后出现错误提示:
问题描述
error C2787: “IContextMenu”: 没有与该对象关联的 GUID
error C2440: “初始化”: 无法从“DWORD_PTR”转换为“const IID *”
从整型转换为指针类型要求 reinterpret_cast、C 样式转换或函数样式转换
error C2440: “初始化”: 无法从“ATL::_ATL_CREATORARGFUNC (__stdcall *)”转换为“DWORD_PTR”
该转换要求 reinterpret_cast、C 样式转换或函数类型转换
上面的IContextMenu也可能是IShellExecuteHook或者其他的Shell Interface。
原因
There are two <comdef.h> header files in VC.NET, one in Vc7/include and the other in Vc7/PlatformSDK/include. The former splits off the smart pointer typedefs into comdefsp.h, and it doesn't include IContextMenu. The latter does. You can try to #include the PlatformSDK header directly, change your INCLUDE path order, or supply the missing typedef yourself
在VC.NET里包含两个<comdef.h>头文件,一个在Vc7/include文件夹中,另一个在Vc7/PlatformSDK/include文件夹中,.net里面前者不包含IContextMenu的GUID,而包含在PlatformSDK中的头文件(ShlObj.h和comdef.h)里。
关键的问题是以下头文件没有包含正确
#include "shlobj.h"
#include "comdef.h"
#include <shlguid.h>
解决方案
一、把 $(VCInstallDir)PlatformSDKinclude 放在 Include 目录第一位,或者不放第一也至 少要在 ($VCInstallDir)include 前面!
如上所述,如果把PlatformSDK/include放在前面仍然不可以的话,就下载新的SDK,把include目录包含进去就好了。
或者直接将PlatformSDK/include下comdef.h绝对路径包含也可
二、自己添加如下的typedef:
----------------------------------------------------------------------------------------------
struct __declspec(uuid("000214e4-0000-0000-c000-000000000046")) IContextMenu;
_COM_SMARTPTR_TYPEDEF(IContextMenu, __uuidof(IContextMenu));
----------------------------------------------------------------------------------------------
那么如何找到interface对应的GUID呢?
比如IContextMenu:000214e4-0000-0000-c000-000000000046
方法1:在注册表中的HKEY_CLASSES_ROOT/Interface中查找。
方法2:PlatformSDKincludecomdef.h 中也有GUID的定义。
方法3:使用Microsoft Visual Studio 2003Common7ToolsBin下的OleView.Exe。
相对来说,第三种方法比较方便。
三、不用COM_INTERFACE_ENTRY(IContextMenu),
换成 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu),
同时要添加 #include <shlguid.h>。