ご存知の方がいたら教えてください。
プッシュボタンをオーナードローで描画しようと調べていると下記の方法を見つけました。
オーナードローのチェックボタン・ラジオボタンの作成 [Update'04.1.21]
1.CButtonの派生クラスを作成する。(Create時にBS_OWNERDRAW|BS_PUSHBUTTONを指定す
る。)
2.SetCheck(),GetCheck()をvirtualでオーバーライドする。またチェック状態をメンバ変数
に設定する。
3.BM_SETCHECKメッセージをON_MESSAGEでメッセージをマップし、メンバ変数を更新する。
4.DrawItem()をオーバーライドし、メンバ変数の状態で表示内容を切り替える。
描画はラジオボタンの例ですが、同様に作成したところ、3でエラーとなります。
ヘッダ部
virtual void SetCheck( int nCheck );
virtual int GetCheck( );
BOOL m_ChkFlg;
ソース部
BEGIN_MESSAGE_MAP(CColorBtn, CButton)
ON_CONTROL_REFLECT(BM_SETCHECK, SetCheck)
END_MESSAGE_MAP()
void COrgBtn::SetCheck( int nCheck )
{
m_ChkFlg = nCheck;
}
int COrgBtn::GetCheck( )
{
return m_ChkFlg;
}
どうぞ、よろしくお願いします。
エラーが発生するときには、エラーメッセージも必ず書きましょう。
ON_CONTROL_REFLECTで指定する関数は、引数無しでなければいけません。
早速の回答ありがとうございます。
エラーの内容は下記のとおりです。
error C2440 'static_cast':'void(_thiscall COrgBtn::*)(int)'から'AFX_PMSG'に変換
できません。
いろいろ試したのですが、まずヘッダ部の宣言からあっているかどうかというところと、
MESSAGE_MAPはCButtonの派生クラスでいいのか、というところからです。
なにぶん初心者なのでよろしくお願いします。
戻り値はLRESULT型でなければいけません。
# VC++6ではコンパイルエラーにならないので
# やっかいなバグを引き起こしていました。
失礼、引数WPARAM、LPARAMも必要です。
正しくは以下のシグニチャになります。
// .h
afx_msg LRESULT OnSetCheck(WPARAM wParam, LPARAM lParam);
// .cpp
LRESULT COrgBtn::OnSetCheck(WPARAM wParam, LPARAM lParam)
{
// TODO:
return 0;
}
また、BM_SETCHECKメッセージを受ける場合は、ON_MESSAGEマクロ
になると思います。
BEGIN_MESSAGE_MAP(COrgBtn, CButton)
ON_MESSAGE(BM_SETCHECK, OnSetCheck)
END_MESSAGE_MAP()
Kerry さんありがとうございます。
無事にコンパイルが通りました。
OnSetCheckはボタンの押下時にコールされると思ったのですが、コールされませんでした。
OnGetCheckはコールされました。イメージはまちがっているのでしょうか?
コードは下記のとおりです。
protected:
afx_msg LRESULT OnSetCheck(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnGetCheck(WPARAM wParam, LPARAM lParam);
BEGIN_MESSAGE_MAP(COrgBtn, CButton)
ON_MESSAGE (BM_GETCHECK, OnGetCheck)
ON_MESSAGE (BM_SETCHECK, OnSetCheck)
END_MESSAGE_MAP()
LRESULT COrgBtn::OnGetCheck(WPARAM wParam, LPARAM lParam) {
return 0;
}
LRESULT COrgBtn::OnSetCheck(WPARAM wParam, LPARAM lParam) {
return 0;
}
ボタン押下時は、親ウィンドウにWM_COMMANDメッセージ
(通知コードBN_CLICKED)が送られます。
ON_CONTROL_REFLECT()を使うと親ウィンドウから返送された
メッセージを処理することができます。
// .h
afx_msg void OnBnClicked();
// .cpp
BEGIN_MESSAGE_MAP(COrgBtn, CButton)
ON_CONTROL_REFLECT(BN_CLICKED, OnBnClicked)
END_MESSAGE_MAP()
void COrgBtn::OnBnClicked()
{
// TODO:
}
Kerryさん、早速の回答ありがとうございます。
今の問題点を説明させていただきます。
現状態でうまくいっていないところは、オプションボタンの凹凸です。
オプションボタンでグループ化されているボタンの中で、あるボタンを押せば既に凹んだ状態に
なり、別のボタンを押せばそれが凹んで前者のボタンが凸になるようにしたいのです。
イメージではDrawItemの中で前者のボタンを押せば、それに関わるDrawItemのitemStateは常
にODS_CHECKEDになると思っていたのですが、そうではないみたいです。
ボタン押下時には自動的にOnSetCheckがコールされ、前者は凸状態に、後者は凹状態になると
思い、今までの質問をさせて頂きました。
DrawItemの中で凹凸を判別する為にはどのようにすればよいのでしょうか?
ちなみにオーナードローにしなければ、うまく凹凸になっています。
BOOL CColorBtn::Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect,
CWnd* pParentWnd, UINT nID )
{
return CButton::Create( lpszCaption,
WS_CHILD|WS_VISIBLE|BS_PUSHLIKE|BS_AUTORADIOBUTTON | BS_OWNERDRAW,
rect,
pParentWnd,
nID);
}
以上、よろしくお願い致します。
ボタンのBS_OWNERDRAWスタイルは他のボタンスタイル(BS_CHECKBOXや
BS_RADIOBUTTONなど)と組み合わせることができません。
よって、BS_OWNERDRAWスタイルを設定した場合、チェックボックスや
ラジオボタンの動作は「独自で実装しなければいけません」
つまり、ボタンのON/OFF状態は、オーナー描画ボタンクラス自身で
管理する必要があります。
(上のコードでON/OFF状態をメンバ変数で保持していましたが、
まさにそのような感じで)
Kerryさんありがとうございます。
オリジナルで作成します。