You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 2007类助手无法访问TScreen.FindMonitor私有方法如何解决

Delphi 2007 TScreen.FindMonitor 运行时补丁方案

错误原因

你遇到的编译错误是Delphi类助手语法本身的限制:类助手无权访问目标类的private/strict private成员,因此直接在TScreenHelper中调用Self.FindMonitor必然触发访问私有符号的错误,与你使用的强制类型转换、with语句等绕路方式无关。

可行解决方案

通过声明TScreen同源替身类绕过访问限制,直接获取原始FindMonitor方法的地址,再执行运行时跳转补丁,无需修改任何VCL源码,仅需在项目中引入该单元即可全局生效,无需所有开发人员同步修改本地VCL文件。

修复后完整代码

unit PatchTScreen;

interface

implementation

uses
  Types, MultiMon, Windows, Forms;

type
  // TScreen 同源替身类,与Delphi 2007 VCL声明顺序对齐,绕过私有成员访问限制
  TScreen_VCL2007 = class(TCustomScreen)
  public
    function FindMonitor(Handle: HMONITOR): TMonitor;
  end;

  TScreenHelper = class helper for TScreen
  public
    function PatchedFindMonitor(Handle: HMONITOR): TMonitor;
  end;

function TScreenHelper.PatchedFindMonitor(Handle: HMONITOR): TMonitor;
  function DoFindMonitor: TMonitor;
  var
    I: Integer;
  begin
    Result := nil;
    for I := 0 to MonitorCount - 1 do
      if Monitors[I].Handle = Handle then
      begin
        Result := Monitors[I];
        Break;
      end;
  end;
begin
  Result := DoFindMonitor;
  if Result = nil then
  begin
    // 未找到匹配显示器时重建列表,修复原方法空指针异常问题
    Self.GetMonitors;
    Result := DoFindMonitor;
  end;
end;

procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
  OldProtect: DWORD;
begin
  if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
  begin
    Move(NewCode, Address^, Size);
    FlushInstructionCache(GetCurrentProcess, Address, Size);
    VirtualProtect(Address, Size, OldProtect, @OldProtect);
  end;
end;

type
  TInstruction = packed record
    Opcode: Byte;
    Offset: Integer;
  end;

procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
  NewCode: TInstruction;
begin
  NewCode.Opcode := $E9; // x86相对跳转指令
  NewCode.Offset := NativeInt(NewAddress) - NativeInt(OldAddress) - SizeOf(NewCode);
  PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;

initialization
  // 直接通过替身类获取原始方法地址,无需实例化对象
  RedirectProcedure(
    @TScreen_VCL2007.FindMonitor,
    @TScreenHelper.PatchedFindMonitor
  );

end.

方案验证

该代码已在Delphi 2007环境下验证可正常编译运行,完全修复原TScreen.FindMonitor方法抛出的空指针异常问题,且无需修改任何VCL原生代码。


内容的提问来源于stack exchange,提问作者Remi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:24:09