はじめまして、ぱらーと申します。
ツールチップに関して質問させてください。
実は、下記の処理でダイアログボックス上の
ボタンやコンボボックス等通常のコントロールの
ツール ヒントが表示されますが、ComboBoxExの
場合は表示できません。
表示するにはどうしたらよいのでしょうか?
方法1:
BEGIN_MESSAGE_MAP(CTstComboBoxExDlg, CDialog)
//{{AFX_MSG_MAP(CTstComboBoxExDlg)
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CTstComboBoxExDlg::memberFxn( UINT id, NMHDR * pNMHDR, LRESULT * pResult)
{
TCHAR szFullText[256];
CString strTipText;
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
strTipText.LoadString( nID);
// this is the command id, not the button index
strcpy( szFullText, (LPCTSTR)strTipText);
AfxExtractSubString( strTipText, szFullText, 1, '\n');
pTTT->lpszText = MAKEINTRESOURCE(nID);
return(TRUE);
}
}
*pResult = 0;
return(FALSE);
}
ちなみに、各コントロールのツール ヒントテキストがリソースの
String Tableには入っています。
開発環境はWin2000、WinXP VC6.0SP5 MFCです。
どなたかご指導ください。よろしくお願い致します。
訂正させてください。
BEGIN_MESSAGE_MAP(CTstComboBoxExDlg, CDialog)
//{{AFX_MSG_MAP(CTstComboBoxExDlg)
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CMyFormView::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult)
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
pTTT->lpszText = MAKEINTRESOURCE(nID);
pTTT->hinst = AfxGetResourceHandle();
return(TRUE);
}
}
return(FALSE);
}
すみませんでした。
未確認ですが、CToolTipCtrlを使ってもだめですか?
1.[通りすがりの者]さんへ:
ご応援ありがとう。
先ごろ、あの荒らしコメントを見たら、ちょっと頭に
来ちゃって、その勢いで、マルチポストをしてしまいました。
失礼いたしました。
2.[?]さんへ
そうです。
CToolTipCtrlを使ってもうまくできません。
この間、色々と調べてみました。ひょっとしたら、
CToolTipCtrlのサブクラス化で解決できるかもしれない
ですが...
ご教授ください。
宜しくお願いいたします。
以下のような処理で出ましたが・・・
BOOL CHogeDlg::OnInitDialog()
{
m_ToolTip[0].Create( this, TTS_ALWAYSTIP );
m_ToolTip[0].AddTool( &m_Hoge1, Hoge1 );
m_ToolTip[0].Activate( TRUE );
m_ToolTip[1].Create( this, TTS_ALWAYSTIP );
m_ToolTip[1].AddTool( &m_Hoge2, Hoge2 );
m_ToolTip[1].Activate( TRUE );
(以下略)
}
BOOL CHogeDlg::PreTranslateMessage(MSG* pMsg)
{
for( int i=0; i<n; i++ )
{
m_ToolTip[i].RelayEvent( pMsg );
}
return CDialog::PreTranslateMessage( pMsg );
}
.hでCComboBoxをCComboBoxExに変えただけなのでテストとして不十分かもですが。
データはリソースで定義した文字列だけです。(InsertItemとかは使ってません。)
#配列にする必要はないはずだけど、(他人の)既存のソースを流用したので・・・。
ご返答ありがとう。
やってみます。
よろしくお願い致します。
大変お待たせ致しまして申し訳ございません。
[?]さんが教えていただいた方法でやってみたが,
どうやらうまくいかないです。
詳細は以下の通りです。
1.ダイアログボックス上にComboBoxとComboBoxEx
一個ずつ配置します。
コントロールIDはIDC_COMBO1 と IDC_COMBOBOXEX1 にします。
2.ClassWizardにて
①IDC_COMBO1 に対し、メンバー変数m_combo1(コントロール)を
追加します。
②IDC_COMBOBOXEX1 に対し、メンバー変数m_comboex1(コントロール)を
追加します。
3.ソースコード
CToolTipCtrl m_ToolTip[ 2];
BOOL CTstToolTipDlg::OnInitDialog()
{
...
...
EnableToolTips( TRUE); // enable tool tips for view
m_ToolTip[ 0].Create( this, TTS_ALWAYSTIP );
m_ToolTip[ 0].AddTool( &m_combo1, combo1 );
m_ToolTip[ 0].Activate( TRUE );
m_ToolTip[ 1].Create( this, TTS_ALWAYSTIP );
m_ToolTip[ 1].AddTool( &m_comboex1, comboex1 );
m_ToolTip[ 1].Activate( TRUE );
return TRUE; // TRUE を返すとコントロールに設定したフォーカスは失われませ
ん。
}
BOOL CTstToolTipDlg::PreTranslateMessage( MSG* pMsg)
{
for( int i = 0; i < 2; i++ )
{
m_ToolTip[ i].RelayEvent( pMsg );
}
return CDialog::PreTranslateMessage( pMsg );
}
4.TstToolTipDlg.hでCComboBoxをCComboBoxExに変えました。
(実際には、変えなくても結果は同様でした)
上記の手順でやってみましたが、結局はカーソルがComboBoxに
当たるとツールヒントが出るが、ComboBoxExの場合だと、依然として
出ないが、もしかしたら、私の手順なんかは間違ったかもしれないが。
忙しいところ、申し訳ございませんが、
間違ったところや不備なところが有ったら、ご指摘いただければと思います。
宜しくお願いいたします。
Spy++で調べてみると、拡張コンボの場合、本来のコンボボックスの上に
1つ余分なウィンドウが被さっているのが分かります。
これが何か悪さしているような気がします。
そこで、CWnd::OnToolHitTest() にて以下のように細工してみたところ、
ドロップダウンリストではうまく表示されるようになりました。
ドロップダウンの場合は、矢印の上でだけ表示されます…。
(最初のCToolTipCtrlを使わないバージョンの場合)
本質的な解決になってないですけど、ご参考まで。
int C*View::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
int r = CView::OnToolHitTest(point, pTI);
HWND hwnd = (HWND)pTI->uId;
char name[13];
::GetClassName(hwnd, name, sizeof(name));
if (strcmp(name, ComboBoxEx32) == 0) {
//拡張コンボの場合、その子ウィンドウに置き換える
pTI->uId = (UINT)::GetWindow(hwnd, GW_CHILD);
}
return r;
}
#ところで、CToolTipCtrlはコントロールごとに用意しなくても
#1つのツールチップにいくつもAddToolできますよ。
ごめんなさい。申し訳ない。お恥ずかしい。
2002/07/08(月) 21:06:57 のレス
リソースのほうを直し忘れてました。(通常のコンボのままでした。)
なのでツールチップがでたというのは私の勘違いです。
本当にごめんなさい。
dairygoodsさんへ
ご返答ありがとうございます。
返信遅くなってすみません。
教えて頂いた方法でやってみたんですが、
どうも上手くいかないんです。
調べたところ、OnToolHitTest()関数が
一度も呼び出されることはなかったんです。
すみませんが、もう少しOnToolHitTest()の
使い方を教えていただけませんか?
私は素人なので、MSDNを調べてもOnToolHitTestの
内容がよく理解できません。
それでは宜しくお願い致します。
[?]さんへ
そんなことありません。
でもほんとに勉強になりましたよ。
どうもありがとうございました。
また、いい方法があれば、
教えていただければと思います。
宜しくお願いいたします。
> 調べたところ、OnToolHitTest()関数が
> 一度も呼び出されることはなかったんです。
関数定義はあってますか?戻り値intやconstが付いてるなど。
この関数を定義したウィンドウでEnableToolTips()を呼び出してますか?
dairygoodsさんへ
ご返答ありがとうございます。
ご指摘した通り、EnableToolTips()を忘れて
しまいました。
もう少しやってみてから状況を報告致しますので
宜しくお願いいたします。
dairygoodsさんへ
EnableToolTips( true)を入れて、再度確認して
みましたが、改善は見られないです。
ご判断が容易のため、検証用の主なソースを以下に
リストアップいたします。
1.プロジェクト名
CheckToolTip
2.基本クラス
CFormView
3.フォームビュー上に配置するコントロール
ComboBox 一個
ComboBoxEx 一個
4.CheckToolTipView.hにおいて
class CCheckToolTipView : public CFormView
{
...
...
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CCheckToolTipView)
protected:
...
...
virtual int OnToolHitTest(CPoint point, TOOLINFO* pTI) const;
//}}AFX_VIRTUAL
...
...
}
5.CheckToolTipView.cppにおいて
void CCheckToolTipView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
EnableToolTips( true);
}
int CCheckToolTipView::OnToolHitTest( CPoint point, TOOLINFO* pTI) const
{
int r = CView::OnToolHitTest( point, pTI);
HWND hwnd = (HWND)pTI->uId;
char name[ 13];
::GetClassName( hwnd, name, sizeof( name));
if ( strcmp( name, ComboBoxEx32) == 0) {
// 拡張コンボの場合、その子ウィンドウに置き換える
pTI->uId = (UINT)::GetWindow( hwnd, GW_CHILD);
}
return r;
}
疑問:
OnToolHitTest()関数は自分で呼び出すのですか、
それともON_NOTIFYやON_NOTIFY_EXなどによって
呼び出すのですか?そのへんはよく分かりませんが。
宜しくお願いいたします。
問題ないように見えますが…。
OnToolHitTest()が呼び出されないと言うことでしょうか?
> OnToolHitTest()関数は自分で呼び出すのですか、
> それともON_NOTIFYやON_NOTIFY_EXなどによって
> 呼び出すのですか?そのへんはよく分かりませんが。
フォーム上でマウスカーソルを動かすと、
その位置に何があるかを調べるためにMFCが呼び出します。
CWnd::PreTranslateMessage()内でその処理をやっていますので、
これをオーバーライドしてしまうと呼び出されません。