Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi TRadioGroup:单击当前选中项两次以取消选中它。能做到吗?_Delphi - Fatal编程技术网

Delphi TRadioGroup:单击当前选中项两次以取消选中它。能做到吗?

Delphi TRadioGroup:单击当前选中项两次以取消选中它。能做到吗?,delphi,Delphi,我搜索了一下,没有找到答案: 我在一个放射组中有四项,其中三项是汽车名称,第四项我称之为“无”。单击第四项时,它将索引设置为-1。到目前为止,这一切都很好。我想有一个功能,如果我点击一个已经选中的项目(activeindex),它会将其设置为-1。这样,我就可以从列表中删除第四个“无”项。这在放射组中可能吗 仅当单击的项目已经是索引(旧索引)并且将被取消选中时,此操作才有效。如果单击了未选中的项目,它仍将为该项目设置索引 谢谢 标准单选按钮的行为与您描述的不同。选中一个单选按钮后,将保持选中状态

我搜索了一下,没有找到答案:

我在一个放射组中有四项,其中三项是汽车名称,第四项我称之为“无”。单击第四项时,它将索引设置为-1。到目前为止,这一切都很好。我想有一个功能,如果我点击一个已经选中的项目(activeindex),它会将其设置为-1。这样,我就可以从列表中删除第四个“无”项。这在放射组中可能吗

仅当单击的项目已经是索引(旧索引)并且将被取消选中时,此操作才有效。如果单击了未选中的项目,它仍将为该项目设置索引


谢谢

标准单选按钮的行为与您描述的不同。选中一个单选按钮后,将保持选中状态,直到选中同一组中的另一个单选按钮为止

然而,尽管如此,您仍然可以通过少量的手动操作来实现您的要求:

type
  TMyForm = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    OriginalWndProcs: array[0..2] of TWndMethod;
    procedure RadioButtonWndProc1(var Message: TMessage);
    procedure RadioButtonWndProc2(var Message: TMessage);
    procedure RadioButtonWndProc3(var Message: TMessage);
    procedure RadioButtonWndProc(const Index: Integer; var Message: TMessage);
  public
    { Public declarations }
  end;

procedure TMyForm.RadioButtonWndProc1(var Message: TMessage);
begin
  RadioButtonWndProc(0, Message);
end;

procedure TMyForm.RadioButtonWndProc2(var Message: TMessage);
begin
  RadioButtonWndProc(1, Message);
end;

procedure TMyForm.RadioButtonWndProc3(var Message: TMessage);
begin
  RadioButtonWndProc(2, Message);
end;

procedure TMyForm.FormShow(Sender: TObject);
var
  NewWndProcs: array[0..2] of TWndMethod;
  I: Integer;
begin
  NewWndProcs[0] := RadioButtonWndProc1;
  NewWndProcs[1] := RadioButtonWndProc2;
  NewWndProcs[2] := RadioButtonWndProc3;

  for I := 0 to 2 do
  begin
    OriginalWndProcs[I] := RadioGroup1.Buttons[I].WindowProc;
    RadioGroup1.Buttons[I].WindowProc := NewWndProcs[I];
  end;
end;

procedure TMyForm.RadioButtonWndProc(const Index: Integer; var Message: TMessage);
begin
  if (Message.Msg = CN_COMMAND) and
     (TWMCommand(Message).NotifyCode = BN_CLICKED) and
     (RadioGroup1.Buttons[Index].Checked) then
  begin
    RadioGroup1.Buttons[Index].Checked := False;
    Exit;
  end;

  OriginalWndProcs[Index](Message);
end;

更新:通过将
TRadioButton
对象直接传递到
RadioButtonWndProc()
而无需使用中间代理方法,上述代码可以稍微简化:

type
  TMyForm = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    OriginalWndProcs: array[0..2] of TWndMethod;
    procedure RadioButtonWndProc(var Message: TMessage);
  public
    { Public declarations }
  end;

procedure TMyForm.FormShow(Sender: TObject);
var
  I: Integer;
  Btn: TRadioButton;
  M: TWndMethod;
begin
  for I := 0 to 2 do
  begin
    Btn := RadioGroup1.Buttons[I];
    Btn.Tag := I;

    OriginalWndProcs[I] := Btn.WindowProc;

    M := RadioButtonWndProc;
    TMethod(M).Data := Btn; // <-- makes Self in RadioButtonWndProc() point to the Button instead of the Form...
    Btn.WindowProc := M;
  end;
end;

procedure TMyForm.RadioButtonWndProc(var Message: TMessage);
var
  Btn: TRadioButton;
begin
  Btn := TRadioButton(Self);

  if (Message.Msg = CN_COMMAND) and
     (TWMCommand(Message).NotifyCode = BN_CLICKED) and
     (Btn.Checked) then
  begin
    Btn.Checked := False;
    Exit;
  end;

  MyForm.OriginalWndProcs[Btn.Tag](Message); // <-- note, using the global Form pointer to reach Form members...
end;


尽管如此,我还是不推荐这种UI设计。这根本不是用户期望单选按钮的行为方式。更好的UI选择是使用
TComboBox
,其中第四项用于不选择任何内容。一个
t组合框
比多个单选按钮占用更少的空间,而且它仍然提供用户期望的单一选择行为。

标准单选按钮的行为与您描述的不同。选中一个单选按钮后,将保持选中状态,直到选中同一组中的另一个单选按钮为止

然而,尽管如此,您仍然可以通过少量的手动操作来实现您的要求:

type
  TMyForm = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    OriginalWndProcs: array[0..2] of TWndMethod;
    procedure RadioButtonWndProc1(var Message: TMessage);
    procedure RadioButtonWndProc2(var Message: TMessage);
    procedure RadioButtonWndProc3(var Message: TMessage);
    procedure RadioButtonWndProc(const Index: Integer; var Message: TMessage);
  public
    { Public declarations }
  end;

procedure TMyForm.RadioButtonWndProc1(var Message: TMessage);
begin
  RadioButtonWndProc(0, Message);
end;

procedure TMyForm.RadioButtonWndProc2(var Message: TMessage);
begin
  RadioButtonWndProc(1, Message);
end;

procedure TMyForm.RadioButtonWndProc3(var Message: TMessage);
begin
  RadioButtonWndProc(2, Message);
end;

procedure TMyForm.FormShow(Sender: TObject);
var
  NewWndProcs: array[0..2] of TWndMethod;
  I: Integer;
begin
  NewWndProcs[0] := RadioButtonWndProc1;
  NewWndProcs[1] := RadioButtonWndProc2;
  NewWndProcs[2] := RadioButtonWndProc3;

  for I := 0 to 2 do
  begin
    OriginalWndProcs[I] := RadioGroup1.Buttons[I].WindowProc;
    RadioGroup1.Buttons[I].WindowProc := NewWndProcs[I];
  end;
end;

procedure TMyForm.RadioButtonWndProc(const Index: Integer; var Message: TMessage);
begin
  if (Message.Msg = CN_COMMAND) and
     (TWMCommand(Message).NotifyCode = BN_CLICKED) and
     (RadioGroup1.Buttons[Index].Checked) then
  begin
    RadioGroup1.Buttons[Index].Checked := False;
    Exit;
  end;

  OriginalWndProcs[Index](Message);
end;

更新:通过将
TRadioButton
对象直接传递到
RadioButtonWndProc()
而无需使用中间代理方法,上述代码可以稍微简化:

type
  TMyForm = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    OriginalWndProcs: array[0..2] of TWndMethod;
    procedure RadioButtonWndProc(var Message: TMessage);
  public
    { Public declarations }
  end;

procedure TMyForm.FormShow(Sender: TObject);
var
  I: Integer;
  Btn: TRadioButton;
  M: TWndMethod;
begin
  for I := 0 to 2 do
  begin
    Btn := RadioGroup1.Buttons[I];
    Btn.Tag := I;

    OriginalWndProcs[I] := Btn.WindowProc;

    M := RadioButtonWndProc;
    TMethod(M).Data := Btn; // <-- makes Self in RadioButtonWndProc() point to the Button instead of the Form...
    Btn.WindowProc := M;
  end;
end;

procedure TMyForm.RadioButtonWndProc(var Message: TMessage);
var
  Btn: TRadioButton;
begin
  Btn := TRadioButton(Self);

  if (Message.Msg = CN_COMMAND) and
     (TWMCommand(Message).NotifyCode = BN_CLICKED) and
     (Btn.Checked) then
  begin
    Btn.Checked := False;
    Exit;
  end;

  MyForm.OriginalWndProcs[Btn.Tag](Message); // <-- note, using the global Form pointer to reach Form members...
end;


尽管如此,我还是不推荐这种UI设计。这根本不是用户期望单选按钮的行为方式。更好的UI选择是使用
TComboBox
,其中第四项用于不选择任何内容。一个
TComboBox
比多个单选按钮占用更少的空间,而且它仍然提供用户期望的单一选择行为。

这不是Windows单选按钮控件的工作方式。在这种情况下,您确定它是为了规避默认的平台行为吗?我认为,您要么必须为TRadioGroup创建子类,要么在面板中创建一个带有单选按钮的自定义控件。这是一种自定义行为,因此需要自定义组件。组合框怎么样?这不是Windows单选按钮控件的工作方式。在这种情况下,您确定它是为了规避默认的平台行为吗?我认为,您要么必须为TRadioGroup创建子类,要么在面板中创建一个带有单选按钮的自定义控件。这是一种自定义行为,因此需要自定义组件。一个组合框怎么样?当表单有一个无线组时,此代码有效。你能告诉我,当我有超过一个以上的广播组时,如何实施同样的计划吗。Thanks@Amazing. 您针对多个放射组的第一个解决方案对我有效。谢谢!我同意你对combobox的设计。然而,遗憾的是,我只能更改现有项目中的逻辑,而不能更改组件。你能告诉我,当我有超过一个以上的广播组时,如何实施同样的计划吗。Thanks@Amazing. 您针对多个放射组的第一个解决方案对我有效。谢谢!我同意你对combobox的设计。然而,遗憾的是,我只能更改现有项目中的逻辑,而不能更改组件。