三、程序代码
//////////////////////////////////////////////////////////////////////////// #ifndef _HYPRILNK_H #define _HYPRILNK_H // Simple text hyperlink derived from CString class CHyperlink : public CString { public: CHyperlink(LPCTSTR lpLink = NULL) : CString(lpLink) { } ~CHyperlink() { } const CHyperlink& operator=(LPCTSTR lpsz) { CString::operator=(lpsz); return *this; } operator LPCTSTR() { return CString::operator LPCTSTR(); } virtual HINSTANCE Navigate() { return IsEmpty() ? NULL : ShellExecute(0, _T("open"), *this, 0, 0, SW_SHOWNORMAL); } }; #endif ///////////////////////////////////////////////////////////////////////////////// #ifndef _STATLINK_H #define _STATLINK_H #include "HyprLink.h" class CStaticLink : public CStatic { public: DECLARE_DYNAMIC(CStaticLink) CStaticLink(LPCTSTR lpText = NULL, BOOL bDeleteOnDestroy=FALSE); ~CStaticLink() { } // Hyperlink contains URL/filename. If NULL, I will use the window text. // (GetWindowText) to get the target. CHyperlink m_link; COLORREF m_color; // Default colors you can change // These are global, so they're the same for all links. static COLORREF g_colorUnvisited; static COLORREF g_colorVisited; static HCURSOR g_hCursorLink; protected: CFont m_font; // underline font for text control BOOL m_bDeleteOnDestroy; // delete object when window destroyed? virtual void PostNcDestroy(); // message handlers DECLARE_MESSAGE_MAP() afx_msg UINT OnNcHitTest(CPoint point); afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); }; #endif _STATLINK_H ///////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "StatLink.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif COLORREF CStaticLink::g_colorUnvisited = RGB(0,0,255); // blue COLORREF CStaticLink::g_colorVisited = RGB(128,0,128); // purple HCURSOR CStaticLink::g_hCursorLink = NULL; IMPLEMENT_DYNAMIC(CStaticLink, CStatic) BEGIN_MESSAGE_MAP(CStaticLink, CStatic) ON_WM_NCHITTEST() ON_WM_CTLCOLOR_REFLECT() ON_WM_LBUTTONDOWN() ON_WM_SETCURSOR() END_MESSAGE_MAP() /////////////////// // Constructor sets default colors = blue/purple. // bDeleteOnDestroy is used internally by PixieLib in CPixieDlg. CStaticLink::CStaticLink(LPCTSTR lpText, BOOL bDeleteOnDestroy) { m_link = lpText; // link text (NULL ==> window text) m_color = g_colorUnvisited; // not visited yet m_bDeleteOnDestroy = bDeleteOnDestroy; // delete object with window? } ////////////////// // Normally, a static control does not get mouse events unless it has // SS_NOTIFY. This achieves the same effect as SS_NOTIFY, but it's fewer // lines of code and more reliable than turning on SS_NOTIFY in OnCtlColor // because Windows doesn't send WM_CTLCOLOR to bitmap static controls. // UINT CStaticLink::OnNcHitTest(CPoint point) { return HTCLIENT; }
////////////////// // Handle reflected WM_CTLCOLOR to set custom control color. // For a text control, use visited/unvisited colors and underline font. // For non-text controls, do nothing. Also ensures SS_NOTIFY is on. // HBRUSH CStaticLink::CtlColor(CDC* pDC, UINT nCtlColor) { ASSERT(nCtlColor == CTLCOLOR_STATIC); DWORD dwStyle = GetStyle();
HBRUSH hbr = NULL; if ((dwStyle & 0xFF) <= SS_RIGHT) {
// this is a text control: set up font and colors if (!(HFONT)m_font) { // first time init: create font LOGFONT lf; GetFont()->GetObject(sizeof(lf), &lf); lf.lfUnderline = TRUE; m_font.CreateFontIndirect(&lf); } // use underline font and visited/unvisited colors pDC->SelectObject(&m_font); pDC->SetTextColor(m_color); pDC->SetBkMode(TRANSPARENT); // return hollow brush to preserve parent background color hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH); } return hbr; } ///////////////// // Handle mouse click: navigate link // void CStaticLink::OnLButtonDown(UINT nFlags, CPoint point) { if (m_link.IsEmpty()) { // no link: try to load from resource string or window text m_link.LoadString(GetDlgCtrlID()) || (GetWindowText(m_link),1); if (m_link.IsEmpty()) return; } // Call ShellExecute to run the file. // For an URL, this means opening it in the browser. // HINSTANCE h = m_link.Navigate(); if ((UINT)h > 32) { // success! m_color = g_colorVisited; // change color Invalidate(); // repaint } else { MessageBeep(0); // unable to execute file! TRACE(_T("*** WARNING: CStaticLink: unable to navigate link %s/n"),(LPCTSTR)m_link); } }
////////////////// // Set "hand" cursor to cue user that this is a link. If app has not set // g_hCursorLink, then try to get the cursor from winhlp32.exe, // resource 106, which is a pointing finger. This is a bit of a kludge, // but it works. // BOOL CStaticLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (g_hCursorLink == NULL) { static bTriedOnce = FALSE; if (!bTriedOnce) { CString windir; GetWindowsDirectory(windir.GetBuffer(MAX_PATH), MAX_PATH); windir.ReleaseBuffer(); windir += _T("//winhlp32.exe"); HMODULE hModule = LoadLibrary(windir); if (hModule) { g_hCursorLink = CopyCursor(::LoadCursor(hModule, MAKEINTRESOURCE(106))); } FreeLibrary(hModule); bTriedOnce = TRUE; } } if (g_hCursorLink) { ::SetCursor(g_hCursorLink); return TRUE; } return FALSE; }
////////////////// // Normally, a control class is not destoyed when the window is; // however, CPixieDlg creates static controls with "new" instead of // as class members, so it's convenient to allow the option of destroying // object with window. In applications where you want the object to be // destoyed along with the window, you can call constructor with // bDeleteOnDestroy=TRUE. // void CStaticLink::PostNcDestroy() { if (m_bDeleteOnDestroy) delete this; } //////////////////////////////////////////////////////////////////////////////
#include "stdafx.h" #include "resource.h" #include "TraceWin.h" #include "StatLink.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif class CMyDialog : public CDialog { public: CMyDialog(CWnd* pParent = NULL); ~CMyDialog(); //protected: private: HICON m_hIcon; CStaticLink m_wndLink1; // web links CStaticLink m_wndLink2; // the button cursor HCURSOR m_hButtonCursor; virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg); DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMyDialog, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_SETCURSOR() END_MESSAGE_MAP()
CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/) : CDialog(IDD_MYDIALOG, pParent) {}
CMyDialog::~CMyDialog() {}
////////////////// // Initialize dialog // BOOL CMyDialog::OnInitDialog() { CDialog::OnInitDialog(); // set up hyperlinks m_wndLink1.m_link = _T("http://www.vckbase.com"); m_wndLink2.m_link = _T("mailto:vckbase@public.hk.hi.cn"); m_wndLink1.SubclassDlgItem(IDC_PDURL, this); m_wndLink2.SubclassDlgItem(IDC_MSDNURL, this); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // load button cursor m_hButtonCursor = AfxGetApp()->LoadCursor(IDC_MYHAND); return TRUE; // return TRUE unless you set the focus to a control }
////////////////// // Set cursor if mouse is over a button. // BOOL CMyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg) { CString sClassName; ::GetClassName(pWnd->GetSafeHwnd(),sClassName.GetBuffer(80),80); if (sClassName=="Button" && m_hButtonCursor) { ::SetCursor(m_hButtonCursor); return TRUE; } return CDialog::OnSetCursor(pWnd, nHitTest, msg); } |
四、小结
本文不仅介绍了动态改变程序中的鼠标形状,还介绍了如何实现静态文本的超连接,读者朋友可以将这部分代码修改后应用到自己开放的应用程序中,例如在程序中添加自己的网页和邮箱地址等,我想这一定是件很令人鼓舞的事情吧。 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |