StatLink.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ////////////////////////////////////////////////////////////////
  2. // PixieLib(TM) Copyright 1997-1999 Paul DiLascia
  3. // If this code works, it was written by Paul DiLascia.
  4. // If not, I don't know who wrote it.
  5. //
  6. // CStaticLink implements a static control that's a hyperlink
  7. // to any file on your desktop or web. You can use it in dialog boxes
  8. // to create hyperlinks to web sites. When clicked, opens the file/URL
  9. //
  10. #include "StdAfx.h"
  11. #include "StatLink.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. COLORREF CStaticLink::g_colorUnvisited = RGB(0,0,255); // blue
  18. COLORREF CStaticLink::g_colorVisited = RGB(128,0,128); // purple
  19. HCURSOR CStaticLink::g_hCursorLink = NULL;
  20. IMPLEMENT_DYNAMIC(CStaticLink, CStatic)
  21. BEGIN_MESSAGE_MAP(CStaticLink, CStatic)
  22. ON_WM_NCHITTEST()
  23. ON_WM_CTLCOLOR_REFLECT()
  24. ON_WM_LBUTTONDOWN()
  25. ON_WM_SETCURSOR()
  26. END_MESSAGE_MAP()
  27. ///////////////////
  28. // Constructor sets default colors = blue/purple.
  29. // bDeleteOnDestroy is used internally by PixieLib in CPixieDlg.
  30. //
  31. CStaticLink::CStaticLink(LPCTSTR lpText, BOOL bDeleteOnDestroy)
  32. {
  33. m_link = lpText; // link text (NULL ==> window text)
  34. m_color = g_colorUnvisited; // not visited yet
  35. m_bDeleteOnDestroy = bDeleteOnDestroy; // delete object with window?
  36. }
  37. //////////////////
  38. // Normally, a static control does not get mouse events unless it has
  39. // SS_NOTIFY. This achieves the same effect as SS_NOTIFY, but it's fewer
  40. // lines of code and more reliable than turning on SS_NOTIFY in OnCtlColor
  41. // because Windows doesn't send WM_CTLCOLOR to bitmap static controls.
  42. //
  43. LRESULT CStaticLink::OnNcHitTest(CPoint point)
  44. {
  45. return HTCLIENT;
  46. }
  47. //////////////////
  48. // Handle reflected WM_CTLCOLOR to set custom control color.
  49. // For a text control, use visited/unvisited colors and underline font.
  50. // For non-text controls, do nothing. Also ensures SS_NOTIFY is on.
  51. //
  52. HBRUSH CStaticLink::CtlColor(CDC* pDC, UINT nCtlColor)
  53. {
  54. ASSERT(nCtlColor == CTLCOLOR_STATIC);
  55. DWORD dwStyle = GetStyle();
  56. HBRUSH hbr = NULL;
  57. if ((dwStyle & 0xFF) <= SS_RIGHT) {
  58. // this is a text control: set up font and colors
  59. if (!(HFONT)m_font) {
  60. // first time init: create font
  61. LOGFONT lf;
  62. GetFont()->GetObject(sizeof(lf), &lf);
  63. lf.lfUnderline = TRUE;
  64. m_font.CreateFontIndirect(&lf);
  65. }
  66. // use underline font and visited/unvisited colors
  67. pDC->SelectObject(&m_font);
  68. pDC->SetTextColor(m_color);
  69. pDC->SetBkMode(TRANSPARENT);
  70. // return hollow brush to preserve parent background color
  71. hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
  72. }
  73. return hbr;
  74. }
  75. /////////////////
  76. // Handle mouse click: navigate link
  77. //
  78. void CStaticLink::OnLButtonDown(UINT nFlags, CPoint point)
  79. {
  80. if (m_link.IsEmpty()) {
  81. // no link: try to load from resource string or window text
  82. m_link.LoadString(GetDlgCtrlID()) || (GetWindowText(m_link),1);
  83. if (m_link.IsEmpty())
  84. return;
  85. }
  86. // Call ShellExecute to run the file.
  87. // For an URL, this means opening it in the browser.
  88. //
  89. HINSTANCE h = m_link.Navigate();
  90. if ((UINT)h > 32) { // success!
  91. m_color = g_colorVisited; // change color
  92. Invalidate(); // repaint
  93. } else {
  94. MessageBeep(0); // unable to execute file!
  95. TRACE(_T("*** WARNING: CStaticLink: unable to navigate link %s\n"),
  96. (LPCTSTR)m_link);
  97. }
  98. }
  99. //////////////////
  100. // Set "hand" cursor to cue user that this is a link. If app has not set
  101. // g_hCursorLink, then try to get the cursor from winhlp32.exe,
  102. // resource 106, which is a pointing finger. This is a bit of a kludge,
  103. // but it works.
  104. //
  105. BOOL CStaticLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  106. {
  107. if (g_hCursorLink == NULL) {
  108. static bool bTriedOnce = FALSE;
  109. if (!bTriedOnce) {
  110. CString windir;
  111. GetWindowsDirectory(windir.GetBuffer(MAX_PATH), MAX_PATH);
  112. windir.ReleaseBuffer();
  113. windir += _T("\\winhlp32.exe");
  114. HMODULE hModule = LoadLibrary(windir);
  115. if (hModule) {
  116. g_hCursorLink =
  117. CopyCursor(::LoadCursor(hModule, MAKEINTRESOURCE(106)));
  118. }
  119. FreeLibrary(hModule);
  120. bTriedOnce = TRUE;
  121. }
  122. }
  123. if (g_hCursorLink) {
  124. ::SetCursor(g_hCursorLink);
  125. return TRUE;
  126. }
  127. return FALSE;
  128. }
  129. //////////////////
  130. // Normally, a control class is not destoyed when the window is;
  131. // however, CPixieDlg creates static controls with "new" instead of
  132. // as class members, so it's convenient to allow the option of destroying
  133. // object with window. In applications where you want the object to be
  134. // destoyed along with the window, you can call constructor with
  135. // bDeleteOnDestroy=TRUE.
  136. //
  137. void CStaticLink::PostNcDestroy()
  138. {
  139. if (m_bDeleteOnDestroy)
  140. delete this;
  141. }