2016-12-07 101 views
1

我在一個巨大的,傳統的源代碼中有幾個體育項目的SetFocus叫工作,但如果控制是可見或不啓用檢查。避免SetFocus的拋出一個異常

由於時間有限,和源代碼的數量巨大,我決定,我要忽略這些錯誤,因爲重點是(在本例中)不是一個關鍵的功能。引發異常會導致完全失敗,而錯過的焦點只是一個光學問題。

我目前的計劃是以下:

1)I創建單元,其具有類輔助這樣的:

type 
    TWinControlEx = class helper for TWinControl 
    procedure SetFocusSafe; 
    end; 

procedure TWinControlEx.SetFocusSafe; 
begin 
    if CanFocus then SetFocus; 
end; 

2)I包括單元,其使用 「.SETFOCUS」 每單元(我將使用全局代碼搜索)

3)我每次更換與.SETFOCUS .SetFocusSafe

還有一個問題是:如果有可能,我想避免的同事ACC最好使用.SetFocus,或忘記包含classhelper單元。

我還有哪些其他選擇?

最好的情況是,如果有一種技術/黑客以使SetFocus的不引發異常。 (無需重新編譯VCL)

+3

這將很容易來修復代碼正確的比你建議的要好。 –

+1

同意最好的解決方案就是解決它。如果你在一個無法集中的控件上調用'SetFocus',那麼你的代碼會以某種方式與應用程序的預期狀態不同步。這指出了您在不恰當的上下文中執行代碼的更廣泛的問題。如果應用程序的狀態不是你所期望的,然後它表明,別的東西已經錯了以前可能級聯到更多的問題向前走了。 –

回答

4

只是修補TWinControl.SetFocus方法:

unit SetFocusFix; 

interface 

implementation 

uses 
    Controls, 
    Forms, 
    SysUtils, 
    Windows; 

type 
    TWinControlHack = class(TWinControl) 
    public 
    procedure SetFocus; override; 
    end; 

procedure TWinControlHack.SetFocus; 
var 
    Parent: TCustomForm; 
begin 
    if not CanFocus then Exit; 

    Parent := GetParentForm(Self); 
    if Parent <> nil then 
    Parent.FocusControl(Self) 
    else if ParentWindow <> 0 then 
    Windows.SetFocus(Handle) 
    else 
    ValidParentForm(Self); 
end; 

procedure RedirectFunction(OrgProc, NewProc: Pointer); 
type 
    TJmpBuffer = packed record 
    Jmp: Byte; 
    Offset: Integer; 
    end; 
var 
    n: UINT_PTR; 
    JmpBuffer: TJmpBuffer; 
begin 
    JmpBuffer.Jmp := $E9; 
    JmpBuffer.Offset := PByte(NewProc) - (PByte(OrgProc) + 5); 
    if not WriteProcessMemory(GetCurrentProcess, OrgProc, @JmpBuffer, SizeOf(JmpBuffer), n) then 
    RaiseLastOSError; 
end; 

initialization 
    RedirectFunction(@TWinControl.SetFocus, @TWinControlHack.SetFocus); 

end. 
3

或者

TWinControlEx = class helper for TWinControl 
    procedure SetFocus; reintroduce; 
    end; 

與...

procedure TWinControlEx.SetFocus; 
var 
    Parent: TCustomForm; 
begin 
    if not CanFocus then Exit; 
    Parent := GetParentForm(Self); 
    if Parent <> nil then 
    Parent.FocusControl(Self) 
    else if ParentWindow <> 0 then 
    Winapi.Windows.SetFocus(Handle) 
    else 
    ValidParentForm(Self); 
end;