StringGridで検索した文字列のフォーカスを維持するには?

解決


枯葉マーク  2004-07-01 08:22:27  No: 9710

また基本的なところ?でつまづいている気がします。教えてください。
検索ダイアログで文字検察するとき、事前のフォーカスが消えてしまい、検索された文字列も、検索ダイアログを消すかフォームをクリックするまでハイライトされません。
過去ログにあったHideSelectionも探したのですが、TInplaceEditのプロパティの中には見当たらず、文法エラーで受け付けてももらえませんでした。
どう振舞ったらよいのでしょうか?

長いですが、コードのおおよそを記載します。
{検索メニューをクリック}
procedure THwdForm.Find1Click(Sender: TObject);
begin
  if StringGrid1.ControlCount > 0 then
  begin
    FindDialog1.FindText := TInplaceEdit(StringGrid1.Controls[0]).SelText;
    FindDialog1.Execute;
  end;
end;

{「次を検索」ボタンを押す}
procedure THwdForm.FindDialog1Find(Sender: TObject);
begin
  if FindDialog1.FindText = '' then
    ShowMessage('空文字列は検索できません')
  else begin
    FindWork(Sender, FindDialog1.FindText);
//  FindDialog1.CloseDialog;  //これをしないとハイライトしないのが困る
  end;
end;

{同列を次行から下まで検索する}
procedure THwdForm.FindWork(Sender: TObject; FText: String);
var
  i: Integer;
  FoundAt, StartPos: Integer;
begin
  with StringGrid1 do
  begin
    for i:=Row+1 to RowCount-1 do
    begin
      StartPos := 0;
      FoundAt := Pos(FText, Cells[Col, i]);
      if FoundAt > 0 then break;
    end;
    if FoundAt = 0 then
      ShowMessage('以降の行に検索文字列は見当たりません')
    else begin
      Row := i;
      Setfocus;
      with TInplaceEdit(Controls[0]) do
      begin
        SelStart := FoundAt + StartPos - 1;
        SelLength := Length(FText);
      end;
    end;
  end;
end;


枯葉マーク  2004-07-01 08:30:06  No: 9711

すみません、コードのなかでStartPosとあるのは、細部の消し忘れです。


枯葉マーク  2004-07-01 08:46:59  No: 9712

あ  それから、自分の頭のなかで選択とハイライトとフォーカスがぐちゃぐちゃになっていると思います。何卒ご斟酌のほどを


スタテツ  2004-07-01 10:35:38  No: 9713

こんな感じでいかがでしょうか?
//〜onDrawCellイベントに〜
procedure THwdForm.StringGrid1DrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
if gdFocused in State then
begin
  beforeFocusedCell.X:=ACol;  // beforeFocusedCell:TPos (private)
  beforeFocusedCell.Y:=ARow;  //
end;
if (beforeFocusedCell.X=ACol) and
   (beforeFocusedCell.Y=ARow) and
   (gdFocused in State = False ) and
   ((Sender as TStringGrid).Focused=False) then
   begin
     (Sender as TStringGrid).Canvas.Brush.Color:=(Sender as TStringGrid).Color;
     (Sender as TStringGrid).Canvas.FillRect(Rect);
     (Sender as TStringGrid).Canvas.DrawFocusRect(Rect);
   end;
end;
>選択とハイライトとフォーカスがぐちゃぐちゃになっていると思います。
確かに^^;


枯葉マーク  2004-07-02 07:37:55  No: 9714

スタテツさん、レス有難うございます。残念ながらまだ解決できていません。
DrawCellイベントはよく分からないのですが、次のif条件が満たされない、
>(gdFocused in State = False ) and
>((Sender as TStringGrid).Focused=False) then
つまり操作のなかでフォーカスを失う瞬間がないのではないかと思えました。

どうも現象の説明がよろしくないようです。
検索ダイアログ表示中も、親フォームのハイライトとその移動が見えるようにしていたい、と言ったら正しいのでしょうか?
たどたどしい説明で恐縮です。


スタテツ  2004-07-02 08:42:02  No: 9715

質問の意図をよく理解できないままの回答でスミマセン;;
>//  FindDialog1.CloseDialog;  //これをしないとハイライトしないのが困る
と有ったのでgdFocusedの属性を持つセルをハイライトと呼んでいるのかと思いました。
1□□□□□□□
2□□■■□□□
3□■■■□□□
4□□□□□□□
5□□□□□□□
ここで言うと[2,2]ですが、StringGrid自体のフォーカスが無くなると■になることを指しているのかと思っただけです。

>検索ダイアログ表示中も、親フォームのハイライトとその移動が見えるようにしていたい
正直やりたいことが分かりません。
ハイライトとはここで言う選択領域■であると仮定して、それが移動とあるので一つのCellのみを選択して移動しながら文字検索を行うということにして回答させていただきます。

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    FindDialog1: TFindDialog;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FindDialog1Find(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
StringGrid1.DefaultColWidth:=10;
StringGrid1.DefaultRowHeight:=10;
StringGrid1.RowCount:=10;
StringGrid1.ColCount:=10;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
FindDialog1.Execute;
end;

procedure TForm1.FindDialog1Find(Sender: TObject);
var i,p:integer;
begin
for i:= 1 to StringGrid1.ColCount-1 do
 for p:= 1 to StringGrid1.RowCount -1 do
 begin
   StringGrid1.Col:=i;
   StringGrid1.Row:=p;
   Application.ProcessMessages;
   sleep(100);
 end;
end;
end.


枯葉  2004-07-02 12:12:51  No: 9716

スタテツさん、お世話をおかけして申し訳ありません。
記載されたコードを動かしてみてビックリしました。こんな大それたことを望んだわけではないのです。
しかしお陰さまで、いろいろいじってみて分かったのは、普通に動けば検索中でも選択表示はされるものだ、という点です。
まあ頓馬な質問をしたものだと恥じ入っております。
自分のコードでは何かの拍子で隠れてしまったのだろうと、原因探しを始めました。本日はもう時間切れです。明日には解決の報告ができるようにしたいです。


枯葉マーク  2004-07-03 13:29:21  No: 9717

ドツボにはまって抜けられないので解決マークは打てません。
基礎的な力量の問題と思いますので、勉強して出直したいと思います。
お騒がせして本当に申し訳ありませんでした。

拙い日本語で意味も意図も伝わらなかったと思います。
エチケットとして①そもそもの狙い②起こっている問題③検討経過について、できるだけの整理をさせていただきます。

①工作しているのは簡単なアンケート集計ソフトで、社内配布の手軽さをあてにしてDelphiに手を染めた次第です。
StringGridで各種定義を管理するにあたり、質問項目の登録動作を次のように想定しました。
1.商品Aの評価、商品Bの評価など、部分的に似た言葉の繰り返しが多いので、代表名称を一組入力しコピー→貼り付けで仮登録する。
2.検索文字A、置換文字Bなどで必要な箇所を置換して完成させる。

この場では単純化のため検索問題として提示しましたが、視認しながらの置換が狙いです。

②困った現象というのは、検索ダイアログ表示中、StringGridでの検索結果が見えなくなったことです。用語の使い方が分からなくて余分な混乱をきたしてしまいました。

③ちょうだいしたコードを手がかりにヒナ型を作り検討して確認できたことは、
・goEditingをFalseにしてセル単位の検索なら、何の支障もなくいける。
・InplaceEditorをターゲットにしても、単一のフォームでは動いた。
・それがMDI子フォームにした途端、なぜか表示が隠れてしまう。
・どうもStringGridにActiveが戻れば表示されるが、検索ダイアログにそれが残っているときはうまくいかないようだ。(goEditing=FalseならそれでもOK)

SetFocusの使い方がまずいのか、VBAのActivateみたいなメソッドはないものか、でも多分おもいがけない初歩的ミスの可能性が一番高いだろう、などと先の見えないトンネルに入ってしまいました。

別のテーマに進みます。またご厄介かけるかもしれませんが、よろしくお願いします。冗長な発言、重ねて失礼いたしました。


にゃ〜  2004-07-03 17:13:42  No: 9718

>・それがMDI子フォームにした途端、なぜか表示が隠れてしまう。
>SetFocusの使い方がまずいのか、…

これでどうかにゃ〜?
MDIでは親フォームにFocusあてるにゃ〜

procedure THwdForm.FindWork(Sender: TObject; FText: String);
var
  .......
begin
    ..............
    else begin
      Row := i;
      MainForm.Setfocus;         ← MDIの親フォーム(MainForm)にフォーカス                  
      with TInplaceEdit(Controls[0]) do
      ..............


枯葉マーク  2004-07-04 02:04:15  No: 9719

にゃ〜さん有難うございます。あっさり解決です。
MDIの親フォームに返すとは思いもよりませんでした。
ほとんど諦めていたのですが、恥はかいてみるものです。
スタテツさん、お世話おかけしました。ご両人に感謝します。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加