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.
20 #include "HyperLink.h"
21 #include "SmartHandle.h"
26 static char THIS_FILE
[] = __FILE__
;
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?
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
);
72 GetWindowText(strWndText
);
73 if (strWndText
.IsEmpty())
75 SetWindowText(m_strURL
);
78 CFont
* pFont
= GetFont();
81 HFONT hFont
= (HFONT
)GetStockObject(DEFAULT_GUI_FONT
);
83 hFont
= (HFONT
) GetStockObject(ANSI_VAR_FONT
);
85 pFont
= CFont::FromHandle(hFont
);
87 ASSERT(pFont
&& pFont
->GetSafeHandle());
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
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()
112 ON_CONTROL_REFLECT(STN_CLICKED
, OnClicked
)
116 void CHyperLink::OnClicked()
118 if(!m_strURL
.IsEmpty())
124 ::SendMessage(this->GetParent()->m_hWnd
,WM_COMMAND
,this->GetDlgCtrlID(),0);
128 HBRUSH
CHyperLink::CtlColor(CDC
* pDC
, UINT
/*nCtlColor*/)
131 pDC
->SetTextColor(m_crHoverColor
);
133 pDC
->SetTextColor(m_crLinkColor
);
136 pDC
->SetBkMode(TRANSPARENT
);
137 return (HBRUSH
)GetStockObject(NULL_BRUSH
);
140 void CHyperLink::OnMouseMove(UINT nFlags
, CPoint point
)
144 m_bOverControl
= TRUE
;
146 if (m_nUnderline
== ulHover
)
147 SetFont(&m_UnderlineFont
);
150 SetTimer(m_nTimerID
, 100, nullptr);
152 CStatic::OnMouseMove(nFlags
, point
);
155 void CHyperLink::OnTimer(UINT_PTR nIDEvent
)
157 CPoint
p(GetMessagePos());
162 if (!rect
.PtInRect(p
))
164 m_bOverControl
= FALSE
;
165 KillTimer(m_nTimerID
);
167 if (m_nUnderline
!= ulAlways
)
170 InvalidateRect(rect
);
173 CStatic::OnTimer(nIDEvent
);
176 BOOL
CHyperLink::OnSetCursor(CWnd
* /*pWnd*/, UINT
/*nHitTest*/, UINT
/*message*/)
180 ::SetCursor(m_hLinkCursor
);
186 BOOL
CHyperLink::OnEraseBkgnd(CDC
* pDC
)
190 pDC
->FillSolidRect(rect
, ::GetSysColor(COLOR_3DFACE
));
195 void CHyperLink::SetURL(CString strURL
)
199 if (::IsWindow(GetSafeHwnd()))
201 m_ToolTip
.UpdateTipText(strURL
, this, TOOLTIP_ID
);
205 CString
CHyperLink::GetURL() const
210 void CHyperLink::SetColors(COLORREF crLinkColor
, COLORREF crHoverColor
)
212 m_crLinkColor
= crLinkColor
;
214 if (crHoverColor
== -1)
215 m_crHoverColor
= ::GetSysColor(COLOR_HIGHLIGHT
);
217 m_crHoverColor
= crHoverColor
;
219 if (::IsWindow(m_hWnd
))
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
)
238 if (::IsWindow(GetSafeHwnd()))
240 if (nUnderline
== ulAlways
)
241 SetFont(&m_UnderlineFont
);
248 m_nUnderline
= nUnderline
;
251 int CHyperLink::GetUnderline() const
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()
262 // first try the windows hand cursor (not available on NT4)
264 # define OCR_HAND 32649
266 HCURSOR hHandCursor
= (HCURSOR
)::LoadImage(nullptr, MAKEINTRESOURCE(OCR_HAND
), IMAGE_CURSOR
, 0, 0, LR_DEFAULTSIZE
| LR_SHARED
);
269 m_hLinkCursor
= hHandCursor
;
272 // windows cursor not available, so try to load it from winhlp32.exe
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
);
281 HCURSOR hHandCursor2
= (HCURSOR
)::LoadImage(hModule
, MAKEINTRESOURCE(106), IMAGE_CURSOR
, 0, 0, LR_DEFAULTSIZE
);
283 m_hLinkCursor
= CopyCursor(hHandCursor2
);
288 HINSTANCE
CHyperLink::GotoURL(LPCTSTR url
)
290 return ShellExecute(nullptr, _T("open"), url
, nullptr, nullptr, SW_SHOW
);