(200分求解)在Form中加入一个TCppWebBrowser,如果获得它的消息或事件啊

gloom 2002-10-24 03:11:34
在Form中使用TCppWebBrowser,除了DoucmentCompelete等之外,如果获得文档的Mouse事件(消息)或KeyBoard事件。
此题200分求解,为避免无解而浪费可用分,先放50,一旦得解,决不食言
...全文
138 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
gk0205 2002-12-19
  • 打赏
  • 举报
回复
收藏呀,精彩就是看不懂
gloom 2002-11-09
  • 打赏
  • 举报
回复
这个问题不能算是完全解决了,但我也收获不少,非常感谢BCB_Fans兄的帮助
bcb_fans 2002-11-07
  • 打赏
  • 举报
回复
最好检测一下

handle=FindWindowEx(handle,NULL,"Internet Explorer_Server",NULL);

的返回值,看看是否为NULL。

============

如果网页中含有Frame,这种方法无法判断网页是否真正下载完成!
gloom 2002-11-07
  • 打赏
  • 举报
回复
不好意思,我的代友贴错了,应该是
//---------------------------------------------------------------------------

void __fastcall TForm1::WebDocumentComplete(TObject *Sender,
LPDISPATCH pDisp, Variant *URL)
{
handle=Web->Handle;
handle=FindWindowEx(handle,NULL,"Shell DocObject View",NULL);
handle=FindWindowEx(handle,NULL,"Internet Explorer_Server",NULL);
pCanvas->Handle =GetWindowDC(handle);
::SetFocus(handle);
//DrawBtn->Enabled =true;
//this->Cursor =crAppStart;
FOldAppProc = (FARPROC)GetWindowLong(handle, GWL_WNDPROC);
FNewAppObjectInstance = MakeObjectInstance(NewAppProc);
SetWindowLong(handle, GWL_WNDPROC, long(FNewAppObjectInstance));
}
bcb_fans 2002-11-07
  • 打赏
  • 举报
回复
我看只能自己实现IDispatch接口了,不然怎么接受事件!?

但是不是调用元素的put_onEvent(...)来设置事件句柄,而是调用IHTMLDocument2的put_mousedown(...)来设置。

你自己先试一下,我也没有编写过这方面的程序。BHO倒是编过,只是在BHO里边接受的事件是诸如OnBeforeNavigate2这种事件,跟你的要求不一样。

如果实在不行,我再试试。
gloom 2002-11-07
  • 打赏
  • 举报
回复
谢谢BCB_FANS兄的热心帮助,我已将分值加到200分,再请问一下,我想知道某个消息(事件)具体是由哪个元素发出的,在IHTMLEventObj有个get_srcElement的方法可以获得,但现在这种处理消息过程无法获得IHTMLEventObj接口,我是否可以用IHTMLElement接口的put_onmousedown(VARIANT v)或类似的函数,这个好像可以更改事件的处理函数,不知道如何使用,在MSDN上说的不是很明白
pBody->put_onEvent( &_variant_t(pDisp) );
// pDisp a pointer to an IDispatch interface
// pBody a pointer to an element of interest
是不是要自己实现IDispatch接口,在Invoke中写事件处理代码,再用此函数将事件与自己的接口关联起来?
gloom 2002-11-06
  • 打赏
  • 举报
回复
另:BCB_Fans兄,你在截获WM_Paint画图时无法显示是正常的,因为你没有截获WM_NCPAINT,这个也会重绘,我对这两个消息都处理就正常。但我不知道为什么不能获得鼠标消息,
//WebBrowser的DoucmentComplete事件
void __fastcall TForm1::WebDocumentComplete(TObject *Sender,
LPDISPATCH pDisp, Variant *URL)
{
AnsiString str="";
switch (Message.Msg)
{
case WM_LBUTTONDOWN:
str="LButtonDown";
break;
case WM_LBUTTONUP:
str="LButtonUp";
break;
case WM_MOUSEMOVE:
str="MouseMove";
break;
case WM_NCPAINT:
CallWindowProc(FOldAppProc,handle,Message.Msg,Message.WParam,Message.LParam);
pCanvas->MoveTo(20,40);
pCanvas->LineTo(100,200);
return;
case WM_PAINT:
CallWindowProc(FOldAppProc,handle,Message.Msg,Message.WParam,Message.LParam);
pCanvas->MoveTo(20,40);
pCanvas->LineTo(100,200);
return;
default:
return;
}
str+=":"+IntToStr(Message.WParam)+":"+IntToStr(Message.LParam);
Memo1->Lines->Add(str);
return ;
}
//自定义的窗口过程
void __fastcall TForm1::NewAppProc(TMessage& Message)
{
AnsiString str="";
switch (Message.Msg)
{
case WM_LBUTTONDOWN:
str="LButtonDown";
break;
case WM_LBUTTONUP:
str="LButtonUp";
break;
case WM_MOUSEMOVE:
str="MouseMove";
break;
case WM_NCPAINT:
CallWindowProc(FOldAppProc,handle,Message.Msg,Message.WParam,Message.LParam);
pCanvas->MoveTo(20,40);
pCanvas->LineTo(100,200);
return;
case WM_PAINT:
CallWindowProc(FOldAppProc,handle,Message.Msg,Message.WParam,Message.LParam);
pCanvas->MoveTo(20,40);
pCanvas->LineTo(100,200);
return;
default:
return;
}
str+=":"+IntToStr(Message.WParam)+":"+IntToStr(Message.LParam);
Memo1->Lines->Add(str);
return ;
}
上面的代码能在HTML上画出我的图形,但不能获得鼠标和键盘事件啊
gloom 2002-11-06
  • 打赏
  • 举报
回复
让老兄见笑了,我知道WebBrowser的三层结构,我上面省略了几行代码:

HWND handle=Web->Handle;
handle=FindWindowEx(handle,NULL,"Shell DocObject View",NULL);
handle=FindWindowEx(handle,NULL,"Internet Explorer_Server",NULL);
PreWndProc=SetWindowLong(handle,GWL_WNDPROC,MyWndProc);

我还真没有也不会替换过窗口过程,我以前是这样试过,获得Internet Exporer_Server的HDC,再在上面绘图,但窗口内容中的图形无法显示,只有在滚动条的部分能画上去。我觉得DHTML在解析HTML标记时会为其中的元素另外分配HDC资源,如果这样的话要获得这些元素的HDC就更难办了。
bcb_fans 2002-11-06
  • 打赏
  • 举报
回复
1、

不可能啊,我使用我贴的代码测试了,的确可以捕获到鼠标消息。
---------------------------------------------------------------------------
void __fastcall TForm1::NewAppProc(TMessage& Message)
{
Message.Result=::CallWindowProc((FARPROC)FOldAppProc,hIE,
Message.Msg,Message.WParam,Message.LParam);

if(Message.Msg == WM_LBUTTONDOWN)
{
//经过测试,单击鼠标时,这个对话框显示了,证明可以捕获鼠标消息
MessageBox(NULL,"Mouse Down",NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
else if(Message.Msg == WM_PAINT)
{
........


我上面已经说了,必须在主窗口完全显示之后,才能替换IE的窗口过程,否则找不到“Internet Explorer_Server”窗口,你可以进行测试,看看找到没有。

2、你上面贴出的代码让人感到不可思议:

(1)

void __fastcall TForm1::WebDocumentComplete(TObject *Sender,
LPDISPATCH pDisp, Variant *URL)
{
AnsiString str="";
switch (Message.Msg)
{
case WM_LBUTTONDOWN:
str="LButtonDown";
break;

DocumentComplete事件是文件下载完成后触发的事件,你怎么在里边检测鼠标消息?而且,那个Message在哪里定义?

(2)
void __fastcall TForm1::NewAppProc(TMessage& Message)
{
AnsiString str="";
switch (Message.Msg)
{
case WM_LBUTTONDOWN:
str="LButtonDown";
break

为什么不把鼠标消息继续往下传?不继续传,IE怎么知道有鼠标消息发生?
bcb_fans 2002-11-05
  • 打赏
  • 举报
回复
//"Shell Embedding" (针对内嵌的TCppWebBrowser,独立的IE为“IEFrame”)
// + "Shell DocObject View"
// + "Internet Explorer_Server"

可以使用SPY++查看。
bcb_fans 2002-11-05
  • 打赏
  • 举报
回复
不会吧?老兄,难道以前你都没有替换过窗口过程?

1、MyWndProc必须是全局函数。

2、如果想让MyWndProc作为成员函数存在,必须这样做:

FARPROC FOldAppProc;
void* FNewAppObjectInstance;

FOldAppProc = (FARPROC)GetWindowLong(Application->Handle, GWL_WNDPROC);
// NewAppProc作为成员函数存在
FNewAppObjectInstance = MakeObjectInstance(NewAppProc);
SetWindowLong(Application->Handle, GWL_WNDPROC, long(FNewAppObjectInstance));

程序结束的时候调用:

SetWindowLong(Application->Handle, GWL_WNDPROC, long(FOldAppProc));
FreeObjectInstance(FNewAppObjectInstance);

3、你上面贴出的代码:

PreWndProc=SetWindowLong(handle,GWL_WNDPROC,MyWndProc);

我不知道你是随手写的,还是在你的程序就真存在这么一行代码,如果是真存在,你截获的是主窗口的窗口过程,跟IE根本就不沾边。当在IE中打开一个页面之后,它的窗口层次如下:

//"Shell Embedding" (针对内嵌的TCppWebBrowser,独立的IE为“IEFrame”)
// + "Shell DocObject View"
// + "Internet Explorer_Server"

真正应该截获的是窗口"Internet Explorer_Server",比如下面的代码:


HWND hIE;

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if(hIE != NULL)
{
SetWindowLong(hIE, GWL_WNDPROC, long(FOldAppProc));
FreeObjectInstance(FNewAppObjectInstance);
}
}
//---------------------------------------------------------------------------
//必须在主窗口完全显示后,才能进行截获。否则找不到窗口“Internet Explorer_Server”。

void __fastcall TForm1::Button2Click(TObject *Sender)
{
TWinControl *WinCtrl;

WinCtrl = (dynamic_cast<TWinControl*>(CppWebBrowser1));
if(WinCtrl != NULL)
{
hIE = WinCtrl->Handle;
hIE = FindWindowEx(hIE,0,"Shell DocObject View",NULL);
hIE = FindWindowEx(hIE,0,"Internet Explorer_Server",NULL);

if(hIE != NULL)
{
FOldAppProc = (FARPROC)GetWindowLong(hIE, GWL_WNDPROC);
FNewAppObjectInstance = MakeObjectInstance(NewAppProc);
SetWindowLong(hIE, GWL_WNDPROC, long(FNewAppObjectInstance));
}
else
{
Memo1->Lines->Add("Null IE Handle.Err = " + SysErrorMessage(GetLastError()));
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::NewAppProc(TMessage& Message)
{
Message.Result=::CallWindowProc((FARPROC)FOldAppProc,hIE,
Message.Msg,Message.WParam,Message.LParam);

if(Message.Msg == WM_LBUTTONDOWN)
{
HDC hIEDC;

hIEDC = GetDC(hIE);
if(hIEDC != NULL)
{
TCanvas *TempCanvas;

TempCanvas = new TCanvas();
TempCanvas->Handle = hIEDC;
TempCanvas->Brush->Color = clRed;
TempCanvas->FillRect(TRect(2,2,10,10));

delete TempCanvas;
ReleaseDC(hIE,hIEDC);
}
else
{
MessageBox(NULL,AnsiString("Null DC.Err = " + SysErrorMessage(GetLastError())).c_str(),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}

MessageBox(NULL,"Mouse Down",NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
else if(Message.Msg == WM_PAINT)
{
//经过我的测试,发现在这里无法显示自己的图形!奇怪!

HDC hIEDC;

hIEDC = GetDC(hIE);
if(hIEDC != NULL)
{
TCanvas *TempCanvas;

TempCanvas = new TCanvas();
TempCanvas->Handle = hIEDC;
TempCanvas->Brush->Color = clRed;
TempCanvas->FillRect(TRect(2,2,10,10));

ReleaseDC(hIE,hIEDC);
delete TempCanvas;
}
}
}
//---------------------------------------------------------------------------

想实际应用,还有很多的事要做!!!
gloom 2002-11-05
  • 打赏
  • 举报
回复
我这样写怎么编译不通过啊?

//声明WndPron
LRESULT CALLBACK TForm1::MyWndProc( HWND hwnd, UINT msg,UINT wParam, LONG lParam );
//设置WndProc函数
PreWndProc=SetWindowLong(handle,GWL_WNDPROC,MyWndProc);
//错误
[C++ Error] main.cpp(604): E2034 Cannot convert 'long (__stdcall * (_closure )(void *,unsigned int,unsigned int,long))(void *,unsigned int,unsigned int,long)' to 'long'
[C++ Error] main.cpp(604): E2342 Type mismatch in parameter 'dwNewLong' (wanted 'long', got 'void')
bcb_fans 2002-11-05
  • 打赏
  • 举报
回复
不清楚!瞎说一下:

1、根据MSDN的说明,IHTMLEventObj对象只有在事件脚本里边才有实际意义,象你通过OnMessage
那样来编程应该没有效果。说白了,就是使用IHTMLDocument2->put_onmousedown(...)来设置
事件的处理句柄,比如自己实现IDispatch接口,然后调用这个方法来设置,这样发生事件的时
候,你的IDispatch接口就可以得到通知了。

2、想在页面上划线,理论上只要调用GetDC得到IE窗口的句柄就可以画了。问题在于:

(1)当页面中含有Frame时,IE5.0建立子窗口来放那个Frame,比如上下两个Frame充满了IE窗口,
这时候想在页面上画线,也就是说画一条线在那两个窗口上面,难度比较大!?

(2)就算IE中没有Frame,想画线也同样很难!因为只要IE刷新,你画的线就没有了!目前比较的
方法就是截获IE窗口的窗口过程,然后检测消息WM_PAINT :

LRESULT CALLBACK MyWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if(uMsg == WM_PAINT)
{
//先进行正常的绘画
CallWindowProc(.......)

//然后再画自己的东西
.....

return;
}
else
{
CallWindowProc(...);
}
}

瞎说了这么多,也不知道有没有用:)
gloom 2002-11-04
  • 打赏
  • 举报
回复
获得IE页面中的事件应该是一个值得探讨的课题,事件和消息还是不一样的,特别是IE页面中,很多方法都可以获得消息,就如BCB_FANS所言,但IE页面中的事件有特别之处,事件的相关参数全是存放在IHTMLEventObj中,消息中并没有很多相关的参数,所以处理IE页面中的事件都需要IHTMLEventObj接口,但你光是获得消息的话意思不大,很多相关的数据消息中没有,要使用IHTMLEventObj来查询获得,至于用途就更广泛了,我自己是想做一个控件:能够随意在HTML页面上绘线、作标记,如同IMarkup的绘线功能,但这有两个难关,一是如题所述的需要自己处理HTML中的事件,另一个难题是如何获得一个覆盖在整个页面上的一个HDC能够用来绘线,我见过一个例子,利用IE5.5的IHTMLElementBehavior和IHTHLPaint属性基本可实现但它只能附在一个页面元素上,不能对整个文档操作,如果对容器操作也有很大问题,看看兄弟们有没有好的方法,由于我对DHTML对象模型不熟悉,在此劳各位了。
xiaomu2188 2002-11-01
  • 打赏
  • 举报
回复
我也研究过TCppWebBrowser,还真没发现有这样的事件,嗯难!
bcb_fans 2002-11-01
  • 打赏
  • 举报
回复
还是不明白你的意思,如果仅仅是为了得到鼠标消息,可以使用进程中WH_GETMESSAGE Hook!!!只是你想用鼠标消息来做什么?说出这个原因,看看有没有别的办法可以办到。
gloom 2002-11-01
  • 打赏
  • 举报
回复
我就是想处理WebBrowser中的鼠标事件和键盘,其它应该是Doucment的吧。
bcb_fans 2002-10-28
  • 打赏
  • 举报
回复
先说一说你的目的吧!详细一点!
gloom 2002-10-28
  • 打赏
  • 举报
回复
我看过一个VC的示例,不全,要用实现一个Dispatch类,再在这个类的Invoke函数中接收消息,不知道在BCB中应该怎么做,
我尝试了一种非正常的方法,在窗口中加一个TApplicationEvents,在它的OnMessage中处理WebBrowser发出来的消息,但无法获得IHTMLEventObj接口。下面是示例,请各位高手看看是否可行:
//我已经在WebBrowser的DocumentComplete中获得了IHTMLDocument2接口。
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg,
bool &Handled)
{
//如果消息是由WebBrowser发出
if (Msg.hwnd !=Web->Handle) return;
if (Msg.message ==WM_LBUTTONDOWN)
{
//ShowMessage(IntToHex((__int64)Msg.hwnd,8));
//如果尚未加载HTML文件则返回
if (!pDoc2) return;
//下面正常
pDoc2->get_parentWindow(&pWin);
if (!pWin)
{
ShowMessage("无法获得IHTMLWindow2接口");
return;
}
//下面出现错误,无法获得pEvent(IHTMLEventObj)
pWin->get_event(&pEvent);
if (!pEvent)
{
ShowMessage("无法获得IHTMLEventObject");
return;
}
pEvent->get_srcElement(&pElem);
BSTR html;
pElem->get_outerHTML(&html);
ShowMessage(html);
SysFreeString(html);
pEvent->Release();
pElem->Release();
pWin->Release();
}
}
warton 2002-10-26
  • 打赏
  • 举报
回复
这个问题我也考虑过,但是,好像没有这方面的资料!!
加载更多回复(1)

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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