Skip to main content
Email Password   helpLost your password?

Introduction

This is my first article. So bear with me. I know it is a simple control but I spent quite a lot of time figuring this out. I hope someone can read this and figure it out quicker.

The Problem

I needed a read-only text box. I created one using the CEdit control. Problem was that, it had a grey background. There is no option or function to change it directly.

The Solution

I derived a class from CEdit called CReadOnlyEdit. I intercepted the background ON_WM_CTLCOLOR_REFLECT() message. This message's function looks like this:

HBRUSH CReadOnlyEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	// TODO: Return a non-NULL brush if the parent's 

	//handler should not be called

	return NULL;
}

To change the background color of the EditBox, instead of returning NULL for the function above, I returned a brush with the color I wanted for the background. Also if you notice in the function, above one of the parameters is a pointer to the Device Context (pDC) of the control. I used the pDC->SetTextColor(COLORREF rgb) function to change the text color. I then ran into a slight problem. The background changed to the correct color and the text did as well but the background of the text stayed white. This was a simple fix. I simply set the background color of the text using pDC->SetBkColor(COLORREF rgb) function. This is my modified function:

HBRUSH CReadOnlyEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	// TODO: Return a non-NULL brush if the parent's 

	//handler should not be called


	//set text color

	pDC->SetTextColor(m_crText);

	//set the text's background color

	pDC->SetBkColor(m_crBackGnd);

  //return the brush used for background this sets control background

  return m_brBackGnd;
}

As you can see my control has three variables: COLORREF m_crText, COLORREF m_crBackGnd, and CBrush m_brBackGnd. I added two functions to my control, one to change the background color (and update the brush) and one to change the text color. Those two functions look like this:

void CReadOnlyEdit::SetBackColor(COLORREF rgb)
{
	//set background color ref (used for text's background)

	m_crBackGnd = rgb;
	
	//free brush

	if (m_brBackGnd.GetSafeHandle())
       m_brBackGnd.DeleteObject();
	//set brush to new color

	m_brBackGnd.CreateSolidBrush(rgb);
	
	//redraw

	Invalidate(TRUE);
}
void CReadOnlyEdit::SetTextColor(COLORREF rgb)
{
  //set text color ref

  m_crText = rgb;

  //redraw

  Invalidate(TRUE);
}

The reason I have a COLORREF background variable is because to change the background color of the device context I need a COLORREF. A problem I ran into was, the entire edit control was not being colored right away, this is why I added the Invalidate(TRUE) call to repaint the control.

That's all there was to it. By the way, my control doesn't set a background or text color by default. This can easily be done in the constructor.

Using the code

Dialog Based:

Create a CEdit control. Control double-click it. The Add Member Variable dialog appears. Choose Control for the Category and CEdit for the variable type. Set the variable name to something like m_wndEdit. When modifying the control, remember m_wndEdit is the control not a string containing the window text. To access the text you will have to use the proper functions for the control (ie. CEdit::SetWindowText()).

Programmatically:

The simplest way I can think of to use this is just change all the CEdit controls you want to be read-only to CReadOnlyEdit.

Changing the colors:

To change the background and text color of the control using the SetBack Color(COLORREF rgb) and SetTextColor(COLORREF rgb) functions. In the demo I use a CColorDialog to get a color. The following is code from my demo. It is located in the Change Back Color button's click function:

void CReadOnlyDlg::OnBack() 
{	
	// call color dialog and change background color

	CColorDialog dlg;
	if (dlg.DoModal() == IDOK)
		m_wndReadOnly.SetBackColor(dlg.GetColor());
	
}

Where m_wndReadOnly is the CReadOnlyEdit control.

Note: My control doesn't set the read-only flag, you have to do this yourself in the CReadOnlyEdit::Create function or in the dialog control properties. Also, this can be done with the CEdit::SetReadOnly(BOOL) function.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionReadonly Textbox inside the GroupBox Control Pin
razhia
17:34 11 Nov '09  
GeneralMandou ver! Pin
L4U80Y
9:11 9 Nov '09  
Generalhaha Pin
caolvchong
19:14 17 Dec '08  
GeneralMuch easier and quicker method Pin
mr. bleh
10:45 30 Oct '07  
GeneralThank you Pin
miniiiii
19:40 29 Jul '07  
GeneralThank you Pin
compex
11:11 8 Jan '07  
QuestionHow to implement this in WTL Pin
CodeFundu
0:46 18 Mar '06  
QuestiontextColor stays grayed when Ctrl is disabled Pin
FriendOfAsherah
23:22 11 Mar '06  
QuestionChaning the font in ReadOnlyEdit Pin
bcamp
12:50 3 Mar '06  
GeneralHow does it work. Pin
CastleIsle
9:05 17 Feb '06  
GeneralHow to make CReadOnlyEdit in MFC ClassWizard ? Pin
krya
0:43 2 Feb '06  
GeneralRe: How to make CReadOnlyEdit in MFC ClassWizard ? Pin
CastleIsle
8:29 17 Feb '06  
Generalmerci Pin
quicksoft
20:45 15 Dec '05  
GeneralAll this for what? Here is one liner to accomplish the same. Pin
the_gurudev
19:07 29 Nov '05  
GeneralRe: All this for what? Here is one liner to accomplish the same. Pin
chiona
14:41 18 Dec '07  
Generalinitializing background- and textcolor without control variable Pin
mekanoo
14:35 9 Sep '05  
GeneralText Background Pin
Brian (BH)
1:37 28 Jan '05  
GeneralRe: Text Background Pin
bob16972
9:04 8 Nov '05  
GeneralGreat first article! Pin
Hans Dietrich
15:05 19 Jan '05  
GeneralHow to do it in c# Pin
nagarsoft
11:08 19 Jan '05  
GeneralRe: How to do it in c# Pin
W. Kleinschmit
23:05 19 Jan '05  
GeneralRe: How to do it in c# Pin
Anonymous
5:42 2 Aug '05  


Last Updated 18 Jan 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009