ツールヒントの表示方法

[戻る]
める 2005/08/16(火) 14:49:43
ダイアログベースのアプリを作成してますが、
ツールチップ(ヒント?)の出し方で悩んでます。

親ダイアログ(A)の中にタブコントロールとボタン2つがあり、
タブコントロールには、子ダイアログ(B)を貼り付けてます。

AのOninitDialog()にてこんなソースを書いてみました。
-----------------------------------------------
m_ToolTip.Create(this, TTS_ALWAYSTIP);
m_ToolTip.SetMaxTipWidth(350);
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 5000); // 表示中の時間(10Sec)
m_ToolTip.SetDelayTime(TTDT_INITIAL, 200);  // 表示迄の時間(200ms)
m_ToolTip.AddTool(m_pTabCtrl, "画面切替");
m_ToolTip.AddTool(GetDlgItem(IDC_BTN_FILEOUT), "出力");
m_ToolTip.AddTool(GetDlgItem(IDC_BTN_QUIT), "終了");
m_pTabCtrl->SetToolTips(&m_ToolTip);
-----------------------------------------------
実行するとタブ部分は「画面切替」と表示されますが
ボタンは何も表示されません。
Bのダイアログの各コントロールにも同様の方法で
ツールチップを設定したのですが表示されません。
何故でしょうか?

また上記を調べている最中に「OnNotifyを使う方法」を見つけましたが、
AのダイアログのOnNotifyで、B上のコントロールのツールチップも
一緒に制御出来るのでしょうか?

宜しくお願い致します。

環境はVC6/MFC/Win2Kです。

める 2005/08/16(火) 15:09:52
半分自己レスです。

>Bのダイアログの各コントロールにも同様の方法で
>ツールチップを設定したのですが表示されません。
>何故でしょうか?
PreTranslateMessage()で「m_ToolTip.RelayEvent(pMsg);」を
宣言していませんでした。

半分解決なのですが、この方法だとA・Bそれぞれに、ToolTipの
オブジェクトを作って管理しないとならないので、作り的に宜しくない
と思います。

今後CとかDとかダイアログが増える場合もあるので、OnNotifyと
StringTableで一元管理する方法を取りたいと思っているので、
ご指南頂けるとありがたいです。

宜しくお願い致します。

dairygoods 2005/08/16(火) 16:05:57
> 今後CとかDとかダイアログが増える場合もあるので、OnNotifyと
> StringTableで一元管理する方法を取りたいと思っているので、
> ご指南頂けるとありがたいです。

MSDN には、かなり詳しいやり方が載っていますが、
どこが分からないのでしょうか。

める 2005/08/16(火) 16:27:08
すみません。Windowsのメッセージの仕組みが
イマイチよく分かっていないので・・・。

B(子ウィンドウ)上で、コントロールにカーソルを当てると、
BのOnNotifyが呼ばれますよね?
その情報をAのOnNotifyに与えてやればいいのかな?と
思っているのですが・・・。

ここの過去ログ
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200211/02110109.txt
で、
---------------------------
NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == TTN_NEEDTEXT)
    GetParentFrame()->SendMessage(WM_NOTIFY, wParam, lParam);
    return CFormView::OnNotify(wParam, lParam, pResult);
---------------------------
こういった回答あったので試してみたのですがAのOnNotifyで異常終了します。
これが正しい手法なのかわからないので原因は特定してませんが、
CFormViewではなくてCDialogなのでまた扱いが違うのかな?と・・・。
MSDN読みながら試行錯誤はしているのですが。申し訳ありません。

dairygoods 2005/08/16(火) 16:41:25
?
見つけた「OnNotifyを使う方法」とは、これのではないのでしょうか?

「CFrameWnd から派生していないウィンドウのツール ヒント」
http://www.microsoft.com/japan/msdn/library/ja/vccore/html/_core_tool_tips.asp

別にメッセージの仕組みがイマイチ分かってなくても、
書いてある通りに実践するだけだと思います。

める 2005/08/16(火) 17:12:57
度々すみません。
↑のリンクの通りにしてやってますが詰まりました。
以下MSDNの名称のまま書きます。

1.BのOninitDialog()で、EnableToolTips(TRUE)を記述。
2.Aのメッセージマップに「ON_NOTIFY_EX( TTN_NEEDTEXT, 0, memberFxn )」を宣言。
3.Aに「memberFxn( UINT id, NMHDR * pTTTStruct, LRESULT * pResult )」を追加。

ここで詰まるのが、実行時にBのコントロール上にマウスを置いた場合に
BのOnNotifyが呼ばれますが、ここからSendMessageでTTN_NEEDTEXTを通知してやれば
AのmemberFxnが呼ばれるのでしょうか?

B→Aへの通知方法が知りたいです。

dairygoods 2005/08/16(火) 19:39:49
>BのOnNotifyが呼ばれますが、ここからSendMessageでTTN_NEEDTEXTを通知してやれば
>AのmemberFxnが呼ばれるのでしょうか?

呼ばれますけど、
ON_NOTIFY_EX も memberFxn も B に追加するのではだめなのですか?

める 2005/08/16(火) 20:18:00
>ON_NOTIFY_EX も memberFxn も B に追加するのではだめなのですか?

ですから「一元で管理」したいのです。
全てのダイアログ(今はBしかありませんが・・・)の
ツールチップを親ウィンドウであるAで管理したいのです。

BのOnNotifyからSendMessageで引数をどのように送ってやれば
良いのかわかりません。以下BのOnNotifyです。
--------------------------------------------------
BOOL CxxxxDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
    NMHDR* pNMHDR = (NMHDR*)lParam;

    if (pNMHDR->code == TTN_NEEDTEXT)
        g_pMainDlg->memberFxn(0, pNMHDR, pResult);

    return CDialog::OnNotify(wParam, lParam, pResult);
}
--------------------------------------------------
memberFxnを直接呼び出してしまっているのですが・・・。
これだとAに記述した「ON_NOTIFY_EX( TTN_NEEDTEXT, 0, memberFxn)」が
全く意味ありませんよね・・・。これは正しいやり方なのでしょうか・・・?

本来なら、SendMessage(TTN_NEEDTEXT, ????, ????)と呼ぶのが
正しい(?)と思う(思い込んでる)のですが。

ひとまず「動き」はしますが、正しくなかったりお行儀が悪いソースは
書きたくないので、セオリーとしてはどうすれば良いのかを知りたいです。
しつこくて申し訳ありません。

dairygoods 2005/08/16(火) 22:26:24
g_pMainDlg->SendMessage(WM_NOTIFY, wParam, lParam);
ではないかと思います。

める 2005/08/17(水) 09:07:29
[[解決]]
おはようございます。

>g_pMainDlg->SendMessage(WM_NOTIFY, wParam, lParam);
でやってみましたが・・・動きました。何故なんでしょう?
ここが、私のイマイチわからない部分なんですが、

AにWM_NOTIFYを送ると、AのOnNotifyに行くのではないのですか?
メッセージマップに記述した「ON_NOTIFY_EX(・・・・,memberFxn)」が
memberFxnに飛ばしているのだとは思っていますが、

引数も謎です。memberFxn()の宣言はこうなってます。
「memberFxn(UINT id, NMHDR * pNMHDR, LRESULT * pResult)」

一応本題から外れてしまうので、解決としますが、
このあたりを、もう少ししっかり勉強したいと思ってます。
MSDNも読んでいるのですがまだ読みこなすには難しいです。

メッセージ関係で参考になるサイトってご存知ですか?
宜しくお願いします。

dairygoods 2005/08/17(水) 10:10:16
> AにWM_NOTIFYを送ると、AのOnNotifyに行くのではないのですか?

その通りです。

で、OnNotify() の標準の処理が、
「メッセージマップ内の ON_NOTIFY* を順番に見ていって、
 通知コード(この場合 TTN_NEEDTEXT)に対応するハンドラ探し出し、
 呼び出す」
というものなので、定義したハンドラ(memberFxn)が呼び出されます。

この時、WPARAMとLPARAMを、そのメッセージに適した型に
変換してくれます。

める 2005/08/17(水) 10:31:51
>「メッセージマップ内の ON_NOTIFY* を順番に見ていって、
なるほど。少しわかりました。

長々とお付き合い頂いて感謝しています。
ありがとうございました。m(__)mもっと精進します。

古いスレッドには追加発言できません。