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. The 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 Edit Box, 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 modifed 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 I need a COLORREF to change the background color of the device context. A problem I ran into was that 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, that remember m_wndEdit is the control, not a string containing the window text. To access the text, you will have to use the proper funtions for the control (such as 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, use 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
Jan 21 2005 – Update
- Fixed Bugs
- Added SetBackColor and SetTextColor functions
Jan 18 2005 – Posted
- Basic bontrol, changed background color to white