Update editorconfig
[TortoiseGit.git] / src / Utils / MiscUI / HyperLink.cpp
blob23a3c7f75bbff53c21710202b1d5d3ef8c7b2684
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2006,2008, 2011 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "HyperLink.h"
21 #include "SmartHandle.h"
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #undef THIS_FILE
26 static char THIS_FILE[] = __FILE__;
27 #endif
29 #define TOOLTIP_ID 1
32 CHyperLink::CHyperLink()
34 m_hLinkCursor = nullptr; // No cursor as yet
35 m_crLinkColor = RGB( 0, 0, 238); // Blue
36 m_crHoverColor = RGB(255, 0, 0); // Red
37 m_bOverControl = FALSE; // Cursor not yet over control
38 m_nUnderline = ulHover; // Underline the link?
39 m_strURL.Empty();
40 m_nTimerID = 100;
43 CHyperLink::~CHyperLink()
45 m_UnderlineFont.DeleteObject();
48 BOOL CHyperLink::DestroyWindow()
50 KillTimer(m_nTimerID);
52 return CStatic::DestroyWindow();
55 BOOL CHyperLink::PreTranslateMessage(MSG* pMsg)
57 m_ToolTip.RelayEvent(pMsg);
58 return CStatic::PreTranslateMessage(pMsg);
62 void CHyperLink::PreSubclassWindow()
64 // Enable notifications - CStatic has this disabled by default
65 ModifyStyle(0, SS_NOTIFY);
67 // By default use the label text as the URL
68 if (m_strURL.IsEmpty())
69 GetWindowText(m_strURL);
71 CString strWndText;
72 GetWindowText(strWndText);
73 if (strWndText.IsEmpty())
75 SetWindowText(m_strURL);
78 CFont* pFont = GetFont();
79 if (!pFont)
81 HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
82 if (!hFont)
83 hFont = (HFONT) GetStockObject(ANSI_VAR_FONT);
84 if (hFont)
85 pFont = CFont::FromHandle(hFont);
87 ASSERT(pFont && pFont->GetSafeHandle());
89 LOGFONT lf;
90 pFont->GetLogFont(&lf);
91 m_StdFont.CreateFontIndirect(&lf);
92 lf.lfUnderline = (BYTE) TRUE;
93 m_UnderlineFont.CreateFontIndirect(&lf);
95 SetDefaultCursor(); // try loading a "hand" cursor
96 SetUnderline();
98 CRect rect;
99 GetClientRect(rect);
100 m_ToolTip.Create(this);
101 m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);
103 CStatic::PreSubclassWindow();
106 BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
107 ON_WM_CTLCOLOR_REFLECT()
108 ON_WM_SETCURSOR()
109 ON_WM_MOUSEMOVE()
110 ON_WM_TIMER()
111 ON_WM_ERASEBKGND()
112 ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
113 END_MESSAGE_MAP()
116 void CHyperLink::OnClicked()
118 if(!m_strURL.IsEmpty())
120 GotoURL(m_strURL);
122 else
124 ::SendMessage(this->GetParent()->m_hWnd,WM_COMMAND,this->GetDlgCtrlID(),0);
128 HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
130 if (m_bOverControl)
131 pDC->SetTextColor(m_crHoverColor);
132 else
133 pDC->SetTextColor(m_crLinkColor);
135 // draw transparent
136 pDC->SetBkMode(TRANSPARENT);
137 return (HBRUSH)GetStockObject(NULL_BRUSH);
140 void CHyperLink::OnMouseMove(UINT nFlags, CPoint point)
142 if (!m_bOverControl)
144 m_bOverControl = TRUE;
146 if (m_nUnderline == ulHover)
147 SetFont(&m_UnderlineFont);
148 Invalidate();
150 SetTimer(m_nTimerID, 100, nullptr);
152 CStatic::OnMouseMove(nFlags, point);
155 void CHyperLink::OnTimer(UINT_PTR nIDEvent)
157 CPoint p(GetMessagePos());
158 ScreenToClient(&p);
160 CRect rect;
161 GetClientRect(rect);
162 if (!rect.PtInRect(p))
164 m_bOverControl = FALSE;
165 KillTimer(m_nTimerID);
167 if (m_nUnderline != ulAlways)
168 SetFont(&m_StdFont);
169 rect.bottom+=10;
170 InvalidateRect(rect);
173 CStatic::OnTimer(nIDEvent);
176 BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/)
178 if (m_hLinkCursor)
180 ::SetCursor(m_hLinkCursor);
181 return TRUE;
183 return FALSE;
186 BOOL CHyperLink::OnEraseBkgnd(CDC* pDC)
188 CRect rect;
189 GetClientRect(rect);
190 pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));
192 return TRUE;
195 void CHyperLink::SetURL(CString strURL)
197 m_strURL = strURL;
199 if (::IsWindow(GetSafeHwnd()))
201 m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
205 CString CHyperLink::GetURL() const
207 return m_strURL;
210 void CHyperLink::SetColors(COLORREF crLinkColor, COLORREF crHoverColor)
212 m_crLinkColor = crLinkColor;
214 if (crHoverColor == -1)
215 m_crHoverColor = ::GetSysColor(COLOR_HIGHLIGHT);
216 else
217 m_crHoverColor = crHoverColor;
219 if (::IsWindow(m_hWnd))
220 Invalidate();
223 COLORREF CHyperLink::GetLinkColor() const
225 return m_crLinkColor;
228 COLORREF CHyperLink::GetHoverColor() const
230 return m_crHoverColor;
233 void CHyperLink::SetUnderline(int nUnderline /*=ulHover*/)
235 if (m_nUnderline == nUnderline)
236 return;
238 if (::IsWindow(GetSafeHwnd()))
240 if (nUnderline == ulAlways)
241 SetFont(&m_UnderlineFont);
242 else
243 SetFont(&m_StdFont);
245 Invalidate();
248 m_nUnderline = nUnderline;
251 int CHyperLink::GetUnderline() const
253 return m_nUnderline;
256 // The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
257 // It loads a "hand" cursor from the winhlp32.exe module
258 void CHyperLink::SetDefaultCursor()
260 if (!m_hLinkCursor)
262 // first try the windows hand cursor (not available on NT4)
263 #ifndef OCR_HAND
264 # define OCR_HAND 32649
265 #endif
266 HCURSOR hHandCursor = (HCURSOR)::LoadImage(nullptr, MAKEINTRESOURCE(OCR_HAND), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
267 if (hHandCursor)
269 m_hLinkCursor = hHandCursor;
270 return;
272 // windows cursor not available, so try to load it from winhlp32.exe
273 CString strWndDir;
274 GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH); // Explorer can't handle paths longer than MAX_PATH.
275 strWndDir.ReleaseBuffer();
277 strWndDir += _T("\\winhlp32.exe");
278 // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
279 CAutoLibrary hModule = LoadLibrary(strWndDir);
280 if (hModule) {
281 HCURSOR hHandCursor2 = (HCURSOR)::LoadImage(hModule, MAKEINTRESOURCE(106), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
282 if (hHandCursor2)
283 m_hLinkCursor = CopyCursor(hHandCursor2);
288 HINSTANCE CHyperLink::GotoURL(LPCTSTR url)
290 return ShellExecute(nullptr, _T("open"), url, nullptr, nullptr, SW_SHOW);