1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009, 2012-2016, 2018 - 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 "LinkControl.h"
21 #include "CommonAppUtils.h"
23 const UINT
CLinkControl::LK_LINKITEMCLICKED
= ::RegisterWindowMessage(L
"LK_LINKITEMCLICKED");
25 CLinkControl::CLinkControl(void)
26 : m_bOverControl(false)
27 , m_hLinkCursor(nullptr)
31 CLinkControl::~CLinkControl(void)
34 * No need to call DestroyCursor() for cursors acquired through
37 m_NormalFont
.DeleteObject();
38 m_UnderlineFont
.DeleteObject();
41 void CLinkControl::PreSubclassWindow()
43 CStatic::PreSubclassWindow();
45 ModifyStyle(0, SS_NOTIFY
);
47 m_hLinkCursor
= ::LoadCursor(nullptr, IDC_HAND
); // Load Windows' hand cursor
48 if (!m_hLinkCursor
) // if not available, use the standard Arrow cursor
50 m_hLinkCursor
= ::LoadCursor(nullptr, IDC_ARROW
);
53 // Create an updated font by adding an underline.
55 CFont
* pFont
= GetFont();
57 pFont
->GetObject(sizeof(lf
), &lf
);
60 NONCLIENTMETRICS metrics
= { 0 };
61 metrics
.cbSize
= sizeof(NONCLIENTMETRICS
);
62 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &metrics
, FALSE
);
63 memcpy_s(&lf
, sizeof(LOGFONT
), &metrics
.lfMessageFont
, sizeof(LOGFONT
));
66 lf
.lfWeight
= FW_BOLD
;
67 m_NormalFont
.CreateFontIndirect(&lf
);
69 lf
.lfUnderline
= TRUE
;
70 m_UnderlineFont
.CreateFontIndirect(&lf
);
72 SetFont(&m_NormalFont
, FALSE
);
75 BEGIN_MESSAGE_MAP(CLinkControl
, CStatic
)
78 ON_WM_CAPTURECHANGED()
84 ON_CONTROL_REFLECT(STN_CLICKED
, OnClicked
)
88 void CLinkControl::OnMouseMove(UINT
/*nFlags*/, CPoint pt
)
95 if (!PtInRect(&rect
, pt
))
100 m_bOverControl
= TRUE
;
101 SetFont(&m_UnderlineFont
, FALSE
);
102 InvalidateRect(nullptr, FALSE
);
107 BOOL
CLinkControl::OnSetCursor(CWnd
* /*pWnd*/, UINT
/*nHitTest*/, UINT
/*message*/)
109 ::SetCursor(m_hLinkCursor
);
113 void CLinkControl::OnCaptureChanged(CWnd
* /*pWnd*/)
115 m_bOverControl
= FALSE
;
116 SetFont(&m_NormalFont
, FALSE
);
117 InvalidateRect(nullptr, FALSE
);
120 void CLinkControl::OnSetFocus(CWnd
* pOldWnd
)
123 __super::OnSetFocus(pOldWnd
);
126 void CLinkControl::OnKillFocus(CWnd
* pOldWnd
)
129 __super::OnKillFocus(pOldWnd
);
132 void CLinkControl::DrawFocusRect()
134 CWnd
*parent
= GetParent();
138 // calculate where to draw focus rectangle, in screen coords
142 InflateRect(&rc
, 1, 1); // add one pixel all around
143 parent
->ScreenToClient(&rc
);
145 CClientDC
dcParent(parent
);
146 dcParent
.DrawFocusRect(&rc
);
150 void CLinkControl::ClearFocusRect()
152 CWnd
*parent
= GetParent();
156 // calculate where to draw focus rectangle, in screen coords
160 InflateRect(&rc
, 1, 1); // add one pixel all around
161 parent
->ScreenToClient(&rc
);
162 // Ask parent to redraw area where we rendered focus rect before.
163 parent
->InvalidateRect(&rc
);
167 void CLinkControl::NotifyParent(UINT msg
)
169 ::PostMessage(GetParent()->GetSafeHwnd(), msg
, (WPARAM
)GetSafeHwnd(), (LPARAM
) 0);
172 UINT
CLinkControl::OnGetDlgCode()
174 UINT dlgCode
= CStatic::OnGetDlgCode();
175 const MSG
*pMsg
= CWnd::GetCurrentMessage();
177 // we want all keys to get the return key
178 dlgCode
|= DLGC_WANTALLKEYS
;
179 dlgCode
|= DLGC_BUTTON
;
180 // but we don't want the tab key since that should be used in dialogs
181 // to switch the focus
182 dlgCode
&= ~DLGC_WANTTAB
;
183 dlgCode
&= ~DLGC_STATIC
;
186 ((MSG
*)pMsg
->lParam
)->message
== WM_KEYDOWN
&&
187 ((MSG
*)pMsg
->lParam
)->wParam
== VK_TAB
)
189 dlgCode
&= ~DLGC_WANTMESSAGE
;
195 void CLinkControl::OnKeyDown(UINT nChar
, UINT
/*nRepCnt*/, UINT
/*nFlags*/)
197 if (nChar
== VK_SPACE
|| nChar
== VK_RETURN
)
199 NotifyParent(LK_LINKITEMCLICKED
);
203 void CLinkControl::OnClicked()
205 NotifyParent(LK_LINKITEMCLICKED
);
208 void CLinkControl::OnEnable(BOOL enabled
)
210 CStatic::OnEnable(enabled
);
213 BOOL
CLinkControl::OnWndMsg(UINT message
, WPARAM wParam
, LPARAM lParam
, LRESULT
* pResult
)
218 NotifyParent(LK_LINKITEMCLICKED
);
221 return CStatic::OnWndMsg(message
, wParam
, lParam
, pResult
);