单击CheckListBox项以切换该项上的检查状态

时间:2014-09-19 22:33:30

标签: delphi checkboxlist

我试图切换TCheckListBox项目状态,因此如果选中它,则取消选中它,反之亦然。这通常只在您点击物理盒本身时切换,但我希望当用户点击项目行的任何位置时切换它。

下面的代码可以使用,但现在可以防止项目在物理框中点击时进行切换(例如,如果它当前未选中,那么他们会在框中单击,它将保持未选中状态)。

代码中是否可能存在这两种行为或错误?

procedure TMainFrm.CheckListBoxModulesMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  APoint: TPoint;
  Index: integer;
begin
  if (Button = mbLeft) then
  begin
    APoint.X := X;
    APoint.Y := Y;
    Index := CheckListBoxModules.ItemAtPos(APoint, True);

    if(Index > -1) then
    begin
      CheckListBoxModules.Checked[Index] := not CheckListBoxModules.Checked[Index];
    end;    
  end;    
end;

3 个答案:

答案 0 :(得分:1)

你的问题是,在你切换状态之后,盒子本身就会再次切换它,因为检查被击中了。

解决方法是撤消此内置检查行为:

procedure TMainFrm.CheckListBoxModulesClickCheck(Sender: TObject);
begin
  CheckListBoxModules.Checked[CheckListBoxModules.ItemIndex] :=
      not CheckListBoxModules.Checked[CheckListBoxModules.ItemIndex];
end;


这样可行,因为当您按代码更改检查状态时,不会触发OnClickCheck。仅在复选框中通过鼠标单击导致的状态更改是相反的。


更好的解决方案是在复选框上点击时根本不切换状态。如果您决定实施此解决方案,请参阅TCheckListBox.GetCheckSize中的代码,了解VCL如何确定复选框大小,并TCheckListBox.MouseDown了解其如何确定位置。

答案 1 :(得分:1)

这种情况下,一点点命中测试会有所帮助。如果用户点击复选框,则不要手动切换检查状态。您可以使用类似于TCheckListBox内部使用的逻辑来确定用户是否单击了复选框。如果鼠标位于复选框上方,让TCheckListBox处理点击。否则,请手动切换。例如:

type
  TCheckListBoxAccess = class(TCheckListBox)
  end;

procedure TMainFrm.CheckListBoxModulesMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Index: Integer;

  procedure DoToggle;
  var
    State: TCheckBoxState;
  begin
    if (Index >= 0) and (Index < CheckListBoxModules.Items.Count) and CheckListBoxModules.ItemEnabled[Index] then
    begin
      State := CheckListBoxModules.State[Index];
      case State of
        cbUnchecked:
          if CheckListBoxModules.AllowGrayed then State := cbGrayed else State := cbChecked;
        cbChecked: State := cbUnchecked;
        cbGrayed: State := cbChecked;
      end;
      CheckListBoxModules.State[Index] := State;
      TCheckListBoxAccess(CheckListBoxModules).ClickCheck;
    end;
  end;

begin
  if Button = mbLeft then
  begin
    Index := CheckListBoxModules.ItemAtPos(Point(X,Y),True);
    if (Index <> -1) and CheckListBoxModules.ItemEnabled[Index] then
      if not TCheckListBoxAccess(CheckListBoxModules).UseRightToLeftAlignment then
      begin
        if X - CheckListBoxModules.ItemRect(Index).Left >= TCheckListBoxAccess(CheckListBoxModules).GetCheckWidth then
          DoToggle;
      end
      else
      begin
        Dec(X, CheckListBoxModules.ItemRect(Index).Right - TCheckListBoxAccess(CheckListBoxModules).GetCheckWidth);
        if (X <= 0) or (X >= TCheckListBoxAccess(CheckListBoxModules).GetCheckWidth) then
          DoToggle;
      end;
  end;
end;

答案 2 :(得分:0)

我为Sertac的答案添加了一些代码来检查按下的女巫键,这样我们也可以用键盘上下移动。

procedre TfrmRelBalanceteGerencial.cklGrupoContasClick(Sender: TObject);
begin
inherited;
  if HiWord(GetKeyState(VK_UP)) <> 0 or HiWord(GetKeyState(VK_DOWN)) then
  begin
  // do nothing
  end
  else
  begin
    cklGrupoContas.Checked[cklGrupoContas.ItemIndex] :=  not   cklGrupoContas.Checked[cklGrupoContas.ItemIndex];
  end;
end;