hlinkctl.cpp
上传用户:onward9999
上传日期:2022-06-27
资源大小:989k
文件大小:14k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /*
  2. Module : HLINKCTRL.CPP
  3. Purpose: Implementation for a MFC class for a static text control class with hyperlink support
  4. Created: PJN / HLINK/1 / 16-06-1997
  5. History: PJN /         / 24-06-1997, hyperlinks are now coloured ala IE
  6.          PJN /         / 15-07-1997, Now supports ShrinkToFit
  7.          PJN           / 11-09-1997, Added support for a highlight look
  8.                                      which includes a highlight color and
  9.                                      a shadowed look. Also fixed a bug 
  10.                                      relating to the Edit controls context
  11.                                      menu.
  12.                                      Also included is a new context menu ala IE3
  13.          PJN           / 06-11-1997, 1) Improved drawing of control by handling WM_CTLCOLOR through MFC message reflection
  14.                                      2) class now derived from CStatic as it should have been from the begining
  15.                                      3) Dropped support for shrink to fit as now no need
  16.                                      4) Description is now taken from controls window text
  17.                                      5) Now using more standard visited and unvisted colors
  18.                                      6) Dropped support for optional underlying and drop shadow effects
  19.                                      7) streamlined some of the functions declarations
  20.                                      8) Wait cursor is now shown when a shortcut is being saved
  21.                                      9) Context menu for control can now be turned off if so desired
  22.          PJN           / 08-12-1997, 1) Removed ON_COMMAND(ID_POPUP_OPEN, OnOpen) from #define which was causing 
  23.                                         to the hyperlink correctly
  24.                                      2) Removed a level 4 warning which was being generated when building in release mode  
  25.          PJN           / 09-01-1998  1) Removed duplicate OnAddToFavorites and OnAddToDesktop functions
  26. Copyright (c) 1997 by PJ Naughter.  
  27. All rights reserved.
  28. */
  29. /////////////////////////////////  Includes  //////////////////////////////////
  30. #include "stdafx.h"
  31. #ifndef HLINK_NOOLE
  32. #define INITGUID
  33. #endif
  34. #include "resource.h"
  35. #include "hlinkctl.h"
  36. #ifndef HLINK_NOOLE
  37. #include <initguid.h>
  38. #endif
  39. #include <winnetwk.h>
  40. #include <winnls.h>
  41. #include <shlobj.h>
  42. #ifndef HLINK_NOOLE
  43. #include <intshcut.h>
  44. #endif
  45. /////////////////////////////////  Macros & Statics ///////////////////////////
  46. #ifdef _DEBUG
  47. #define new DEBUG_NEW
  48. #undef THIS_FILE
  49. static char THIS_FILE[] = __FILE__;
  50. #endif
  51. ///////////////////////////////// Implementation //////////////////////////////
  52. BEGIN_MESSAGE_MAP(CHLinkCtrl, CStatic)
  53. ON_WM_CONTEXTMENU()
  54. //{{AFX_MSG_MAP(CHLinkCtrl)
  55.   ON_WM_SETCURSOR()
  56.   ON_WM_LBUTTONDOWN()
  57. ON_WM_MOUSEMOVE()
  58. ON_COMMAND(ID_POPUP_COPYSHORTCUT, OnCopyShortcut)
  59. ON_COMMAND(ID_POPUP_PROPERTIES, OnProperties)
  60. //}}AFX_MSG_MAP
  61. ON_WM_CTLCOLOR_REFLECT()
  62.   ON_COMMAND(ID_POPUP_OPEN, OnOpen)
  63. #ifndef HLINK_NOOLE
  64. ON_COMMAND(ID_POPUP_ADDTOFAVORITES, OnAddToFavorites)
  65.   ON_COMMAND(ID_POPUP_ADDTODESKTOP, OnAddToDesktop)
  66. #endif
  67. END_MESSAGE_MAP()
  68. CHLinkCtrl::CHLinkCtrl()
  69. {
  70. m_Color = RGB(0, 0, 255);
  71. m_VisitedColor = RGB(128, 0, 128);
  72. m_HighlightColor = RGB(255, 0, 0);
  73. m_bShrinkToFit = TRUE;
  74.   m_bUseHighlight = TRUE;
  75. m_State = ST_NOT_VISITED;
  76.   m_OldState = ST_NOT_VISITED;
  77.   m_bShowingContext = FALSE;
  78.   m_bAllowContextMenu = TRUE;
  79. //Load up the cursors
  80. m_hLinkCursor = AfxGetApp()->LoadCursor(IDC_HLINK);
  81.   m_hArrowCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
  82. }
  83. CHLinkCtrl::~CHLinkCtrl()
  84. {
  85. }
  86. void CHLinkCtrl::SetHyperLink(const CString& sActualLink)
  87. {
  88. SetActualHyperLink(sActualLink);
  89. }
  90. void CHLinkCtrl::SetHyperLinkDescription(const CString& sDescription)
  91. {
  92.   SetWindowText(sDescription);
  93. }
  94. CString CHLinkCtrl::GetHyperLinkDescription() const
  95. {
  96.   CString sDescription;
  97.   GetWindowText(sDescription);
  98.   return sDescription;
  99. }
  100. void CHLinkCtrl::SetActualHyperLink(const CString& sActualLink)
  101. {
  102. m_sActualLink = sActualLink;
  103. }
  104. BOOL CHLinkCtrl::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
  105. {
  106.   if (m_bShowingContext)
  107.     ::SetCursor(m_hArrowCursor);
  108.   else
  109.    ::SetCursor(m_hLinkCursor);
  110. return TRUE;
  111. }
  112. void CHLinkCtrl::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) 
  113. {
  114.   PostMessage(WM_COMMAND, ID_POPUP_OPEN);
  115. }
  116. void CHLinkCtrl::OnOpen()
  117. {
  118.   if (Open())
  119.   m_State = ST_VISITED;
  120. }
  121. void CHLinkCtrl::SetLinkColor(const COLORREF& color) 
  122. m_Color = color; 
  123. UpdateWindow(); 
  124. }
  125. void CHLinkCtrl::SetVisitedLinkColor(const COLORREF& color) 
  126. m_VisitedColor = color; 
  127. UpdateWindow(); 
  128. }
  129. void CHLinkCtrl::SetHighlightLinkColor(const COLORREF& color) 
  130. m_HighlightColor = color; 
  131. UpdateWindow(); 
  132. }
  133. void CHLinkCtrl::OnMouseMove(UINT nFlags, CPoint point) 
  134. {
  135.   if (!m_bUseHighlight)
  136.     return;
  137. CRect rc;
  138. GetClientRect(rc);
  139. if (rc.PtInRect(point))
  140. {
  141. if (m_State != ST_HIGHLIGHTED)
  142. {
  143. SetCapture();
  144. HighLight(TRUE);
  145. }
  146. else
  147. {
  148. if (m_State == ST_HIGHLIGHTED)
  149. {
  150. HighLight(FALSE);
  151. ReleaseCapture();
  152. }
  153. }
  154. CStatic::OnMouseMove(nFlags, point);
  155. }
  156. void CHLinkCtrl::HighLight(BOOL state)
  157. {
  158. if (state)
  159. {
  160. if (m_State != ST_HIGHLIGHTED)
  161. {
  162. m_OldState = m_State;
  163. m_State = ST_HIGHLIGHTED;
  164. Invalidate();
  165. }
  166. }
  167. else
  168. {
  169. if (m_State == ST_HIGHLIGHTED)
  170. {
  171. m_State = m_OldState;
  172. Invalidate();
  173. }
  174. }
  175. }
  176. void CHLinkCtrl::OnContextMenu(CWnd*, CPoint point)
  177. {
  178.   if (!m_bAllowContextMenu)
  179.     return;
  180.   HighLight(FALSE);
  181. ReleaseCapture();
  182.   
  183. if (point.x == -1 && point.y == -1)
  184.   { //keystroke invocation CRect rect; GetClientRect(rect); ClientToScreen(rect); point = rect.TopLeft(); point.Offset(5, 5); } CMenu menu; VERIFY(menu.LoadMenu(IDR_HLINK_POPUP)); CMenu* pPopup = menu.GetSubMenu(0); ASSERT(pPopup != NULL); CWnd* pWndPopupOwner = this;
  185.   m_bShowingContext = TRUE; pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, pWndPopupOwner);
  186.   m_bShowingContext = FALSE;
  187. }
  188. void CHLinkCtrl::OnCopyShortcut() 
  189. {
  190.   if (OpenClipboard())
  191.   {
  192.     int nBytes = sizeof(TCHAR) * (m_sActualLink.GetLength() + 1);
  193.     HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nBytes);
  194.     TCHAR* pData = (TCHAR*) GlobalLock(hMem);
  195.     _tcscpy(pData, (LPCTSTR) m_sActualLink);
  196.     GlobalUnlock(hMem);
  197.    SetClipboardData(CF_TEXT, hMem);
  198.     CloseClipboard();
  199.   }
  200. }
  201. void CHLinkCtrl::OnProperties() 
  202. {
  203. ShowProperties();
  204. }
  205. void CHLinkCtrl::ShowProperties() const
  206. {
  207. CHLinkSheet propSheet(IDS_HLINK_PROPERTIES, this->GetParent());
  208.   propSheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;
  209.   propSheet.SetBuddy(this);
  210.   propSheet.DoModal();
  211. }
  212. BOOL CHLinkCtrl::Open() const
  213. {
  214.   CWaitCursor cursor;
  215. #ifndef HLINK_NOOLE
  216.   //First try to open using IUniformResourceLocator
  217.   BOOL bSuccess = OpenUsingCom();
  218.   
  219.   //As a last resort try ShellExecuting the URL, may
  220.   //even work on Navigator!
  221.   if (!bSuccess)
  222.     bSuccess = OpenUsingShellExecute();
  223. #else
  224.   BOOL bSuccess = OpenUsingShellExecute();
  225. #endif
  226.   return bSuccess;
  227. }
  228. #ifndef HLINK_NOOLE
  229. BOOL CHLinkCtrl::OpenUsingCom() const
  230. {
  231.   //Get the URL Com interface
  232.   IUniformResourceLocator* pURL;
  233.   HRESULT hres = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (void**) &pURL);
  234.   if (!SUCCEEDED(hres))
  235.   {
  236.     TRACE("Failed to get the IUniformResourceLocator interfacen");
  237.     return FALSE;
  238.   }
  239.   hres = pURL->SetURL(m_sActualLink, IURL_SETURL_FL_GUESS_PROTOCOL);
  240.   if (!SUCCEEDED(hres))
  241.   {
  242.     TRACE("Failed in call to SetURLn");
  243.     pURL->Release();
  244.     return FALSE;
  245.   }
  246.   //Open the URL by calling InvokeCommand
  247.   URLINVOKECOMMANDINFO ivci;
  248.   ivci.dwcbSize = sizeof(URLINVOKECOMMANDINFO);
  249.   ivci.dwFlags = IURL_INVOKECOMMAND_FL_ALLOW_UI;
  250.   ivci.hwndParent = GetParent()->GetSafeHwnd();
  251.   ivci.pcszVerb = "open";
  252.   hres = pURL->InvokeCommand(&ivci);
  253.   if (!SUCCEEDED(hres))
  254.   {
  255.     TRACE("Failed to invoke URL using InvokeCommandn");
  256.     pURL->Release();
  257.     return FALSE;
  258.   }
  259.   // Release the pointer to IUniformResourceLocator.
  260.   pURL->Release();
  261.   return TRUE;
  262. }
  263. #endif
  264. BOOL CHLinkCtrl::OpenUsingShellExecute() const
  265. {
  266. HINSTANCE hRun = ShellExecute(GetParent()->GetSafeHwnd(), _T("open"), m_sActualLink, NULL, NULL, SW_SHOW);
  267.   if ((int) hRun <= 32)
  268.   {
  269.     TRACE("Failed to invoke URL using ShellExecuten");
  270.     return FALSE;
  271.   }
  272.   return TRUE;
  273. }
  274. #ifndef HLINK_NOOLE
  275. BOOL CHLinkCtrl::AddToSpecialFolder(int nFolder) const
  276. {
  277.   //Give the user some feedback
  278.   CWaitCursor cursor;
  279.   // Get the shell's allocator. 
  280.   IMalloc* pMalloc;
  281.   if (!SUCCEEDED(SHGetMalloc(&pMalloc))) 
  282.   {
  283.     TRACE("Failed to get the shell's IMalloc interfacen");
  284.     return FALSE;
  285.   }
  286.   //Get the location of the special Folder required
  287.   LPITEMIDLIST pidlFolder;
  288.   HRESULT hres = SHGetSpecialFolderLocation(NULL, nFolder, &pidlFolder); 
  289.   if (!SUCCEEDED(hres))
  290.   {
  291.     TRACE("Failed in call to SHGetSpecialFolderLocationn");
  292.     pMalloc->Release();
  293.     return FALSE;
  294.   }
  295.   //convert the PIDL to a file system name and
  296.   //add an extension of URL to create an Internet 
  297.   //Shortcut file
  298.   TCHAR sFolder[_MAX_PATH];
  299.   if (!SHGetPathFromIDList(pidlFolder, sFolder))
  300.   {
  301.     TRACE("Failed in call to SHGetPathFromIDList");
  302.     pMalloc->Release();
  303.     return FALSE;
  304.   }
  305.   TCHAR sShortcutFile[_MAX_PATH];  
  306.   CString sLinkDescription;
  307.   GetWindowText(sLinkDescription);
  308.   _tmakepath(sShortcutFile, NULL, sFolder, sLinkDescription, _T("URL"));
  309.   //Free the pidl
  310.   pMalloc->Free(pidlFolder);
  311.   //Do the actual saving
  312.   BOOL bSuccess = Save(sShortcutFile);
  313.   // Release the pointer to IMalloc
  314.   pMalloc->Release(); 
  315.   return bSuccess;
  316. }
  317. #endif
  318. #ifndef HLINK_NOOLE
  319. void CHLinkCtrl::OnAddToFavorites() 
  320. {
  321.   AddToSpecialFolder(CSIDL_FAVORITES);
  322. #endif
  323. #ifndef HLINK_NOOLE
  324. void CHLinkCtrl::OnAddToDesktop() 
  325. {
  326.   AddToSpecialFolder(CSIDL_DESKTOP);
  327. #endif
  328. #ifndef HLINK_NOOLE
  329. BOOL CHLinkCtrl::Save(const CString& sFilename) const
  330. {
  331.   //Get the URL Com interface
  332.   IUniformResourceLocator* pURL;
  333.   HRESULT hres = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (void**) &pURL);
  334.   if (!SUCCEEDED(hres))
  335.   {
  336.     TRACE("Failed to get the IUniformResourceLocator interfacen");
  337.     return FALSE;
  338.   }
  339.   hres = pURL->SetURL(m_sActualLink, IURL_SETURL_FL_GUESS_PROTOCOL);
  340.   if (!SUCCEEDED(hres))
  341.   {
  342.     TRACE("Failed in call to SetURLn");
  343.     pURL->Release();
  344.     return FALSE;
  345.   }
  346.   // Get the IPersistFile interface for 
  347.   // saving the shortcut in persistent storage.
  348.   IPersistFile* ppf;
  349.   hres = pURL->QueryInterface(IID_IPersistFile, (void **)&ppf);
  350.   if (!SUCCEEDED(hres))
  351.   {
  352.     TRACE("Failed to get the IPersistFile interfacen");
  353.     pURL->Release();
  354.     return FALSE;
  355.   }
  356.   // Save the shortcut via the IPersistFile::Save member function.
  357.   #ifndef _UNICODE
  358.   WORD wsz[_MAX_PATH];
  359.   MultiByteToWideChar(CP_ACP, 0, sFilename, -1, wsz, _MAX_PATH);
  360.   hres = ppf->Save(wsz, TRUE);
  361.   #else
  362.   hres = ppf->Save(sFilename, TRUE);
  363.   #endif
  364.   if (!SUCCEEDED(hres))
  365.   {
  366.     TRACE("IPersistFile::Save failed!n");
  367.     ppf->Release();
  368.     pURL->Release();
  369.     return FALSE;
  370.   }
  371.   // Release the pointer to IPersistFile.
  372.   ppf->Release();
  373.   // Release the pointer to IUniformResourceLocator.
  374.   pURL->Release();
  375.   return TRUE;
  376. #endif
  377. #ifdef _DEBUG
  378. HBRUSH CHLinkCtrl::CtlColor(CDC* pDC, UINT nCtlColor) 
  379. #else
  380. HBRUSH CHLinkCtrl::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
  381. #endif
  382. {
  383. ASSERT(nCtlColor == CTLCOLOR_STATIC);
  384. DWORD dwStyle = GetStyle();
  385. if (!(dwStyle & SS_NOTIFY)) 
  386.   {
  387. // Turn on notify flag to get mouse messages and STN_CLICKED.
  388. // Otherwise, I'll never get any mouse clicks!
  389. ::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle | SS_NOTIFY);
  390. }
  391. HBRUSH hbr = NULL;
  392. if ((dwStyle & 0xFF) <= SS_RIGHT) 
  393.   {
  394. // Modify the font to be underline
  395.     if (!((HFONT) m_font))
  396.     {
  397.   LOGFONT lf;
  398.   GetFont()->GetObject(sizeof(lf), &lf);
  399.   lf.lfUnderline = TRUE;
  400.   m_font.CreateFontIndirect(&lf);
  401.     }
  402. pDC->SelectObject(&m_font);
  403.     //set the text colors
  404.     switch (m_State)
  405.     {
  406.   case ST_NOT_VISITED: pDC->SetTextColor(m_Color); break;
  407.   case ST_VISITED:    pDC->SetTextColor(m_VisitedColor); break;
  408.   case ST_HIGHLIGHTED: pDC->SetTextColor(m_HighlightColor); break;
  409.       default: ASSERT(FALSE);
  410.     }
  411. pDC->SetBkMode(TRANSPARENT);
  412. // return hollow brush to preserve parent background color
  413. hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
  414. }
  415. return hbr;
  416. }
  417. /*IMPLEMENT_DYNCREATE(CHLinkPage, CPropertyPage)
  418. CHLinkPage::CHLinkPage() : CPropertyPage(CHLinkPage::IDD)
  419. {
  420. //{{AFX_DATA_INIT(CHLinkPage)
  421. //}}AFX_DATA_INIT
  422.   m_pBuddy = NULL;
  423. }
  424. CHLinkPage::~CHLinkPage()
  425. {
  426. }
  427. void CHLinkPage::DoDataExchange(CDataExchange* pDX)
  428. {
  429. CPropertyPage::DoDataExchange(pDX);
  430. //{{AFX_DATA_MAP(CHLinkPage)
  431. //}}AFX_DATA_MAP
  432. }
  433. BEGIN_MESSAGE_MAP(CHLinkPage, CPropertyPage)
  434. //{{AFX_MSG_MAP(CHLinkPage)
  435. //}}AFX_MSG_MAP
  436. END_MESSAGE_MAP()
  437. IMPLEMENT_DYNAMIC(CHLinkSheet, CPropertySheet)
  438. CHLinkSheet::CHLinkSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
  439. :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
  440. {
  441.   AddPage(&m_page1);
  442. }
  443. CHLinkSheet::CHLinkSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
  444. :CPropertySheet(pszCaption, pParentWnd, iSelectPage)
  445. {
  446.   AddPage(&m_page1);
  447. }
  448. CHLinkSheet::~CHLinkSheet()
  449. {
  450. }
  451. BEGIN_MESSAGE_MAP(CHLinkSheet, CPropertySheet)
  452. //{{AFX_MSG_MAP(CHLinkSheet)
  453. //}}AFX_MSG_MAP
  454. END_MESSAGE_MAP()
  455. BOOL CHLinkPage::OnInitDialog() 
  456. {
  457. CPropertyPage::OnInitDialog();
  458. ASSERT(m_pBuddy);
  459.   GetDlgItem(IDC_NAME)->SetWindowText(m_pBuddy->GetHyperLinkDescription());
  460.   GetDlgItem(IDC_URL)->SetWindowText(m_pBuddy->GetActualHyperLink());
  461. return TRUE;
  462. }
  463. */