如何停止 TRadioButton 对箭头键的反应?

How to stop TRadioButton reacting at arrow keys?

我有一个面板,水平放置了几个 TRadioButton。如果最左边的按钮获得焦点并且我按下向左箭头,焦点会跳到最右边的按钮。当所有箭头到达边缘时,我想停止这种行为。可能吗 ? 我尝试覆盖 WM_KEYDOWN 但按下箭头键时按钮从未收到此消息。

  TRadioButton = class(StdCtrls.TRadioButton)
  protected
    procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
    procedure WMKeyUp(var Message: TWMKeyUp); message WM_KEYUP;
  public
    BlockLeft, BlockRight: Boolean;
    constructor Create(AOwner: TComponent); override;
  end;

constructor TRadioButton.Create(AOwner: TComponent);
begin
 inherited;
 BlockLeft:= False;
 BlockRight:= False;
end;

procedure TRadioButton.WMKeyDown(var Message: TWMKeyDown);
begin
 if BlockLeft and (Message.CharCode = VK_LEFT) then Exit;
 if BlockRight and (Message.CharCode = VK_RIGHT) then Exit;

 inherited;
end;

procedure TRadioButton.WMKeyUp(var Message: TWMKeyUp);
begin
 if BlockLeft and (Message.CharCode = VK_LEFT) then Exit;
 if BlockRight and (Message.CharCode = VK_RIGHT) then Exit;
 inherited;
end;

VCL 偏移键盘消息成为控件通知并将其发送到消息的目标控件。因此,您应该拦截 CN_KEYDOWN 消息。

如果这是一次性设计考虑,我更愿意在表单级别处理此行为,因为 IMO 控件本身不应该关心它的放置位置。对于所有单选按钮都应该表现相似的表单,示例可能是:

procedure TForm1.CMDialogKey(var Message: TCMDialogKey);
begin
  if ActiveControl is TRadioButton then
    case Message.CharCode of
      VK_LEFT, VK_UP: begin
        if ActiveControl.Parent.Controls[0] = ActiveControl then begin
          Message.Result := 1;
          Exit;
        end;
      end;
      VK_RIGHT, VK_DOWN: begin
        if ActiveControl.Parent.Controls[ActiveControl.Parent.ControlCount - 1]
            = ActiveControl then begin
          Message.Result := 1;
          Exit;
        end;
      end;
    end;
  inherited;
end;


如果这不是一次性行为,我会按照维多利亚在问题评论中提到的那样编写一个容器控件。