同濟大學 羅筱波 ---- 在當今的網絡時代,超聯接無所不在,在各種各樣的軟件上我們都可以看到它的存在,這幾乎成了一個必不可少的一項宣傳內容。如果能在自己的程序中加入一個超聯接,那么會使我們的程序帶上鮮明的網絡特征。但是在vc6.0中并沒有提供一個用于制作超聯接的控件,因此只有自己編寫實現此功能的程序。下面是本人編寫的一個實現超聯接的類,希望能與大家分享。
---- 制作思路是:從類CStatic 派生出一個子類CsuperLinkCtrl,然后為子類CsuperLinkCtrl加入適當的函數使其能響應鼠標的消息和實現超聯接的功能。制作過程如下:
---- 一、首先從類CStatic 派生出一個子類CsuperLinkCtrl,用classwizard生成的頭文件具體代碼如下:
class CSuperLinkCtrl : public CStatic { // Construction public: CSuperLinkCtrl(); CSuperLinkCtrl(COLORREF clickedtextcor,COLORREF moveontextcor,COLORREF ordinarytextcor); // Attributes public: COLORREF m_crText; //超聯接文本的顏色 // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSuperLinkCtrl) //}}AFX_VIRTUAL
// Implementation public: BOOL SetLinkAddress(CString linkaddress); //用于設置超聯接的地址 void MouseLeave(void); void MouseEnter(void); void SetLinkCursor(HCURSOR hCursor); //用于設置超聯接的鼠標形狀 void SetSuperLink(BOOL setlink); virtual ~CSuperLinkCtrl();
// Generated message map functions protected: CString m_linktext; // shell 調用的聯接參數 BOOL m_bClicked; // 鼠標是否單擊超聯接 HCURSOR m_hCursor; // 鼠標移動到超聯接上時的鼠標形狀 //{{AFX_MSG(CSuperLinkCtrl) 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); afx_msg void OnMouseMove(UINT nFlags, CPoint point); //}}AFX_MSG
DECLARE_MESSAGE_MAP() private: BOOL m_bcaptured; //捕捉鼠標移動 COLORREF m_clickedtextcor; //單擊超聯接后文本的顏色 COLORREF m_moveontextcor; //鼠標移動到超聯接時的文本的顏色 COLORREF m_ordinarytextcor; //未激活超聯接時文本的顏色 LOGFONT m_lf; CFont m_font; //超聯接上的文本的字體 };
---- 二、為類編寫實現文件
---- 在類的兩個重載構造函數中完成類的初始化工作
CSuperLinkCtrl::CSuperLinkCtrl() { m_bClicked=FALSE; m_bcaptured=FALSE; m_clickedtextcor=RGB(0,255,255); m_moveontextcor=RGB(0,255,0); m_ordinarytextcor=RGB(0,0,255); m_crText=m_ordinarytextcor; // 設置初始化字體顏色 ::GetObject((HFONT)GetStockObject (DEFAULT_GUI_FONT),sizeof(m_lf),&m_lf); //取得當前的缺省字體 m_lf.lfUnderline = TRUE; //為當前缺省字體加入下劃線 BOOL bCreated = m_font.CreateFontIndirect(&m_lf); // 創建超聯接字體 ASSERT(bCreated); m_hCursor=NULL; }
CSuperLinkCtrl::CSuperLinkCtrl(COLORREF clickedtextcor,COLORREF moveontextcor,COLORREF ordinarytextcor) { m_bClicked=FALSE; m_bcaptured=FALSE; m_clickedtextcor=clickedtextcor; m_moveontextcor=moveontextcor; m_ordinarytextcor=ordinarytextcor; m_crText=m_ordinarytextcor; // 設置初始化字體顏色 ::GetObject((HFONT)GetStockObject (DEFAULT_GUI_FONT),sizeof(m_lf),&m_lf); //取得當前的缺省字體 m_lf.lfUnderline = TRUE; //為當前缺省字體加入下劃線 BOOL bCreated = m_font.CreateFontIndirect(&m_lf); // 創建超聯接字體 ASSERT(bCreated); m_hCursor=NULL; } 在類的析構函數中刪除在類的構造函數中創建的字體 CSuperLinkCtrl::~CSuperLinkCtrl() { m_font.DeleteObject(); //刪除在類的構造函數中創建的字體 } 用classwizard為類加入如下消息映射并編寫消息映射函數 BEGIN_MESSAGE_MAP(CSuperLinkCtrl, CStatic) //{{AFX_MSG_MAP(CSuperLinkCtrl) ON_WM_CTLCOLOR_REFLECT() ON_WM_LBUTTONDOWN() ON_WM_SETCURSOR() ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() 編寫消息映射函數CtlColor()用于實現超聯接文本顏色的變化 HBRUSH CSuperLinkCtrl::CtlColor(CDC* pDC, UINT nCtlColor) { // TODO: Change any attributes of the DC here if (CTLCOLOR_STATIC == nCtlColor) { pDC->SelectObject(&m_font); pDC->SetTextColor(m_crText); pDC->SetBkMode(TRANSPARENT); } HBRUSH hBrush = ::CreateSolidBrush (GetSysColor(COLOR_3DFACE)); //創建一個刷子句柄 return hBrush; // 返回一個用來畫控件背景的刷子句柄 } 實現鼠標按下左鍵消息 void CSuperLinkCtrl::OnLButtonDown (UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_bClicked=TRUE; m_crText=m_clickedtextcor; //設置超聯接文本的顏色 RedrawWindow(); // 重畫控件實現超聯接文本顏色的變化 if(m_linktext!="") //如果設置了超聯接的地址則調用 ShellExecute函數實現超聯接 ShellExecute(NULL, "open", m_linktext, NULL, NULL, SW_SHOWNORMAL); CStatic::OnLButtonDown(nFlags, point); // 調用基類響應函數 }
設置超聯接文本上的鼠標形狀的消息映射函數 BOOL CSuperLinkCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: Add your message handler code here and/or call default if (m_hCursor) // 如果已取得光標句柄則設置新的鼠標形狀 { ::SetCursor(m_hCursor); return TRUE; } return CStatic::OnSetCursor(pWnd, nHitTest, message); }
設置超聯接文本上的光標句柄 void CSuperLinkCtrl::SetLinkCursor(HCURSOR hCursor) { m_hCursor = hCursor; } 響應鼠標移動消息 void CSuperLinkCtrl::OnMouseMove (UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default SetCapture(); // 捕捉鼠標 POINT mpoint; GetCursorPos(&mpoint); // 取得當前鼠標位置 CRect rect; GetWindowRect(&rect); // 取得控件的窗口大小 if(!rect.PtInRect(mpoint)) // 判斷鼠標是否在控件的窗口內 { // 鼠標不在控件的窗口內 m_bcaptured=FALSE; ReleaseCapture(); // 釋放鼠標捕捉 MouseLeave(); // 調用mouseleave()函數 return; } // 鼠標在控件的窗口內 if(m_bcaptured) // 如果鼠標在窗口內且已經被捕捉則返回 return; m_bcaptured=TRUE; MouseEnter(); //調用MouseEnter()函數 ReleaseCapture(); // 釋放鼠標捕捉 CStatic::OnMouseMove(nFlags, point); // 調用基類響應函數 } 在MouseEnter()和MouseLeave() 函數中設置鼠標進入和離開時的超聯接文本的顏色 void CSuperLinkCtrl::MouseEnter() { m_crText=m_bClicked? m_clickedtextcor : m_moveontextcor; RedrawWindow(); // 重畫控件實現超聯接文本顏色的變化 }
void CSuperLinkCtrl::MouseLeave() { m_crText=m_bClicked? m_clickedtextcor : m_ordinarytextcor; RedrawWindow(); // 重畫控件實現超聯接文本顏色的變化 }
在SetLinkAddress()函數中設置超聯接到地址 BOOL CSuperLinkCtrl::SetLinkAddress(CString linkaddress) { // 驗證地址的合法性 if(linkaddress.Find("http")!=-1) m_linktext=linkaddress; else if(linkaddress.Find("@")!=-1) m_linktext="mailto:"+linkaddress; else { MessageBox("Error: wrong superlink format"); m_linktext=""; return FALSE; } return TRUE; }
---- 由于static控件并不響應鼠標消息,所以還需在派生的子類中作些修改。下面函數是使static控件能響應鼠標消息的關鍵(因為通常static控件只能響應很少一部分消息)
void CSuperLinkCtrl::SetSuperLink(BOOL setlink) { if (setlink) // 此處必須加入ModifyStyle(), 使static控件能響應鼠標消息 ModifyStyle(0,SS_NOTIFY); else ModifyStyle(SS_NOTIFY,0); }
---- 至此類CsuperLinkCtrl已制作完成便可在其它程序中使用了。
---- 使用方法有兩種:一是用classwizard使一個static控件與一個CsuperLinkCtrl變量相關聯,另一種方法是定義一個CsuperLinkCtrl變量然后用SubclassDlgItem()使它與一個static控件相關聯。
---- 使用示例:
---- 首先將SuperLinkCtrl1.h和SuperLinkCtrl1.cpp加入到工程的目錄中,然后定義一個變量CSuperLinkCtrl m_test; 然后在對話框中加入一個static控件,設置其ID為IDC_STATICTEST,之后在對話框的OnInitDialog()函數中加入如下代碼即可
m_test.SubclassDlgItem(IDC_STATICTEST,this); // IDC_STATICTEST是一個需要子類化的static控件的ID m_test.SetSuperLink(TRUE); //設置控件為超聯接控件 m_test.SetLinkCursor(AfxGetApp()-> LoadCursor(IDC_CURSORHAND)); // 設置超聯接控件的鼠標形狀 m_test.SetLinkAddress("xxxx@citiz.net"); // 設置超聯接的地址
---- 怎么樣,趕緊試一下吧!
|