这是我学习COM遇到的几个基本问题其解决
黄森堂(vcmfc)著
1.我用ATL生成一个组件对象,我在COM中使用IDD_IEncrypt,这个在哪里写义,是啥?GUID?
答:IDD_IEncrypt是GUID,也称作CLSID,放到该项目的对象的xxx_i.c文件中。
2.S_OK,NOERROR等常量中定义在哪些文件上(偷一下懒)(VC6.0)。
答:winerror.h中
3.我在一个ASP组件对象中有构造函数使用SysAllocString()分配内存在该对象的类变量,在DLL Release memory的时候,我要调用SysFreeString(),可是好像该对象没有析构函数,我在哪儿处理。
答:可以自己添个析构函数,在里面调用SysFreeString。或可以使用_bstr_t或CComBSTR,就省得释放内存了。
4.BSTR指针的内容如何拷贝到LPOLESTR指针上?
答:BSTR是COM使用的特殊字符串类型,它的开头是BSTR所包含的字符串的字节长度,然后才是字符串,该字符串以null
结束,不过普通的字符串中间是不允许包含null的,但是BSTR允许,因为它前面已经有该字符串的长度了。如果要在BSTR和我们
所常见的字符串类型转换,一般不必自己转换,用_bstr_t类就可以。这也是微软所推荐的。比如要从BSTR m_bstrA 转为 char*
可以这样:
char* pStr;
pStr = (char*)_bstr_t(m_bstrA);
很简单吧。
如果要从char* pStr转为BSTR,这样作:
BSTR m_bstrA;
m_bstrA = _bstr_t(pStr).copy();
其它类型转换我没试过,不过从char*转为
LPCTSRT之类应该就不会太难了。
(注:看一看第9条,唉!,自已够笨的)
5.在COM方法中能不能使用try...catch?
答:在COM中可以用try,catch块,但在Project->Settings->C/C++->C++ Language下要选中Enable Exception Handling。如果你用try,catch块,可在catch块中可以这样写:Error((BSTR)e.Description, IID_*, e.Error())(e是_com_error)。
6.我的组件有一个方法Encrypt,需要传入一个加密字符串,加密后将字符串返回给VB,在VB中我使用 s=jj.Encrypt("数据"),那么我在COM中该如何定义该方法?
答:返回值要是[out]属性,要想用以上方法使用,最后一个参数用[out,retval]BSTR* pEncryptString,这将作为返回字符串。
完整定义如下:
[id(2), helpstring("加密")] HRESULT Encrypt(BSTR EncryptString,[out,retval]BSTR *pEncryptString);]
7.我的属性为什么不能进行赋值?
我在组件里加一个属性Key,可以get与put,在组件源程序中有get_Key()与put_Key(),get_Key工作正常,可我的put_Key不正常呀!,源程序如下:
STDMETHODIMP CEncrypt::put_Key(BSTR newVal)
{
m_pKey=newVal;//m_pKey为类变量,如下定义:BSTR m_pKey;
return S_OK;
}
答:m_pKey=SysAllocString(newVal);
8.如何更改控件或组件的在注册时存放在注册表中的名称?
自已答:告诉你,不在.idl,在你的xxx.rgs文件中,全改了,是不是已经...,嘿嘿~~.
9.ATL中CComBSTR与_bstr_t的区别?嘿嘿~~,我现在才明白一点,高手莫笑。
答:
共同点:对于BSTR到BSTR,BSTR到对象(CComBSTR/_bstr_t),对象到BSTR,两者之间没有什么区别,CComBSTR与_bstr_t都能很好地管理处理BSTR.
异同点:_bstr_t提供了BSTR到char,wchar_t指针的处理,也就是说能把BSTR的内容拷贝成char*,而CComBSTR就没有这种功能。
10.OLE_COLOR与COLORREF,VARIANT_BOOL与BOOL有何区别?
答:我是不知道,不过可以直接进行赋值。嘿嘿..,是不是太土吧!
以下是陆大虾的进课:
OLE_COLOR与COLORREF之间是有一定区别的。OLE_COLOR和COLORREF都是DWORD类型,但对于COLORREF来说,它的最高一个字节永远是0x00。即如果是红色,对于COLORREF来说是0x000000FF。而OLE_COLOR的最高一个字节有两种情况:0x80(也就是10000000,最高位是1)或0x00(也就是00000000,最高位是0)。当OLE_COLOR的最高位是0时,它与COLORREF是相同的,最后三个字节代表RGB,可以相互赋值。例如红色用OLE_COLOR来表示同样是0x000000FF。但当OLE_COLOR的最高位是1时,它的中间两个字节一定都是0x00,最后一个字节表示的是系统颜色索引值。例如系统定义菜单的颜色索引值是4,所以用OLE_COLOR来表示就是0x80000004。在VB中,如果你选中一个FORM,在它的属性页中你可以看到它的BackColor属性,你点击下拉框,就可以选择是使用调色板色还是系统色,调色板色就是对应了OLE_COLOR的高位为0的情况,系统色对应的是OLE_COLOR高位为1的情况。你试一下就知道是怎么回事了。
VARIANT_BOOL和BOOL之间也有区别。BOOL为long,在BOOL中,TURE为1,FALSE为0。VAIRNAT_BOOL为short,在VARIANT_BOOL中,VARIANT_TRUE为-1(0xFFFF),VARIANT_FALSE为0(0x0000)。并且VARIANT_BOOL是和VB中的Boolean相同的,就像BSTR和String的关系一样。所以,在自动化组件及控件中应该使用VARIANT_BOOL。
11.如何知道该Activex是在VB的设计时还是运行时?
答:判断run-mode和design-mode的方法是CComControl::GetAmbientUserMode,你可以在MSDN中找到这个函数的用法。
12.我的ActiveX控件有一个属性Algin,我想在VB中列出其属性值出现一个ComboBox来列出我定义的几个值?,有的枚举出来左边有图像,右边有文字说明,这是如何实现的?
答:简单的静态枚举直接在 IDL 文件中定义枚举类型,把属性的类型定为枚举类型即可。动态枚举比较麻烦,主要涉及到 IPerPropertyBrowsingImpl<CATLControlWin> 的下列方法:MapPropertyToPage, GetPredfinedStrings, GetPredefinedValue, GetDisplayString。具体实现方法请参考《Visual C++ 5 ActiveX 编程指南》,Jerry Anderson 著,清华大学出版社。
以下简单的静态枚举的代码片段(以Align属性说明):
//typedef enum tagFontAlign{Left=0,Center=1,Right=2}FontAlign;(比较完整的如下)
typedef enum tagFontAlign
{
[helpstring("Left")]Left=0,
[helpstring("Center")]Center=1,
[helpstring("Right")]Right=2,
}FontAlign;
[propget, id(2), helpstring("对齐方式")] HRESULT Align([out, retval] FontAlign *pVal);
[propput, id(2), helpstring("对齐方式")] HRESULT Align([in] FontAlign newVal);
在接下来的接口定义中添加属性Align时,属性的数据类型就填FontAlign,其它操作照常。编译完以后,你就应该在VB Project中的Object Browser中看到有这么一个枚举类型。在控件属性中选中Align时,就会有个Combo Box让你选择FontAlign中的一个值。
13.如何创建一个容器,像VB中的Tabbed Dialog容器,控件在它范围内移动?
答:这要靠控件容器实现 ISimpleFrameSite 接口,在 MSDN 中搜索 Extending ATL 3.0 Control Containment to Help You Write Real-world Containers。
14.在ATL中使用其默认的Font属性的话,会产生以下错误:
warning MIDL2039 : interface does not conform to [oleautomation] attribute
warning MIDL2039 : interface does not conform to [oleautomation] attribute
warning MIDL2039 : interface does not conform to [oleautomation] attribute
答:这可是困惑我N天,也不知道白了多少根头发,这是一个BUG,在Microsoft的KnowLedge的有这一个BUG报告:
“BUG: MIDL2039 Warning with IFontDisp/IPictureDisp Parameter Type”
15.在ATL中产生的Active X中使用默认的Font属性的话,在VB中的对象属性页中对其属性进行赋值,会产生一个错误:
“Invalid Properties Value”.
答:该属性在ATL产生后需要在作些设置才能用,在Microsoft的KnowLedge的有一篇文章:
《Using Fonts in ATL Controls with NiceText.exe》
16.在ATL中产生的Active X中使用默认的Font属性,在.IDL中产生默认接口定义,该如何使用该接口定义呢?
答:#include <ocidl.h>
IFont *piFont;
HRESULT hr;
HFONT hfont;
hr = m_pFont->QueryInterface(IID_IFont, (void **)&piFont);
if(SUCCEEDED(hr))
{
hr = piFont->get_hFont(&hfont);
}
lhxx的小贡献
在程序中调用要动态分配内存或实例的COM时要注意要用指针的地址来进行参数传递:
... Sample(int **pInput)
{
*pInput = ...;
....
}
... Sample1( BSTR *pbstr)
{
*pbstr = (BSTR) malloc (.....);
....
}
如何打算学习ActiveX开发的话,这本书一定要看《Visual C++ 5 Active X编程指南》,学习COM一定要看《Inside COM》,《COM原理与应用》;还可参雨考我在CSDN的文档中心上发表的《COM错误处理》,嘿嘿~~,初学者看之有大补呀!,^_^.....
感谢以下这批狼:陆谊、edyang、info_xsd、oulix、wjf、lhxx、...,且前两头可是超级恶狼呀!
这都是本菜鸟的愚见,不对之处请莫笑,否则我没脸见人呀!,下次不敢发表了。