Codwiz51's Wiki

RSS

Navigation







Quick Search
»
Advanced Search »
This article applies to windows applications coded using WTL and Visual Studio 2008.

Update: I've but together an example WTL dialog that implements this code. Click here to download the sample program: WTLEditCtrlExample.7z

My apologies to those that tried to download the program, the wiki code didn't handle an image and an anchor properly. It may have had something to do with upgrading to a later version.

WTL CTLCOLOREDIT Sample

I've noticed that there are a lot of questions about how to change the text and background color of a Windows edit control. An excellent article has been written on code project, which utilizes a custom class and handles the WM_PAINT message: "A WTL Dim Edit Control". This is a nice article. However, I want to show you two different approaches. Both utilize the WM_CTLCOLOREDIT message.

The first method uses a class derived from WTL's CEdit class:

// Make sure {{#include atlcrack.h}} is in your stdafx.h header
// A simple extended class that allows you to set the foregound
// and background color of an edit control.  Make sure you
// place REFLECT_NOTIFICATIONS in your message map.
class CEditEx : public CWindowImpl< CEditEx, CEdit >

{
	BEGIN_MSG_MAP(CEditEx)
		MSG_OCM_CTLCOLOREDIT(OnCtlColorEdit);
	END_MSG_MAP()

public:
	HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit);
};

HBRUSH CEditEx::OnCtlColorEdit(CDCHandle dc, CEdit edit)
{
	dc.SetTextColor( (COLORREF) RGB(0, 0, 200) );

	return HBRUSH( GetStockObject( WHITE_BRUSH ) ) ;
}

You can wire this into your project by placing the following macro in your message map: REFLECT_NOTIFICATIONS();. You'll notice I've used the WTL message crack macro to handle the reflected WM_CTLCOLOREDIT message (OCM_CTLCOLOREDIT). The advantage of using the derived class is that you can define private variables for the foreground and background colors of the text box. It allows the control to be self-contained, with the only external code being the reflect macro. The example program illustrates this approach.

The next method handles the WM_CTLCOLOREDIT message directly in the dialog's message map:

// MainDlg.h code
BEGIN_MSG_MAP(CMainDlg)
	...
	MSG_WM_CTLCOLOREDIT(OnDlgCtlColorEdit);
	...
END_MSG_MAP()

public:
	HBRUSH OnDlgCtlColorEdit(CDCHandle dc, CEdit edit);

// MainDlg.cpp code
HBRUSH CMainDlg::OnDlgCtlColorEdit(CDCHandle dc, CEdit edit)

{
	// Only handle message for file destination edit control
	if (edit == GetDlgItem(ID_OF_EDIT_CONTROL))
	{
		dc.SetTextColor( (COLORREF) RGB(200, 0, 0) );

	}
	else
		// Turn off message handled boolean
		// This allows the message to pass down to
		// be reflected.
		SetMsgHandled(FALSE);

	// Must return an HBRUSH
	return HBRUSH( GetStockObject( WHITE_BRUSH ) ) ;

}

Why did I add a test for the Id of the edit control? Well, I discovered while working with this code that if you did not set the message handled bool to false, then all of the WM_CTLCOLOREDIT messages are eaten, whether you handle them or not. This is important if you want to handle some colors through a derived edit class and some in the dialog:

BEGIN_MSG_MAP(CMainDlg)
	...
	MSG_WM_CTLCOLOREDIT(OnDlgCtlColorEdit);
	REFLECT_NOTIFICATIONS();
	...
END_MSG_MAP()

Unless OnDlgCtlColorEdit sets the message handled bool to false, REFLECT_NOTIFICATIONS() will never see the WM_CTLCOLOREDIT messages and will not reflect them to the derived class' message map. Download the code here.

ScrewTurn Wiki version 3.0.2.509. Some of the icons created by FamFamFam.