【发布时间】:2015-03-23 17:48:18
【问题描述】:
我正在编写一个从 tExCustomControl 派生的自定义按钮,而这又是从 tCustomControl 派生的。 tExCustomControl 组件负责绘制和显示标题。我设法使用 WinAPI 显示带有下划线的加速字符的标题。我如何告诉 Windows 加速键与 tExButton 相关联,以便它可以处理事件?
【问题讨论】:
我正在编写一个从 tExCustomControl 派生的自定义按钮,而这又是从 tCustomControl 派生的。 tExCustomControl 组件负责绘制和显示标题。我设法使用 WinAPI 显示带有下划线的加速字符的标题。我如何告诉 Windows 加速键与 tExButton 相关联,以便它可以处理事件?
【问题讨论】:
您不会告诉 Windows 任何事情。当用户键入加速键时,Windows 会向您的应用发送 WM_SYSCHAR 消息,VCL 会自动处理该消息。当 VCL 搜索哪个控件处理加速器时,您的组件将收到一条 CM_DIALOGCHAR 消息,您需要对其进行响应,例如:
type
TMyCustomButton = class(tExCustomControl)
private
procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
end;
procedure TMyCustomButton.CMDialogChar(var Message: TCMDialogChar);
begin
if IsAccel(Message.CharCode, Caption) and Enabled and Visible and
(Parent <> nil) and Parent.Showing then
begin
Click;
Result := 1;
end else
inherited;
end;
IsAccel() 是Vcl.Forms 单元中的公共函数:
function IsAccel(VK: Word; const Str: string): Boolean;
它从提供的 Str 值解析加速器,并将其与提供的 VK 值进行比较。
例如,上面的代码正是TSpeedButton 实现加速器的方式。
【讨论】:
Key... 事件实现加速器。 VCL 预处理加速键击并相应地生成CM_DIALOGCHAR 消息。 VCL 将消息广播到子控件、菜单和操作列表,直到其中一个响应匹配的加速器。只要您的控件每个都有一个独特的加速器,就应该只有一个响应消息。如果多个控件具有相同的加速器,那么当然这将是一个先到先得的场景,其中一个最终处理消息。