FMXでStringGridの行や列毎に色を変える、Modalウィンドゥを閉じる


yTake  2017-03-18 15:14:08  No: 48611  IP: 192.*.*.*

yTakeです。再び、ご教授頂けるでしょうか?
TStringGridで処理に時間が掛かった場合の進捗表示にModalウィンドゥでProgressBarを表示する事とします。
処理終了後、そのままModalウィンドゥを閉じようと思いますが、FMXではPostMessageが使えない様です。
調べてみるとTMessageManageを使って、”ModalResult”の値を0以外に設定すればModalウィンドゥが閉じられる様に思います。
ただ、記述方法が分かりません。
どうも、FMXではマルチプラットフォーム対応の為か、VCLで簡単に出来た事が難解になっている様に思います。

StringGridを行毎や列毎に背景色を変える事も、簡単ではありません。
VCLでは”onDrawCell”にRowとColの値により背景色を変える事ができました。(DefaultDrawingをFalseにする)
FMXのStringGridでもDefaultDrawingのパラメータがあるので、同様の考え方で実現できそうですが、実際にはCol位置の把握など、具体的にどの様にすべきか、不明瞭です。

また、セル内の文字を再描画する必要があると思います。DrawTextの代わりにTextOutを使うのでしょう。


今ひとつ理解があやふやで、こちらも記述が分かりません。


何か参考になる情報はあるでしょうか?サンプルコードがあるとなおうれしいです。

具体的に質問できれば良いのですが、そもそもFMXを良く分かっていません。
それほど難しい事をやろうとしているつもりはないのですが、FMXでは難しいです。


アドバイス頂けるでしょうか?


当方、
32bitWindows10+DELPHI XE6(update1) with FMX
です。

編集 削除
igy  2017-03-18 15:26:09  No: 48612  IP: 192.*.*.*

> StringGridを行毎や列毎に背景色を変える事も、簡単ではありません。 

行ごとの場合、OptionsプロパティにAlternatingRowBackgroundがあります。
# バージョンによっては、Optionsプロパティの中じゃなく、AlternatingRowBackgroundプロパティの場合もあります。

編集 削除
igy  2017-03-18 15:36:29  No: 48613  IP: 192.*.*.*

> 行ごとの場合、OptionsプロパティにAlternatingRowBackgroundがあります。 
> # バージョンによっては、Optionsプロパティの中じゃなく、AlternatingRowBackgroundプロパティの場合もあります。

これは、1 行おきに背景色を設定する場合に使用します。

編集 削除
igy  2017-03-18 15:42:50  No: 48614  IP: 192.*.*.*

あと、あまり詳しくないのですが、
DrawColumnCellイベントで、描画とか、できそうです。

編集 削除
yTake  2017-03-18 18:51:39  No: 48615  IP: 192.*.*.*

igyさん、ありがとうございます。

AlternatingRowBackgroundについてはネット上で情報を見つけていたのですが、こちらの環境では見当たらなくて、Option下にあったのですね。簡単に1行おきの色分けができました。

onDrawColumnCellでもう少し細かい芸当が出来そうです。
取り敢えず、列方向にはここで試行錯誤してみます。

編集 削除
yTake  2017-03-22 14:54:02  No: 48616  IP: 192.*.*.*

間が空いてしまいましたが、yTakeです。
少々長いです。

1)
一応、行・列毎の背景色の設定は、ある程度実現出来ました。
ただ、行の色分けにAlternatingRowBackgroundを”True”としましたが、その色が分かりません。
”FMX.Grid.Style”にalternatingBackgroundColorと言う変数がある様ですが、uses節で”FMX.Grid.Style”を読んでいますが、未定義の識別子になってしまいます。

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
DefaultDrawing=False
AlternatiingRowBackground=True
を設定しいます。
procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas; const Column: TColumn;
  const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var
    i, j  : Word;
    str   : String;
begin
    j :=  Row;
    i :=  column.Index ;
    str :=  Value.ToString;
    if  ( i mod 5 ) = 0 then
    begin
        Canvas.Fill.Color   :=  claLightGray;
        Canvas.FillRect( Bounds, 0, 0, AllCorners, 1, TCornerType.Round );
        CAnvas.Fill.Color :=  claBlack;
        Canvas.FillText( Bounds, str, False, 100, [TFillTextFlag.RightToLeft], TTextAlign.Center, TTextAlign.Center );
    end
    else
    begin
        Canvas.Fill.Color   :=  Canvas.Fill.DefaultColor;
        Canvas.FillRect( Bounds, 0, 0, AllCorners, 1, TCornerType.Round );
        CAnvas.Fill.Color :=  claBlack;
        Canvas.FillText( Bounds, str, False, 100, [TFillTextFlag.RightToLeft], TTextAlign.Center, TTextAlign.Center );
    end;
end;
としました。
StringGridに書き込むところでは、
    for i := 0 to col2 do
    begin
        StringColumn_1[ i ] :=  TStringColumn.Create( Form1.StringGrid1 );
        StringColumn_1[ i ].Width :=  60;
        StringColumn_1[ i ].Header  :=  IntToStr( i );
        Form1.StringGrid1.AddObject( StringColumn_1[ i ] );
        if  i = 0 then
        begin
            StringColumn_1[ i ].Locked  :=  True;
            for j := 0 to dcm_Data_1.row2 - 1 do
                Form1.StringGrid1.Cells[ i, j ] := FloatToStrF( j + 1, ffFixed, 5, 0 );
        end
        else
        begin
//            StringColumn_1[ i ].Align  :=  TTextAlign.Center; ①
            for j := 0 to row2 - 1 do
            begin
//               Form1.StringGrid1.Columns[ i ].Align  :=  taCenter; ②
                Form1.StringGrid1.Cells[ i, j ] := FloatToStrF( MTX2.MTX[ i - 1, j ].dens, ffFixed, 5, 0 );
            end;
        end;
    end;
としています。

問題は、背景色の着いたセルにテキストをセンター寄りにして書き直すところです。
つまり、背景色を塗り直してその後元の文字列を描画していますが、AlternatingBackgroundColorが何色か分からない為、背景色の塗り直しが出来ていません。
AlternatingBackgroundColorの色を知るにはどの様にするのでしょう?

或いは、予めセンター寄りにしてから、StringGridへ書き込めば良い様にも考えましたが、アライメントが出来ません。
TAlignLayoutとTTextAlignには互換性がありません。或いはTAlignLayoutとTAlignmentには互換性がありませんとなります。(①と②)


2)
また、処理に時間が掛かる為、ModalウィンドウにProgressBarを表示して、進捗が分かる様にする件では、処理終了後Modalウィンドゥを閉じる事が出来ない為、Modalウィンドゥは諦めて、単に別ウィンドウにProgressBarを表示する事で実現しました。
VCLでは”PostMessage”を利用してModalを閉じられる様ですが、FMXでは難しい様です。


3)
一方で、ビットマップの表示が出来なくなりました。
経緯:
先にDelphi XE6作成したBitmapの描画に問題のないプロジェクトをXE10.1 Berlinに読み込んで実行した場合、ほぼ問題なく(少なくとも自分で描画した画像は)XE10.1 Berlinでも描画できています。
ただ、色々試行錯誤の後、エラー”例外クラスEReadError(メッセージ’プロパティFormFactor.Widthが存在しません’)を送出しました”が出る様になってしまい。これが解消できない為、
新たにXE10.1 Berlinで同様のBitmapルーチンを作成しましたが、Bitmapが描画されません。
経緯ここまで。
Bitmapデータを作成するところと作成したBitmapをImageへ描画するところは同じ様にコーディングしているはずですが、、、
Bitmapの作成、
procedure draw_bitmap( var bmp0 : TBitMap ; row0, col0 : Word ; var MTX0 : RRMTX );
var
    i, j    : Word;
    offsetX : Word;
    offsetY : Word;
    vBitMapData : TBitmapData;
    vPixelColor : TAlphaColor;
    tmpColor    : TAlphaColor;
    clr : Byte;
begin
    if row0 > col0 then
    begin
        bmp0.SetSize( row0, row0 );
        offsetX := ( row0 - col0 ) div 2;
        offsetY := 0;
    end
    else
    begin
        bmp0.SetSize( col0, col0 );
        offsetX := 0;
        offsetY := ( col0 - row0 ) div 2;
    end;
    bmp0.Map( TMapAccess.Write, vBitMapData );
    for j := 0 to row0 - 1 do
    begin
        for i := 0 to col0 - 1 do
        begin
            clr :=  255 - MTX0.MTX[ i, j ].disp;
            vPixelColor :=  ( clr shl  0 ) +
                            ( clr shl  8 ) +
                            ( clr shl 16 ) +
                              4278190080;
            vBitMapData.SetPixel( offsetX + i, offsetY + j, vPixelColor );
//            tmpColor  :=  vBitMapData.GetPixel( offsetX + i, offsetY + j );
        end;
    end;
    bmp0.Unmap( vBitMapData );
end;

Imageへの描画
    srcRect.Top     :=  0 ;
    srcRect.Left    :=  0 ;
    srcRect.Right   :=  bmp2.Width ;
    srcRect.Bottom  :=  bmp2.Height ;

    dstRect.Top     :=  0 ;
    dstRect.Left    :=  0 ;
    dstRect.Right   :=  Form1.Image1.Width;
    dstRect.Bottom  :=  Form1.Image1.Height;

    Form1.Image1.Bitmap.Canvas.BeginScene();
    Form1.Image1.Bitmap.Canvas.DrawBitmap( bmp2, srcRect, dstRect, 1.0, False );
    Form1.Image1.Bitmap.Canvas.EndScene();
    Form1.Image1.EndUpdate();

です。

Bitmapデータは任意の矩形ですが、描画すべきImageは正方形である為、その中央に描画される様にBitmapにオフセットをを持たせています。

それをCanvas.DrawBitmapで描画させているだけなのですが、なぜか描画されません。

違いはと言えばXE6でのFMXは”デスクトップアプリケーション”を選択しましたが、XE10.1でFMXで”デスクトップアプリケーション”の選択がなく、”マルチデバイスアプリケーション”で”空のアプリケーション”を選択しました。
が、特に問題ではない様に思えます。


質問が取り留めなくなってしまいました。何か、アドバイスがあればお願い致します。


当方、
64bitWindows10Pro
DELPHI XE10.1 Berlin (Starter)

編集 削除
Mr.XRAY  2017-03-22 18:32:46  No: 48617  IP: 192.*.*.*

>プロパティFormFactor.Widthが存在しません

このエラーが発生した場合は,プロジェクトのファイルを必要最小限だけにしてからプロジェクトを開いてみてください.
異なるバージョンの Delphi のプロジェクトを開く際に発生することがあります.
VCL の場合は ... Windows という表示の場合もあります.

http://mrxray.on.coocan.jp/Delphi/Others/Delphi_Versionl.htm


>AlternatingBackgroundColorの色を知るにはどの様にするのでしょう? 

オンラインヘルプで確認できます.

http://docwiki.embarcadero.com/Libraries/Berlin/ja/FMX.Grid.Style.TStyledGrid.AlternatingBackgroundColor

あるいは自分で調べます.
(以下のコードは uses に FMX.Grid.Style が必要)
その下のコードと共に,動作確認は Windows 7 U64(SP1) + Delphi 10.1 Berlin Starter


procedure TForm1.Button1Click(Sender: TObject);
var
  LColor : TAlphaColor;
begin
  LColor := TStyledGrid.AlternatingBackgroundColor;
  ShowMessage('$' + IntToHex(LColor, 8));
end;

FireMonkey の場合,色は以下のようになっています.

procedure TForm1.Button2Click(Sender: TObject);
var
  LColorRec : TAlphaColorRec;
begin
  LColorRec.A := $FF;  //アルファ値.最上位バイト
  LColorRec.R := $FF;  //赤.次のバイト値
  LColorRec.G := $00;  //緑.その次のバイト値
  LColorRec.B := $00;  //青.最下位のバイト値

   //色の簡単な確認方法
  //フォームにTRectangle(Shapesタブ)を配置
  Rectangle1.Fill.Color := LColorRec.Color;
  Rectangle2.Fill.Color := $FFFF0000;
end;


以下の Delphi Forum のページから AFSoft さんのサイトの記事を読みやすくした HTML ファイルが入手できます.
FireMonkey の記事があります.参考になると思います.

[VCL・ビジュアルプログラミング] [ごくごく基本的な VCL の使い方] 
http://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=21

編集 削除
yTake  2017-03-22 20:28:42  No: 48618  IP: 192.*.*.*

Mr.XRAYさん、ありがとうございます。

取り敢えず、AlternatingBackgroundColorに関して解決しました。ありがとうございました。
ヘルプは何度も参照し、FMX.Grid.Styleをuses節に含めれば未定義は解消されるはずと思い込んでいました。

変数使用に、接頭辞的に用いる事は考えませんでした。"FMX.Grid.Style."と入力したところで、自動補完が働いたのですが、予想に反して"AlternatingBackgroundColor"ではなく、"TStyledGrid"他がリストされ、その後に"AlternatingBackgroundColor"を指定する事が出来ました。

必ずしも、uses節で参照指定しなくても、直接指定する手法がある事、分かりました。

Canvas.Fill.Color := FMX.Grid.Style.TStyledGrid.AlternatingBackgroundColor;

として、背景色の塗り直しが出来ました。


この他の点も、アドバイスを参考にして、追及してみます。

編集 削除