这样取地址为什么不可以?帮忙看看,谢谢

shines77 2005-06-15 05:57:25
var
lpTimerProc: Pointer;

begin
lpTimerProc := Pointer(@Self.OnScrollTimer);
end;

错误如下:

[Error] _Bxxxxx.pas(865): Variable required
...全文
204 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
shines77 2005-06-16
  • 打赏
  • 举报
回复
to Scarlette(Lord of Borland):

陶,好多年没有看见你了,真是巧啊,你竟然这么有空:)时常都会想起原来在上海的同事,你,海峰,李锐,老刀。。。(其实偶是个比较怀旧的人)。我现在在湖南株洲混(原来的一个北京同事自己搞的小公司),你最近玩暴雪的魔兽世界么,我现在和朱海峰同学还有一帮年轻人一块玩:)我们在一区,我估计你也在玩了,这个东西是当初朱海峰2001年告诉我的,结果却是我玩得比较多,去年在家呆了一年玩了很久WoW欧服,现在在一家小公司混饭吃,挣点Money玩WoW。

to kiboisme(蓝色光芒):

碰上老朋友了,心情比较高兴,大概是这样的,我在写一个IE拦截Flash,广告的插件,其中拦截浮动广告的部分,由于无法在BHO(Browser Helper Object)里响应IE的onScroll事件,所以只能用个定时器,在OnTimer里(也就是我自己写的回调函数OnScrollTimer,因为BHO是IE的组件不是窗体,没有WindowProc,也就不能用默认的OnTimer事件)定时的拦截浮动广告的DIV层(好像3721也是这样干的,不是即时拦截的,大概也是用定时器),由于在OnScrollTimer里必须调用类成员变量,无法使用全局的变量(因为IE有可能一个进程可以开多个窗体,每个窗体都会启动一次BHO组件)

lpTimerProc := Pointer(@OnScrollTimer);  // OnScrollTimer写成全局的肯定是可以的

lpTimerProc := Pointer(@TBrowserHelp.OnScrollTimer);  // 如果OnScrollTimer写成类成员函数,但这样也类似于C++的类static成员函数,它没有Self指针,所以会出错

nIDTimer := SetTimer(hwndWB, IDT_SCROLL_TIMER, SCROLL_INTERVAL_TIME, lpTimerProc);

不过我现在想到解决的办法了,在OnScrollTimer里通过hwnd转换出IE的IWebbrowser2或IHTMLDocument2接口,不过目前hwnd有点问题,吃饭先,回来再讨论

蓝色光芒 2005-06-16
  • 打赏
  • 举报
回复
Type
TComEventProc = Procedure(uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;
TCOMOBJ_Test = Class(TComObject)
private
F : TComEventProc;
public
property OnEvent : TComEventProc read F Write F;
published
end;



var
Obj : TCOMOBJ_Test;
P1 : Pointer;
begin
//OBJ := TCOMOBJ_Test.Create;//这样直接创建要出错。^_^
P1 := @OBJ.OnEvent;
if P1 = NIL then exit;
end;
直接就可以编译,我不知道你是不是这个意思?
shines77 2005-06-16
  • 打赏
  • 举报
回复
to ZyxIp(绝望中...)
像你那样可以,但是一样没有Self指针

to kiboisme(蓝色光芒):
var
Obj : TCOMOBJ_Test;
P1 : Pointer;
begin
//OBJ := TCOMOBJ_Test.Create;//这样直接创建要出错。^_^
P1 := @OBJ.OnEvent; // *** 估计这里跟 P1 := @TCOMOBJ_Test.OnEvent; 是一样的
if P1 = NIL then exit;
end;

另……问题已经解决,我已经可以把hwnd转换成相应的IWebBrowser2,代码如下:

function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
hInst: HWND;
lRes: Cardinal;
MSG: Integer;
pDoc: IHTMLDocument2;
ObjectFromLresult: TObjectFromLresult;
begin
Result := S_FALSE;
hInst := LoadLibrary('Oleacc.dll');
if hInst <> 0 then
begin
@ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult');
if @ObjectFromLresult <> nil then
begin
try
MSG := RegisterWindowMessage('WM_HTML_GETOBJECT');

SendMessageTimeOut(WHandle, MSG, 0, 0, SMTO_ABORTIFHUNG, 50, lRes); // 这里用50ms会不会太短了?我程序好像有点慢,所以我改为这个值,一帮用1000ms
Result := ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc);
if Result = S_OK then
begin
(pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp, IWebbrowser2, IE);
end;
finally
// do nothing
end;
end;
FreeLibrary(hInst);
end;
end;

function GetIEFromWBHWND(hwndWB: HWND; var IE: IWebbrowser2): HRESULT;
var
WndChild: Integer;
begin
Result := S_FALSE;
// walk Shell DocObject View->Internet Explorer_Server
WndChild := FindWindowEX(hwndWB, 0, 'Shell DocObject View', nil);
if WndChild <> 0 then
begin
WndChild := FindWindowEX(WndChild, 0, 'Internet Explorer_Server', nil);
if WndChild <> 0 then
Result := GetIEFromHWND(WndChild, IE); // Get Iwebbrowser2 from Handle
end;
end;
Scarlette 2005-06-15
  • 打赏
  • 举报
回复
……晕……

Object Pascal的Event不是4字节的指针,是8字节的!这和C++的“类方法指针”有点类似,不过C++的类方法指针内保存的是入口地址或VMT索引、调用约定、是否为virtual等等;Object Pascal保存的是实例指针(Self)、调用约定、VMT索引,但不用保存是否为virtual,因为Object Pascal的编译器将Event Handler Method一律编译为Dynamic,不管你用了什么指示字(常规、virtual、dynamic)。

你是没得选的,把Callback连接到一个事件只能加一个wrapper的。

另……郭子你消失那么多年了,现在在哪里混?
shines77 2005-06-15
  • 打赏
  • 举报
回复
to kiboisme(蓝色光芒):

我的还是不行,为什么你的可以?我的类是派生自TComObject,不会是因为这个吧,我是Delphi 7

to ZyxIp(绝望中...):

先下班了,明天再试试你的代码,谢谢
ZyxIp 2005-06-15
  • 打赏
  • 举报
回复
Type
TOnScrollTimerEvent=Procedure (Value:Integer) of object;

TTest_Obj=Class
procedure OnScrollTimer(Value:Integer);
end;
vea
AOnScrollTimer:TOnScrollTimerEvent;
begin
AOnScrollTimer:=Self.OnScrollTimer;
end;
shines77 2005-06-15
  • 打赏
  • 举报
回复
procedure TBrxxxxx.OnScrollTimer(uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;

我试试你的
蓝色光芒 2005-06-15
  • 打赏
  • 举报
回复
//晕,我这里可以啊。
var
P : Pointer;
begin
P := TMethod(Self.OnMouseMove).Code;
end;

你的OnScrollTimer是个什么样子的过程?
shines77 2005-06-15
  • 打赏
  • 举报
回复
还是不行
[Error] _BrowserHelp.pas(899): Invalid typecast
蓝色光芒 2005-06-15
  • 打赏
  • 举报
回复
但是成员函数的指针和一般的Procedure/Function不一样。值得注意。
蓝色光芒 2005-06-15
  • 打赏
  • 举报
回复
var
P : Pointer;
begin
P := TMethod(Self.OnScrollTimer).Code;
end;
shines77 2005-06-15
  • 打赏
  • 举报
回复
还是不行,难道无法取得实现的成员函数的地址??
shines77 2005-06-15
  • 打赏
  • 举报
回复
还是错的
[Error] _BrowserHelp.pas(865): Not enough actual parameters

也许我知道怎么做了,申明一个函数指针类型
g961681 2005-06-15
  • 打赏
  • 举报
回复
lpTimerProc := Pointer(Self.OnScrollTimer);应该就可以了吧!
shines77 2005-06-15
  • 打赏
  • 举报
回复
如果把OnScrollTimer作为全局的函数,则lpTimerProc := Pointer(@OnScrollTimer); 是可以的

可是我不想弄为全局的,因为我需要Self的指针值。

或者谁知道如果在SetTimer()时传递一个结构的地址给OnScrollTimer,如果OnScrollTimer为全局的,我必须向办法把Self的地址传给OnScrollTimer。如果@Self.OnScrollTimer可行,就不必传了。该怎么弄?

原始的代码如下:
lpTimerProc := Pointer(@Self.OnScrollTimer);
nIDTimer := SetTimer(hwndWB, IDT_SCROLL_TIMER, SCROLL_INTERVAL_TIME, lpTimerProc);
if nIDTimer <> 0 then
begin
....
end;

5,928

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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