这是81个TEdit-s(MyEdit [bx,by,x,y])处理的onchange过程,动态创建并以4维海量分组。现在我正在尝试编辑Edits只接受1位数。 “仅数字”部分正常工作,但“仅1位”部分提供访问冲突错误(AVE)。代码:
procedure TForm1.OnHandleChange(Sender: TObject);
var
bx,by,x,y,len : Integer;
begin
bx:=(sender as TEdit).tag div 1000;
by:=(sender as TEdit).tag div 100-10*bx;
x:=(sender as TEdit).tag div 10-100*bx-10*by;
y:=(sender as TEdit).tag-bx*1000-by*100-x*10;
{*The line below gives the error*}
if not (MyEdit[bx,by,x,y].text[1] in ['1'..'9']) then MyEdit[bx,by,x,y].text:='';
MyEdit[bx,by,x,y].SelStart:=length(MyEdit[bx, by, x,y].text);
if length(MyEdit[bx, by, x,y].text) >1
then MyEdit[bx,by,x,y].text:=MyEdit[bx,by,x,y].text[2];
end;
虽然有AVE,程序仍会执行并运行。每次我输入一个字母而不是一个数字 - 错误来了,我点击确定,程序完成工作。但有必要删除该错误。有什么办法吗?
答案 0 :(得分:3)
MyEdit[bx,by,x,y].text[1]
假设编辑框文本非空,即至少有1个单个字符。当编辑框文本为空时,Text
属性为空字符串,访问第一个字符会导致访问冲突。
我注意到你明确地将编辑框文本设置为空字符串,当然用户可以这样做。所以你当然必须警惕这种可能性。
通过检查编辑框是否为空来解决问题。
var
Text: string;
....
Text := MyEdit[bx,by,x,y].Text;
if (Length(Text)=1) and (Text[1] in ['1'..'9']) then
....
访问冲突的另一个可能的候选者是MyEdit[bx,by,x,y]
是否导致对阵列的越界访问。也许你的Tag字段的数学都搞砸了。这看起来很奇怪。
正如我在下面所述,Sender as TEdit
似乎在这里更有意义。
更多一般性评论:
(Sender as TEdit).tag
。将该值读入局部变量一次。或者可能将(Sender as TEdit)
存储到本地变量中。bx
,by
,x
和y
?当然Sender as TEdit
就是你所需要的。MyEdit[bx,by,x,y]
来重复自己。将该引用存储到本地变量中,并在随后的任何引用中使用它。bx
计算by
,x
,y
和Tag
,请不要在事件处理程序中对其进行内联。将该计算放在专用的辅助方法中。同样是一个专门的辅助方法,它朝着相反的方向发展。并测试这些功能确实是相互反转的。举个例子,这些助手可能如下所示:
procedure PackCoordinates(const bx, by, x, y: Byte; out Tag: Integer);
begin
LongRec(Tag).Bytes[0] := bx;
LongRec(Tag).Bytes[1] := by;
LongRec(Tag).Bytes[2] := x;
LongRec(Tag).Bytes[3] := y;
end;
procedure UnpackCoordinates(const Tag: Integer; out bx, by, x, y: Byte);
begin
bx := LongRec(Tag).Bytes[0];
by := LongRec(Tag).Bytes[1];
x := LongRec(Tag).Bytes[2];
y := LongRec(Tag).Bytes[3];
end;
答案 1 :(得分:0)
为什么需要那个处理程序?只需设置TMaskEdit
的掩码即可。 '9'似乎是你需要的。
AV原因是David发现的。但在TLama建议中,我将我的意见带回答。
还有DRY principle。不要一次又一次地做计算。做一次并记住结果。
Sender
已经是你的编辑了。没有必要再次搜索它了!不要繁殖和删除 - 这些操作很昂贵。特别是当您删除10而不是2,4,8,16,...
时并且不管怎么说 - 你可以在这里使用类型转换自然地分割值。
使用4D阵列非常奇怪。非常。你真的需要吗?
总而言之,归结为
type TTagSplit = packed record
case byte of
0: (Tag: integer);
1: (bx, by, x, y: byte); end;
procedure CreatingEdits...
var tt: TTagSplit; e: TEdit;
begin
for ... do begin
e := TEdit.Create(MainForm);
....
tt.bx := ...; tt. by := ....
e.Tag := tt.Tag;
end;
end;
procedure TForm1.OnHandleChange(Sender: TObject);
var
bx,by,x,y,len : Integer;
e : TEdit; txt: string;
tt: TTagSplit;
begin
e := Sender as TEdit;
tt.Tag := e.Tag;
bx := tt.bx; by := ....
// Here you do not need those bx and rest - just demo how to get them
txt := e.Text;
if length(txt) > 1
then e.Text := txt[2]
else
if txt > '' then
if not (txt[1] in ['1'..'9'])
then e.Text := '';
end;
但是带来简历 - 只需使用TMaskEdit就可以使所有代码都不需要。 TMaskedit本身会检查内容是一位数还是空位。唯一要检查的是数字不为零。
樱桃到那个馅饼 - 你根本不需要81个编辑盒!您应该将一个TStringGrid
设置为9x9大小。