-2

これは、81 個の TEdit-s (MyEdit[bx,by,x,y]) の処理された onchange プロシージャであり、動的に作成され、4 次元の塊にグループ化されます。今のところ、1 桁のみを受け入れるように Edits をプログラムしようとしています。「数字のみ」の部分は正常に動作しますが、「1 桁のみ」の部分は Access Violation Error (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がありますが、プログラムは実行され動作します。数字の代わりに文字を入力するたびに、エラーが発生し、[OK] をクリックすると、プログラムが機能します。しかし、そのエラーを取り除く必要があります。何か方法はありますか?

4

2 に答える 2

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
  ....

アクセス違反の可能性があるもう 1 つの候補はMyEdit[bx,by,x,y]、配列の境界外アクセスになる場合です。おそらく、Tag フィールドを使用した数学がすべて台無しになっている可能性があります。私にはかなり奇妙に見えます。

以下で述べるように、Sender as TEditここではより理にかなっているように見えます。


より一般的なコメント:

  • プレゼンテーション、つまり GUIm を基礎となるデータから分離する必要があります。入力データとしてビジュアル コントロールの 4D 配列を使用して解決したくはありません。
  • 繰り返し続けないでください(Sender as TEdit).tag。その値を一度ローカル変数に読み込みます。(Sender as TEdit)または、おそらくローカル変数に保存します。
  • bxbyxおよびyまったく計算していないのはなぜですか? 確かSender as TEditに必要なのはそれだけです。
  • これらを計算しなければならない場合でも、何MyEdit[bx,by,x,y]度も繰り返し書いてはいけません。その参照をローカル変数に格納し、それを後続の参照で使用します。
  • bx、、およびfromを計算する必要がある場合はby、イベント ハンドラーでインラインで実行しないでください。その計算を専用のヘルパー メソッドに入れます。同様に、反対方向に進む専用のヘルパー メソッド。そして、これらの関数が実際に互いに逆であることをテストします。xyTag

例を挙げると、これらのヘルパーは次のようになります。

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;
于 2012-10-15T10:10:46.407 に答える
0

なぜそのハンドラーが必要なのですか? のマスクを設定するだけですTMaskEdit。「9」が必要なようです。


AVの理由はデビッドによってスポットされました。しかし、TLama の提案で、私は自分のコメントに答えを出します。


DRY原則もあります。何度も計算しないでください。一度実行して、結果を覚えておいてください。

  • その方が速いため、場合によってははるかに高速です (TEdit.text を要求することは Windows GDI サービスを要求することであり、通常の変数を読み取るだけではありません)。
  • その方が信頼性が高いため、同じフォーラムをあちこちにコピーすると、タイプミスが発生し、 u[ が異なる式で終わる可能性があります。
  • そのほうが将来性があるからです。いつの日か数式を変更しますか? 出現箇所をすべて検索するのではなく、1 か所だけで作成する必要があります。
  • Davidが指摘したように、Senderすでにあなたの編集です。もう探しても無駄!

乗算および削除しないでください。これらの操作はコストがかかります。特に、2,4,8,16 の代わりに 10 で削除すると...

とにかく分割しないでください-ここで型キャストを使用して値を自然に分割できます。


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 自体が、コンテンツが 1 桁または空であることをチェックします。チェックする唯一のことは、数字がゼロでないことです。


そして、そのパイの上にチェリー - 81 個の編集ボックスはまったく必要ありません! 1TStringGridセットを9x9サイズに入れるだけです。

于 2012-10-15T10:40:32.603 に答える