XTHyperLink.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:12k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTHyperLink.cpp : implementation of the CXTHyperLink class.
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/Resource.h"
  22. #include "Resource.h"
  23. #include "Common/XTPResourceManager.h"
  24. #include "Common/XTPColorManager.h"
  25. #include "Common/XTPDrawHelpers.h"
  26. #include "XTHyperLink.h"
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CXTHyperLink
  34. /////////////////////////////////////////////////////////////////////////////
  35. #ifndef IDC_HAND
  36. #define IDC_HAND            MAKEINTRESOURCE(32649)
  37. #endif
  38. CXTHyperLink::CXTHyperLink()
  39. {
  40. // try to load the system hand cursor.
  41. m_hcurHand = AfxGetApp()->LoadStandardCursor(IDC_HAND);
  42. // if not found, use the toolkit version
  43. if (m_hcurHand == NULL)
  44. m_hcurHand = XTPResourceManager()->LoadCursor(XTP_IDC_HAND);
  45. m_clrBack = COLORREF_NULL;
  46. m_clrLink = RGB(0x00, 0x00, 0xFF); // blue
  47. m_clrHover = RGB(0xFF, 0x00, 0x00); // red
  48. m_clrVisited = RGB(0x80, 0x00, 0x80); // dark purple
  49. m_bUnderline = true;
  50. m_bMouseOver = false;
  51. m_bVisited = false;
  52. m_bPreSubclassInit = true;
  53. m_bShellExec = true;
  54. m_bTipEnabled = true;
  55. }
  56. CXTHyperLink::~CXTHyperLink()
  57. {
  58. }
  59. IMPLEMENT_DYNAMIC(CXTHyperLink, CStatic)
  60. BEGIN_MESSAGE_MAP(CXTHyperLink, CStatic)
  61. //{{AFX_MSG_MAP(CXTHyperLink)
  62. ON_WM_SETCURSOR()
  63. ON_WM_CREATE()
  64. ON_WM_CTLCOLOR_REFLECT()
  65. ON_WM_MOUSEMOVE()
  66. ON_WM_TIMER()
  67. ON_WM_ERASEBKGND()
  68. ON_WM_PAINT()
  69. ON_WM_WINDOWPOSCHANGED()
  70. //}}AFX_MSG_MAP
  71. ON_WM_NCHITTEST_EX()
  72. ON_CONTROL_REFLECT_EX(STN_CLICKED, OnClicked)
  73. END_MESSAGE_MAP()
  74. BOOL CXTHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  75. {
  76. // if the hand cursor is not NULL and the mouse is over text,
  77. // set the hand cursor.
  78. if (m_hcurHand && IsLinkHot())
  79. {
  80. ::SetCursor(m_hcurHand);
  81. return TRUE;
  82. }
  83. return CStatic::OnSetCursor(pWnd, nHitTest, message);
  84. }
  85. LRESULT CXTHyperLink::OnNcHitTest(CPoint /*point*/)
  86. {
  87. return (LRESULT)HTCLIENT;
  88. }
  89. BOOL CXTHyperLink::CreateFont(CFont& font, BOOL bUnderline)
  90. {
  91. // use the control's font.
  92. if (::IsWindow(m_hWnd))
  93. {
  94. CFont* pFont = GetFont();
  95. if (pFont->GetSafeHandle())
  96. {
  97. LOGFONT lf = {0};
  98. pFont->GetLogFont(&lf);
  99. lf.lfUnderline = (BYTE)bUnderline;
  100. font.DeleteObject();
  101. return (font.CreateFontIndirect(&lf));
  102. }
  103. }
  104. // use system font.
  105. NONCLIENTMETRICS ncm;
  106. ::ZeroMemory(&ncm, sizeof(NONCLIENTMETRICS));
  107. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  108. VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  109. sizeof(NONCLIENTMETRICS), &ncm, 0));
  110. ncm.lfStatusFont.lfUnderline = (BYTE)bUnderline;
  111. font.DeleteObject();
  112. return (font.CreateFontIndirect(&ncm.lfStatusFont));
  113. }
  114. bool CXTHyperLink::InitFont()
  115. {
  116. if (!CreateFont(m_font, m_bUnderline))
  117. return false;
  118. if (::IsWindow(m_hWnd))
  119. {
  120. SetFont(&m_font);
  121. RedrawWindow();
  122. return true;
  123. }
  124. return false;
  125. }
  126. void CXTHyperLink::SetURL(LPCTSTR lpszLink)
  127. {
  128. m_strLink = lpszLink;
  129. if (m_strTipText.IsEmpty())
  130. {
  131. m_strTipText = m_strLink;
  132. }
  133. if (!m_strTipText.IsEmpty())
  134. {
  135. if (!::IsWindow(m_toolTip.m_hWnd))
  136. {
  137. m_toolTip.Create(this);
  138. m_toolTip.AddTool(this, m_strTipText);
  139. m_toolTip.Activate(m_bTipEnabled);
  140. }
  141. else
  142. {
  143. m_toolTip.UpdateTipText(m_strLink, this);
  144. }
  145. }
  146. }
  147. bool CXTHyperLink::Init()
  148. {
  149. if (::IsWindow(m_hWnd))
  150. {
  151. // only use the window text if this is a text link and
  152. // the URL has not already been initialized first.
  153. if (IsTextControl())
  154. {
  155. if (m_strLink.IsEmpty())
  156. {
  157. GetWindowText(m_strLink);
  158. }
  159. SetURL(m_strLink);
  160. }
  161. ModifyStyle(NULL, SS_NOTIFY);
  162. return InitFont();
  163. }
  164. return false;
  165. }
  166. void CXTHyperLink::PreSubclassWindow()
  167. {
  168. CStatic::PreSubclassWindow();
  169. if (m_bPreSubclassInit)
  170. {
  171. // Initialize the control.
  172. Init();
  173. }
  174. }
  175. int CXTHyperLink::OnCreate(LPCREATESTRUCT lpCreateStruct)
  176. {
  177. if (CStatic::OnCreate(lpCreateStruct) == -1)
  178. return -1;
  179. // Initialize the control.
  180. Init();
  181. return 0;
  182. }
  183. BOOL CXTHyperLink::PreCreateWindow(CREATESTRUCT& cs)
  184. {
  185. if (!CStatic::PreCreateWindow(cs))
  186. return FALSE;
  187. // When creating controls dynamically Init() must
  188. // be called from OnCreate() and not from
  189. // PreSubclassWindow().
  190. m_bPreSubclassInit = false;
  191. return TRUE;
  192. }
  193. void CXTHyperLink::ReportError(int iErrorNo)
  194. {
  195. CString strMessage;
  196. switch (iErrorNo)
  197. {
  198. case 0:                      XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_0);                   break;
  199. case SE_ERR_FNF:             XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_FNF);             break;
  200. case SE_ERR_PNF:             XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_PNF);             break;
  201. case SE_ERR_ACCESSDENIED:    XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_ACCESSDENIED);    break;
  202. case SE_ERR_OOM:             XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_OOM);             break;
  203. case ERROR_BAD_FORMAT:       XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_BAD_FORMAT);      break;
  204. case SE_ERR_SHARE:           XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_SHARE);           break;
  205. case SE_ERR_ASSOCINCOMPLETE: XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_ASSOCINCOMPLETE); break;
  206. case SE_ERR_DDETIMEOUT:      XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_DDETIMEOUT);      break;
  207. case SE_ERR_DDEFAIL:         XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_DDEFAIL);         break;
  208. case SE_ERR_DDEBUSY:         XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_DDEBUSY);         break;
  209. case SE_ERR_NOASSOC:         XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_NOASSOC);         break;
  210. case SE_ERR_DLLNOTFOUND:     XTPResourceManager()->LoadString(&strMessage, XT_IDS_SE_ERR_DLLNOTFOUND);     break;
  211. default:
  212. {
  213. CString str;
  214. XTPResourceManager()->LoadString(&str, XT_IDS_SE_ERR_UNKOWN);
  215. strMessage.Format(str, iErrorNo);
  216. }
  217. }
  218. ::MessageBeep(MB_ICONEXCLAMATION);
  219. AfxMessageBox(strMessage, MB_ICONEXCLAMATION | MB_OK);
  220. }
  221. bool CXTHyperLink::GotoURL(LPCTSTR lpszLink/*=NULL*/, int nShowCmd/*=SW_SHOW*/, LPCTSTR lpszParams/*=NULL*/, LPCTSTR lpszDir/*=NULL*/)
  222. {
  223. if (!lpszLink)
  224. lpszLink = m_strLink;
  225. // open the URL
  226. int iRetVal = (int)(INT_PTR)::ShellExecute(NULL, _T("open"),
  227. lpszLink, lpszParams, lpszDir, nShowCmd);
  228. // alert user if there was an error.
  229. if (iRetVal <= HINSTANCE_ERROR)
  230. ReportError(iRetVal);
  231. return (iRetVal > HINSTANCE_ERROR);
  232. }
  233. HBRUSH CXTHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)
  234. {
  235. UNUSED_ALWAYS(nCtlColor);
  236. ASSERT(nCtlColor == CTLCOLOR_STATIC);
  237. if (IsTextControl())
  238. {
  239. HBRUSH hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
  240. if (m_clrBack == COLORREF_NULL)
  241. {
  242. hbr = (HBRUSH)::DefWindowProc(::GetParent(m_hWnd), WM_CTLCOLORSTATIC, (WPARAM)pDC->GetSafeHdc(), (LPARAM)m_hWnd);
  243. }
  244. // draw the current state color.
  245. if (m_bMouseOver)
  246. {
  247. pDC->SetTextColor(m_clrHover);
  248. }
  249. else if (m_bVisited)
  250. {
  251. pDC->SetTextColor(m_clrVisited);
  252. }
  253. else
  254. {
  255. pDC->SetTextColor(m_clrLink);
  256. }
  257. pDC->SetBkMode(TRANSPARENT);
  258. return hbr;
  259. }
  260. return NULL;
  261. }
  262. void CXTHyperLink::OnMouseMove(UINT nFlags, CPoint point)
  263. {
  264. if (IsTextControl() && IsLinkHot())
  265. {
  266. SetTimer(1, 10, NULL);
  267. }
  268. CStatic::OnMouseMove(nFlags, point);
  269. }
  270. void CXTHyperLink::OnTimer(UINT_PTR nIDEvent)
  271. {
  272. if (IsTextControl())
  273. {
  274. bool bMouseOver = IsLinkHot();
  275. if (bMouseOver != m_bMouseOver)
  276. {
  277. m_bMouseOver = bMouseOver;
  278. RedrawWindow();
  279. }
  280. if (!m_bMouseOver)
  281. {
  282. KillTimer(1);
  283. }
  284. }
  285. CStatic::OnTimer(nIDEvent);
  286. }
  287. BOOL CXTHyperLink::PreTranslateMessage(MSG* pMsg)
  288. {
  289. if (::IsWindow(m_toolTip.m_hWnd) && m_bTipEnabled)
  290. {
  291. m_toolTip.RelayEvent(pMsg);
  292. }
  293. return CStatic::PreTranslateMessage(pMsg);
  294. }
  295. BOOL CXTHyperLink::OnEraseBkgnd(CDC* pDC)
  296. {
  297. if (m_clrBack == COLORREF_NULL)
  298. return CStatic::OnEraseBkgnd(pDC);
  299. return TRUE;
  300. }
  301. void CXTHyperLink::OnPaint()
  302. {
  303. // if the WS_EX_TRANSPARENT style is set, we have to use
  304. // default paint routines otherwise our background will still
  305. // be painted.
  306. if (((::GetWindowLong(m_hWnd, GWL_EXSTYLE)
  307. & WS_EX_TRANSPARENT) != 0) || (m_clrBack == COLORREF_NULL))
  308. {
  309. Default();
  310. }
  311. else
  312. {
  313. CPaintDC dc(this);
  314. // Get the client rect, and paint to a memory device context.  This will
  315. // help reduce screen flicker. Pass the memory device context to the
  316. // default window procedure do default painting.
  317. CXTPClientRect r(this);
  318. CXTPBufferDC memDC(dc);
  319. memDC.FillSolidRect(r, GetBackColor());
  320. CStatic::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0);
  321. }
  322. }
  323. void CXTHyperLink::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
  324. {
  325. CStatic::OnWindowPosChanged(lpwndpos);
  326. // if we are resized, redraw hyperlink.
  327. RedrawWindow();
  328. }
  329. BOOL CXTHyperLink::OnClicked()
  330. {
  331. if (IsLinkHot())
  332. {
  333. if (m_bShellExec)
  334. {
  335. m_bVisited = GotoURL(m_strLink, SW_SHOW);
  336. }
  337. else
  338. {
  339. m_bVisited = true;
  340. }
  341. }
  342. // make sure tooltip is removed.
  343. if (::IsWindow(m_toolTip.m_hWnd) && m_bTipEnabled)
  344. m_toolTip.SendMessage(TTM_POP);
  345. return (!IsTextControl());   // continue routing
  346. }
  347. bool CXTHyperLink::IsLinkHot()
  348. {
  349. // if this isn't a text control, just return true
  350. if (!IsTextControl())
  351. return true;
  352. // get the text for the hyperlink control.
  353. CString strText;
  354. GetWindowText(strText);
  355. // get the size of the text.
  356. CWindowDC dc(NULL);
  357. CFont* pFont = dc.SelectObject(GetFont());
  358. CSize size = dc.GetTextExtent(strText);
  359. dc.SelectObject(pFont);
  360. // get the total size of the hyperlink
  361. CRect r;
  362. GetWindowRect(&r);
  363. // construct the actual size of the text.
  364. CRect rHot = r;
  365. switch (GetStyle() & (SS_LEFT | SS_CENTER | SS_RIGHT))
  366. {
  367. case SS_LEFT:
  368. {
  369. rHot.right = rHot.left + size.cx;
  370. }
  371. break;
  372. case SS_CENTER:
  373. {
  374. int cx = (r.Width() - size.cx) / 2;
  375. rHot.right -= cx;
  376. rHot.left += cx;
  377. }
  378. break;
  379. case SS_RIGHT:
  380. {
  381. rHot.left = rHot.right - size.cx;
  382. }
  383. break;
  384. }
  385. // get the cursor location, if it is over the
  386. // text, return true, this means the hyperlink
  387. // should appear hot.
  388. CPoint pt;
  389. ::GetCursorPos(&pt);
  390. if (rHot.PtInRect(pt))
  391. {
  392. return true;
  393. }
  394. return false;
  395. }
  396. void CXTHyperLink::EnableToolTips(bool bEnable/*= true*/)
  397. {
  398. m_bTipEnabled = bEnable;
  399. // if the tooltip control is already created, activate or
  400. // deactivate it.
  401. if (::IsWindow(m_toolTip.m_hWnd))
  402. {
  403. m_toolTip.Activate(bEnable);
  404. }
  405. }
  406. void CXTHyperLink::SetTipText(LPCTSTR lpszTipText)
  407. {
  408. m_strTipText = lpszTipText;
  409. // if the tooltip control is already created, update the
  410. // tip text.
  411. if (::IsWindow(m_toolTip.m_hWnd))
  412. {
  413. m_toolTip.UpdateTipText(m_strTipText, this);
  414. }
  415. }