1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2011 - Sven Strickroth <email@cs-ware.de>
4 // Copyright (C) 2008-2012 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 BEGIN_MESSAGE_MAP(CToolTips
, CToolTipCtrl
)
26 ON_NOTIFY_REFLECT_EX( TTN_NEEDTEXT
, &CToolTips::OnTtnNeedText
)
31 BOOL
CToolTips::OnTtnNeedText(NMHDR
*pNMHDR
, LRESULT
*pResult
)
33 if (pNMHDR
->code
== TTN_NEEDTEXTW
)
35 LPNMTTDISPINFO lpnmtdi
= (LPNMTTDISPINFO
)pNMHDR
;
36 UINT_PTR nID
= pNMHDR
->idFrom
;
38 if (lpnmtdi
->uFlags
& TTF_IDISHWND
)
40 // idFrom is actually the HWND of the tool
41 nID
= ::GetDlgCtrlID((HWND
)nID
);
44 auto iterFind
= toolTextMap
.find((unsigned int)nID
);
45 if (iterFind
!= toolTextMap
.end())
47 lpnmtdi
->lpszText
= (LPTSTR
)(LPCTSTR
)iterFind
->second
;
48 lpnmtdi
->hinst
= AfxGetResourceHandle();
56 BOOL
CToolTips::AddTool(CWnd
* pWnd
, UINT nIDText
, LPCRECT lpRectTool
/* = NULL */, UINT_PTR nIDTool
/* = 0 */)
58 CString sTemp
= LoadTooltip(nIDText
);
59 toolTextMap
[::GetDlgCtrlID(pWnd
->GetSafeHwnd())] = sTemp
;
60 return CToolTipCtrl::AddTool(pWnd
, LPSTR_TEXTCALLBACK
, lpRectTool
, nIDTool
);
63 BOOL
CToolTips::AddTool(CWnd
* pWnd
, LPCTSTR lpszText
/* = LPSTR_TEXTCALLBACK */, LPCRECT lpRectTool
/* = NULL */, UINT_PTR nIDTool
/* = 0 */)
65 if (lpszText
!= LPSTR_TEXTCALLBACK
)
66 toolTextMap
[::GetDlgCtrlID(pWnd
->GetSafeHwnd())] = CString(lpszText
);
67 return CToolTipCtrl::AddTool(pWnd
, lpszText
, lpRectTool
, nIDTool
);
70 void CToolTips::AddTool(int nIdWnd
, UINT nIdText
, LPCRECT lpRectTool
/* = NULL */, UINT_PTR nIDTool
/* = 0 */)
72 AddTool(((CDialog
*)m_pParentWnd
)->GetDlgItem(nIdWnd
), nIdText
, lpRectTool
, nIDTool
);
75 void CToolTips::AddTool(int nIdWnd
, CString sBalloonTipText
, LPCRECT lpRectTool
/* = NULL */, UINT_PTR nIDTool
/* = 0 */)
77 AddTool(((CDialog
*)m_pParentWnd
)->GetDlgItem(nIdWnd
), sBalloonTipText
, lpRectTool
, nIDTool
);
80 void CToolTips::DelTool( CWnd
* pWnd
, UINT_PTR nIDTool
/* = 0 */)
82 toolTextMap
.erase(::GetDlgCtrlID(pWnd
->GetSafeHwnd()));
83 return CToolTipCtrl::DelTool(pWnd
, nIDTool
);
86 void CToolTips::DelTool( int nIdWnd
, UINT_PTR nIDTool
/* = 0 */)
88 return DelTool(((CDialog
*)m_pParentWnd
)->GetDlgItem(nIdWnd
), nIDTool
);
91 BOOL
CToolTips::ShowBalloon(CWnd
*pWnd
, UINT nIDText
, UINT nIDTitle
, UINT icon
/* = 0 */)
93 CString sTemp
= LoadTooltip(nIDText
);
95 const HWND hwndTT
= CreateWindow
99 TTS_NOPREFIX
|TTS_BALLOON
|TTS_ALWAYSTIP
|TTS_CLOSE
,
100 CW_USEDEFAULT
, CW_USEDEFAULT
,
101 CW_USEDEFAULT
, CW_USEDEFAULT
,
111 ti
.cbSize
= sizeof(ti
);
112 ti
.uFlags
= TTF_TRACK
| TTF_IDISHWND
| TTF_PARSELINKS
;
113 ti
.hwnd
= pWnd
->GetSafeHwnd();
114 ti
.lpszText
= sTemp
.GetBuffer();
115 ::SendMessage(hwndTT
, TTM_ADDTOOL
, 0, (LPARAM
)&ti
);
116 ::SendMessage(hwndTT
, TTM_SETTITLE
, icon
, (LPARAM
)(LPCTSTR
)CString(MAKEINTRESOURCE(nIDTitle
)));
117 ::SendMessage(hwndTT
, TTM_SETMAXTIPWIDTH
, 0, 800);
119 // Position the tooltip below the control
121 ::GetWindowRect(pWnd
->GetSafeHwnd(), &rc
);
122 ::SendMessage(hwndTT
, TTM_TRACKPOSITION
, 0, MAKELONG(rc
.left
+ 10, rc
.bottom
));
125 ::SendMessage(hwndTT
, TTM_TRACKACTIVATE
, TRUE
, (LPARAM
)&ti
);
130 void CToolTips::ShowBalloon(int nIdWnd
, UINT nIdText
, UINT nIDTitle
, UINT icon
/* = 0 */)
132 ShowBalloon(((CDialog
*)m_pParentWnd
)->GetDlgItem(nIdWnd
), nIdText
, nIDTitle
, icon
);
135 CString
CToolTips::LoadTooltip( UINT nIDText
)
138 sTemp
.LoadString(nIDText
);
139 // tooltips can't handle \t and single \n, only spaces and \r\n
140 sTemp
.Replace('\t', ' ');
141 sTemp
.Replace(_T("\r\n"), _T("\n"));
142 sTemp
.Replace(_T("\n"), _T("\r\n"));
146 void CToolTips::RelayEvent(LPMSG lpMsg
, CWnd
* dlgWnd
)
148 if (lpMsg
->message
== WM_NULL
)
151 if(dlgWnd
&& ((lpMsg
->message
== WM_MOUSEMOVE
) || (lpMsg
->message
== WM_NCMOUSEMOVE
)) && (lpMsg
->hwnd
== dlgWnd
->m_hWnd
))
153 // allow tooltips for disabled controls
157 pt
.x
= LOWORD(lpMsg
->lParam
);
158 pt
.y
= HIWORD(lpMsg
->lParam
);
160 for (auto it
= toolTextMap
.cbegin(); it
!= toolTextMap
.cend(); ++it
)
162 CWnd
* pWndCtrl
= dlgWnd
->GetDlgItem(it
->first
);
163 pWndCtrl
->GetWindowRect(&rect
);
164 if (lpMsg
->message
== WM_MOUSEMOVE
)
165 dlgWnd
->ScreenToClient(&rect
);
167 if(rect
.PtInRect(pt
) )
169 // save the original parameters
170 HWND origHwnd
= lpMsg
->hwnd
;
171 LPARAM origLParam
= lpMsg
->lParam
;
173 // translate and relay the mouse move message to
174 // the tooltip control as if they were sent
175 // by the disabled control
176 lpMsg
->hwnd
= pWndCtrl
->m_hWnd
;
178 if (lpMsg
->message
== WM_MOUSEMOVE
)
179 dlgWnd
->ClientToScreen(&pt
);
180 pWndCtrl
->ScreenToClient(&pt
);
181 lpMsg
->lParam
= MAKELPARAM(pt
.x
, pt
.y
);
183 __super::RelayEvent(lpMsg
);
185 // restore the original parameters
186 lpMsg
->hwnd
= origHwnd
;
187 lpMsg
->lParam
= origLParam
;
193 // Let the ToolTip process this message.
194 __super::RelayEvent(lpMsg
);