I have an old Delphi VCL project build in Rad Studio 2007. This version contains a bug in the TScreen.FindMonitor method. I am trying to fix this using a seperate helper class like stated in Is there a runtime patch for AV in TMonitor.GetBoundsRect?. The only problem is that I can't get this to work. Delphi can't compile and gives error "Cannot access private symbol TScreen.FindMonitor". Also tried using a WITH self DO statement, casting self to TScreen, casting to pointer and using MethodAddress, but nothing seems to work.
My code
unit PatchTScreen;
interface
implementation
uses
  Types, MultiMon, Windows, Forms;
type
  TFindMonitorMethod = function(Handle: HMONITOR): TMonitor of object;
  TScreenHelper = class helper for TScreen
  private
    function FindMonitorAddress: Pointer;
    function PatchedFindMonitorAddress: Pointer;
    function PatchedFindMonitor(Handle: HMONITOR): TMonitor;
  end;
function TScreenHelper.FindMonitorAddress: Pointer;
var
  MethodPtr: TFindMonitorMethod;
begin
  MethodPtr := Self.FindMonitor;
  Result := TMethod(MethodPtr).Code;
end;
function TScreenHelper.PatchedFindMonitorAddress: Pointer;
var
  MethodPtr: TFindMonitorMethod;
begin
  MethodPtr := Self.PatchedFindMonitor;
  Result := TMethod(MethodPtr).Code;
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
    // If we didn't find the monitor, rebuild the list (it may have changeed)
    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
  PInstruction = ^TInstruction;
  TInstruction = packed record
    Opcode: Byte;
    Offset: Integer;
  end;
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
  NewCode: TInstruction;
begin
  NewCode.Opcode := $E9;//jump relative
  NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
  PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
initialization
  RedirectProcedure(
    TScreen(nil).FindMonitorAddress,       // safe to use nil, don't need to instantiate an object
    TScreen(nil).PatchedFindMonitorAddress // likewise
  );
end.
The compile error occures in TScreenHelper.FindMonitorAddress.
The only way I have been able to fix this issue is by changing the original Delphi code of TScreen.FindMonitor in Forms.pas and recomipling the unit with my project. But this is not an actual solution I would like to use, because other developers must make the same changes etc.
