单击CheckListBox项目以切换该项目的检查状态
问题描述:
我试图切换TCheckListBox
项目状态,因此如果选中它,则取消选中它,反之亦然。这通常只在您点击物理盒本身时才会切换,但我希望它在用户单击项目行上的任意位置时切换。单击CheckListBox项目以切换该项目的检查状态
下面的代码可以工作,但是现在可以防止物品在物理框中单击时可以切换(例如,如果当前未选中,那么它们会在框中单击,并保持未选中状态)。
是否有可能在代码中同时存在两种行为或错误?
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;
答
你的问题是,在你切换状态后,盒子本身会在检查命中后再次切换它。
一个解决办法是取消这个内置的检查行为:
procedure TMainFrm.CheckListBoxModulesClickCheck(Sender: TObject);
begin
CheckListBoxModules.Checked[CheckListBoxModules.ItemIndex] :=
not CheckListBoxModules.Checked[CheckListBoxModules.ItemIndex];
end;
这工作,因为当您通过代码更改检查状态OnClickCheck
不被解雇。只有在复选框中鼠标点击导致的状态变化才会颠倒过来。
更好的解决方案是当点击复选框时不切换状态。如果您决定实施此解决方案,请参阅TCheckListBox.GetCheckSize
中的代码,了解VCL如何确定复选框大小以及TCheckListBox.MouseDown
确定位置的方式。
答
这是一种点击测试帮助点的情况。如果用户点击复选框,则不要手动切换检查状态。您可以使用类似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;
答
我已经给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;
类似于'如果y> 16然后开始...结束' – bummi 2014-09-19 22:41:08
嗯我想这是有效的。 X确实。 – ikathegreat 2014-09-19 22:52:27