Click here to Skip to main content
15,881,709 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
changing only selected text color not entire text in CEDIT control of mfc
Posted
Comments
Sandeep Mewara 13-Jun-12 5:51am    
And the issue/question is?

Hi,

According to my understanding, character formatting is not available with MFC CEdit control. If you changed the text color of CEdit control, it will affect the entire string. For this purpose better to use Rich Edit Controls, it had this functionality http://msdn.microsoft.com/en-us/library/06832atz.aspx[^]. If you want to stick with CEdit control, you may need to use some difficult logic. For example using "GetSel" method to find the selected string then find the co-ordinate positions and use "TextOut" method, but am not sure about this.
 
Share this answer
 
Here is a solution for a single-line edit control ... will implement multi-line later

void CODEdit::OnPaint()
{
	// Prepare to draw
	CPaintDC dc(this); 
	CRect rClient;
	GetClientRect(&rClient);
	DWORD dwStyle = GetStyle();
	CString cstrText;
	GetWindowText(cstrText);

	// Double buffer 
	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);
	CBitmap bmp;
	bmp.CreateDiscardableBitmap(&dc, 
		rClient.Width(), rClient.Height());
	dcMem.SelectObject(bmp);
	dcMem.SelectObject(GetFont());

	// Draw border
	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);

	// Draw text
	CRect rTxt = rClient;
	UINT nFormat = DT_LEFT|DT_TOP|DT_SINGLELINE;
	// Handle margins
	DWORD dwMargins = GetMargins();
	rTxt.InflateRect(-LOWORD(dwMargins), 0, -HIWORD(dwMargins), 0);
	rTxt.InflateRect(-1,-1,-1,-1);
	// Handle selected text
	DWORD dwSel = GetSel();
	int iStartSel = LOWORD(dwSel);
	int iEndSel = HIWORD(dwSel);

	if((iStartSel == 0) && (iEndSel == 0))
	{
		// No selection, just draw
		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());
		}
	}

	// Update the screen
	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);
 
Share this answer
 
Comments
SonicMouse 13-Nov-13 15:48pm    
there are GDI memory leaks in this.

dcMem.SelectObject(bmp);
dcMem.SelectObject(GetFont());

You never select the old objects back in to the DC -- so the original DC can never delete them.

You do it correctly with the CPen object, though.

Oh, and CreateDiscardableBitmap() is depreciated.
JJMatthews 14-Nov-13 2:25am    
Ive always thought that the MFC GDI classes did that for you. I always watch my programs with the task manager to see if the Memory, Handles, and GDI objects increase. The classes seem to clean up all the handles. I will look into it more.
SonicMouse 16-Nov-13 2:47am    
Windows may babysit with GDI objects in MFC... I don't know. But MS still says (to this day) in the docs:

SelectObject():
This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.
JJMatthews 20-Nov-13 6:17am    
I wouldnt call it "baby sitting", objects are released/destroyed in class destructors. As a minimalist, if my handle and GDI object count does not increase in the task manager then that is good enough for me.

The purpose of the post was to demonstrate a method for drawing the inner portion (text) of an edit control. If someone wishes to use this method I would recommend that they format the code to fit the rest of their code (programming style).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900