2

为了解决我们系统中的一些问题,我需要实现事件 OnKeyDownOnKeyPress框架(TFrame)。目前做了一个姑息的解决方案,但它非常难看并且存在任何问题。

该过程或多或少如下:

1) 我创建了这个事件OnKeyDown并且OnKeyPress

2)在一个基于TForm的标准表单中,实现了一个拦截执行键的控件。因此,此过程在框架上执行第一个关键事件,然后在表单上执行关键事件。

我不得不这样做,因为我希望 OnKeyDown 事件在框架之前和表单之后执行。实现工作,但我会考虑更好的代码。

任何人都可以提出更好的解决方案吗?有没有更优雅的方法来解决这个问题?

4

2 回答 2

2

尝试这个。与其创建 TFrame 后代,不如在框架中创建 KeyDown 和 KeyPress 过程,例如

procedure TFrame2.KeyDown(var Key: Word; Shift: TShiftState);
begin
  Memo1.Lines.Add('KeyDown: '+IntToStr(Key));
end;

procedure TFrame2.KeyPress(var Key: Char);
begin
  Memo1.Lines.Add('KeyPress: '+IntToStr(ord(Key)));
end;

然后从形式的 OnKeyDown 和 OnKeyPress 调用它们,例如

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Frame21.KeyDown(Key,Shift);
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  Frame21.KeyPress(Key);
end;
于 2013-10-09T02:59:06.567 回答
1

我做了一些更多的测试,得到了一个更简单的解决方案,该解决方案的原理没有问题。

1)我通过递归函数获得了我的框架的基础类型对象。

2) 如果活动控件包含在标准框架中,则调用 OnKeyDown、OnKeyPress 事件执行。

如果有人需要什么,下面是我的应用程序测试代码。

Unit UnFrameBase;

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, ActnList;

Type
  TFrameBase = Class(TFrame)
    PnlBase: TPanel;
  Private
  Public
    Procedure EventFrameKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState); Virtual;
  End;

Implementation


{$R *.dfm}

{ TFrameBase }

Procedure TFrameBase.EventFrameKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState);
Begin
  //nothing
End;

End.


Unit UnControlsClassTest;

interface

uses Classes, Controls;

Function ActiveControlAs(AControl: TWinControl;
  AClass: TWinControlClass): TWinControl;

    Function CheckControl(Var C: TWinControl; ControlClass: TWinControlClass): Boolean;
    Var
      Parent: TWinControl;
    Begin
      Result := (C Is ControlClass);
      If (Result = False) And (C <> Nil) And (C.Parent <> Nil) Then
      Begin
        Parent := C.Parent;
        Result := CheckControl(Parent, ControlClass);
        If Result Then
          C := Parent;
      End;
    End;


Var
  C: TWinControl;

Begin
  C := AControl;
  If CheckControl(C, AClass) Then
    Result := C
  Else
    Result := Nil;

End;


Unit UnMainFormTest;

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, UnFrameCustomer,  UnFrameBase;

Type
  TFormMain = Class(TForm)
    Procedure FormCreate(Sender: TObject);
    Procedure BtnTestarClick(Sender: TObject);
    Procedure FormKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState);
  Private
    Function GetInstanceActiveFrame(AActiveControl: TWinControl): TFrameBase;
  Public
    { Public declarations }
  End;

Implementation

Uses UnControlsClassTest;

{$R *.dfm}


Function TFormMain.GetInstanceActiveFrame(AActiveControl: TWinControl): TFrameBase;
Begin
  Result := TFrameBase(ActiveControlAs(AActiveControl, TFrameBase));
End;

Procedure TFormMain.FormKeyDown(Sender: TObject; Var Key: Word; Shift: TShiftState);
Var
  LActiveFrame: TFrameBase;

Begin
  LActiveFrame := GetInstanceActiveFrame(ActiveControl);
  If Assigned(LActiveFrame) Then
    LActiveFrame.EventoFrameKeyDown(Sender, Key, Shift);

  If Key In [VK_DOWN, VK_RETURN] Then
  Begin
    Perform(WM_NEXTDLGCTL, 0, 0);
    Key := 0;
  End
  Else If Key = VK_UP Then
  Begin
    Perform(WM_NEXTDLGCTL, 1, 0);
    Key := 0;
  End;
End;
于 2013-10-09T17:45:15.620 回答