引言
做用戶界面的時候經常要用到一些靜態文本控件,顯示一些文字信息,但是 MFC 提供的 CStatic類的功能過於簡單,無法滿足高級需求。為此我從 CStatic 派生了一個類 CLabelEx,擴展了CStatic。第一次投稿,水平不足請大家見諒。我從 vckbase.com 學到了很多很多東西 ,該是我回報的時候了。
一、功能簡介
新增的功能主要有:
1、設置背景圖片SetBGBitmap();設置鼠標經過時的背景圖片SetMouseOverBGBitmap();設置鼠標單擊後的背景圖片SetClickedBGBitmap();
2、設置標簽圖片,SetLabelBitmap();設置鼠標經過時的標簽圖片SetMouseOverLabelBitmap();設置鼠標單擊時的標簽圖片
3、文字功能
(1)設置字體顏色,下劃線等就不說了.
(2)感應鼠標經過時自動加上下劃線,自動把文字變藍(就像一個超鏈接一樣)
4、邊框和背景
可以設置/取消邊框,指定邊框顏色;設置背景色,並填充整個標簽
二、實現原理
1、其實就是在OnPaint()裡畫出各種效果:
void CLabelEx::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetTextColor(m_crText);
dc.SetBkMode(TRANSPARENT);
dc.SelectObject(this->GetFont());
///准備工作
CRect rect;
CDC MemDC;
CPen BorderPen,*pOldPen,UnderLinePen;
CBrush BGBrush,*pOldBrush;
BITMAP bm;
int nTextLeft=0,nTextTop=0; //文字輸出的位置
this->GetClientRect(&rect);
MemDC.CreateCompatibleDC(&dc);
MemDC.SetMapMode(dc.GetMapMode());
///畫邊框
if(m_bBorder)
{
BorderPen.CreatePen(PS_SOLID,1,m_crBorder);
BGBrush.CreateSolidBrush(m_crBG);
pOldPen=dc.SelectObject(&BorderPen);
pOldBrush=dc.SelectObject(&BGBrush);
dc.Rectangle(&rect);
dc.SelectObject(pOldPen);
dc.SelectObject(pOldBrush);
rect.DeflateRect(1,1);
}
///貼背景圖
if(m_bClicked && m_ClickedBGBm.GetSafeHandle()!=NULL)
{
MemDC.SelectObject(m_ClickedBGBm);
dc.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),
&MemDC,0,0,SRCCOPY);
}
else if(m_bOver && m_MouseOverBGBm.GetSafeHandle()!=NULL)//鼠標經過的時候
{
MemDC.SelectObject(m_MouseOverBGBm);
dc.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),
&MemDC,0,0,SRCCOPY);
}
else if(m_BGBm.GetSafeHandle()!=NULL)
{
MemDC.SelectObject(m_BGBm);
dc.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),
&MemDC,0,0,SRCCOPY);
}
///貼標簽圖片
if(m_bClicked && m_ClickedLabelBm.GetSafeHandle()!=NULL)
{
m_ClickedLabelBm.GetBitmap(&bm);
double fScal=bm.bmWidth*1.0/bm.bmHeight;
nTextLeft=int(rect.Height()*fScal)+4;
MemDC.SelectObject(m_ClickedLabelBm);
dc.StretchBlt(rect.left,rect.top,int(rect.Height()*fScal),rect.Height(),
&MemDC,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
}
else if(m_bOver && m_MouseOverLabelBm.GetSafeHandle()!=NULL)
{
m_MouseOverLabelBm.GetBitmap(&bm);
double fScal=bm.bmWidth*1.0/bm.bmHeight;
nTextLeft=int(rect.Height()*fScal)+4;
MemDC.SelectObject(m_MouseOverLabelBm);
dc.StretchBlt(rect.left,rect.top,int(rect.Height()*fScal),rect.Height(),
&MemDC,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
}
else if(m_LabelBm.GetSafeHandle()!=NULL)
{
m_LabelBm.GetBitmap(&bm);
double fScal=bm.bmWidth*1.0/bm.bmHeight;
nTextLeft=int(rect.Height()*fScal)+4;
MemDC.SelectObject(m_LabelBm);
dc.StretchBlt(rect.left,rect.top,int(rect.Height()*fScal),rect.Height(),
&MemDC,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
}
else
{
nTextLeft=4;
}
///輸出文字
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CString strText;
this->GetWindowText(strText);
nTextTop=rect.top+(rect.Height()-tm.tmHeight)/2;
if(strText.GetLength()>0)
{
dc.TextOut(nTextLeft,nTextTop,strText);
}
///畫下劃線
if(m_bUnderLine)
{
nTextLeft-=2;
nTextTop=nTextTop+tm.tmHeight+1;
UnderLinePen.CreatePen(PS_SOLID,1,m_crUnderLine);
pOldPen=dc.SelectObject(&UnderLinePen);
dc.MoveTo(nTextLeft,nTextTop);
dc.LineTo(nTextLeft+tm.tmAveCharWidth*strText.GetLength(),nTextTop);
}
}
注:對字體加下劃線我沒有使用直接設置字體下劃線的方法,因為我覺得那樣不好看,呵呵
2、感應鼠標用的方法如下所示:
在MouseMove裡SetCapture()和ReleaseCapture();
void CLabelEx::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (m_bOver) // Cursor is currently over control
{
CRect rect;
GetClientRect(rect);
if (!rect.PtInRect(point))
{
m_bOver = FALSE;
if(m_bAutoUnderLine) ///自動下劃線
{
this->SetUnderLine(FALSE,RGB(0,0,0));
}
if(m_bHighLight) //自動高亮
{
///恢復原來的字體顏色
this->SetTextColor(m_crBackText);
}
RedrawWindow();
ReleaseCapture();
return;
}
}
else // Cursor has just moved over control
{
m_bOver = TRUE;
if(m_bAutoUnderLine)
{
this->SetUnderLine(TRUE,RGB(0,0,255));
}
if(m_bHighLight)
{
m_crBackText=m_crText;
this->SetTextColor(RGB(0,0,255));
}
RedrawWindow();
SetCapture();
::SetCursor(m_hHandCur);
}
CStatic::OnMouseMove(nFlags, point);
}
注:這種方法簡單方便,但是有一個問題,看附帶的工程,單擊Label1彈出一個對話框後Label1無法恢復原狀。我一直沒解決這個問題.若誰知道請告知我 [email protected]