ビットマップ付きボタンにツールヒントを表示する

Visual C++プログラミングのメモ

【Visual C++ 2008】【MFC】

 「ダイアログにビットマップ付きボタンを実装する(4bitカラー編)」「ダイアログにビットマップ付きボタンを実装する(24bitカラー編)」のボタンに、ツールヒントを表示する方法。

(1)
 リソースビューにて、Toolbarの該当する(ツールヒントを表示したい)ボタンを選択して、[プロパティ]-[その他]-[Prompt]に表示する文字列を入力する。 その際、頭に必ず「\n」を付加すること。


(例)
\nファイルを開く

 もしくは、rcファイルを直接書き換えるなら、以下を追加する。


(例)
IDBUTTON1,IDBUTTON2,IDBUTTON3にそれぞれ「ファイルを開く」「すべてを保存」「終了」のツールヒントを表示する場合。

STRINGTABLE
BEGIN
    IDBUTTON1               "\nファイルを開く"
    IDBUTTON2               "\nすべてを保存"
    IDBUTTON3               "\n終了"
END

 IDはボタンのIDと一致させる。

(2)
 OnInitDialogの「// TODO: 初期化をここに追加します。」より後にて、一連のツールバー読み込み処理の最後に以下を記述。 (ツールバークラス(CToolBar)のメンバ変数がm_wndToolBarの場合)


    m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS);

(3)
 ダイアログのクラスヘッダのprotectedに、メンバ関数定義を追加。


    afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);

(4)
 メッセージマップに、以下を追加。 これで、TTN_NEEDTEXTWメッセージがダイアログに飛ぶと、OnToolTipText関数を呼び出す。


    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)

(5)
 メンバ関数を記述。 これは、Visual C++付属サンプルに入っている「DLGCBR32」のMdlsmain.cppより引用したものである。 オリジナルの関数は、メッセージがTTN_NEEDTEXTA,TTN_NEEDTEXTW、 [構成プロパティ]-[全般]-[プロジェクトの既定値]-[文字セット]が「Unicode文字セットを使用する」「マルチバイト文字セットを使用する」 の順列組み合わせ4パターンに対応している。 以下に示した関数は、TTN_NEEDTEXTWと「Unicode文字セットを使用する」の組み合わせのみを取り出した。
(コメントもそのままなので、差分を取って確認してください)


BOOL CXxxxDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
    // allow top level routing frame to handle the message
    if (GetRoutingFrame() != NULL)
        return FALSE;

    // need to handle both ANSI and UNICODE versions of the message
    TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
    wchar_t szFullText[256];
    CString strTipText;
    UINT_PTR nID = (UINT_PTR)pNMHDR->idFrom;
    if (pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
    {
        // idFrom is actually the HWND of the tool
        nID = ((UINT_PTR)(WORD)::GetDlgCtrlID((HWND)nID));
    }

    if (nID != 0) // will be zero on a separator
    {
        AfxLoadString((UINT)nID, szFullText);
            // this is the command id, not the button index
        AfxExtractSubString(strTipText, szFullText, 1, '\n');
    }

    wcsncpy_s(pTTTW->szText, (sizeof(pTTTW->szText)/sizeof(pTTTW->szText[0])),
        strTipText, _TRUNCATE);

    *pResult = 0;

    // bring the tooltip window above other popup windows
    ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
        SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);

    return TRUE;    // message was handled
}

 7/Vista/XP/2000で動作確認したところ、メッセージマップでTTN_NEEDTEXTAのみ記述した場合は、TTN_NEEDTEXTAが飛んでくる。 TTN_NEEDTEXTWのみ(あるいは両方)記述した場合は、TTN_NEEDTEXTWが飛んでくる。 これは、Unicode文字セット/マルチバイト文字セットのどちらでコンパイルしても同様である。 どの組み合わせでも正常動作するが、TTN_NEEDTEXTA,TTN_NEEDTEXTWのメッセージの違いが何に依存しているのかは不明である。

(メモ)

  • サンプルの場所は、C:\Program Files\Microsoft Visual Studio 9.0\Samples\1041\AllVCLanguageSamples.zip
  • MSDNライブラリの「CControlBar::SetBarStyle」「CControlBar::GetBarStyle」を参照のこと