2014-09-06 3 views
0

브라우저에서 응용 프로그램을 가상화하기 위해 Thinfinity UI을 사용하기 시작했습니다. 가상화 될 때 애플리케이션의 기본 창은 브라우저 캔버스의 경계까지 최대화됩니다. 사실상 데스크탑은 브라우저 캔버스의 크기로 축소됩니다. 또한 팝업 메뉴와 같은 컨트롤을 배치 할 때 브라우저 캔버스의 경계를 초과하는 경우가 종종 있습니다.Vcl.Forms.TScreen.WorkAreaRect에서 반환 한 값을 변경할 수 있습니까?

Vcl.Forms.TScreen.WorkAreaRect에 대한 호출 결과를 브라우저 캔버스의 경계에 설정할 수 있다면이 문제를 극복 할 수 있다고 생각합니다. 이것이 가능한가?

+1

소스 코드를보고 교체해야 할 사항을 찾아 우회하십시오. 필요한 것을 수행하는 최저 수준의 기능을 우회하십시오. –

답변

3

@GadDLord의 How to change the implementation (detour) of an externally declared function을 기반으로 TScreen.GetWorkAreaRect에서 사용되는 SystemParametersInfoW를 연결할 수 있습니다. 죽은 링크를 막기 위해 코드 부분을 복사했습니다.

type 
    //strctures to hold the address and instructions to patch 
    TJumpOfs = Integer; 
    PPointer = ^Pointer; 

    PXRedirCode = ^TXRedirCode; 
    TXRedirCode = packed record 
    Jump: Byte; 
    Offset: TJumpOfs; 
    end; 

    PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp; 
    TAbsoluteIndirectJmp = packed record 
    OpCode: Word; 
    Addr: PPointer; 
    end; 

var 
DataCompareBackup: TXRedirCode; //Store the original address of the function to patch 

//get the address of a procedure or method of a function 
function GetActualAddr(Proc: Pointer): Pointer; 
begin 
    if Proc <> nil then 
    begin 
    if (Win32Platform = VER_PLATFORM_WIN32_NT) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then 
     Result := PAbsoluteIndirectJmp(Proc).Addr^ 
    else 
     Result := Proc; 
    end 
    else 
    Result := nil; 
end; 

//patch the original function or procedure 
procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode); 
var 
    n: {$IFDEF VER230}NativeUInt{$ELSE}DWORD{$ENDIF}; 
    Code: TXRedirCode; 
begin 
    Proc := GetActualAddr(Proc); 
    Assert(Proc <> nil); 
    //store the address of the original procedure to patch 
    if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then 
    begin 
    Code.Jump := $E9; 
    Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code); 
    //replace the target procedure address with the new one. 
    WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n); 
    end; 
end; 
//restore the original address of the hooked function or procedure 
procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode); 
var 
    n: {$IFDEF VER230}NativeUInt{$ELSE}Cardinal{$ENDIF}; 
begin 
    if (BackupCode.Jump <> 0) and (Proc <> nil) then 
    begin 
    Proc := GetActualAddr(Proc); 
    Assert(Proc <> nil); 
    WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n); 
    BackupCode.Jump := 0; 
    end; 
end; 


function MySystemParametersInfo(uiAction, uiParam: UINT; 
    pvParam: Pointer; fWinIni: UINT): BOOL; stdcall; 
begin 
    Result := SystemParametersInfoA(uiAction, uiParam,pvParam,fWinIni); 
    if uiAction=SPI_GETWORKAREA then 
     begin 
     // Fake just for demo 
     TRect(pvParam^).Right := 1234; 
     end 
end; 


procedure TForm3.Button1Click(Sender: TObject); 
begin 
    Caption := IntToStr(Screen.WorkAreaRect.Right) 
end; 

initialization 
HookProc(@SystemParametersInfoW, @MySystemParametersInfo, DatacompareBackup); 
finalization 
UnHookProc(@SystemParametersInfoW, DatacompareBackup);