我试图切换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;
答案 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;