入力可能なコンボボックスにツールチップを設定する
MFC で、入力可能なコンボボックス (スタイルに CBS_DROPDOWN が設定されているもの) に対して、ツールチップを設定します。サンプルは、上が入力不可 (ドロップダウンリスト)、下が入力可能 (ドロップダウン) のコンボボックスです。それぞれ、m_DropdownList と m_DropdownCombo にマッピングしてあります。
以下が、OnInitDialog 内でのツールチップ作成部分
// OnInitDialog
if (m_ToolTip.Create (this))
{
m_ToolTip.AddTool (&m_DropdownList, _T ("ドロップダウンリスト"));
m_ToolTip.AddTool (&m_DropdownCombo, _T ("ドロップダウンコンボ"));
}
で、PreTransrateMessage で以下のようにしてツールチップにマウスイベントを渡します。
// PreTranslateMessage
BOOL CDropdownTooltipDialog::PreTranslateMessage (MSG* pMsg)
{
switch (pMsg->message)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
m_ToolTip.RelayEvent (pMsg);
break;
default:
break;
}
return CDialog::PreTranslateMessage (pMsg);
}
ダイアログを表示して、コンボボックスをマウスでポイントすると、ドロップダウンリストの方はツールチップを表示しますが、ドロップダウンの方は表示しません。しかしドロップダウンの上辺の端ぎりぎりくらいにポインタを持っていくと、上のように表示されます。これは、ドロップダウンの方は入力するためのエディットボックスが前面に作成されているためです。というわけで、今回のお題はこちら。
Spy++ で確認すると、ドロップダウンの子ウインドウに、Edit クラスのウインドウが見えます。こいつの HWND を EnumChildWindow で取得することにします。まず、ダイアログクラスにコールバック関数を定義します。また、コールバック関数内で Edit の HWND を受け取りたいので、HWND 型のメンバ変数も追加しておきます。
// CDropdownTooltipDialog ダイアログクラスの宣言 class CDropdownTooltipDialog : public CDialog { DECLARE_DYNAMIC(CDropdownTooltipDialog) public: CDropdownTooltipDialog (CWnd* pParent = NULL); virtual ~CDropdownTooltipDialog (void); enum { IDD = IDD_DROPDOWNTOOLTIP }; protected: CToolTipCtrl m_ToolTip; CComboBox m_DropdownCombo; CComboBox m_DropdownList; // エディットボックスのウインドウハンドル HWND m_hWndDropdownEdit; virtual void DoDataExchange (CDataExchange* pDX); // DDX/DDV サポート virtual BOOL OnInitDialog (void); virtual BOOL PreTranslateMessage (MSG* pMsg); afx_msg void OnDestroy (void); // EnumChildWindows のコールバック関数を追加 static BOOL CALLBACK EnumChildOfDropdown (HWND hWnd, LPARAM lParam); DECLARE_MESSAGE_MAP() };
// コールバック関数の実装 BOOL CALLBACK CDropdownTooltipDialog::EnumChildOfDropdown (HWND hWnd, LPARAM lParam) { // ウインドウクラス名を取得します TCHAR szClassName [MAX_PATH]; ZeroMemory (szClassName, sizeof szClassName); if (GetClassName (hWnd, szClassName, MAX_PATH)) { // Edit なら、求める HWND です(多分) if (0 == _tcsicmp (_T ("Edit"), szClassName)) { ((CDropdownTooltipDialog *)lParam)->m_hWndDropdownEdit = hWnd; return FALSE; // 列挙を中断します } } return TRUE; }
OnInitDialog で、Edit の HWND を取得します。
BOOL CDropdownTooltipDialog::OnInitDialog (void)
{
CDialog::OnInitDialog();
if (m_ToolTip.Create (this))
{
m_ToolTip.AddTool (&m_DropdownList, _T ("ドロップダウンリスト"));
m_ToolTip.AddTool (&m_DropdownCombo, _T ("ドロップダウンコンボ"));
}
// 子ウインドウを列挙
BOOL bRet = ::EnumChildWindows (m_DropdownCombo, (WNDENUMPROC) EnumChildOfDropdown, (LPARAM) this);
return TRUE;
}
で、問題は PreTranslateMessage。ここではコメントにもあるように、マウスイベントを受け取った場合に、それがドロップダウンのエディットボックスなら、HWND をドロップダウンに摩り替えて、イベントをツールチップに処理させます。
BOOL CDropdownTooltipDialog::PreTranslateMessage (MSG* pMsg)
{
switch (pMsg->message)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
if (pMsg->hwnd == m_hWndDropdownEdit)
{// ドロップダウンの Edit なら、ドロップダウンの HWND として RelayEvent します。
MSG Msg;
CopyMemory (&Msg, pMsg, sizeof (MSG));
Msg.hwnd = (HWND) m_DropdownCombo;
m_ToolTip.RelayEvent (&Msg);
break;
}
m_ToolTip.RelayEvent (pMsg);
break;
default:
break;
}
return CDialog::PreTranslateMessage (pMsg);
}
トラックバック
- このエントリーにトラックバック:
- http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/1068
コメント