AVE:访问冲突@模块中的地址:DELPHI7
这是81 TEdit-s(MyEdit[bx,by,x,y])的处理过的onchange过程,动态创建并分组在一个4维的海量数据中。目前,我正在尝试对编辑进行编程,使其仅接受1位数字。“仅数字”部分工作正常,但“仅1数字”部分给出访问冲突错误(AVE)。守则:AVE:访问冲突@模块中的地址:DELPHI7,delphi,delphi-7,access-violation,Delphi,Delphi 7,Access Violation,这是81 TEdit-s(MyEdit[bx,by,x,y])的处理过的onchange过程,动态创建并分组在一个4维的海量数据中。目前,我正在尝试对编辑进行编程,使其仅接受1位数字。“仅数字”部分工作正常,但“仅1数字”部分给出访问冲突错误(AVE)。守则: procedure TForm1.OnHandleChange(Sender: TObject); var bx,by,x,y,len : Integer; begin bx:=(sender as TEdit).tag div 1000
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,但程序执行并工作。每次我输入一个字母而不是一个数字-错误出现时,我单击“确定”,程序就完成了工作。但有必要消除这一错误。有什么办法吗?
MyEdit[bx,by,x,y].text[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]
导致对数组的越界访问。也许你对标记字段的数学计算都搞砸了。我觉得很奇怪
正如我在下面所述,发送者作为TEdit
在这里似乎更有意义
更一般性的评论:
- 您确实需要将表示(即GUI)与底层数据分离。您真的不想使用4D视觉控件数组作为输入数据进行求解
- 不要重复
(发送者为TEdit)。标记
。将该值读入局部变量一次。或者将
存储到局部变量中(发送方为TEdit)
- 你为什么要计算bx、by、x和y呢?当然,
是您所需要的一切发送者作为TEdit
- 即使你必须计算这些,也不要反复写
不止一次。将该引用存储到局部变量中,并在任何后续引用中使用该引用MyEdit[bx,by,x,y]
- 如果需要从
计算Tag
、bx
、by
和x
,请不要在事件处理程序中内联执行。将该计算放在专用的助手方法中。同样,一个专用的辅助方法也会朝相反的方向发展。并检验这些函数是否确实是彼此相反的y
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;
为什么需要那个处理者?只需设置
TMaskEdit
的掩码即可9'似乎是你需要的
大卫发现了AV的原因。但在特拉马的建议下,我把我的评论带到了一个答案
还有。不要一次又一次地计算。做一次,记住结果
- 因为这更快,有时快得多(询问TEdit.text是询问Windows GDI服务,而不仅仅是读取常规变量)
- 因为这更可靠-在这里和那里复制相同的forumla,你可能会用不同的公式输入和结束u
- 因为这更能证明未来。有一天你会改变公式吗?你只需要在一个地方做,而不是搜索所有发生的事情
- 正如David所指出的,
已经是您的编辑。再次搜索它没有意义Sender
不要乘法和删除-这些操作很昂贵。尤其是当你删除10而不是10时 而且无论如何都不要分割-您可以在这里使用typecast自然分割值
使用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大小。oops,抱歉有点小错误。“只有1位数”部分正常工作,但“只有位数”part给出了错误。.如果不是,请看以开头的行。thanksIt最好在编辑框的OnKey事件中测试数字。@Keith-他根本不应该使用任何键事件!TMaskEdit只是开箱即用。@Arioch,请回答,而不是发表这么多评论。@Arioch,我已经看到很多答案开始了作为某人答案的补充…不复制答案的内容。因此,我认为发布你自己的答案并附带附加信息说这是对某人帖子的补充是完全可以的。@Arioch'the我不理解你的评论。请详细说明。好的,我更正了你在这里说的话,谢谢。但主要问题是em仍然在这里,我尝试了David的代码,错误仍然出现。在这里和那里调用.text而不是缓存比as
和数组引用MyEdit[bx,by,x,y]更昂贵的操作
。作为第一个优化步骤,要尽量减少与操作系统的交互。需要使用本地文本变量。@Arioch'性能在这里不是一个考虑因素。这一切都是为了让代码可读、可维护和正确。遵循DRY原则。用户正在敲击键盘。想象一下需要多少CPU周期。令人着迷性能不是这里需要的。@TLama如果编辑实例不是全部创建的,那么OnChange
处理程序将不会启动,因为没有控制。当然Sender as TEdit
是这里需要的。所有这些div
数学都很奇怪。我需要4个维度,因为在检查数独时我们需要编辑以检查行、行和3x3