2016-12-07 152 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;