1.設(shè)計(jì)原理
CStatic類是從CWnd類繼承出來的一個(gè)靜態(tài)文本框類,它對(duì)應(yīng)靜態(tài)文本框控件。靜態(tài)文本框控件常用來在對(duì)話框上顯示軟件信息或者是提示信息。本例采用重載CStatic類的方法,用類的成員函數(shù)完成上面的功能。
2.具體實(shí)現(xiàn)
使用類向?qū)梢粋€(gè)基類為CStatic的CHyperLinker類。
在CHyperLinker.h文件中,添加類的如下成員變量:
// Attributes
public:
COLORREF m_InitColor; // 超級(jí)鏈接開始時(shí)的文本顏色
COLORREF m_VisitedColor; // 超級(jí)鏈接被訪問過的的文本顏色
COLORREF m_CoverColor; // 鼠標(biāo)移動(dòng)到超級(jí)鏈接文本框上的文本顏色
BOOL m_bAboveControl; // 記錄當(dāng)前鼠標(biāo)是否停留在超級(jí)鏈接上方
BOOL m_bVisited; // 記錄超級(jí)鏈接是否被訪問過
BOOL m_bUnderLine; // 文本是否帶下劃線
CString m_sURL; // URL信息
CFont m_Font; // 字體
HCURSOR m_hLinkCursor; // 鼠標(biāo)形狀
在CHyperLinker.h文件中,添加類的如下成員函數(shù)聲明:
// Operations
public:
// 設(shè)置對(duì)應(yīng)文本框?qū)傩灾?/p>
void SetAttrbute(CString url = "www.baidu.com", COLORREF InitColor = RGB(0,0,255),
COLORREF VisitedColor = RGB(255,0,0),
COLORREF CoverColor = RGB(125,125,0), BOOL bUnderLine = TRUE);
// shell 外部的程序
BOOL OpenUsingShellExecute();
// 設(shè)置字體
void SetFont(CFont *font);
// Generated message map functions
protected:
//{{AFX_MSG(CHyperLinker)
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
在CHyperLinker.cpp中添加如下的函數(shù)定義:
CHyperLinker::CHyperLinker()
{
m_bAboveControl = FALSE;
m_bUnderLine = FALSE;
m_bVisited = FALSE;
}
CHyperLinker::~CHyperLinker()
{
}
BEGIN_MESSAGE_MAP(CHyperLinker, CStatic)
//{{AFX_MSG_MAP(CHyperLinker)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHyperLinker message handlers
void CHyperLinker::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect rect;
GetClientRect(rect); // 得到當(dāng)前文本框的矩形區(qū)域
static BOOL bIsIn = FALSE; // 判斷前一次鼠標(biāo)是否已經(jīng)在文本框區(qū)域
if (rect.PtInRect(point)) // 在區(qū)域內(nèi)
{
m_bAboveControl = TRUE; // 記錄鼠標(biāo)已經(jīng)停留在超級(jí)鏈接文本框的上方
if (!bIsIn) // 如果是第一次停留,則用其他顏色重繪文本
{
SetCapture(); // 設(shè)置鼠標(biāo)捕獲
bIsIn = TRUE;
Invalidate(); // 調(diào)用CtrlColor重繪文本
}
}
else
{
m_bAboveControl = FALSE; // 記錄鼠標(biāo)不在超級(jí)鏈接文本框的上方
if (bIsIn) // 如果是第一次離開區(qū)域,則用其他顏色重繪文本
{
ReleaseCapture(); // 釋放鼠標(biāo)捕獲
bIsIn = FALSE;
Invalidate(); // 調(diào)用CtrlColor重繪文本
}
}
CStatic::OnMouseMove(nFlags, point);
}
void CHyperLinker::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
OpenUsingShellExecute(); // shell外部程序
m_bVisited = TRUE; // 表示應(yīng)經(jīng)點(diǎn)擊過超級(jí)鏈接文本框
Invalidate(); // 調(diào)用CtrlColor重繪文本
CStatic::OnLButtonDown(nFlags, point);
}
BOOL CHyperLinker::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: Add your message handler code here and/or call default
HCURSOR LinkCurlor = ::AfxGetApp()->LoadCursor(IDC_CUR_HAND);
::SetCursor(LinkCurlor);
return TRUE;
return CStatic::OnSetCursor(pWnd, nHitTest, message);
}
HBRUSH CHyperLinker::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
ASSERT(nCtlColor == CTLCOLOR_STATIC);
DWORD dwStyle = GetStyle();
if (!(dwStyle & SS_NOTIFY))
{
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle | SS_NOTIFY);
}
HBRUSH hbr = NULL;
if ((dwStyle & 0xFF) <= SS_RIGHT)
{
// modify the font to be underline
if (!((HFONT)m_Font))
{
LOGFONT lf;
GetFont()->GetObject(sizeof(lf), &lf);
lf.lfUnderline = m_bUnderLine;
m_Font.CreateFontIndirect(&lf);
}
pDC->SelectObject(&m_Font);
// set the text color
if (m_bVisited)
{
pDC->SetTextColor(m_VisitedColor);
}
else
{
if (m_bAboveControl)
{
pDC->SetTextColor(m_CoverColor);
}
else
{
pDC->SetTextColor(m_InitColor);
}
}
pDC->SetBkMode(TRANSPARENT);
hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
}
// TODO: Return a non-NULL brush if the parent's handler should not be called
return hbr;
}
void CHyperLinker::SetAttrbute(CString url, COLORREF InitColor, COLORREF VisitedColor,
COLORREF CoverColor, BOOL bUnderLine)
{
m_sURL = url;
m_InitColor = InitColor;
m_VisitedColor = VisitedColor;
m_CoverColor = CoverColor;
m_bUnderLine = bUnderLine;
}
BOOL CHyperLinker::OpenUsingShellExecute()
{
HINSTANCE hRun = ShellExecute(GetParent()->GetSafeHwnd(),
_T("open"), m_sURL, NULL, NULL, SW_SHOW);
if((int)hRun <= 32)
{
AfxMessageBox(_T("提供的超級(jí)鏈接或者指定的文件無法執(zhí)行"), MB_OK, 0);
return FALSE;
}
return TRUE;
}
void CHyperLinker::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
DWORD dwStyle = GetStyle();
::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY); // 設(shè)置動(dòng)態(tài)窗口屬性
CStatic::PreSubclassWindow();
}
void CHyperLinker::SetFont(CFont *font)
{
// 設(shè)置字體
memcpy(&m_Font, font, sizeof(CFont));
// 根據(jù)字體的長(zhǎng)度和寬度設(shè)置靜態(tài)框的長(zhǎng)度和寬度
CDC *pDC = GetDC();
CFont *pOldfont = pDC->SelectObject(&m_Font);
CString str;
GetWindowText(str);
CSize size = pDC->GetTextExtent(str, str.GetLength());
SetWindowPos(NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE);
pDC->SelectObject(pOldfont);
ReleaseDC(pDC);
}
注:IDC_CUR_HAND是自己添加的鼠標(biāo)資源,Windows NT 5.0以后的版本可已使用IDC_HAND
3.應(yīng)用實(shí)例
利用MFC AppWizard 生成一個(gè)基于對(duì)話框的項(xiàng)目,在對(duì)話框上添加三個(gè)Static控件,修改ID分別為IDC_LINKER、IDC_LOCALFILE和IDC_NET,用Class Wizard 為這三個(gè)控件生成3個(gè)CHyperLinker對(duì)象,在對(duì)話框InitDialog函數(shù)中添加如下的代碼:
// TODO: Add extra initialization here
m_linker.SetAttrbute("http://blog.sina.com.cn/luoshuquan108");// 鏈接到我的博客
m_localfile.SetAttrbute("E:\\musics\\Helloween - Forever and One.mp3");// 打開本地文件
CFont *font = new CFont;
font->CreatePointFont(200, "微軟雅黑");
m_net.SetAttrbute("mailto:luoshuquan108@hotmail.com");// 給我發(fā)郵件
m_net.SetFont(font); // 設(shè)置字體
參考資料:《Visual C++ 網(wǎng)絡(luò)通信編程使用案例精選》 人民郵電出版社 丁展 劉海英等編著
ISBN-7-115-12164-8/TP·3903
聯(lián)系客服