Delphi 在自定义控件中使用TNotifyEvent时无法检测按键
我有一个来自Delphi 在自定义控件中使用TNotifyEvent时无法检测按键,delphi,Delphi,我有一个来自TCustomListBox的自定义控件,我正试图在我的组件源代码中重写OnKeyDown方法 我遇到的问题是,当使用我的组件时,我无法检测到按下了什么键。参数var关键字:Word似乎已变得多余,因此我不确定是否以正确的方式执行此操作,这可能解释了我的问题 下面是一个精简的源代码示例: type TMyListBox = class(TCustomListBox) private FOnClick: TNotifyEvent; FOnKeyDown: TNo
TCustomListBox
的自定义控件,我正试图在我的组件源代码中重写OnKeyDown
方法
我遇到的问题是,当使用我的组件时,我无法检测到按下了什么键。参数var关键字:Word
似乎已变得多余,因此我不确定是否以正确的方式执行此操作,这可能解释了我的问题
下面是一个精简的源代码示例:
type
TMyListBox = class(TCustomListBox)
private
FOnClick: TNotifyEvent;
FOnKeyDown: TNotifyEvent;
FOnMouseDown: TNotifyEvent;
protected
procedure Click; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnClick: TNotifyEvent read FOnClick write FOnClick;
property OnKeyDown: TNotifyEvent read FOnKeyDown write FOnKeyDown;
property OnMouseDown: TNotifyEvent read FOnMouseDown write FOnMouseDown;
end;
implementation
constructor TMyListBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OnClick := FOnClick;
OnKeyDown := FOnKeyDown;
OnMouseDown := FOnMouseDown;
end;
destructor TMyListBox.Destroy;
begin
inherited Destroy;
end;
procedure TMyListBox.Click();
begin
inherited;
// do something
if Assigned(FOnClick) then
FOnClick(Self);
end;
procedure TMyListBox.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited;
// do something
if Assigned(FOnKeyDown) then
FOnKeyDown(Self);
end;
procedure TMyListBox.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited;
// do something
if Assigned(FOnMouseDown) then
FOnMouseDown(Self);
end;
在常规项目中尝试我的组件时:
procedure TForm1.MyListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_DELETE then
begin
ShowMessage('test'); // never triggers
end;
end;
我想这可能与我如何凌驾于事件之上有关?listbox键控的标准声明如下所示:
procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
//
end;
区别在于Sender
参数,但我在我的组件源代码中不使用该参数
因此,我想知道为什么我无法检测到按下的键,以及我是否应该以不同/更好的方式重写这些方法
谢谢。
OnKeyDown
、onkeydup
和OnKeyPress
都不是TNotifyEvents
OnKeyDown
和onkeydup
是TKeyEvent
,而OnKeyPress
是TKeyPressEvent
TNotifyEvent
定义为
type
TNotifyEvent = procedure (Sender: TObject) of object;
TKeyEvent
和TKeyPressEvent
的定义如下:
type
TKeyEvent = procedure(Sender: TObject; var Key: Word;
Shift: TShiftState) of object;
TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object;
因此,如果将FOnKeyDown
声明为typeTNotifyEvent
,则它可以接受的唯一参数是Sender:TObject
。如果希望它接受与TKeyEvent
相同的参数,则将其声明为TKeyEvent
。这同样适用于TMouseEvent
和OnClick
或者,更好的方法是将它们升级为从祖先发布,因为它们已经在TCustomListBox
中声明为受保护:
type
TMyListBox = class(TCustomListBox)
protected
procedure Click; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnClick;
property OnKeyDown;
property OnMouseDown;
end;
发件人
将自动为您提供;这是触发事件的组件。因此,在OnClick
处理程序中,TButton
,Sender
将是单击的按钮。你没有选择是否接受它;VCL将这样做。您可以选择不使用它,但无论您是否愿意,您都将获得它(并且必须声明您的过程正在接收它)。OnKeyDown
、onkeydup
和OnKeyPress
都不是TNotifyEvents
OnKeyDown
和onkeydup
是TKeyEvent
,而OnKeyPress
是TKeyPressEvent
TNotifyEvent
定义为
type
TNotifyEvent = procedure (Sender: TObject) of object;
TKeyEvent
和TKeyPressEvent
的定义如下:
type
TKeyEvent = procedure(Sender: TObject; var Key: Word;
Shift: TShiftState) of object;
TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object;
因此,如果将FOnKeyDown
声明为typeTNotifyEvent
,则它可以接受的唯一参数是Sender:TObject
。如果希望它接受与TKeyEvent
相同的参数,则将其声明为TKeyEvent
。这同样适用于TMouseEvent
和OnClick
或者,更好的方法是将它们升级为从祖先发布,因为它们已经在TCustomListBox
中声明为受保护:
type
TMyListBox = class(TCustomListBox)
protected
procedure Click; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnClick;
property OnKeyDown;
property OnMouseDown;
end;
发件人
将自动为您提供;这是触发事件的组件。因此,在OnClick
处理程序中,TButton
,Sender
将是单击的按钮。你没有选择是否接受它;VCL将这样做。您可以选择不使用它,但无论您是否愿意,您都将获得它(并且必须声明您的过程正在接收它)。因此,您正在尝试创建自己的OnKeyDown
和OnMouseDown
类型的TNotifyEvent
事件,但是在您的项目中,您希望它们的类型是TKeyEvent
和TMouseEvent
?或者问题出在哪里?只要看看TListBox
的源代码并从中学习:o)@TLama当你这样说的时候,我所做的看起来确实很奇怪,直到后来有人向我指出这个问题,我才意识到这个问题。因此,你试图制作自己的OnKeyDown
和OnMouseDown
类型的TNotifyEvent
事件,但在你的项目中,你希望它们是TKeyEvent
和TMouseEvent
类型的?或者问题出在哪里?只要看看TListBox
的源代码,并从中学习:o)@TLama当你这样说的时候,我所做的确实很奇怪,直到后来有人向我指出,我才意识到问题的存在。好东西,谢谢你的帮助和意见肯:)我想为前几周的事道歉,因为我可能对你说了攻击性的或粗鲁的话,所以没有什么不愉快的感觉?:-)好极了:)我现在明白我做错了什么,尤其是在特拉玛的评论之后。基本上,我是在将正确定义的键盘和鼠标事件转换为标准事件,因此正如您在回答中所说,我只是删除了所有TNotifyEvent内容,并更改了发布的方法,如:property OnClick代码>好东西,谢谢你的帮助和输入肯:)我想为前几周的事道歉,因为我可能对你说了攻击性的或粗鲁的话,所以没有什么不愉快的感觉?:-)好极了:)我现在明白我做错了什么,尤其是在特拉玛的评论之后。基本上,我是在将正确定义的键盘和鼠标事件转换为标准事件,因此正如您在回答中所说,我只是删除了所有TNotifyEvent内容,并更改了发布的方法,如:property OnClick代码>