喫茶XRAYトップページ

[スレッド全体
]

[7605] StringGridと格闘中…結果報告返信 削除
2014/5/17 (土) 23:25:58 taki
何とか使えそうです。

Gridの1列目に商品コード、2列目に商品名、3列目に数量とします。
商品コードを入力後、Tabキーを押すと商品名が検索されて表示され、
3列目へキャレットが移動するようにします。

このコードは色々と試行錯誤した結果です。参考になればうれしいです。

もし、別のコードを試される場合、プログラムが無限ループになることが多いので、
暴走しても終了できるようにIDEの環境で実行してください。


Form1にStringGrid1とTimer1を配置します。

(定義部は省略)

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Options := StringGrid1.Options + [goEditing,goTabs,goAlwaysShowEditor];
  StringGrid1.FixedCols := 0;
  StringGrid1.FixedRows := 0;
  Timer1.Enabled := false;
  Timer1.Interval := 100;   // もっと短くても良いと思います。
end;

procedure wait1000;  // 約1000m秒間待つ
var
  i:integer;
begin
  for i := 1 to 10 do begin
    Application.ProcessMessages;
    sleep(100);
  end;
end;

// データベースモドキ '123'を受け取ると'abc'を返し、それ以外は'Err'を返す。
function DBmodoki(val:string):string;
begin
  if val = '123' then result := 'abc' else result := 'Err';
end;

procedure TForm1.StringGrid1GetEditText(Sender: TObject; ACol, ARow: Integer;
  var Value: string);
begin
  beep;        // このイベントが発生したことを確認するため。本来不要
  wait1000;    // もし暴走した時に暴走を緩やかにするため。本来不要

  if ACol = 1 then begin
    Value := DBmodoki(StringGrid1.Cells[0,ARow]);
    Timer1.Enabled := true;       // TTimerにTabキーを押させる
  end;
end;

// ↓がミソです。
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := false;
  StringGrid1.Perform(WM_KEYDOWN, VK_TAB, 1);
  StringGrid1.Perform(WM_KEYUP, VK_TAB, 1);
end;

end.

============================================
以下の例は無限ループになります。

  if ACol = 1 then begin
    StringGrid1.Cells[1,ARow] := DBmodoki(StringGrid1.Cells[0,ARow]);
    Timer1.Enabled := true;  // TTimerにTabキーを押させる
  end;

キャレット(カーソル)があるセルに対してコードで文字を書き込むとループします。
StringGridからフォーカスを奪うShowmessage()等もループします。
もし、Showmessage()を使いたい場合はTimerにShowmessage()のコードを書きます。


[7607] Re:StringGridと格闘中…結果報告返信 削除
2014/5/19 (月) 09:05:00 おかぽん
▼ takiさん

タイマーとかあまり使わないので、暴走した経験はありませんが
イカはどうでしょう?

procedure TForm1.StrGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
  //列が0から1へ移動しようとしており、同一行であるかの判定
  if (StrGrid1.Col = 0) and (ACol = 1) and
     (StrGrid1.Row = AROw) then begin
    //商品コードから商品名を取得し入力
    StrGrid1.Cells[1, ARow] := DBmodoki(StrGrid1.Cells[0, ARow]);
    //ここではセル移動を行わない
    CanSelect := False;
    //数量列に移動
    StrGrid1.Col := 2;
  end;
end;

セルの移動前に、移動先のセルの値を書き換えるので、
> キャレット(カーソル)があるセルに対してコードで文字を書き込むとループします。
には、あてはまらないと思います。

Delphi 5 のコードですけど、参考になれば幸いです。

[7608] Re2:StringGridと格闘中…結果報告返信 削除
2014/5/19 (月) 10:37:16 taki
▼ おかぽんさん

ありがとうございます。

> セルの移動前に、移動先のセルの値を書き換えるので、
> > キャレット(カーソル)があるセルに対してコードで文字を書き込むとループします。
> には、あてはまらないと思います。
>
> Delphi 5 のコードですけど、参考になれば幸いです。


Delphi XE4 では

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
 //列が0から1へ移動しようとしており、同一行であるかの判定
  if (StringGrid1.Col = 0) and (ACol = 1) and
      (StringGrid1.Row = ARow) then begin
     //商品コードから商品名を取得し入力
    StringGrid1.Cells[1, ARow] := DBmodoki(StringGrid1.Cells[0, ARow]);
     //ここではセル移動を行わない
    CanSelect := False;
     //数量列に移動
    StringGrid1.Col := 2;
  end;
end;

で正常(かつ理想通り)に動くことを確認しました。

OnSelectCellイベントはグリッド内のセルが選択される前に発生します。
CanSelect パラメータを false に設定すると,セルを選択できなくすることができます。

地雷を踏む前に検知してフタをして飛び越えたらいいんですね。なるほど。



[▼次のスレッド]
INCM/CMT
Cyclamen v3.82