AVE:访问冲突@模块中的地址:DELPHI7

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

这是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;
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