星期三, 八月 30, 2006

CBitmapButton のツールチップ (CTalkButton クラス)

CTalkButton クラスについて CFolderDialog に続いて
作った2つ目のオリジナルの クラスだ。 できればこんな遠
回りは したくなかったが、結果的に大仕事になってしまった。
(前と同じじゃん。) 原因は VC++環境のツールバーに
ある。大きさは変えられるものの 色が16色しか使えない。
いまどきこんな色数じゃボタンの機能を表すにあたって著
しく 表現の幅を狭められてしまう。  アイコンも最初は16
色になっているので酩酊してしまうが、後で256色に変更
できる ので、 まあよしとしよう。(最初から256色だとな
およいが。 自作のアプリケーションで 16色アイコンなん
ぞ使ったことがない。)せっかくツールバー 用にと画像を用
意したのに16色に落とすと何がなんだか分からなくなって
しまった。 努力を無にしたくなかったのでビットマップボタン
を並べてツールバーに 見せたが、 ツールチップが出ない
ところや、 ステータスバーの表示もないところがいかにも
自作という感じだ。 で、自作のツールバーにツールチップ
ステータスバーの表示機能を持たせようという試みが
泥沼化しこのクラスになった。 本当は CDialogBar を
使いたかったがダイアログエディタで乗っけた CButton
に BS_ BITMAP でもってビットマップを貼り付けるのがど
うしてもうまくいかず、そのうちに CTalkButtonクラスの
方が何とか形になったので途中であきらめてしまった。
CButton の BS_BITMAP を使いこなす方法はだい
ぶ後になってら分かった。ついでにツールチップのテキス
トの入れ も。でも CReBar が使いこなせた方がプロっぽ
いかも?)class CTalkButton CBitmapButton をその
まま使ってたんではどうしてもツールチップやステータスバー
の表 示が うまくできなかった。なのでこのクラスは
CBitmapButton を継承し機能拡張を行っている。
#if !defined(AFX_TALKBUTTON_H__1DC177F6
_3055_45D1_9E99_0B07854838C4__INCLUDED_)

#define AFX_TALKBUTTON_H__1DC177F6_

3055_45D1_9E99_0B07854838C4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TalkButton.h : ヘッダー ファイル
//
///////////////////////////////////////////////////
// CTalkButton ウィンドウ
class CTalkButton : public CBitmapButton
{
// コンストラクション
public:
CTalkButton();
// アトリビュート
public:
// オペレーション
public:
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CTalkButton)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
// インプリメンテーション
public:
CToolTipCtrl ttc;
virtual ~CTalkButton();
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CTalkButton)
afx_msg void

OnMouseMove(UINT nFlags, CPoint point);

afx_msg int
OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ は前行の直前に追加の宣言
//を挿入します。
#endif // !defined(AFX_TALKBUTTON_H__
1DC177F6_3055_45D1_9E99_0B07854838C4
__INCLUDED_)

使用法 CBitmapButton に対して追加したメンバ関数
はハンドラだけなので使用方法は CBitmapButton と
同じ。
いつも View のメンバに入れて OnCreate() の
中で Create する方法でしか使っていないので 違う使い
方をしたときにどうなるかは分からない。
CRect rect_hlp(0, 0, 32, 32);
helpButton.Create("",

BS_OWNERDRAW BS_PUSHBUTTON
WS_CHILD WS_VISIBLE, rect_hlp, this,
ID_ABOUT);
helpButton.LoadBitmaps(IDB_HLP_FREE,

IDB_HLP_PUSH, IDB_HLP_FREE, IDB_HLP_PUSH);
 ↑ な感じでいつも使っている。各パラメータの意味は

CBitmapButton を参照。// TalkButton.cpp :
インプリメンテーション ファイル
//
#include "stdafx.h"
#include "TalkButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////
// CTalkButton
CTalkButton::CTalkButton()
{
}
CTalkButton::~CTalkButton()
{
}
BEGIN_MESSAGE_MAP(CTalkButton,

CButton)
//{{AFX_MSG_MAP(CTalkButton)
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////
// CTalkButton メッセージ ハンドラ
// ツールチップとステータスバーにツールヒントを出

せるビットマップボタン
int CTalkButton::OnCreate(LPCREATESTRUCT

lpCreateStruct)
{
if (CButton::OnCreate(lpCreateStruct) == -1)
return -1;
ttc.Create(this); // 以下ツールチップの作成・登録
ttc.Activate(TRUE);
CRect rect;
CWnd::GetClientRect(&rect);
ttc.AddTool(this, (UINT)GetDlgCtrlID(), &rect,

(UINT)GetDlgCtrlID());
return 0;
}
BOOL CTalkButton::PreTranslateMessage(

MSG* pMsg)
{
// ツールチップのおきまり
if (m_hWnd)
ttc.RelayEvent(pMsg);
return CButton::PreTranslateMessage(pMsg);
}
void CTalkButton::OnMouseMove(UINT nFlags,

CPoint point)
{
// 親ウインドウのステータスバーにツールヒントを表示する。
if (GetCapture() == this) {
CRect rect;
CWnd::GetClientRect(&rect);
if (!rect.PtInRect(point)) { // マウスがボタンの外

に出たときに idle を出したいから
KillTimer(999); // 自分の上にいるときだけキャ
プチャしてるんだよ。
ReleaseCapture(); // どんくさいだろ。
GetParent()->GetParentFrame()->

SetMessageText(AFX_IDS_IDLEMESSAGE);
}
} else {
GetParent()->GetParentFrame()->

SetMessageText((UINT)GetDlgCtrlID());
SetCapture();
SetTimer(999, 200, NULL); // 親ウインドウ監視タイマー
}
// 自作のツールバーにツールチップを出そうとしてえらい苦労した。
// あんまりうまくいかないんで、あきらめてステータスバーの表示に
// 変更したがそれでも大変だった。
// この CTalkButton を CBitmapButton から派生させることで
// 乗り切ったが、あとでツールチップも実装した。
// 結局、派生クラスを作るんだったらツールチップのほうが楽だった。
// 親ウインドウがバックグラウンドになったときにステータスバーを
// idle に戻したかったのでまたタイマーに頼ってしまった。
CButton::OnMouseMove(nFlags, point);
}
void CTalkButton::OnTimer(UINT nIDEvent)
{
// 親ウインドウがバックグラウンドになったときは

キャプチャーをやめる
if (GetForegroundWindow() != GetParent()->

GetParentFrame()) {
KillTimer(999); // またタイマー使っちゃったよ。
ReleaseCapture(); // もっといいメッセージないの?
GetParent()->GetParentFrame()->

SetMessageText(AFX_IDS_IDLEMESSAGE);
}
CButton::OnTimer(nIDEvent);
}




没有评论: