将在主线程得到的接口指针传递到新线程中使用的问题.........

kezhon 2008-10-27 07:47:10
在对话框上放置一个WebBrowser控件,取得所加载页面的某一个select表单元素的指针IHTMLSelectElement,
然后此接口指针列集后传递给一个工作线程,在此线程中用散列得到接口spSelectElement。
用spSelectElement成功得到此select域里面的所有option元素;
然后用put_selectedIndex()设定选中项。
hr = spSelectElem->put_selectedIndex(i);
执行完毕后hr==SD_OK。
然后试图用IHTMLElement3的fireEvent()来激发onchange事件。
					VARIANT_BOOL vRect;
BSTR Eventonchange = SysAllocString(L"onchange");
CComQIPtr< IHTMLElement3 > spElem3;
hr=spSelectElem->QueryInterface(IID_IHTMLElement3,(void**)&spElem3);
ASSERT(SUCCEEDED(hr));
hr=spElem3->fireEvent(Eventonchange,0,&vRect);
ASSERT(SUCCEEDED(hr));
spElem3.Release();

但执行到
hr=spElem3->fireEvent(Eventonchange,0,&vRect);
ASSERT(SUCCEEDED(hr)); 这一步时,编译器指出:
hr 0x800706f4 向占位程序传送了空的索引指针。 HRESULT
然后就报错。

大家注意上面是通过spSelectElem->QueryInterface(IID_IHTMLElement3,(void**)&spElem3);得到IHTMLElement3接口的;
后来我把IHTMLElement3接口也在主线程列集,传递到工作线程再散列,爆出的问题跟之前一模一样。

高人指点下是怎么回事?

...全文
229 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
kezhon 2008-10-28
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 jameshooo 的回复:]
激发事件时必须创建一个有效的事件对象ITHMLEventObj,所以不能在第二个参数中传递NULL。
这么多接口需要列集,是不是觉得列集太麻烦?其实不麻烦,只需要列集一个根接口即可,比如IWebBrowser2或者IHTMLDocument2即可,剩下的事情就从这个接口开始导航吧,后续接口不再需要列集。
[/Quote]非常感谢胡大哥,在你的帮助下,我对这个问题的困惑逐渐明白。
CComQIPtr< IHTMLEventObj > spEo;    
hr = spDoc4->createEventObject(NULL, &spEo);

CComQIPtr<IDispatch> spDisp(spEo);
CComVariant var(spDisp);
VARIANT_BOOL bCancel = VARIANT_FALSE;

CComQIPtr< IHTMLElement3 > spElem3;
hr=spSelectElem->QueryInterface(IID_IHTMLElement3,(void**)&spElem3);
ASSERT(SUCCEEDED(hr));

hr = spElem3->fireEvent(L"onchange", &var, &bCancel);
ASSERT(SUCCEEDED(hr));


上面是我从网上找到的代码,来createEventObject。但执行报错createEventObject参数貌似不应该为空。我真是搞不懂这个createEventObject到底是怎么用的。以前没用它,fireEvent也很成功啊?
Amuro1987218 2008-10-28
  • 打赏
  • 举报
回复
能查询到IHTMLDocument2么,实在不行用IServiceProvider中转一下
kezhon 2008-10-28
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 jameshooo 的回复:]
只需要列集一个根接口即可,比如IWebBrowser2或者IHTMLDocument2即可,剩下的事情就从这个接口开始导航吧,后续接口不再需要列集。
[/Quote]
请问胡兄,如果只传递了IHTMLSelectElement接口或来,怎样才能得到IHTMLDocument4接口?
hr = spSelectElem->QueryInterface(IID_IHTMLDocument4,(void**)&spDoc4);
编译器指出: hr E_NOINTERFACE HRESULT
看来这样不行,有木别的方法可以达到这个目的?


jameshooo 2008-10-27
  • 打赏
  • 举报
回复
激发事件时必须创建一个有效的事件对象ITHMLEventObj,所以不能在第二个参数中传递NULL。
这么多接口需要列集,是不是觉得列集太麻烦?其实不麻烦,只需要列集一个根接口即可,比如IWebBrowser2或者IHTMLDocument2即可,剩下的事情就从这个接口开始导航吧,后续接口不再需要列集。
sys0004 2008-10-27
  • 打赏
  • 举报
回复


HRESULT fireEvent(
BSTR bstrEventName,
VARIANT *pvarEventObject,
VARIANT_BOOL *pfCancelled
);


Parameters

bstrEventName
[in] BSTR that specifies the name of the event to fire.
pvarEventObject
[in] Pointer to a VARIANT that specifies the IHTMLEventObj interface from which the event properties are obtained.
pfCancelled
[out, retval] VARIANT_BOOL that receives one of the following values:

VARIANT_TRUE
Event fired successfully.
VARIANT_FALSE
Event was cancelled.

我觉得应该是第二个参数不能设置为空,具体怎么设偶也没弄过,不太了解。
kezhon 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sys0004 的回复:]
0x800706f4表明是参数的问题,确认你传入的参数都合法先。
[/Quote]
//********************************点燃"onchange"事件********************************/
VARIANT_BOOL vRect;
BSTR Eventonchange = SysAllocString(L"onchange");
CComQIPtr< IHTMLElement3 > spElem3;
hr=spSelectElem->QueryInterface(IID_IHTMLElement3,(void**)&spElem3);
ASSERT(SUCCEEDED(hr));
hr=spElem3->fireEvent(Eventonchange,0,&vRect);
ASSERT(SUCCEEDED(hr));//此处报错,前一步编译器显示:
//hr 0x800706f4 向占位程序传送了空的索引指针。 HRESULT
spElem3.Release();
//****************************************************************/

你看我代码都贴出来了。spElem3->fireEvent(Eventonchange,0,&vRect);有三个参数,看哪一个都不像会出错的啊?
还有,为什么0x800706f4表明是参数的问题?
sys0004 2008-10-27
  • 打赏
  • 举报
回复
0x800706f4表明是参数的问题,确认你传入的参数都合法先。
kezhon 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sys0004 的回复:]
引用 5 楼 kezhon 的回复:

引用 2 楼 akirya 的回复:
看样子激发连接点也需要列集一次.
fireEvent()函数所需要的IHTMLElement3接口指针,我后来也列集传递了过来,实验结果跟之前一模一样!


你确认列集、散集每一步都成功了?
[/Quote]我sorry我刚记错了,是50分,我去结了,给了你46分。
我严重确认列集散列都做成功了,因为我在调试中仔细观察每一步执行的情况,列集散列以及传递都没有问题。
而且很蹊跷的是,传过来的IHTMLSelectElement指针可以得到这个表单域的option选项,spSelectElem->get_length也很准确。
但是spSelectElem->put_selectedIndex执行后返回的hr显示SD_OK.
pElem3->fireEvent执行后显示:/hr 0x800706f4 向占位程序传送了空的索引指针。 HRESULT
然后就报错。
sys0004 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 kezhon 的回复:]
引用 2 楼 akirya 的回复:
看样子激发连接点也需要列集一次.
fireEvent()函数所需要的IHTMLElement3接口指针,我后来也列集传递了过来,实验结果跟之前一模一样!
[/Quote]

你确认列集、散集每一步都成功了?
sys0004 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 kezhon 的回复:]
引用 3 楼 sys0004 的回复:
貌似的列集、散集下接口

列集、散集的概念介绍:http://www.builder.com.cn/2007/1015/556787.shtml
------------------------
ps:LZ上一个帖子还没结呢
哈哈,哥们你放心啊,那个帖子100点我给你90点,现在去结。
帮我看看这个帖子的问题吧~~
[/Quote]

汗,那个帖子总共才50分
那个马甲都得了也到不了1000分,LZ给点就行了,不然以为俺倒分呢
kezhon 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 akirya 的回复:]
看样子激发连接点也需要列集一次.
[/Quote]fireEvent()函数所需要的IHTMLElement3接口指针,我后来也列集传递了过来,实验结果跟之前一模一样!
kezhon 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sys0004 的回复:]
貌似的列集、散集下接口

列集、散集的概念介绍:http://www.builder.com.cn/2007/1015/556787.shtml
------------------------
ps:LZ上一个帖子还没结呢
[/Quote]哈哈,哥们你放心啊,那个帖子100点我给你90点,现在去结。
帮我看看这个帖子的问题吧~~
sys0004 2008-10-27
  • 打赏
  • 举报
回复
貌似的列集、散集下接口

列集、散集的概念介绍:http://www.builder.com.cn/2007/1015/556787.shtml
------------------------
ps:LZ上一个帖子还没结呢
  • 打赏
  • 举报
回复
看样子激发连接点也需要列集一次.
kezhon 2008-10-27
  • 打赏
  • 举报
回复
大家可以通过这个帖子跟详细地了解整个问题的来龙去脉:
将主线程对话框上的(WebBrowser控件页面元素的DOM接口指针IHTMLSelectElement)传递给新线程,为什么操作不成功?

之前发贴有人说:每个使用COM的线程都要调用CoInitialize和Counitialize。
我在线程函数的里面加上这两个函数后,问题依然如果。
而且我之前没有用线程时,没有用此连个函数初始化,也很正常。不知何故,是否因为程序中有使用ADO,所以我在app中曾经调用过:
BOOL CWorkshopApp::InitInstance()
{
//TODO: call AfxInitRichEdit2() to initialize richedit2 library.
if(!AfxOleInit())
{
AfxMessageBox(_T("OLE初始化出错!"));
return FALSE;
}


出问题的这部分代码是:
		HRESULT hr;
m_listTT[k].ResetContent();
CComQIPtr< IHTMLSelectElement > spSelectElem;
if(ArrSpSelectElem.GetAt(k, spSelectElem))
{
nCount--;
long length = 0;
spSelectElem->get_length(&length);

CStringArray strArrText;
if(GetOptionsTextValue(spSelectElem, strArrText, 0))
{
for(int i=0; i<strArrText.GetCount(); i++)
{
m_listTT[k].AddString(strArrText[i]);
}
}
else
{ return false; }
for(int i=0; i<length; i++)
{
//AddToDB(i);

hr = spSelectElem->put_selectedIndex(i);
if(FAILED(hr)) AfxMessageBox(_T("Fail to put_selectedIndex"));
//********************************点燃"onchange"事件********************************/
VARIANT_BOOL vRect;
BSTR Eventonchange = SysAllocString(L"onchange");
CComQIPtr< IHTMLElement3 > spElem3;
hr=spSelectElem->QueryInterface(IID_IHTMLElement3,(void**)&spElem3);
ASSERT(SUCCEEDED(hr));
hr=spElem3->fireEvent(Eventonchange,0,&vRect);
ASSERT(SUCCEEDED(hr));//此处报错,前一步编译器显示:
//hr 0x800706f4 向占位程序传送了空的索引指针。 HRESULT
spElem3.Release();
//****************************************************************/
m_listTT[k].SetCurSel(i);

15,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧