Stringgridのセル内複数行表示の色つけについて

解決


タイガー  2013-12-19 23:45:01  No: 45761

こんにちは。
Stringgridのdraw cellについての質問です。
セル内に複数行を改行を使って表示させているのですが、draw cellで色を分けて付ける方法を教えてください。
stringgrid1.cells[0,1]:='父'+#13#10+'母';
----------
Stringgrid1drawcell
Var
S:string;
begin
  S:=stringgrid1.cells[acol,arow];
  Stringgrid1.canvas.fillrect(rect);
  Drawtextex(stringgrid1.canvas.handle,
                     Pchar(s),
                     Length(s),
                     Rect,
                     Dt_left,
                     Nil);
End;
以上のようなコードで表示させています。
父を赤色に、母を青色にする場合どのようにするのか教えてください。


D  2013-12-21 07:56:35  No: 45762

"父"と"母"の二回に分けて描画します。

まずStringgrid1のCanvasのFontのColorを赤にして"父"を描画。
次にDrawtextexの戻り値を利用するなどしてRect.Topの値を調整。
そしてStringgrid1のCanvasのFontのColorを青にして"母"を描画。

多分こんな感じで。


monaa  2013-12-22 02:11:14  No: 45763

参考程度程度のサンプルですが、
キャンバスに色付きテキストを描いてみました。

procedure DrawColorText(aCanvas:TCanvas; const aRect:TRect; const aText:string);
var
  tw,th,ch,cw:Integer;
  i: Integer;
const
  RedChar  = '父雄牡♂兄弟123'; //赤にしたい文字
  BlueChar = '母雌牝♀姉妹456'; //青にしたい文字
  TabSize  = 50;
procedure DrawReturn;
begin
  inc(th,ch);
  tw := aRect.Left;
end;
begin
  tw := aRect.Left;
  th := aRect.Top;
  ch := aCanvas.TextHeight('l');
  aCanvas.Lock;
  for i := 1 to Length(aText) do
  begin
    case Word(aText[i]) of
      $A:;
      $D:DrawReturn; //改行
      $9:begin;//Tagを実装するならここに記述
        tw := ((tw div TabSize)+1) * TabSize;
      end;
      else begin
        if Pos(aText[i],BlueChar)>0 then
          aCanvas.Font.Color := clBlue else
        if Pos(aText[i],RedChar)>0 then
          aCanvas.Font.Color := clRed else
          aCanvas.Font.Color := clWindowText;
        cw := aCanvas.TextWidth(aText[i]);
        if tw+cw > aRect.Right then //右側で折り返し
          DrawReturn;
        aCanvas.TextOut(tw,th,aText[i]);
        inc(tw,cw);
      end;
    end;
  end;
  aCanvas.Unlock;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Canvas.Brush.Style := bsClear;
  DrawColorText(Canvas, Rect(0,0,Memo1.Width, Memo1.Height), Memo1.Text);
end;


タイガー  2013-12-27 22:08:56  No: 45764

Dさんminnaさんコメントありがとうございます。
理解するのに時間がかかるので参考にしながらやってみます。


タイガー  2013-12-30 01:18:49  No: 45765

こんにちは
stringgridのdrawcellを使っての描画の質問です。
------------------------------
stringgrid1.cells[0,1]:='父'+
                          #13#10+
                          '母';
------------------------------
一行目の父を青色
二行目の母を赤色に描画する場合
  s:=stringgrid1.cells[Acol,Arow];

    if((ARow=0) and (ACol=1)) then
    with Canvas do begin
      fillrect(rect);//一度表示を消す
      Brush.Color:=clwhite;
      Font.Color:=clblue;
      DrawTextEx(StringGrid1.Canvas.Handle,
             PChar(S),
             Length(S),
             Rect,
             DT_left,
             nil);
      dt:=DrawTextEx(StringGrid1.Canvas.Handle,
             PChar(S),
             Length(S),
             Rect,
             DT_left,
             nil);
      if(dt>12)and(dt<=24)then begin
        fillrect(rect);
        Font.Color:=clred;
        DrawTextEx(StringGrid1.Canvas.Handle,
             PChar(S),
             Length(S),
             Rect,
             DT_left,
             nil);
       end;
     end;//
-------------------
以上のようなコードでdrawtextの戻り値を利用して見たのですが、表示は赤色になってしまいます。結局、戻り値の値だけで一行目二行目を判定できていません。Rect.topの値を調整するというのは、どのようにするのでしょうか?


KHE00221  2013-12-30 02:54:08  No: 45766

procedure TForm3.FormCreate(Sender: TObject);
begin
    StringGrid1.Cells[1,1] := '父'#13#10'母';
    StringGrid1.Cells[2,1] := '父母';
end;

procedure TForm3.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;Rect: TRect; State: TGridDrawState);
var
  Text: String;
  I,H: Integer;
  S1,S2: String;
  BRect: TRect;
begin
    if not ( gdFixed in state ) then
    begin

      StringGrid1.Canvas.Brush.Color := StringGrid1.Color;
      StringGrid1.Canvas.FillRect(Rect);
      Text := StringGrid1.Cells[ACol,ARow]; //CELLのText

      I := Pos ( #13#10,Text); //#13#10の位置取得
      if ( I <> 0 ) then
      begin
        S1 := Copy(Text,0,I);                   //#13#10より前の文字
        S2 := Copy(Text,I+2,Length(Text)-I);    //#1310より後ろの文字
        H := StringGrid1.Canvas.TextHeight(S1); //前の文字の高さ
        //#13#10の前を描画
        StringGrid1.Canvas.Font.Color := clRed;
        StringGrid1.Canvas.TextRect(Rect,Rect.Left,Rect.Top,S1);
        //#13#10の後を描画
        BRect := Rect;
        BRect.Top := BRect.Top + H;
        StringGrid1.Canvas.Font.Color := clBlue;
        StringGrid1.Canvas.TextRect(BRect,Rect.Left,Rect.Top+H,S2);
      end
      else
      begin
        //#13#10の無いCELL
        StringGrid1.Canvas.Font.Color := StringGrid1.Font.Color;
        StringGrid1.Canvas.TextRect(Rect,Text);
      end;
    end;
end;


タイガー  2013-12-30 04:53:02  No: 45767

KHE00221さん。早速の回答ありがとうございます。
思い通りに描画できました。
そこでもうひとつだけ、二行のやり方はわかりましたが、三行目もある場合
i:=ansipos(#13#10,text);
showmessage(inttostr(i));にして結果を見たところ1つだけしかヒットしませんでした。
S1 := Copy(Text,0,I);                   //#13#10より前の文字
S2 := Copy(Text,I+2,Length(Text)-I);    //#1310より後ろの文字
'父'#13#10'母'#13#10'弟'
のように三行目の描画も教えてくさい。


KHE00221  2013-12-30 20:59:25  No: 45768

procedure TForm3.FormCreate(Sender: TObject);
begin
     StringGrid1.Cells[1,1] := '父'#13#10'母'#13#10'妹'#13#10'弟'#13#10;  //最後改行あり
     StringGrid1.Cells[2,1] := '父'#13#10'母'#13#10'妹';                  //最後改行なし
     StringGrid1.Cells[3,1] := '父'#13#10'母';
     StringGrid1.Cells[4,1] := '父母';
     StringGrid1.RowHeights[1] := 50;
end;

var
    FontColors: array[0..3] of TColor = (clRed,clBlue,clGreen,clYellow);

procedure TForm3.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
    C,I: Integer;
    S: String;
    FC: TColor;
begin

    if not ( gdFixed in state ) then
    begin
      FC := StringGrid1.Font.Color;
      StringGrid1.Canvas.Brush.Color := StringGrid1.Color;
      StringGrid1.Canvas.FillRect(Rect);
      Text := StringGrid1.Cells[ACol,ARow]; //全体文字
      C := 0;
      while (Text <> '') do
      begin
        I := Pos ( #13#10,Text);
        if I<>0 then
        begin
          //改行あり
          S := Copy(Text,0,I);                   //改行までの文字
          Text := Copy(Text,I+2,Length(Text)-I); //Textを改行以降の文字にする
        end
        else
        begin
          //改行なし
          S := Text;
          Text := '';
        end;
        StringGrid1.Canvas.Font.Color := FontColors[C];
        StringGrid1.Canvas.TextRect(Rect,Rect.Left,Rect.Top,S);
        Rect.Top := Rect.Top + StringGrid1.Canvas.TextHeight(S);
        //Rect.top が Rect.Bottom を超えるのを防ぐ
        if ( Rect.Top > Rect.Bottom ) then Rect.Top := Rect.Bottom;
        Inc(C);
      end;
      StringGrid1.Canvas.Font.Color := FC;
    end;

end;


タイガー  2013-12-31 01:07:45  No: 45769

KHE00221さん。
Font colorを配列にするというアイデアは初心者には思いつきません。
サンプルコードありがとうございます。

色を付けるのは他にもしてみたいことがあります。
父母の父は青色に母は赤色にするとかです。
Drawcellの複雑な?色つけはposを利用して文字の長さを判定していくようにしていけばいいですか?


KHE00221  2013-12-31 02:43:14  No: 45770

procedure TForm1.FormCreate(Sender: TObject);
begin
     StringGrid1.Cells[1,1] := 'A父Bと11母22'#13#10'妹33'#13#10'44弟'#13#10;  //最後改行あり
     StringGrid1.Cells[2,1] := '父'#13#10'11母22'#13#10'妹';                    //最後改行なし
     StringGrid1.Cells[3,1] := '父'#13#10'母';
     StringGrid1.Cells[4,1] := '父母';
     StringGrid1.ColWidths[1] := 100;
     StringGrid1.RowHeights[1] := 50;
end;

var
    Keys: array[0..3] of String = ('父','母','妹','弟');
    FontColors: array[0..3] of TColor = (clRed,clBlue,clGreen,clYellow);

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
    I,J,K: Integer;
    S1: String;
    DefaultColor: TColor;
    Text: String;
    BRect: TRect;
begin

    if not ( gdFixed in state ) then
    begin

      DefaultColor := StringGrid1.Font.Color;
      StringGrid1.Canvas.Brush.Color := StringGrid1.Color;
      StringGrid1.Canvas.FillRect(Rect);
      Text := StringGrid1.Cells[ACol,ARow]; //全体文字
      BRect := Rect;
      I := 1;
      while (I < Length (Text)) do
      begin
        K := -1;
        for J := Low ( Keys ) to High ( Keys ) do
        begin
          if Copy(Text,I,Length(Keys[J])) = Keys[J] then K := J;
        end;
        if ( K <> -1 ) then
        begin
          StringGrid1.Canvas.Font.Color := FontColors[K];
          StringGrid1.Canvas.TextRect(BRect,BRect.Left,BRect.Top,Keys[K]);
          StringGrid1.Canvas.Font.Color := DefaultColor;
          BRect.Left := BRect.Left + StringGrid1.Canvas.TextWidth(Keys[K]);
          I := I + Length (keys[K]);
        end
        else
        begin
          if ( Copy(Text,I,2) = #13#10 ) then
          begin
            BRect.Left := Rect.Left;
            BRect.Top  := BRect.Top + StringGrid1.Canvas.TextHeight('A'); //A は適当
            Inc(I);
          end
          else
          begin
            S1 := Copy(Text,I,1);
            StringGrid1.Canvas.TextRect(BRect,BRect.Left,BRect.Top,S1);
            BRect.Left := BRect.Left + StringGrid1.Canvas.TextWidth(S1);
          end;
          Inc(I);
        end;
      end;

      StringGrid1.Canvas.Font.Color := DefaultColor;
    end;

end;


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

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






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