【发布时间】:2016-12-24 18:41:42
【问题描述】:
我有一个 Checkbox1,我想自定义当用户单击复选框的标题(文本)时,它不会更改其状态(选中/未选中),但只有在单击实际复选框方格时才会更改。
这是具有 2 个全局变量的当前代码,一个表示何时跳过更改状态,一个表示何时跳过更改状态,一个记住当前状态并确保在 OnClick 后保持不变 - 因为当流在 OnClick 中时状态已经更改:
var
gSkipClick:boolean = false;
gPrevState:boolean;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
// Make sure previous state is assigned when Skip
if gSkipClick then
Checkbox1.Checked := gPrevState;
end;
procedure TForm1.CheckBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (x > 12) then
begin
// Click outside checkbox square
gSkipClick := True; // skip Click
gPrevState := CheckBox1.Checked; // save current state
end
else
gSkipClick := False; // enable Click
end;
现在我想用 TCheckBox 中的 2 个新属性来替换全局变量:
TCheckBox = class(Vcl.StdCtrls.TCustomCheckBox)
private
FSkipStateChange:Boolean;
FPrevState:Boolean;
protected
published
property SkipStateChange:Boolean read FSkipStateChange write FSkipStateChange;
property PrevState:Boolean read FPrevState write FPrevState;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
// Click outside checkbox square
If TCheckBox(Checkbox1).SkipStateChange Then
Checkbox1.Checked := TCheckBox(Checkbox1).PrevState;
end;
procedure TForm1.CheckBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (x > 12) then
begin
// Click outside checkbox square
TCheckBox(Checkbox1).SkipStateChange := True;
TCheckBox(Checkbox1).PrevState := Checkbox1.Checked;
end
else
TCheckBox(Checkbox1).SkipStateChange := False;
end;
它可以工作,但是如果我点击标题然后关闭表单,就会出现这个错误:
Project Project1.exe 引发异常类 $C0000005 并带有消息 '在 0x004080c5 的访问冲突:读取地址 0x0000000d'。
错误发生在procedure TMonitor.Destroy; in System unit:
procedure TMonitor.Destroy;
begin
if (MonitorSupport <> nil) and (FLockEvent <> nil) then { <-- ERROR ON THIS LINE}
MonitorSupport.FreeSyncObject(FLockEvent);
FreeMem(@Self);
end;
我做错了什么,为什么会出现错误?
【问题讨论】:
-
复选框并不总是 12 像素宽。您的代码在复选框宽度不同的系统上效果不佳。另外,我认为您应该将逻辑添加到您的复选框类中。
-
我还没有考虑到这一点。我假设您在谈论不同的 Windows 版本 (XP...10) 对吗?
-
其他想要显示有关控件的附加信息的程序通常会在控件旁边包含一个额外 UI 元素,例如“信息”图像。请不要按照您的建议降低复选框的可用性。网站默认会这样做,这很糟糕。
-
你不会有两个控件。你会有一个将两者结合起来的。你这样做的逻辑是有缺陷的——你正在改变标准 UI 组件的行为,使其行为方式与用户期望的方式不同。我的用户会非常沮丧,因为他们知道 Windows 是如何工作的,并且不希望跳过箍来使用他们的应用程序。如果您需要执行与复选框不同的操作,请不要使用复选框 - 使用更合适的控件。
-
不要削弱复选框本身!创建一个新的复合控件,由无标题复选框和关联的 TLabel 组成。通过 TFrame 或半官方自定义容器包将它们合二为一
标签: delphi delphi-10.1-berlin tcheckbox