【環境:Win98, VC++6.0, MFC, View/Doc】
CColorDialogで指定した色をView上で確認できるように、
ツールバーに指定した色を表示しておきたいと考えています。
そこで、ツールバーにスタティックコントロールを配置し、
スタティックコントロールの背景を指定した色で塗り潰すことにしました。
ツールバーにコントロールを追加することはできたのですが、
そのコントロールをどのように操作したらよいのか分からず、困っております。
どなたか分かる方がいらっしゃいましたら、ご教授願います。
(1)シンボルブラウザから「IDC_PNT_COLOR」を追加
(2)MainFrm.hに「CStatic m_edit;」を追加
(3)MainFrm.cppに以下のソースを追加
if (!m_m_wndToolBar.CreateEx(・・){
・・略・・
}
m_wndToolBar.SetButtonInfo(4,IDC_PNT_COLOR, TBBS_SEPARATOR, 30);
CRect rect;
m_wndToolBarPnt.GetItemRect(4, &rect);
rect.DeflateRect(2,2);
m_edit.Create(NULL, WS_CHILD |WS_VISIBLE |SS_WHITEFRAME,
rect, &m_wndToolBar, IDC_PNT_COLOR);
これでツールバーに白い四角が表示されます。
CStatic でなく、CStatic 派生クラスを作って自分で描画するとか。
あるいは、ツールバー上のコントロールからの通知メッセージは CmainFrame に届いた
と思うので、CMainFrame で WM_CTLCOLORSTATIC メッセージを処理してみるとか。
渋木宏明(ひどり) 様の
>CMainFrame で WM_CTLCOLORSTATIC メッセージを処理
を試してみようと思ったのですが、WM_CTLCOLORSTATIC メッセージは
どこで捕まえたらよいのでしょうか?
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200207/02070026.txt
に
>MFCならばOnCtlColor()、SDKならばWM_CTLCOLORSTATICを使用します
とあったので、OnCtlColor()をClassWizardで探したのですが、ありません。
尋ねてばかりで申し訳ありませんが、ご教授頂けると幸いです。
> とあったので、OnCtlColor()をClassWizardで探したのですが、ありません。
メッセージ欄のWM_CTLCOLORで関数を追加すればOKです。
> メッセージ欄のWM_CTLCOLORで関数を追加すればOKです。
クラス名「CMainFrame」でもそれ以外のクラスでも「WM_CTLCOLOR」はありませんでした。
Dialogベースでは、メッセージ欄にあるのを確認しましたが、
View/Docではメッセージ欄にないようです。
現在の開発は、View/Docで行っています。
上記関数がない以上、渋木宏明(ひどり) 様の
> CStatic でなく、CStatic 派生クラスを作って自分で描画するとか。
で行うしかないのでしょうかね。
こちらも試してみます。
>クラス名「CMainFrame」でもそれ以外のクラスでも「WM_CTLCOLOR」はありませんでし
た。
クラスウィザードの、メッセージフィルタを適当に調節すれば出てくるでしょ?
渋木宏明(ひどり) 様の言われた通り、
メッセージフィルタを「最上位フィルタ」→「ダイアログ」または、
「ウィンドウ」にすることで「WM_CTLCOLOR」が表示され、
CMainFrameにOnCtlColorを追加することができました。
そこで、試しに黒く塗り潰そうと以下のソースを記述しました。
(ツールバーへの追加方法は最初に述べた通りです。)
HBRUSH CMainFrame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFrameWnd::OnCtlColor(pDC, pWnd, nCtlColor);
CBrush brDlg;
COLORREF colEditText;
brDlg.CreateSolidBrush( RGB(0,0,0) );
colEditText = RGB(0,255,255);
switch( nCtlColor ){
case CTLCOLOR_STATIC:
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(colEditText);
return (HBRUSH) brDlg;
}
return hbr;
}
しかし、実行するとOnCtlColor()を通りません。
ヘルプでは、
「子コントロールが描画される直前に、フレームワークから
このメンバ関数が呼び出されます。」
とあるので、ツールバーにスタティックコントロールを追加した時点で
OnCtlColor()が呼び出されると考えていたのですが、違うのでしょうか?
> m_edit.Create(NULL, WS_CHILD |WS_VISIBLE |SS_WHITEFRAME,
> rect, &m_wndToolBar, IDC_PNT_COLOR);
m_wndToolBarが親になっているので、
通知はm_wndToolBarに届いているのでは。
> 通知はm_wndToolBarに届いているのでは
ツールバーへ届く通知はどこで取得できるのでしょうか?
聞いてばかりで本当に申し訳ないです。
> ツールバーへ届く通知はどこで取得できるのでしょうか?
ツールバーをサブクラス化します。
実際のところどこに届いているかは、Spy++で確認してみてください。
>しかし、実行するとOnCtlColor()を通りません。
ツールバーが受け止めちゃってて、CMainFrame までは転送してくれてないみたいです
ね ;-p
WM_COMMAND 系は転送してくれるので、他のも転送してくれると思ってたんですが。。。
こうなると
・ツールバー派生クラスを作成して、そこで WM_CTRLCOLOR を処理する
・CStatic 派生クラスを作成して自分で描画する
しかなさそうです。
ツールバー派生クラスを作るか、サブクラスで行うかは好みかな。
返信が遅くなりまして、すみません。
> ツールバーをサブクラス化します。
ツールバーをサブクラス化したことがないので、
> ・CStatic 派生クラスを作成して自分で描画する
を行うことにしました。
そして、何とかツールバーに色を表示することができました。
以下、結果です。
(1) CStatic派生クラスを作成し、以下のソースを記述。
BOOL CStaticEx::SetBackColor(COLORREF color)
{
//HBRUSH bgBrush をヘッダで宣言し、CStaticExで初期化しておく
::DeleteObject( m_bgBrush );
m_bgBrush = ::CreateSolidBrush( color );
return RedrawWindow();
}
HBRUSH CStaticEx::CtlColor(CDC* pDC, UINT nCtlColor)
{
return m_bgBrush;
}
(2) ツールバーにCStatic派生を追加
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
・・略・・
m_wndToolBar.SetButtonInfo(4,IDC_PNT_COLOR, TBBS_SEPARATOR, 30);
CRect rect;
m_wndToolBar.GetItemRect(4, &rect);
rect.DeflateRect(2,2);
m_ColorView.Create(NULL, WS_CHILD |WS_VISIBLE , rect,
lBar, IDC_PNT_COLOR);
・・略・・
}
(3) CStatic背景色の初期化
void CTestView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CStaticEx* staticEx;
staticEx = ((CMainFrame*)AfxGetMainWnd())->GetStaticEx();
if ( ! staticEx->SetBackColor( RGB(255,0,0) ) ){
//エラー処理
}
}
ClassWizard メッセージにWM_CTLCOLOR と =WM_CTLCOLOR の二つがありました。
=WM_CTLCOLORに気付かず、WM_CTLCOLOR で追加されたOnCtlColor()関数で
色々試していたのですが、この関数は通過しませんでした。
ふと、=WM_CTLCOLORに気付き、この関数(CtlColor())でやってみると、
うまくいきました。
何故メッセージにWM_CTLCOLORが二つあるのかは分かりませんが、
どこかで「=WM_CTLCOLOR」のように「=」があると通過する(使える)メッセージである
ということを見た気がします。
また、この二つにどういう違いがあるのかも今のところ理解できていません。
助言を頂いた方々、ありがとうございました。
> ClassWizard メッセージにWM_CTLCOLOR と =WM_CTLCOLOR の二つがありました。
WM_CTRLCOLOR は、子ウィンドウが親に向かって「色を決めてくれ」と
投げるメッセージです。
#CStaticにさらに子ウィンドウを作れば、
#OnCtlColorが呼び出されます。
=WM_CTLCOLOR は、WM_CTRLCOLOR を受け取った親ウィンドウが、
「そんなの自分で決めろ」とWM_CTRLCOLOR を投げたウィンドウに
投げ返すメッセージです。
(これはMFCだけの機能です。)
詳しいことは、MSDNの
「テクニカル ノート 62: Windows コントロールのメッセージ返送」
を参照してください。
MSDNをみてみます。
詳細をありがとうございます。