Delphi Tshift Vcl.Controls和System.class中的状态
我正在为我的应用程序编写一个新组件,它使用鼠标事件和按键事件。鼠标事件和按键事件都需要参数类型TShiftState,尽管在引入按键事件声明后,我收到以下三种方法的错误“E2009不兼容类型:'参数列表不同'” 申报代码如下:Delphi Tshift Vcl.Controls和System.class中的状态,delphi,Delphi,我正在为我的应用程序编写一个新组件,它使用鼠标事件和按键事件。鼠标事件和按键事件都需要参数类型TShiftState,尽管在引入按键事件声明后,我收到以下三种方法的错误“E2009不兼容类型:'参数列表不同'” 申报代码如下: TOnKeyDownEvent = procedure(Sender: TObject; Key : Word; Shift : TShiftState) of object; TOnKeyPressEvent = procedure(Sender: TObject; K
TOnKeyDownEvent = procedure(Sender: TObject; Key : Word; Shift : TShiftState) of object;
TOnKeyPressEvent = procedure(Sender: TObject; Key : Char) of object;
TOnKeyUpEvent = procedure(Sender: TObject; Key : Word; Shift : TShiftState) of object;
FOnKeyDownEvent : TOnKeyDownEvent;
FOnKeyPressEvent : TOnKeyPressEvent;
FOnKeyUpEvent : TOnKeyUpEvent;
property OnKeyDownEvent : TOnKeyDownEvent read FOnKeyDownEvent write FOnKeyDownEvent;
property OnKeyPressEvent : TOnKeyPressEvent read FOnKeyPressEvent write FOnKeyPressEvent;
property OnKeyUpEvent : TOnKeyUpEvent read FOnKeyUpEvent write FOnKeyUpEvent;
procedure KeyDown(Sender: TObject; Key : Word; Shift : TShiftState);
procedure KeyPress(Sender: TObject; Key : Char);
procedure KeyUp(Sender: TObject; Key : Word; Shift : TShiftState);
Self.OnKeyDown := Self.KeyDown;
Self.OnKeyPress := Self.KeyPress;
Self.OnKeyUp := Self.KeyUp;
导致错误的代码如下所示:
TOnKeyDownEvent = procedure(Sender: TObject; Key : Word; Shift : TShiftState) of object;
TOnKeyPressEvent = procedure(Sender: TObject; Key : Char) of object;
TOnKeyUpEvent = procedure(Sender: TObject; Key : Word; Shift : TShiftState) of object;
FOnKeyDownEvent : TOnKeyDownEvent;
FOnKeyPressEvent : TOnKeyPressEvent;
FOnKeyUpEvent : TOnKeyUpEvent;
property OnKeyDownEvent : TOnKeyDownEvent read FOnKeyDownEvent write FOnKeyDownEvent;
property OnKeyPressEvent : TOnKeyPressEvent read FOnKeyPressEvent write FOnKeyPressEvent;
property OnKeyUpEvent : TOnKeyUpEvent read FOnKeyUpEvent write FOnKeyUpEvent;
procedure KeyDown(Sender: TObject; Key : Word; Shift : TShiftState);
procedure KeyPress(Sender: TObject; Key : Char);
procedure KeyUp(Sender: TObject; Key : Word; Shift : TShiftState);
Self.OnKeyDown := Self.KeyDown;
Self.OnKeyPress := Self.KeyPress;
Self.OnKeyUp := Self.KeyUp;
有人能告诉我为什么上面的代码不起作用吗?您缺少
键
参数必须是var
参数,以便匹配TKeyEvent
的签名,我猜您正试图将其分配给:
procedure(Sender: TObject; var Key : Word; Shift : TShiftState) of object;
这是因为事件处理程序可以更改密钥代码。由于编译器声明的原因,您的代码无法编译。赋值右侧的值类型与左侧的属性类型不匹配,具体原因是参数列表不同 如问题所述,没有明显的原因。参数列表确实匹配。唯一可能的解释是,参数列表中使用的类型名称相同,但类型不同 如果在不同的单元中使用相同的名称声明多个类型,这是可能的。您可以通过对
uses
子句重新排序来解决问题,以确保所有代码引用相同的类型。或者通过以UnitName.TypeName
的形式给出其全名来显式指定类型
另一个看似合理的解释是,事实并非如问题所述。例如,可能
Self.KeyDown
指的是方法TWinControl.KeyDown
,而不是您的方法 你走错了路。不要让组件将处理程序分配给它自己的事件。现有的Key(Down/Up/Press)
方法由TWinControl
公开,您应该覆盖这些方法;现有的OnKey(Down/Up/Press)
事件可以升级到已发布的。不要定义自己的方法和事件,请使用本机方法和事件,例如:
type
TMyComp = class(...)
protected
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
procedure KeyPress(var Key: Char); override;
published
property OnKeyDown;
property OnKeyUp;
property OnKeyPress;
end;
procedure TMyComp.KeyDown(var Key: Word; Shift: TShiftState);
begin
...
inherited; // trigger the native OnKeyDown event
end;
procedure TMyComp.KeyUp(var Key: Word; Shift: TShiftState);
begin
...
inherited; // trigger the native OnKeyUp event
end;
procedure TMyComp.KeyPress(var Key: Char);
begin
...
inherited; // trigger the native OnKeyPress event
end;
鼠标事件以类似的方式工作。在您显示的代码上下文中,什么是Self
?另外,组件的祖先是什么?在我看来,你正在重新说明已经做了什么…@James_Hill你在哪里宣布了按键关闭程序。如果它在类声明之外,那么很明显您会遇到这样的错误。因为FOnKeyDownEvent是一种需要在对象中声明的TOnKeyDownEvent类型(请参见TOnKeyDown声明前面的对象的)。我想你可以在你的单位里,在全球范围内宣布这个键控程序。我同意特拉玛的观点。您的祖先是什么?请提供SSCCE。问题中的代码很好。请尝试演示演示问题的代码。特拉玛:代码格式正确,我刚刚提取了相关部分。除对象过程外,第一段代码是类型,其余代码包含在对象中。第二个块在构造函数中。洛格曼:同上。All:@jpfollenius有这个问题的答案,这代表我是一个愚蠢的错误。关于公认的答案,问题中的代码是假的。这假设控件来自TWinControlI,我正在使用我正在制作的组件创建一组新事件,尽管它的代码稍微多一些,我想以类似的方式构造所有事件。我知道鼠标事件和按键事件可以通过重写来完成,但是我创建的新事件不能以这种方式完成。如果有一个强有力的理由使用重写的方法,那么我会考虑改变我的方法,但是关于可读性和一致性,我想这样做,因为有很多事件需要编写。@ DavidHeffernan:非窗口控件不能接收键盘输入。是的,假设组件是一个TWinControl
后代。@James_-Hill:这并不否定我在回答中所说的。要处理用户输入,请使用覆盖。这就是他们在那里的目的。对于创建新的自定义事件,您仍然不会让组件将处理程序分配给自己的事件,这会阻止其他任何人分配处理程序,而且它是冗余的。如果您在实现自定义事件时遇到问题,则需要提出新问题并提供这些详细信息。我无法理解这是如何回答您提出的问题的@James,问题中哪里有var param?@DavidHeffernan问题是试图找出为什么会出现错误“E2009不兼容类型:'参数列表不同'”。我认为这是由于类和控件中存在的tshift状态,但这是因为参数'Key:Word'应该是'var-Key:Word'。我很快排除了参数列表的差异,因为当在IDE中悬停在单词上时,它表明参数列表是相同的,除了拥有TShiftState的类之外。在我的代码声明中,它说它是在System.Class中声明的,在继承的对象中,它说它来自VCL.Controls。问题代码中没有var
参数。那么赋值运算符的任一侧如何具有var
param,或期望具有var
param呢。事件类型没有var
param。指定给事件的方法没有var
param。显然问题中的信息是错误的。@DavidHeffernan问题是我们不知道Self
所指的是什么(请注意,所使用的属性称为OnKeyDown
,而不是如上所述的OnKeyDownEvent
),所以我只是猜测,因为我记得我自己把签名弄错了,并处理了那个错误