XE3でCheckBoxの色を指定

解決


mizuki  2013-01-22 00:39:54  No: 43650

Win7 + XE3 starter
お世話になります。  D6 personalからXE3に移植中でいろいろと苦戦しています。  D6では下記のようなコードでpnlst上にCheckBoxをCreateして着色し、白抜き文字で名前を書いて問題なく動いていました。それがXE3では指定の色に着色されず(透明)また文字色も白抜きにはならず黒になってしまいます。

for i := 1 to nst do begin 

    chk_st[i] := Tcheckbox.Create(form1); 
    with chk_st[i] do
    begin
        height:=12;
        width:=120;

        Color:=st_color[i];
        caption:=st_nam[i];
        font.Color:=rgb(255,255,255);

                left:=5;
                top:=225 +i*14;
       
        Parent :=form1.pnlst;
        Tag:=i;
        onMouseMove:=form1.st_MouseMove;
        onmousedown:=form1.st_mousedown;

    end;    // with
  end;      //for  

そのようにしたらD6のように表現できるのか?  ご教示ください。


DEKO  2013-01-22 05:22:16  No: 43651

とりあえず、以下を見てもらうとして... (^-^;A

[【C++ Builder XE2】TCheckBoxのフォント色の変更について (Embarcadero Discussion Forums)]
https://forums.embarcadero.com/thread.jspa?threadID=81986&tstart=0

"リンク先のリンク先" のコードではフォント色しか変更されません。
背景色を変更できるようにするには、

"リンク先のリンク先" のコードの

    SetBkMode(canv.Handle, Ord(TRANSPARENT));

の上に、

    if not Self.ParentColor then
      begin
        canv.Brush.Color := Self.Color;
        canv.FloodFill(BtnWidth + 1, 0, canv.Pixels[BtnWidth + 1, 0], fsSurface);
      end;

を記述すれば文字色/背景色を変更できます。


mizuki  2013-01-22 21:45:02  No: 43652

DEKO様  ご教示をありがとうございます。
リンク先のコードを眺めておりましたが残念ながら当方の理解のレベルを超えたものでした。現状のコードをベースに具体的にどのように追加変更をしたら良いか教えてください。

今回の質問とは別にTCheckBoxを貼り付けて背景色、文字色の指定を試しましたがやはりこれも指定色を反映できませんでしたが、この場合も同様な対策が必要なのでしょうか?


とりあえず  2013-01-23 00:02:29  No: 43653

>今回の質問とは別にTCheckBoxを貼り付けて背景色、文字色の指定を試しましたがしましたがやはりこれも指定色を反映できませんでした

Formに貼り付けたTCheckBoxの背景色、文字色を変えたいなら、

type
  TCheckBox = class({Vcl.}StdCtrls.TCheckBox)
  private
    FOriginalCaption: string;
    _MySetCap: Boolean;
    procedure WMPaint(var msg: TWMPaint); message WM_PAINT;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  end;
type
  TForm1 = class(TForm)
    CheckBox1: TCheckBox;

  ...........................

  Form1: TForm1;

implementation

{$R *.dfm}

procedure TCheckbox.CMTextChanged(var Message: TMessage);
begin
  inherited;
  if _MySetCap then Exit;
  FOriginalCaption := Caption;
end;

procedure TCheckbox.WMPaint(var msg: TWMPaint);
var
  BtnWidth: Integer;
  canv: TControlCanvas;
begin
  BtnWidth := GetSystemMetrics(SM_CXMENUCHECK);

  _MySetCap := True;
  if not (csDesigning in ComponentState) then
    Caption := '';
  _MySetCap := False;
  inherited;
  canv := TControlCanvas.Create;
  try
    canv.Control := Self;
    canv.Font := Font;
    if not Self.ParentColor then   // デフォルトでは、Self.ParentColor は True?
      begin
// SetBkMode(canv.Handle, Ord(OPAQUE));
        canv.Brush.Color := clBlue; //Self.Color; // とりあえず背景は青色
        canv.FloodFill(BtnWidth + 1, 0, canv.Pixels[BtnWidth + 1, 0], fsSurface);
      end;
    SetBkMode(canv.Handle, Ord(TRANSPARENT));
    canv.Font.Color := clYellow; //Self.Font.Color;     // とりあえずCaption文字は黄色
    canv.TextOut(BtnWidth + 1, 2, FOriginalCaption);
  finally
    canv.Free;
  end;
end;


mizuki  2013-01-23 02:24:52  No: 43654

DEKO様  とりあえず様  ご教示をありがとうございます。
コードの内容は理解できないまま早速FormにCheckBox1を貼り付けてテストを開始してみました。  でもまだエラーだらけで進んでいません。  動いてしまえば何とか理解も進むかと思ったのですが。
とにかくテストを進めるしかないようです。ありがとうございました。


DEKO  2013-01-23 02:54:42  No: 43655

定義部 (interface の下) で、フォームの定義より前 (interface の type の下) に、

  TCheckBox = class(StdCtrls.TCheckBox)  // XE2 以降なら class(Vcl.StdCtrls.TCheckBox)
  private
    FOriginalCaption: string;
    _MySetCap: Boolean;
    procedure WMPaint(var msg: TWMPaint); message WM_PAINT;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  end;

これを記述して、

procedure TCheckbox.CMTextChanged(var Message: TMessage);
...
procedure TCheckbox.WMPaint(var msg: TWMPaint);
...

これらを実装部 (implementation の下) に記述するだけですよ。

TCheckBox の ParentColor が False なら、Color の値が背景色になり Font.Color が文字色となります。


DEKO  2013-01-23 03:46:48  No: 43656

[TCheckBox の文字色と背景色を変えたい (Delphi)]
http://ht-deko.minim.ne.jp/ft1301.html#130122_01


mizuki  2013-01-24 00:19:26  No: 43657

DEKO様  大変ありがとうございました。ご指摘のリンクのサンプルにはUses節に何を書き込むかなどが具体的に出ていましたので確実に再現できました。テストしたところ貼り付けたCheckBox(静的)もCreateしたものも着色に成功しましたので本体のプログラムに実装して着色が確認できました。
しかしCheckBoxの上に他のアプリを表示したり本ソフトを最小化から復元したりした際には色が消えてしまう(VBのAutoRedraw=falseのような)現象に直面しました。(静的、動的とも)しかし消えた枠の上にマウスを移動すると着色が再現されます。

何度も恐縮ですがこれを消えないようにする方法などありましたらご教示ください。よろしくお願いします。


DEKO  2013-01-24 01:43:18  No: 43658

> 他のアプリを表示したり
当方の XE3 では再現できませんでした。

> 本ソフトを最小化から復元したり
これも再現できませんでしたが、
フォームの OnResize イベントハンドラに

  CheckBox1.Invalidate;
  ...

と書いてやればばいいと思います。


mizuki  2013-01-24 03:08:25  No: 43659

DEKO様  何度もすみません。
色が消えてしまう現象についての記述が間違っていました。見られる現象は
1.着色済みのCheckBoxのあるForm全体をドラッグしてScreen右端に隠し、それをまた中央に戻したときに一度隠された部分の色が消えている。

2.Momo1を配置して(例えば)
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
begin
Memo1.left:=x;
Memo1.top:=y+20;
end;

のようにしてMemo1をCheckBox上に移動すると色が消える。

3.消えたCheckBoxにマウスを移動すると色が再現される。

というようなものです。よろしくお願いします。


DEKO  2013-01-24 07:28:25  No: 43660

ちょっと見た目が変わりますが、

    if not Self.ParentColor then
      begin
        canv.Brush.Color := Self.Color;
        canv.FloodFill(BtnWidth + 1, 0, canv.Pixels[BtnWidth + 2, 0], fsSurface);
      end;

これをコメントアウトして、

SetBkMode(canv.Handle, Ord(TRANSPARENT));

SetBkMode(canv.Handle, Ord(OPAQUE));

にすれば、文字列の背景色は変わります (TCheckBox の背景色ではありません)。

# 本格的にやりたければ、自前でオーナードローして下さい。


DEKO  2013-01-24 07:39:05  No: 43661

SetBkMode(canv.Handle, Ord(TRANSPARENT));

SetBkMode(canv.Handle, Ord(OPAQUE));
canv.Brush.Color := Self.Color;

です。


mizuki  2013-01-24 19:15:12  No: 43662

DEKO様  これで所期の目的を達成することができました。解決に至るまでお付き合いいただき大変感謝しております。  最終的にこんなコードでやったとご報告しようと思いましたがほとんどDEKO様のサイト
http://ht-deko.minim.ne.jp/ft1301.html#130122_01
のコピペですので割愛させていただきました。  ありがとうございました。


DEKO  2013-01-24 21:34:44  No: 43663

[続・TCheckBox の文字色と背景色を変えたい (Delphi)]
http://ht-deko.minim.ne.jp/ft1301.html#130124

また変えちゃいましたけどね (^-^;A


mizuki  2013-01-25 02:02:18  No: 43664

(この文は先ほど送ったものが掲載されなかったので再送しました)

DEKO様  再度ありがとうございます。  早速最新のものを実装して動作を確認しました。  しかし文の最後に「  TCheckbox だけでなく、TRadioButton にも同様の処理が必要になります。また、無理矢理テーマを外しているので、予測できないような問題が起こるかもしれません...ご利用は計画的に」などと警告が出ていて不安になってしまいました。  そこでまた1つ前のバージョン(FillRectしないもの)に戻しました。各種のOS、バージョンなどで汎用性を脅かすような何か不安が考えられるような問題があるのでしょうか?


DEKO  2013-01-25 02:17:05  No: 43665

> 無理矢理テーマを外しているので(中略)ご利用は計画的に
この一文は、"SetWindowTheme() でテーマを外した場合" に掛かっています。

FillRect() しようがしまいが、やっている事は同じですので、
2013/01/24 版の方がいいのではないかと思います。

# 2013/01/22 改定版は TAB キーを押して TCheckBox にフォーカス矩形を表示
# させた時、その矩形が背景色の矩形と異なる問題があり、
# "WordWrap = True" に対処できなかったり、TCheckBox.Height をいじった時に
# 垂直方向にセンタリングされないという問題もあります。


mizuki  2013-01-25 03:03:46  No: 43666

DEKO様  「テーマ」とは何かを理解していませんのでどのような不安があるのか判断できませんでした。  とにかく最新版に戻してみましたのでこれで進めてみます。  

このコードを実装した結果では文字の右端が欠ける場合がいくつか見られましたので  FOriginalCaption := Caption + '         '; のようにして文末を足してみました。  本当にありがとうございました。


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

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






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