高分提问! VC DOM 编程,已经取得了IHTMLFormElement 的对象,想收到 from 提交的消息,用 put_onsubmit没反应,请指教

vcPlayer 2008-09-11 03:19:14
VC DOM 编程,已经取得了IHTMLFormElement 的对象,想收到 from 提交的消息,用 put_onsubmit没反应,请指教

我的代码:

CComVariant vEvent;
CComPtr< COnWebEvent > pOnWebEvent;

vEvent.pdispVal = (IDispatch*)pOnWebEvent;
spFormElement->put_onsubmit( vEvent );

其中的 COnWebEvent 是这么写的

class COnWebEvent : public IDispatch
{
public:
COnWebEvent();
~COnWebEvent();

virtual HRESULT STDMETHODCALLTYPE Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr);
};


我在 COnWebEvent 里面 和 Invoke 里面都下了断点和打印调试信息,都没反应,请指教
...全文
749 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
vcPlayer 2008-09-12
  • 打赏
  • 举报
回复
额,本来要结贴的,结果发现一个问题。。。。

这个现在是设定一个自定义的接受消息的 invoke,然后紧接着的代码就是模拟点击我感兴趣的页面元素提交表单。但是我不模拟点击,而是用手工点击的话,我的接收器就接收不到消息。

我现在想枚举到所有的页面表单之后,不用代码去立即点击。而是用手工去点击了页面之后,我的接收器也能收到消息,是需要保存哪个变量?还是说应该怎么做?



... ...

hr = spFormElement->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
if (hr == S_OK)
{
// Find the connection point.
hr = pCPC->FindConnectionPoint( DIID_HTMLFormElementEvents , &pCP);
if (hr == S_OK)
{
// Advise the connection point.
hr = pCP->Advise((IUnknown*)&pOnWebEvent, &dwCookie);
if ( FAILED( hr ) ) ::AfxMessageBox("bbb");
}
pCPC->Release();
}


//----------------------------------------------------------------------------------
//枚举表单中的元素,找到与input 有关的项,如果发现为 image 类型的按钮,就点击。

CComQIPtr< IHTMLElement > spAllInputElement;
spFormElement->QueryInterface( IID_IHTMLElement , (void**)&spAllInputElement );

CComQIPtr< IDispatch > spCollDisp;
CComQIPtr< IHTMLElementCollection > spCollElement;

spAllInputElement->get_all( (IDispatch**)&spCollDisp );
spCollDisp->QueryInterface( IID_IHTMLElementCollection , (void**)&spCollElement );

long nCollCount = 0;
spCollElement->get_length(&nCollCount);

for( long i = 0 ; i< nCollCount ; i++ )
{
CComQIPtr< IDispatch > MyDisp;
CComQIPtr< IHTMLInputElement > spInputElement;


hr = spCollElement->item( CComVariant(i) , CComVariant() , &MyDisp );
if ( FAILED( hr ) ) continue;

if( !MyDisp )//容错
return;

hr = MyDisp->QueryInterface( IID_IHTMLInputElement , (void**)&spInputElement );
if ( FAILED( hr ) ) continue;


if( !strnicmp(lpType , "image" , 5) )//如果发现 为 image 类型的按钮就点击之
{
CComQIPtr< IHTMLElement > spSingleElement;

hr = spInputElement->QueryInterface( IID_IHTMLElement , (void**)&spSingleElement);
if( FAILED( hr ) ) continue;

hr = spSingleElement->click();
if( FAILED( hr ) ) continue;

}

vcPlayer 2008-09-12
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 jameshooo 的回复:]
发给我吧,hubaihua@gmail.com
[/Quote]

yjgx007 老大已经帮忙修改了,
用连接点可以,但是 put_onsubmit() 还是不行,呵呵,不知道为啥,感谢老大参与,给分。
vcPlayer 2008-09-12
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 yjgx007 的回复:]
sorry, 你的OnWebEvent.cpp没加到工程中,我重写了这个类 : )

引用计数很重要, 你可不能给假的哦!
另外QueryInterface不能简单返回this指针, 要根据继承接口的IID进行识别.
[/Quote]

感谢老大,用连接点已经可以了。。。但是 put_onsubmit() 还是不行,不过能解决问题就可以了,给分。
yjgx007 2008-09-12
  • 打赏
  • 举报
回复
sorry, 你的OnWebEvent.cpp没加到工程中,我重写了这个类 : )

引用计数很重要, 你可不能给假的哦!
另外QueryInterface不能简单返回this指针, 要根据继承接口的IID进行识别.
yjgx007 2008-09-12
  • 打赏
  • 举报
回复
我帮你修正了下这个类, 很多接口没实现, 特别是AddRef, Release,你自已在Invoke设断点试下(当form提交后,你的代码是点击图片元素,提交表单).修正后的工程已发到你邮箱.

class	COnWebEvent : public IDispatch// , public CCmdTarget 
{
public:
COnWebEvent():m_dwRef(1)
{};
~COnWebEvent(){};

//HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
// /* [out] */ UINT *pctinfo);

//HRESULT STDMETHODCALLTYPE GetTypeInfo(
// /* [in] */ UINT iTInfo,
// /* [in] */ LCID lcid,
// /* [out] */ ITypeInfo **ppTInfo);

//HRESULT STDMETHODCALLTYPE GetIDsOfNames(
// /* [in] */ REFIID riid,
// /* [size_is][in] */ LPOLESTR *rgszNames,
// /* [in] */ UINT cNames,
// /* [in] */ LCID lcid,
// /* [size_is][out] */ DISPID *rgDispId);

//virtual HRESULT STDMETHODCALLTYPE Invoke(
// /* [in] */ DISPID dispIdMember,
// /* [in] */ REFIID riid,
// /* [in] */ LCID lcid,
// /* [in] */ WORD wFlags,
// /* [out][in] */ DISPPARAMS *pDispParams,
// /* [out] */ VARIANT *pVarResult,
// /* [out] */ EXCEPINFO *pExcepInfo,
// /* [out] */ UINT *puArgErr);


DWORD m_dwRef;
// IUnknown
STDMETHOD(QueryInterface)(const struct _GUID &riid,void ** ppv){
*ppv = NULL;

if (IID_IUnknown == riid)
{
*ppv = (LPUNKNOWN)this;
AddRef();
return NOERROR;
}
else if (IID_IDispatch == riid)
{
*ppv = (IDispatch*)this;
AddRef();
return NOERROR;
}
else
{
return E_NOTIMPL;
}
}
ULONG __stdcall AddRef(void){
return ++m_dwRef;
}
ULONG __stdcall Release(void){
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
// IDispatch
STDMETHOD(GetTypeInfoCount)(unsigned int *){
TRACE("GetTypeInfoCount\n"); return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo)(unsigned int,unsigned long,struct ITypeInfo ** ){
TRACE("GetTypeInfo\n"); return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames)(const IID &,LPOLESTR *,UINT,LCID,DISPID *){
TRACE("GetIDsOfNames\n"); return E_NOTIMPL;
}
STDMETHOD(Invoke)(long dispID,const struct _GUID &,unsigned long,unsigned short,struct tagDISPPARAMS * pParams,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *)
{
return NOERROR;
}
};

jameshooo 2008-09-12
  • 打赏
  • 举报
回复
发给我吧,hubaihua@gmail.com
yjgx007 2008-09-12
  • 打赏
  • 举报
回复
或者直接在构造中完成.
yjgx007 2008-09-12
  • 打赏
  • 举报
回复
put_onsubmit应该是可以的, 你少了指定variant类型的步骤,看下面代码:
vEvent.pdispVal = (IDispatch*)&pOnWebEvent;
vEvent.vt = VT_DISPATCH;
vcPlayer 2008-09-12
  • 打赏
  • 举报
回复
sorry,贴漏了一段代码,在 if( !strnicmp(lpType , "image" , 5) ) 的上面有一段代码漏了。



//取得表单域,并且点击按钮
CComBSTR vName,vVal,vType;

hr = spInputElement->get_name( &vName );
if( FAILED( hr ) ) continue;

hr = spInputElement->get_value( &vVal );
if( FAILED( hr ) ) continue;

hr = spInputElement->get_type( &vType );
if( FAILED( hr ) ) continue;

if( !strnicmp(lpType , "image" , 5) )//如果发现 为 image 类型的按钮就点击之
{
CComQIPtr< IHTMLElement > spSingleElement;

hr = spInputElement->QueryInterface( IID_IHTMLElement , (void**)&spSingleElement);
if( FAILED( hr ) ) continue;

hr = spSingleElement->click();
if( FAILED( hr ) ) continue;

}

vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 jameshooo 的回复:]
pDisp的类型一般使用CComPtr <IDispatch>,后面要注意判断spFormElement是否空,其他还看不出问题
[/Quote]

跟你说的一样。。。。我也看不出问题。。。

不知道能不能把工程发给老大看看?
jameshooo 2008-09-11
  • 打赏
  • 举报
回复
pDisp的类型一般使用CComPtr<IDispatch>,后面要注意判断spFormElement是否空,其他还看不出问题
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
CComQIPtr< IHTMLFormElement > spFormElement = pDisp;
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复

CComQIPtr< IDispatch > pDisp;
hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue;

if( !pDisp )//容错
return;

CComQIPtr< IHTMLFormElement > spFormElement = pDisp;



jameshooo 2008-09-11
  • 打赏
  • 举报
回复
真是稀奇,spFormElements是什么类型的变量?CComPtr<IHTMLFormElement>?
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
谢谢,我的实现代码跟你的一样,:)。。。。。

还有可能是哪里的问题?

put_onsubmit() 返回值是 E_NOTIMPL
jameshooo 2008-09-11
  • 打赏
  • 举报
回复
Invoke里面改成return S_OK; 一下子写错了,习惯用HRESULT hr;变量
jameshooo 2008-09-11
  • 打赏
  • 举报
回复
给你帖一段实现代码:

class COnWebEvent : public IDispatch
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef()
{
return 1;
}

virtual ULONG STDMETHODCALLTYPE Release()
{
return 1;
}

virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID* ppvObj)
{
if (iid==__uuidof(IDispatch) || iid==__uuidof(IUnknown))
{
if (ppvObj)
*ppvObj = this;
return S_OK;
}
return E_NOINTERFACE;
}

virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT * /*pctinfo*/)
{
return E_NOTIMPL;
}

virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT /*iTInfo*/, LCID /*lcid*/, ITypeInfo ** /*ppTInfo*/)
{
return E_NOTIMPL;
}

virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID /*riid*/, LPOLESTR * /*rgszNames*/, UINT /*cNames*/, LCID /*lcid*/, DISPID * /*rgDispId*/)
{
return E_NOTIMPL;
}

virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember,REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult,EXCEPINFO * pexcepinfo, UINT * puArgErr)
{
// do something
// 在这里设置断点试试
return hr;
}
};
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 jameshooo 的回复:]
不要用栈变量,用全局变量申明一个COnWebEvent变量再试。
你的COnWebEvent到底是怎么写的?Invoke没有被调用到吗?put_onsubmit()返回值是什么?
[/Quote]

就是 InVoke 没有被调用到啊,所以才奇怪。。。被调用到就说明已经收到通知了,我现在是连通知都没收到
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 jameshooo 的回复:]
不实现AddRef/QueryInterface之类的方法你居然能编译通过?不可能吧。
[/Quote]

当然,后面改成老大说的那样,肯定是要写个空函数的。 :)
vcPlayer 2008-09-11
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 yjgx007 的回复:]
xinyi78528@163.com
[/Quote]

邮件已发,里面有简单的说明,先谢谢老大。
加载更多回复(25)

3,055

社区成员

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

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