XE2のStringGridで二重に表示されるのは?


4OZ レベルライン  2011-12-14 20:40:54  No: 41346

7や2007からXE2へアプリを移植しています。
その中で、StringGridの表示がおかしくなってしまいます。
具体的には、各セルの表示をセルの中心にしている場合、
Fixセルと(1,1)のセルが左端(標準の表示)とセルの中心の表示の
二重表示になります。他のセルは問題なく中心の表示になっています。
確認のため、新しいフォームにButtonとStringGridを一つ置き、
下記のコードで実験しても同様です。

procedure TForm1.Button1Click(Sender: TObject);
var
  i:Integer;
begin
  //適当なデータの表示
  for i := 0 to 4 do
  begin
    StringGrid1.Cells[i,0] := IntToStr(i);
    StringGrid1.Cells[i,1] := IntToStr(i*i);
    StringGrid1.Cells[i,2] := IntToStr(i*i*2);
    StringGrid1.Cells[i,3] := IntToStr(i*i*3);
  end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  X,Y,SH,SW :Integer;
begin
  StringGrid1.Canvas.FillRect(Rect);

  SW := StringGrid1.Canvas.TextWidth( StringGrid1.Cells[ACol,ARow]) div 2;
  SH := StringGrid1.Canvas.TextHeight(StringGrid1.Cells[ACol,ARow]) div 2;
  X  := Rect.Left + (Rect.Right - Rect.Left) div 2 - SW ;
  Y  := Rect.Top  + (Rect.Bottom - Rect.Top) div 2 - SH ;

  StringGrid1.Canvas.TextOut(X,Y,StringGrid1.Cells[ACol,ARow]);
end;
StringGridをクラシック表示にすると問題なく表示できますが・・・・・
対処方法は何かないでしょうか?

よろしくお願いします。


KHE00221  2011-12-16 05:13:09  No: 41347

>https://www.petitmonte.com/bbs/answers?question_id=7366

こっちの答えににもなるだけど

TStringGrid = class(vcl.Grids.TStringGrid);

procedure TForm2.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
    X,Y,SH,SW :Integer;
    ARect: TRect;
    FOnDrawCell: TDrawCellEvent;
    S: String;
    C: TColor;
begin
    FOnDrawCell := StringGrid1.OnDrawCell;
    StringGrid1.OnDrawCell := nil;

    if StyleServices.Enabled then Rect.Left := Rect.Left - 4;

    //背景再描画
    if gdFixed in State then C := StringGrid1.FixedColor else C := StringGrid1.Color;
    StringGrid1.DrawCellBackground(Rect,C,State,ACol,ARow);

    //テキスト再描画
    S := StringGrid1.Cells[ACol,ARow];
    SW := StringGrid1.Canvas.TextWidth(S);
    SH := StringGrid1.Canvas.TextHeight(S);
    X  := Rect.Left + ((Rect.Right - Rect.Left) - SW) div 2;
    Y  := Rect.Top  + ((Rect.Bottom - Rect.Top) - SH) div 2;
    if StyleServices.Enabled then
    begin
      ARect := System.Classes.Rect(X-6,Rect.Top,Rect.Right,Rect.Bottom);
    end
    else
    begin
      ARect := System.Classes.Rect(X-2,Y-2,Rect.Right,Rect.Bottom);
    end;
    StringGrid1.DrawCell(ACol,ARow,ARect,State);

    StringGrid1.OnDrawCell := FOnDrawCell;
end;


4OZ レベルライン  2011-12-16 19:29:08  No: 41348

KHE00221さま、ありがとうございます。
上記コードで二重表示の問題はクリアーできました。

ただ、2つほど疑問が残りましたのでお教えいただけますでしょうか?

1.何も処理をしないコード(7や2007でのコード)の場合
Fixedセル以外にセル(1,1)も2重表示になりますがなぜなのでしょうか?

2.KHE00221さまのコードを使用させていただいた場合、
StringGridのフォーカスが当たっているセルの表示について
      他のコンポーネントにフォーカスがある場合==>表示内容が消える
      StringGridにフォーカスが当たっている場合==>内容が表示される

過去に「フォーカスの当たっているセルの背景の色をなになにする」と
同様の考え方だろうかな?と思い、探しましたが見つけることができませんでした。
このため、疑問として残ってしまいました。

申し訳ありませんが、疑問の解消のお手伝いをよろしくお願いいたします。


Mr.XRAY  2011-12-16 20:49:05  No: 41349

こんにちは.

TStringGridのOnDrawCellイベントは,内部でDrawCellメソッドを実行しています.
ソースコードを追いかけるのは大変ですが...

OnDrawCellイベントが呼び出された時点で,DrawCellメソッドが実行されています.
このDrawCellメソッドは既に文字の描画を行っています.
したがって,既にレスにあるように,一度背景を塗り潰さないと,DrawCellが描画した
内容が見えてしまうことになります.
OnDrawCellで描画すると,重ね書きということになります.

「難解」と言われている私のサイトの記事ですが,参考になれば,
[05_セルのカスタム描画 - 文字列のアライメント]
http://mrxray.on.coocan.jp/Delphi/plSamples/050_TStringGrid_OnDrawCell.htm#05


KHE00221  2011-12-17 04:34:24  No: 41350

>1.何も処理をしないコード(7や2007でのコード)の場合
>Fixedセル以外にセル(1,1)も2重表示になりますがなぜなのでしょうか?

意味が分からない

>2.KHE00221さまのコードを使用させていただいた場合、
>StringGridのフォーカスが当たっているセルの表示について
>    他のコンポーネントにフォーカスがある場合==>表示内容が消える
>    StringGridにフォーカスが当たっている場合==>内容が表示される

表示内容消えないのでなんとも・・・・

フォーカスの色の事なら

    //背景再描画
    if gdFixed in State then
    begin
     C := StringGrid1.FixedColor;
    end
    else
    begin
      if gdSelected in State then C := clRed else C :=       StringGrid1.Color;
    end;
    StringGrid1.DrawCellBackground(Rect,C,State,ACol,ARow);

で指定できる


4OZ レベルライン  2011-12-17 08:17:01  No: 41351

>>1.何も処理をしないコード(7や2007でのコード)の場合
>>Fixedセル以外にセル(1,1)も2重表示になりますがなぜなのでしょうか?

>意味が分からない
確認されず意味不明???

質問時のコードで3台のPCで7、2007、XE、XE2で確認しています。
[0,0]  [0,1]  [0,2]  [0,3]====>Fixd
[1,0]  [1,1]=====>>ここ「Fixedでないセル」が2重表示です
[2,0]
[3,0]
  ↑
Fixed

Fixedセルが2重表示は分かるにしても、どうしてセル[1,1]までそうなのか

他のセルはOKです。

>表示内容消えないのでなんとも・・・・
同様に3台で確認していますが、質問時のコードで、
Button1でStringGridに内容を表示させると
StringGridではセル[1,1]にフォーカスがあたっていると思いますが、
フォーム上ではButton1にフォーカスがあります、
この状態で、StringGridのセル[1,1]の表示が消えた形になります。
ここで、StringGridをクリック(選択)すると[1,1]のセルの表示がされます。
StringGrid.SetFocusで回避はできますが、
同一フォーム上で他の処理をしていく場合(ほかのButton等が在った場合など)、
この表示の問題が出てきます。

腕ずくで回避しないといけないのでしょうか????


KHE00221  2011-12-17 18:37:08  No: 41352

Fixedを描画するときは fsClear
Cells を描画するときは fsSolid

>Fixedセルが2重表示は分かるにしても、どうしてセル[1,1]までそうなのか

Cells(1,1) は Fixed の直後なので fsClear なので 2重に表示されてしまう

>この状態で、StringGridのセル[1,1]の表示が消えた形になります。

消えるじゃなくて2重表示?

Cellをクリックすると

1) ClickしたCell描画 (fsSolid)
2) Clickする前にあった Cell  を描画 (fsSolid)
3) なぜか Cell(0,0) を描画 (fsClear)

ここでフォーカスを失うと fsClear のまま fsSelected だったセルが
描画されるので 2重に表示される


KHE00221  2011-12-17 18:39:42  No: 41353

>Cells(1,1) は Fixed の直後なので fsClear なので 2重に表示されてしまう
これうそ


KHE00221  2011-12-17 18:47:21  No: 41354

gsSelected は fsClear
gsFouces は fsSolid

最初 Cells(1,1) が Selected で、 Button Click で  フォーカス
をうしなって  Cells(1,1) だけ fsClear

なので ほかのセルを選んで Button1 Click  するとそこが2重表示

クリックすると Selected と Fouces になるので  Solid
エリア指定すると Fouces のとこは fsSolid だけど
ほかのとこは fsClear で2重表示


KHE00221  2011-12-17 18:48:28  No: 41355

あくまで動作からの推測


4OZ レベルライン  2011-12-17 19:46:33  No: 41356

問題の切り分けです

1.「2重表示」==>まだなぜなのかは理解できていませんが、
お教えいただいたコードで回避できました。

2.セル[1,1]が表示されない
お教えいただいたコードでやってみて同様でした。
Button1でStringGridに適当なデータを表示します。

[0,0]  [0,1]  [0,2]  [0,3]====>Fixd
[1,0]  [1,1]=====>>このセルの内容が表示されません
[2,0]
[3,0]

フォーム上にButton2とButton3を置き

procedure TForm1.Button2Click(Sender: TObject);
begin
  StringGrid1.SetFocus;//===> セル[1,1]のデータが表示される(2重表示ではない)
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Button1.SetFocus;//===> セル[1,1]のデータ表示が消える
end;
このような動きをします。

実際のアプリを作成した場合使い勝手が悪くなります、
回避方法はないでしょうか?


4OZ レベルライン  2011-12-17 19:59:21  No: 41357

追加です
実験していくと
StringGridがフォーカスを失うとき、
選択されているセルの内容の表示が消えます。
上の  Buttonでフォーカスを他のコンポーネントに移すとき
StringGridで選択されているセルが任意の場合でも、
そのセルのデータ表示が消えてしまいます。

セル[2,2]に選択されているときに、
ほかのコンポーネントにフォーカスが移動すると、
セル[2,2]の内容が非表示になってしまいます。


4OZ レベルライン  2011-12-18 20:00:48  No: 41358

追加実験しました

XP+XE  XP+XE2では  StringGridからフォーカスが他のコンポーネントに移ると、
StringGridのフォーカスがあたっているセルで、表示が消えます。==>上の実験

7(64Bit)+XE2 の場合KHE00221さまのコードで正常に表示されます。
StringGridがフォーカスを失っても正常な表示です。

OSによって動きが違ってきていますので考えてしまいます。


KHE00221  2011-12-18 20:41:11  No: 41359

XP + XE2 できえないので  
わかりません!


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

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






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