vs2008 外部调用ActiveX控件接口方法

转自:http://topic.csdn.net/u/20090605/16/018e26e9-06e2-4e0d-8099-bc8eb326afde.html

 

sndaxdrs:
初学activeX ,我写的一个 activeX控件测试程序。 分别调用两个 自定义方法, 分别出现 “找不到成员”,和“非选择性的参数”的提示对话框。 一直不知道原因 。但是调用 AboutBox() 方法可以调用成功。

  我用activeX控件测试容器测试时。 AboutBox() 也可以成功。而调用其它方法时会显示
  tstcon32.exe 中的 0x7c812afb 处最可能的异常: Microsoft C++ exception: COleException @ 0x0012ef70 。
  调用不成功。

我已经分别用 控件测试容器和 regsvr32 注册过 控件了,控件测试成功。

由于是初学者,在此 希望能够得到大家的帮助。

fengrx:
使用向导加方法只是生成接口文件中的接口定义吧。
看下类文件中有没有方法的实现,如果没有就自己手工添加接口的实现。

举例:
接口文件中定义:
[id(DISPID_ABOUTBOX), helpstring("AboutBox")] HRESULT AboutBox(void);

头文件中定义:
STDMETHOD(AboutBox)(void);

cpp文件中实现:
STDMETHODIMP CResoftSignCtrl::AboutBox(void)
{
CAboutDlg dlg;
dlg.DoModal();
return S_OK;
}

sndaxdrs:
有实现的 void CCurveChartCtrl::Hello(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加调度处理程序代码
 
MessageBox("Hello!");
}

这是我写的一个 实现。


顺便说一下。 我自己写 activeX控件。 添加几个方法。都可以测试成功的。

我现在 需要用到别人给我的一个 控件 。 我调用 它的方法 。 显示是 “找不到成员”,

我又在 程序中又添加了一个方法。 就是上面这段代码。 当调用 时显示 “非选择性的参数”


求助大家/希望能得到帮助。

fengrx:
此控件在什么程序中使用的,一般使用此控件的程序会缓存一份此控件的函数表。
如果增加了新函数,不删除缓存文件,新函数是无法使用的。

此控件在什么程序中使用的?

例如对于word2003使用控件时会在临时文件夹保存两个文件夹:
VBE
Word8.0

你这个图表控件是在哪儿使用的?

sndaxdrs:
这个 控件是一个 显示曲线。有点 类似 股票的 波动曲线。 

我还想问下 如果添加新函数。怎么来删除缓存文件呢?

lzy91093:
我以前遇到“非选择性的参数”问题原因:
1,接口文件中定义的参数(个数、类型、顺序)与实现类中不同
2,接口文件定义的该函数id与实现的cpp文件中的一些映射宏(如BEGIN_EVENT_MAP/END_EVENT_MAP、BEGIN_DISPATCH_MAP/END_DISPATCH_MAP)里面的函数列表的顺序不一致

不知对你有没有帮助

sndaxdrs:

fengrx .. 你好,问题并没有解决。你只是告诉我添加一个方法我只是编译通过而已。但“找不到成员” 还是没有解决。你告诉我的方法。即使可以解决“非选择性参数”这个问题。也是解决不了“找不到成员“ 这个问题。 我的最终目的是 要解决“非选择性参数”


  我再重复一下我的问题。 别人给我一外activeX 控件。 上面有且仅有一个方法 [id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify);. 我写客户端调用 这个方法时 显示“找不到成员”。 我一直不知道原因 。


 为了 测试这个控件 。我又加了一个方法。 调用 我加入的 方法时会 出现 “非选择性参数”


我的最终目的是要解决 “ 找不到成员” 的问题。 希望能得到大家的帮助。 这个问题我几天解决不了。 工作无法继续。

修改一个 笔误, 上面第二行的 “我的最终目的是 要解决“非选择性参数””改成“我的最终目的是 要解决“找不到成员””
 
lzy91093:
两个问题好像是同一个问题,DISPID_ABOUTBOX定义的是几?贴出头文件和cpp文件帮你看看

sndaxdrs:
#define DISPID_ABOUTBOX (-552)

下面只有一个方法
dispinterface _DCurveChart
{
properties:
methods:

[id(DISPID_ABOUTBOX)] void AboutBox();
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify);
};

这是方法的实现部分
LONG CCurveChartCtrl::InitEx(LPCTSTR target, LONG chart_id, LONG type, LONG item, LPCTSTR verify)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

g_pSysLog->AppendLog(LOG_DEBUG,"InitEx");

strcpy(m_szVerify, verify);
m_nChartID = chart_id;
m_nChartType = type;
m_nTypeFlag = type | (item << 6);
m_nItem = item;
strcpy(m_szSoapEndPoint,target);
m_bInitChart = TRUE;

if (m_bCreateChart)
{
InitChartData();
return 0;
}

return 0;
}

lzy91093:
1,改成[id(2)] void AboutBox();
2,实现类中确保映射表中AboutBox函数在InitEx下面

再试试
BEGIN_DISPATCH_MAP/END_DISPATCH_MAP中间是怎么写的?

sndaxdrs:
BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl)
DISP_FUNCTION_ID(CCurveChartCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(CCurveChartCtrl, "InitEx", dispidInitialize, InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR)
END_DISPATCH_MAP()

fengrx:
在我印象中接口中的返回值类型只能是:HRESULT
上次加的方法也是吧。
你自己加方法时,接口文件中定义的,返回值类型都定义成HRESULT试下,如果需要返回其它类型,请在参数中定义,设置为out
 
sndaxdrs:
http://topic.csdn.net/u/20071103/10/80B268B1-61C6-4C31-BF22-203AEB49FA7A.html
http://topic.csdn.net/u/20080219/21/4080D185-40C3-4490-ADAA-A3F0D84A0F7A.html


给大家看看两个相关的主题。
 
lzy91093:
to fengrx:返回类型可以不是HRESULT

to sndaxdrs:解决了?

AboutBox的id改成2后把映射
BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION_ID(CCurveChartCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 
DISP_FUNCTION_ID(CCurveChartCtrl, "InitEx", dispidInitialize, InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) 
END_DISPATCH_MAP()
里面的两个函数位置颠倒一下,编译,注册,再在控件调用端重新添加控件(重新到处CCurveChartCtrl类)应该就好了

重新导出CCurveChartCtrl类
 
BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION_ID(CCurveChartCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 
DISP_FUNCTION_ID(CCurveChartCtrl, "InitEx", dispidInitialize, InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) 
END_DISPATCH_MAP() 

改成
BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION(CCurveChartCtrl, "InitEx", InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) 
DISP_FUNCTION(CCurveChartCtrl, "AboutBox", AboutBox, VT_EMPTY, VTS_NONE) 
END_DISPATCH_MAP() 

[id(DISPID_ABOUTBOX)] void AboutBox(); 
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify); 
改成
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify); 
[id(2)] void AboutBox(); 

顺便说一句,调用AboutBox出现“非选择性参数”错误是因为在空间内部调用的是InitEx,由于该函数的参数都是必选的(不是可选参数),调用时按AboutBox的格式传入的是无参数

注意DISP_FUNCTION和DISP_FUNCTION_ID的区别,如果用DISP_FUNCTION,其ID按映射中的顺序从1开始依次排列,用DISP_FUNCTION_ID则在影射中指定ID(如这里的dispidInitialize),不管是哪一种,都要保证该ID与idl文件中对应的接口定义里面的id一致。
再有就是注册与重新导出控件类,如果方便建议重做一个调用控件的工程。

sndaxdrs:
问题解决。非常非常感谢lzy91093 对我的帮助。 同时也 非常感谢lzy91093。解决办法为 lzy91093 的方法。 

BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION_ID(CCurveChartCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 
DISP_FUNCTION_ID(CCurveChartCtrl, "InitEx", dispidInitialize, InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) 
END_DISPATCH_MAP() 

改成 
BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION(CCurveChartCtrl, "InitEx", InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) 
DISP_FUNCTION(CCurveChartCtrl, "AboutBox", AboutBox, VT_EMPTY, VTS_NONE) 
END_DISPATCH_MAP() 

[id(DISPID_ABOUTBOX)] void AboutBox(); 
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify); 
改成 
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify); 
[id(2)] void AboutBox(); 

 

不过我还要问一下 lzy91093 , 发生这种错误的根源在哪里呢?

lzy91093:
控件内部是根据调用方传来的ID区寻找内部的函数的,ID给错了,就调用不到或调用到其他函数里了。(粗浅认识,不对处请方家指正)
其实你影射里用DISP_FUNCTION_ID也是可以的,是要保证IDL文件中定义的一致也是可以的:

BEGIN_DISPATCH_MAP(CCurveChartCtrl, COleControl) 
DISP_FUNCTION_ID(CCurveChartCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 
DISP_FUNCTION_ID(CCurveChartCtrl, "InitEx", 1, InitEx, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_BSTR) //
END_DISPATCH_MAP() 

[id(DISPID_ABOUTBOX)] void AboutBox(); 
[id(1), helpstring("方法Initialize")] LONG InitEx(BSTR target, LONG chart_id, LONG type, LONG item, BSTR verify); 

 

 

你可能感兴趣的:(vs2008 外部调用ActiveX控件接口方法)