Ignore WM_NULL in Tooltip.cpp, avoid assert in debug mode
[TortoiseGit.git] / src / Utils / MiscUI / Tooltip.cpp
blobe88ed624498866607bc15e8875c83182b6ad69be
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.
21 #include "stdafx.h"
22 #include "Tooltip.h"
25 BEGIN_MESSAGE_MAP(CToolTips, CToolTipCtrl)
26 ON_NOTIFY_REFLECT_EX( TTN_NEEDTEXT, &CToolTips::OnTtnNeedText )
27 END_MESSAGE_MAP()
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);
43 if (toolTextMap.find((unsigned int)nID) != toolTextMap.end())
45 lpnmtdi->lpszText = (LPTSTR)(LPCTSTR)(CString)toolTextMap[(unsigned int)nID];
46 lpnmtdi->hinst = AfxGetResourceHandle();
47 *pResult = 0;
48 return TRUE;
51 return FALSE;
54 BOOL CToolTips::AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool /* = NULL */, UINT_PTR nIDTool /* = 0 */)
56 CString sTemp = LoadTooltip(nIDText);
57 toolTextMap[::GetDlgCtrlID(pWnd->GetSafeHwnd())] = sTemp;
58 return CToolTipCtrl::AddTool(pWnd, LPSTR_TEXTCALLBACK, lpRectTool, nIDTool);
61 BOOL CToolTips::AddTool(CWnd* pWnd, LPCTSTR lpszText /* = LPSTR_TEXTCALLBACK */, LPCRECT lpRectTool /* = NULL */, UINT_PTR nIDTool /* = 0 */)
63 if (lpszText != LPSTR_TEXTCALLBACK)
64 toolTextMap[::GetDlgCtrlID(pWnd->GetSafeHwnd())] = CString(lpszText);
65 return CToolTipCtrl::AddTool(pWnd, lpszText, lpRectTool, nIDTool);
68 void CToolTips::AddTool(int nIdWnd, UINT nIdText, LPCRECT lpRectTool /* = NULL */, UINT_PTR nIDTool /* = 0 */)
70 AddTool(((CDialog*)m_pParentWnd)->GetDlgItem(nIdWnd), nIdText, lpRectTool, nIDTool);
73 void CToolTips::AddTool(int nIdWnd, CString sBalloonTipText, LPCRECT lpRectTool /* = NULL */, UINT_PTR nIDTool /* = 0 */)
75 AddTool(((CDialog*)m_pParentWnd)->GetDlgItem(nIdWnd), sBalloonTipText, lpRectTool, nIDTool);
78 void CToolTips::DelTool( CWnd* pWnd, UINT_PTR nIDTool /* = 0 */)
80 toolTextMap.erase(::GetDlgCtrlID(pWnd->GetSafeHwnd()));
81 return CToolTipCtrl::DelTool(pWnd, nIDTool);
84 void CToolTips::DelTool( int nIdWnd, UINT_PTR nIDTool /* = 0 */)
86 return DelTool(((CDialog*)m_pParentWnd)->GetDlgItem(nIdWnd), nIDTool);
89 BOOL CToolTips::ShowBalloon(CWnd *pWnd, UINT nIDText, UINT nIDTitle, UINT icon /* = 0 */)
91 CString sTemp = LoadTooltip(nIDText);
93 const HWND hwndTT = CreateWindow
95 TOOLTIPS_CLASS,
96 _T(""),
97 TTS_NOPREFIX|TTS_BALLOON|TTS_ALWAYSTIP|TTS_CLOSE,
98 CW_USEDEFAULT, CW_USEDEFAULT,
99 CW_USEDEFAULT, CW_USEDEFAULT,
100 pWnd->GetSafeHwnd(),
101 NULL,
102 NULL,
103 NULL
105 if (hwndTT == NULL)
106 return FALSE;
108 TOOLINFO ti = { 0 };
109 ti.cbSize = sizeof(ti);
110 ti.uFlags = TTF_TRACK | TTF_IDISHWND | TTF_PARSELINKS;
111 ti.hwnd = pWnd->GetSafeHwnd();
112 ti.lpszText = sTemp.GetBuffer();
113 ::SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti);
114 ::SendMessage(hwndTT, TTM_SETTITLE, icon, (LPARAM)(LPCTSTR)CString(MAKEINTRESOURCE(nIDTitle)));
115 ::SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, 800);
117 // Position the tooltip below the control
118 RECT rc;
119 ::GetWindowRect(pWnd->GetSafeHwnd(), &rc);
120 ::SendMessage(hwndTT, TTM_TRACKPOSITION, 0, MAKELONG(rc.left + 10, rc.bottom));
122 // Show the tooltip
123 ::SendMessage(hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
125 return TRUE;
128 void CToolTips::ShowBalloon(int nIdWnd, UINT nIdText, UINT nIDTitle, UINT icon /* = 0 */)
130 ShowBalloon(((CDialog*)m_pParentWnd)->GetDlgItem(nIdWnd), nIdText, nIDTitle, icon);
133 CString CToolTips::LoadTooltip( UINT nIDText )
135 CString sTemp;
136 sTemp.LoadString(nIDText);
137 // tooltips can't handle \t and single \n, only spaces and \r\n
138 sTemp.Replace('\t', ' ');
139 sTemp.Replace(_T("\r\n"), _T("\n"));
140 sTemp.Replace(_T("\n"), _T("\r\n"));
141 return sTemp;
144 void CToolTips::RelayEvent(LPMSG lpMsg, CWnd * dlgWnd)
146 if (lpMsg->message == WM_NULL) return;
147 if(dlgWnd && ((lpMsg->message == WM_MOUSEMOVE) || (lpMsg->message == WM_NCMOUSEMOVE)) && (lpMsg->hwnd == dlgWnd->m_hWnd))
149 // allow tooltips for disabled controls
150 CRect rect;
151 POINT pt;
153 pt.x = LOWORD(lpMsg->lParam);
154 pt.y = HIWORD(lpMsg->lParam);
156 for (std::map<UINT, CString>::iterator it = toolTextMap.begin(); it != toolTextMap.end(); ++it)
158 CWnd * pWndCtrl = dlgWnd->GetDlgItem(it->first);
159 pWndCtrl->GetWindowRect(&rect);
160 if (lpMsg->message == WM_MOUSEMOVE)
161 dlgWnd->ScreenToClient(&rect);
163 if(rect.PtInRect(pt) )
165 // save the original parameters
166 HWND origHwnd = lpMsg->hwnd;
167 LPARAM origLParam = lpMsg->lParam;
169 // translate and relay the mouse move message to
170 // the tooltip control as if they were sent
171 // by the disabled control
172 lpMsg->hwnd = pWndCtrl->m_hWnd;
174 if (lpMsg->message == WM_MOUSEMOVE)
175 dlgWnd->ClientToScreen(&pt);
176 pWndCtrl->ScreenToClient(&pt);
177 lpMsg->lParam = MAKELPARAM(pt.x, pt.y);
179 __super::RelayEvent(lpMsg);
181 // restore the original parameters
182 lpMsg->hwnd = origHwnd;
183 lpMsg->lParam = origLParam;
184 return;
189 // Let the ToolTip process this message.
190 __super::RelayEvent(lpMsg);