Delphi 64 位 DLL:OleCtrls 事件问题
Delphi 64bit DLL: OleCtrls events issues
我已经将 DLL 从 32 位转换为 64 位,没有任何问题,但是当我从占用大量内存的 64 位应用程序加载此 DLL 时,应用程序崩溃并在加载 DLL 时自行关闭。
DLL 是一个带有 TWebBrowser 的简单表单。我使用 Delphi 10 西雅图。
调试后发现vcl单元有64位转换问题"Vcl.OleCtrls.pas"这样解决:
procedure TOleControl.HookControlWndProc;
var
WndHandle: HWnd;
begin
if (FOleInPlaceObject <> nil) and (WindowHandle = 0) then
begin
WndHandle := 0;
FOleInPlaceObject.GetWindow(WndHandle);
if WndHandle = 0 then raise EOleError.CreateRes(@SNoWindowHandle);
WindowHandle := WndHandle;
//DefWndProc := Pointer(GetWindowLong(WindowHandle, GWL_WNDPROC));//OLD
DefWndProc := Pointer(GetWindowLongPtr(WindowHandle, GWL_WNDPROC));
CreationControl := Self;
//SetWindowLong(WindowHandle, GWL_WNDPROC, Longint(@InitWndProc));//OLD
SetWindowLongPtr(WindowHandle, GWL_WNDPROC, LONG_PTR(@InitWndProc));
SendMessage(WindowHandle, WM_NULL, 0, 0);
end;
end;
这解决了崩溃问题,但不再触发 TWebBrowser 事件并且仅在 64 位上发生。
如何修复 TWebBrowser 事件?
您是否发现类似问题或解决事件的解决方法?
谢谢
我发现另一个生成 TWebBrowser 事件问题的转换错误。
在 Emba 单位 "Vcl.OleCtrls.pas":
procedure TOleControl.InvokeEvent(DispID: TDispID; var Params: TDispParams);
{$IFDEF CPUX64}
var
EventMethod: TMethod;
ParamBlock : TParamBlock;
i : Integer;
StackParams2 : array of Int64;
begin
GetEventMethod(DispID, EventMethod);
//if Integer(EventMethod.Code) < 000 then Exit; //OLD
if Int64(EventMethod.Code) < 000 then Exit; //NEW
ParamBlock.RegRCX := Int64(EventMethod.Data);
ParamBlock.RegRDX := Int64(Self);
if Params.cArgs > 2 then
begin
SetLength(StackParams2, Params.cArgs-2);
end;
for i := 1 to Params.cArgs do
case i of
1: ParamBlock.RegR8 := Int64(Params.rgvarg[Params.cArgs-1].unkVal);
2: ParamBlock.RegR9 := Int64(Params.rgvarg[Params.cArgs-2].unkVal);
else
StackParams2[i-3] := Int64(Params.rgvarg[Params.cArgs-i].unkVal);
end;
ParamBlock.StackDataSize := Length(StackParams2) * sizeof(Pointer);
ParamBlock.StackData := @StackParams2[0];
RawInvoke(EventMethod.Code, @ParamBlock);
end;
{$ELSE !CPUX64}
整数转换产生溢出,内存使用率高,InvokeEvent 过程退出时未调用实际事件。使用 Int64 转换解决。
我希望 Emba 能够集成此修复并找到类似的。
我已经将 DLL 从 32 位转换为 64 位,没有任何问题,但是当我从占用大量内存的 64 位应用程序加载此 DLL 时,应用程序崩溃并在加载 DLL 时自行关闭。
DLL 是一个带有 TWebBrowser 的简单表单。我使用 Delphi 10 西雅图。
调试后发现vcl单元有64位转换问题"Vcl.OleCtrls.pas"这样解决:
procedure TOleControl.HookControlWndProc;
var
WndHandle: HWnd;
begin
if (FOleInPlaceObject <> nil) and (WindowHandle = 0) then
begin
WndHandle := 0;
FOleInPlaceObject.GetWindow(WndHandle);
if WndHandle = 0 then raise EOleError.CreateRes(@SNoWindowHandle);
WindowHandle := WndHandle;
//DefWndProc := Pointer(GetWindowLong(WindowHandle, GWL_WNDPROC));//OLD
DefWndProc := Pointer(GetWindowLongPtr(WindowHandle, GWL_WNDPROC));
CreationControl := Self;
//SetWindowLong(WindowHandle, GWL_WNDPROC, Longint(@InitWndProc));//OLD
SetWindowLongPtr(WindowHandle, GWL_WNDPROC, LONG_PTR(@InitWndProc));
SendMessage(WindowHandle, WM_NULL, 0, 0);
end;
end;
这解决了崩溃问题,但不再触发 TWebBrowser 事件并且仅在 64 位上发生。
如何修复 TWebBrowser 事件?
您是否发现类似问题或解决事件的解决方法?
谢谢
我发现另一个生成 TWebBrowser 事件问题的转换错误。 在 Emba 单位 "Vcl.OleCtrls.pas":
procedure TOleControl.InvokeEvent(DispID: TDispID; var Params: TDispParams);
{$IFDEF CPUX64}
var
EventMethod: TMethod;
ParamBlock : TParamBlock;
i : Integer;
StackParams2 : array of Int64;
begin
GetEventMethod(DispID, EventMethod);
//if Integer(EventMethod.Code) < 000 then Exit; //OLD
if Int64(EventMethod.Code) < 000 then Exit; //NEW
ParamBlock.RegRCX := Int64(EventMethod.Data);
ParamBlock.RegRDX := Int64(Self);
if Params.cArgs > 2 then
begin
SetLength(StackParams2, Params.cArgs-2);
end;
for i := 1 to Params.cArgs do
case i of
1: ParamBlock.RegR8 := Int64(Params.rgvarg[Params.cArgs-1].unkVal);
2: ParamBlock.RegR9 := Int64(Params.rgvarg[Params.cArgs-2].unkVal);
else
StackParams2[i-3] := Int64(Params.rgvarg[Params.cArgs-i].unkVal);
end;
ParamBlock.StackDataSize := Length(StackParams2) * sizeof(Pointer);
ParamBlock.StackData := @StackParams2[0];
RawInvoke(EventMethod.Code, @ParamBlock);
end;
{$ELSE !CPUX64}
整数转换产生溢出,内存使用率高,InvokeEvent 过程退出时未调用实际事件。使用 Int64 转换解决。
我希望 Emba 能够集成此修复并找到类似的。