ボタン背景の描画方法は?

解決


ぴょぴょ  2007-12-13 20:34:02  No: 67179

ボタンをオーナードローしています。
円形のボタンを描画するためにマスク画像との演算で合成させようとしました。

HDC hMemDC;

if ( (hMemDC = CreateCompatibleDC(hDC)) != NULL ){
  HBITMAP hSelBmp = (HBITMAP)SendMessage( hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0 );
  int pos;
  
  if ( itemState & ODS_DISABLED ){    // 無効状態
    pos = 3;
  }
  else if ( itemState & ODS_SELECTED ){  // 押された状態
    pos = 2;
  }
  else if ( itemState & ODS_FOCUS ){    // フォーカス状態
    pos = 0;
  }
  else{                  // 通常の状態
    pos = 1;
  }
  // マスクの描画
  SelectObject( hMemDC, hMaskBitmap );
  BitBlt( hMemBitmapDC, 0, 0, PUSH_XSIZE, PUSH_YSIZE, hMemDC, 0, 0, SRCAND );
  // ボタンの描画
  SelectObject( hMemDC, hSelBmp );
  BitBlt( hDC, 0, 0, PUSH_XSIZE, PUSH_YSIZE, hMemDC, (PUSH_XSIZE * pos), 0, SRCPAINT );
  // 後始末
  DeleteDC( hMemDC );
}

こんな感じですが円形の外周が上手く表示されません。
いろいろと試して気づきました。
最初にボタンの背景部分を描画していないようです。

そこで質問です。
ボタンの背景を描画するにはどうすれば良いでしょうか?
最初は NULL_BURSH を使いましたが出来ませんでした。

ダイアログで作っています。
このとき WM_CTLCOLORDLG メッセージを処理してウインドウ全体を
外部のビットマップ(ファイル)より描画しています。
このビットマップのボタン領域をボタンのオーナードローのときに
描画させたいのです。そうしないとマスクの描画を SRCAND しても
無意味で円形の外周が上手く表示されませんので。

どうすればボタン領域の背景(WM_CTLCOLORDLG で描画している画像)を
ボタンのオーナードロー時に描画すれば良いでしょうか?
お願い致します。


gak  2007-12-15 01:24:21  No: 67180

円形ボタンに対しての WM_CTLCOLORBTN(最後が'BTN'ね)メッセージが親にきた時に
GetStockObject(HOLLOW_BRUSH) を返せば良いと思うよ。

これで見た目上円形ボタンの表示はできる。

ただ、ボタンの実体は四角形のままなので円形外(で元の四角形内)を
クリックされた場合 BN_CLICK が発生する。
これが気になるようなら SetWindowRgn() を使用してボタンの形状そのもの
(というと御幣があるが)を変える手段を取った方が良いかと。


ぴょぴょ  2007-12-15 02:38:33  No: 67181

> 円形ボタンに対しての WM_CTLCOLORBTN(最後が'BTN'ね)メッセージが親にきた時に
> GetStockObject(HOLLOW_BRUSH) を返せば良いと思うよ。
これはダイアログの WM_CTLCOLORBTN メッセージですよね。
記述したらボタンの背景が勝手に描画されました。
ちょっと不思議です。

> ただ、ボタンの実体は四角形のままなので円形外(で元の四角形内)を
> クリックされた場合 BN_CLICK が発生する。
これを忘れていました。
前の質問でリージョンの方が良いとアドバイスされていましたが
リージョンを使う意味を良く分かっていなかったようです。

見た目上は円形ボタンが描画できましたが、クリックにも対応するには
リージョンを使わないと無理っぽいね。ビットマップのリージョンは
大変そうな気がします。いずれリージョンにも対応する予定です。

あといろいろと試してみたらボタンをサブクラス化して WM_ERASEBKGND の
メッセージに対して何も処理しないで return 0; を返せば WM_CTLCOLORBTN の
メッセージで GetStockObject(HOLLOW_BRUSH) を返したのと同じ効果がでました。

今回はボタンをサブクラス化して使っていたので WM_ERASEBKGND の方に
ボタン背景を描画できる仕組みをとりました。
これで解決しました。

本当にありがとうございました。
(オーナードローしているのに背景は別の場所で処理されていたとは…)


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

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






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