Here is a solution for a single-line edit control ... will implement multi-line later
void CODEdit::OnPaint()
{
CPaintDC dc(this);
CRect rClient;
GetClientRect(&rClient);
DWORD dwStyle = GetStyle();
CString cstrText;
GetWindowText(cstrText);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmp;
bmp.CreateDiscardableBitmap(&dc,
rClient.Width(), rClient.Height());
dcMem.SelectObject(bmp);
dcMem.SelectObject(GetFont());
CPen penBorder;
penBorder.CreatePen(PS_SOLID, 1, m_crBorder);
CPen* pOldPen = dcMem.SelectObject(&penBorder);
dcMem.FillSolidRect(rClient, m_crBack);
dcMem.Rectangle(rClient);
dcMem.SelectObject(pOldPen);
CRect rTxt = rClient;
UINT nFormat = DT_LEFT|DT_TOP|DT_SINGLELINE;
DWORD dwMargins = GetMargins();
rTxt.InflateRect(-LOWORD(dwMargins), 0, -HIWORD(dwMargins), 0);
rTxt.InflateRect(-1,-1,-1,-1);
DWORD dwSel = GetSel();
int iStartSel = LOWORD(dwSel);
int iEndSel = HIWORD(dwSel);
if((iStartSel == 0) && (iEndSel == 0))
{
dcMem.DrawText(cstrText, cstrText.GetLength(), rTxt, nFormat);
}
else
{
int iCurX = rTxt.left;
int iStartChar = 0;
int iEndChar = (iStartSel == 0 ? iEndSel : iStartSel);
while(iStartChar < cstrText.GetLength())
{
CString cstrPart = cstrText.Mid(iStartChar, (iEndChar - iStartChar));
BOOL bSel = (iStartChar == iStartSel);
dcMem.SetTextColor(bSel ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) : ::GetSysColor(COLOR_WINDOWTEXT));
dcMem.SetBkColor(bSel ? ::GetSysColor(COLOR_HIGHLIGHT) : m_crBack);
CRect rSel = rTxt;
rSel.left = iCurX;
dcMem.DrawText(cstrPart, cstrPart.GetLength(), rSel, nFormat);
iCurX += dcMem.GetTextExtent(cstrPart, cstrPart.GetLength()).cx;
iStartChar = iEndChar;
iEndChar = ((iStartChar == iStartSel) ? iEndSel : cstrText.GetLength());
}
}
dc.BitBlt(0, 0, rClient.Width(), rClient.Height(), &dcMem, 0, 0, SRCCOPY);
}
The colors (type COLORREF)are member variables of my class, I would set them like this: ... looks nice
m_crBorder = RGB(128,160,192);
m_crBack = RGB(255,255,255);