編輯框是常用控件之一,同時也是一種完全自實作較為繁瑣的控件。本例實作了對編輯框的簡單的自繪制,在保留其自身的強大功能的前提下,實作了編輯框的邊框、背景、文字顔色以及禁用态的各種顔色的替換。
要想重繪,我們必須知道要繪什麼。通過觀察預設的編輯框我們可以很清楚的看到編輯框有三個最基礎的部分需要我們繪制,他們分别是3D邊框、背景和文字,再進一步分析我們會發現他們是一個基本視窗的兩個部分,即客戶區和非客戶區。這樣一來我們就知道應該用什麼函數有針對性的繪制什麼區域了,由于提供了源碼,這裡僅就基本原理和技術細節加以讨論,不過多地羅列代碼。
為了繪制非客戶區,我重載了OnNcPaint函數,通過這個函數可以很輕松的去掉編輯框3D外觀,畫成我們自己想要的形式。至于客戶區,為了保留編輯框光标閃爍、字元處理、自動回行等功能,我并未重載OnPaint函數。也就是說我并未重繪客戶區,而是選擇了一個替代的辦法。
我們使用編輯框,用的就是它的文本編輯功能,而我們想要改變的隻是文字及背景顔色。通過這種分析我們就會很清楚我們需要做的事情,那就是設定文字顔色和背景色。我用的方法是重載CtlColor函數,在其中根據編輯框禁用和啟用的不同狀态,設定了不同的顔色,很好的實作了預期目的。
從嚴格意義上來說,我并沒有對編輯框重繪,隻是簡單的繪制了邊緣,但同樣很好的實作預期的效果。當然這個例子還有許多的不盡人意的地方,如果大家有更好的方還希望我們一同交流。
1. 主要實作内容
顯示主要有: 邊框, 背景, 文字顔色, 禁用态的各種顔色.
2. 邊框
邊框可以通過重載OnNCPaint實作.
例如:
void CMyEdit::OnNcpaint()
{
CRect rect, rc;
CDC* pDC;
int nSaveDC;
pDC = GetWindowDC();
GetWindowRect(&rect);
rect -= rect.TopLoeft();
rc = rect;
rc.InflateRect(-GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
nSaveDC = pDC->SaveDC();
pDC->ExcludeClipRect(&rc);
pDC->FillSolidRect(&rect, RGB(255,255,255));
pDC->RestoreDC(nSaveDC);
pDC->FrameRect(&rect, &CBrush(150,150,150));
ReleaseDC(pDC);
}
3. 背景
背景可以通過重載OnEraseBkgnd實作
BOOL CMyEdit::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return 0;
return CEdit::OnEraseBkgnd(pDC);
}
你也可以貼圖:
BOOL CMyEdit::OnEraseBkgnd(CDC* pDC)
{
//TODO: 在此添加消息處理程式代碼和/或調用預設值
CDC memDC;
memDC.CreateCompatibleDC(pDC);
HBITMAP hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), "C:\\res\\bmp00001.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
CBitmap* pBmp = CBitmap::FromHandle(hBitmap);
memDC.SelectObject(pBmp);
BITMAP bitMap;
pBmp->GetBitmap(&bitMap);
CRect rect;
GetClientRect(&rect);
//拉伸貼圖
pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, bitMap.bmWidth, bitMap.bmHeight, SRCCOPY);
memDC.DeleteDC();
return TRUE;
//return CEdit::OnEraseBkgnd(pDC);
}
4. 字型顔色
HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetBkMode(TRANSPARENT); // 透明
pDC->SetTextColor(RGB(255, 255, 255)); // 字型色彩
return (HBRUSH)GetStockObject(DKGRAY_BRUSH); // 字型背景(OnEraseBkgnd隻是避免閃爍)
}
這裡需要注意的是,設定透明是在=WM_CTLCOLOR裡設定的,不是在WM_CTLCOLOR中.
有=的是從父視窗反射回來的消息.當然也可以在父視窗的WM_CTLCOLOR中設定透明,不過這樣就封裝得不好了.