Link to home
Start Free TrialLog in
Avatar of ied168i
ied168iFlag for United States of America

asked on

Text color of Child dialog editbox for MFC 6

How can I set the text color of an edit box on a dialog with the style of Child?  I have tried solutions using OnCtlColor in the dialog code but it never seems to get executed.  I am setting the values in the editbox from the MainFrm.cpp of the MDI project.  The dialog is always visible, not called like a temporary dialog.

Thanks for any help.
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi ied168i,

you're right, 'OnCtlColor' is the correct place to handle it. Take a look at the attached code: It causes all edit controls display their text green colored except 'IDC_EDIT_TEST' which displays the text in red.

Hope that helps,

ZOPPO
HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	if(nCtlColor == CTLCOLOR_EDIT)
	{
		UINT nID = pWnd->GetDlgCtrlID();
		switch(nID)
		{
		case IDC_EDIT_TEST:
			pDC->SetTextColor( RGB( 255, 0, 0 ) );
			break;
		default:
			pDC->SetTextColor( RGB( 0, 255, 0 ) );
			break;
		}
	}

	return hbr;
}

Open in new window

Avatar of ied168i

ASKER

Thanks for the response, I put it into the code for the dialog, still doesn't work.  I have also tried something like this before.  I have added AfxMessageBox("something") to the OnInitDialog and the added OnCtlColor in the code for the dialog but these never seem to get executed.  The dialog is brought up by a function called in CMainFrame::OnCreate as a child, not a popup using an 'if (dlgPixMap.DoModal() == IDOK)'.  The init for the dialog, or any other code in the class for the dialog, doesn't seem to ever be executed, maybe because of the way it is created and used or maybe a link got deleted during the development.  Can I color the text from outside the dialog code?  is there a way of intercepting the drawing of the editbox from outside of the dialog code?  Or what could be missing that would allow the dialog code to be executed?

Thanks for any help.
Hi again,

maybe you could post the complete code (or at least anything relevant to this problem)?

Did you add the 'OnCtlColor' manually or via ClassView/-Wizard? If manually please check if there's a 'ON_WM_CTLCOLOR()' entry in the message map.

>> Can I color the text from outside the dialog code?  is there a way of intercepting the drawing of the editbox from outside of the dialog code?

It might be possible to find a workaround for this, but I guess it would be much more difficult than finding the reason why your functions aren't called. 'OnInitDialog' should be called in any case, and using 'OnCtlColor' is the preferred way to do what you want to do ...

ZOPPO
Avatar of ied168i

ASKER

Thanks for your response.  I think you are right, it should be easier to solve the execution problem.

I did add the 'ON_WM_CTLCOLOR()' manually because it was not available in the Wizard(maybe there is a reason for that?).  The Dialog style is set to 'Child' in the properties.  I would think that the dialog code would be initialized when the dialog is loaded - is there somewhere I can look to find the chain of creation execution?  Maybe it is missing from the project?

The dialog has several buttons on it that are mapped in the app and view, these all work correctly.  It also has the edit boxes that I can successfully write values into - these are the ones I want to set the text color on.

The project is proprietary and large so I cannot post all code.

Thanks for your help.
Dialog's message map followed by 'OnCtlColor':

BEGIN_MESSAGE_MAP(EditPixelMap1, CDialog)
	//{{AFX_MSG_MAP(EditPixelMap1)
	ON_EN_CHANGE(IDA_EDITPIXMAP, OnChangeEditpixmap)
	ON_BN_CLICKED(IDC_PMSHOWDYN, OnPmshowdyn)
	ON_EN_CHANGE(IDC_EDIT1_PIXELS, OnChangeEdit1Pixels)
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
	ON_WM_CTLCOLOR()
END_MESSAGE_MAP()




HBRUSH EditPixelMap1::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
AfxMessageBox("OnCtlColor");	

	if(nCtlColor == CTLCOLOR_EDIT)
	{
		UINT nID = pWnd->GetDlgCtrlID();
		switch(nID)
		{
		case IDC_EDIT1_PIXELS:
			pDC->SetTextColor( RGB( 255, 0, 0 ) );
			break;
		default:
			pDC->SetTextColor( RGB( 0, 255, 0 ) );
			break;
		}
	}
	return hbr;
}



The dialog is created by the code below which is executed by the 'OnCreate' in the MainFrm.cpp for the project:

BOOL CMainFrame::CreatePMEditDialog()
{
	if (!m_wndPMEDlgBar.Create(this, IDB_EDITPIXMAP, CBRS_FLYBY, IDB_EDITPIXMAP))
	{
		TRACE0("Failed to create PixMapEdit dialog bar\n");
		return FALSE;      // fail to create
	}
	m_wndPMEDlgBar.SetWindowText(_T("Pixel Map Editor"));//title also used in CSunFlowerApp::PreTranslateMessage
	m_wndPMEDlgBar.EnableDocking(0);

	// Get previous position of PME toolbar
	CPoint pt;
	pt.x = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window7"), -1);
	pt.y = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window8"), -1);
	if ( (pt.x<0) || (pt.x>(GetSystemMetrics(SM_CXSCREEN)-50)) )
		pt.x = GetSystemMetrics(SM_CXSCREEN) - 300;
	if ( (pt.y<0) || (pt.y>(GetSystemMetrics(SM_CYSCREEN)-200)) )
		pt.y = 50;
	FloatControlBar(&m_wndPMEDlgBar, pt);

	CString szEdit;
	szEdit.Format("");
	SetPixelMapEditText(szEdit);

	return TRUE;
}

Open in new window

Hm - maybe the problem is somehow caused by the fact the dialog is a child of a control bar. I'm not quite sure about this, but it might be the control bar 'see's the WM_VTL_COLOR message first and, for any reason, doesn't pass it to the dialog.

How is the 'm_wndPMEDlgBar' implements? Which base class does it use? Could you post some of the creation code? If I know more about it maybe I'm able to reproduce it ...

And another question about the dialog: Do you have any of the styles DS_CONTROL and WS_EX_CONTROLPARENT declared for the dialog or the parent control bar?
Avatar of ied168i

ASKER

I have attached the code that creats the dialog.  The base class is CDialog, the message handler is the Child Window, per the classwizard.  I tried setting the message handler to Dialog but still no execution in the EditPixelMap1.cpp code.  In the MainFrm.h, m_wndPMEDlgBar is defined as a CDialogBar.  

Can you explain how the dialog can be a child of a control bar and where I could look to see this?  Where would the code be for it's parent control bar?

I also attached the section from the project .rc file for the dialog after the creation code, don't know if this helps.

I don't see where DS_CONTROL and WS_EX_CONTROLPARENT are declared for the dialog or parent control bar, may I haven't looked in the right place.  In the dialog properties there are no styles set.

Thanks for all of your help.
Creation code for the dialog:

BOOL CMainFrame::CreatePMEditDialog()
{
	if (!m_wndPMEDlgBar.Create(this, IDB_EDITPIXMAP, CBRS_FLYBY, IDB_EDITPIXMAP))
	{
		TRACE0("Failed to create PixMapEdit dialog bar\n");
		return FALSE;      // fail to create
	}
	m_wndPMEDlgBar.SetWindowText(_T("Pixel Map Editor"));//title also used in CSunFlowerApp::PreTranslateMessage
	m_wndPMEDlgBar.EnableDocking(0);

	// Get previous position of PME toolbar
	CPoint pt;
	pt.x = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window7"), -1);
	pt.y = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window8"), -1);
	if ( (pt.x<0) || (pt.x>(GetSystemMetrics(SM_CXSCREEN)-50)) )
		pt.x = GetSystemMetrics(SM_CXSCREEN) - 300;
	if ( (pt.y<0) || (pt.y>(GetSystemMetrics(SM_CYSCREEN)-200)) )
		pt.y = 50;
	FloatControlBar(&m_wndPMEDlgBar, pt);

	CString szEdit;
	szEdit.Format("");
	SetPixelMapEditText(szEdit);

	return TRUE;
}


Section of the .rc file for the project:

IDB_EDITPIXMAP DIALOGEX 0, 0, 156, 203
STYLE WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDA_EDITPIXMAP,7,6,89,190,ES_MULTILINE | ES_UPPERCASE | 
                    ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
    LTEXT           "Show:",IDC_STATIC,103,6,27,8
    PUSHBUTTON      "Raw",IDC_PMSHOWRAW,102,15,45,12
    PUSHBUTTON      "Origional PM",IDC_PMSHOWORIG,102,29,45,12
    PUSHBUTTON      "Current PM",IDC_PMSHOWCURR,102,43,45,12
    EDITTEXT        IDC_EDIT1_PIXELS,107,122,36,12,ES_AUTOHSCROLL,
                    WS_EX_TRANSPARENT
    LTEXT           "Pixels",IDC_STATIC,102,114,30,8
    EDITTEXT        IDC_EDIT1_ROWS,107,144,35,12,ES_AUTOHSCROLL
    LTEXT           "Rows",IDC_STATIC,102,136,32,8
    EDITTEXT        IDC_EDIT1_COLUMNS,107,165,35,12,ES_AUTOHSCROLL
    LTEXT           "Columns",IDC_STATIC,102,157,33,8
    EDITTEXT        IDC_EDIT1_LINES,107,184,36,12,ES_AUTOHSCROLL
    LTEXT           "Lines",IDC_STATIC,103,176,31,8
    CONTROL         "Dynamic",IDC_PMSHOWDYN,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,104,100,43,10
    PUSHBUTTON      "Revt to Orig",IDC_PMREVERT,102,57,45,12
    PUSHBUTTON      "Save PM",IDC_PMSAVE,102,76,45,12
END

Open in new window

ok, I think now the case is clear: your dialog class isn't used at all (therefor even OnInitDialog isn't called). The dialog is handled within the CDialogBar (you only pass the dialog's resource ID to 'm_wndPMEDlgBar.Create') so you'll have to handle the WM_CTLCOLOR there too. To do so you'll have to derive a class from CDialogBar and use this for 'm_wndPMEDlgBar'. Then add the message handler in this new class.

Hope that helps,

ZOPPO
Avatar of ied168i

ASKER

Ok, I deleted the .cpp and .h files from the project, restarted VC, it said it couldn't find the file, I clicked 'remove' for both of them, so they are out of the project.  I used classwizard to create a new class, added the WM_INITDIALOG and WM_CTLCOLOR message handlers.  I put an AfxMessageBox("something") in each handler but still no response.  Is the create somehow not linking to the class that I created for the dialog?  Maybe my create statement is incorrect/missing something?

In your last post, you said "The dialog is handled within the CDialogBar (you only pass the dialog's resource ID to 'm_wndPMEDlgBar.Create') so you'll have to handle the WM_CTLCOLOR there too." - this would be the MainFrm.ccp?   I don't see WM_CTLCOLOR listed for this class in the classwizard.  If I add it manually, it also doesn't seem to be executed.

The help for CDialogBar >> Dialog Bar Topics, says that "Dialog bars are extensions to a main window and any dialog-bar control-notification messages, such as BN_CLICKED or EN_CHANGE, will be sent to the parent of the dialog bar — the main window." - same as above.

I attached the OnCtlColor that I added.  I also added 'ON_WM_CTLCOLOR()' as the last entry in the message map.  If I replace the 'HBRUSH hbr = CMainFrame::OnCtlColor(pDC ....' with 'HBRUSH hbr = CDialog::OnCtlColor(pDC...', I get an error that 'cannot access protected member declared in class 'CDialog' '

Thanks for all of your help.
HBRUSH CMainFrame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CMainFrame::OnCtlColor(pDC, pWnd, nCtlColor);

AfxMessageBox("CMainFrame::OnCtlColor");

	return hbr;
}

Open in new window

I guess you again created your class based on CDialog since the ClassWizard doesn't provide a CDialogBar as base class when creating a new class for a dialog resource.

But you can do this manually: Within the created CDialog derived class replace all occurances of 'CDialog' with 'CDialogBar' in both the header and the cpp file. Delete the auto-generated constructor of that class too both in header and cpp to avoid compilation error caused by mismatching constructor.

Next include the header of the new class in 'mainfrm.h' before the 'class CMainFrame' and replace the 'CDialogBar' for 'm_wndPMEDlgBar' with the new classes name.

Add a WM_CTLCOLOR message handler as usual to the new class (should be available vie ClassWizard) and implement it as shown above.

Thus it should work (at least it does in a test project I made from the scratch with these mentioned changes).

Hope that helps,

ZOPPO

Avatar of ied168i

ASKER

The OnCtlColor is still not being executed.  The base class is now CDialogBar in the classwizard class info tab.  I have attached the cpp and h files.  Once I manually changed the base class to CDialogBar, the WM_CTLCOLOR became available in the classwizard.  I added this but still no execution.

I have also attached the dialog bar creation code that resides in MainFrm.cpp - I am not clear about your statement: "and replace the 'CDialogBar' for 'm_wndPMEDlgBar' with the new classes name."  The m_wndPMEDlgBar is a type CDialogBar in the MainFrm.h.  And '#include "EditPixMapDlg1.h"' is above '#include "MainFrm.h"'.

Also, I am using MFC6 for this project, have not moved to .net yet, don't know if this is an issue either.

Thanks for all of your help.
File EditPixMapDlg1.cpp:

// EditPixMapDlg1.cpp : implementation file
//

#include "stdafx.h"
#include "SunFlower.h"
#include "EditPixMapDlg1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// EditPixMapDlg1 dialog


//EditPixMapDlg1::EditPixMapDlg1(CWnd* pParent /*=NULL*/)
//	: CDialogBar(EditPixMapDlg1::IDD, pParent)
EditPixMapDlg1::EditPixMapDlg1( /*=NULL*/)
	: CDialogBar()
{
	//{{AFX_DATA_INIT(EditPixMapDlg1)
	m_nPixelCount = _T("");
	m_nRows = _T("");
	m_nColumns = _T("");
	m_nLines = _T("");
	//}}AFX_DATA_INIT
}


void EditPixMapDlg1::DoDataExchange(CDataExchange* pDX)
{
	CDialogBar::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(EditPixMapDlg1)
	DDX_Text(pDX, IDC_EDIT1_PIXELS, m_nPixelCount);
	DDX_Text(pDX, IDC_EDIT1_ROWS, m_nRows);
	DDX_Text(pDX, IDC_EDIT1_COLUMNS, m_nColumns);
	DDX_Text(pDX, IDC_EDIT1_LINES, m_nLines);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(EditPixMapDlg1, CDialogBar)
	//{{AFX_MSG_MAP(EditPixMapDlg1)
	ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// EditPixMapDlg1 message handlers


HBRUSH EditPixMapDlg1::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialogBar::OnCtlColor(pDC, pWnd, nCtlColor);
	
	// TODO: Change any attributes of the DC here
AfxMessageBox("new OnCtlColor");	
	
	// TODO: Return a different brush if the default is not desired
	return hbr;
}


File EditPixMapDlg1.h:

#if !defined(AFX_EDITPIXMAPDLG1_H__32012004_3D66_4926_B51E_592053790141__INCLUDED_)
#define AFX_EDITPIXMAPDLG1_H__32012004_3D66_4926_B51E_592053790141__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EditPixMapDlg1.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// EditPixMapDlg1 dialog

class EditPixMapDlg1 : public CDialogBar
{
// Construction
public:
//	EditPixMapDlg1(CWnd* pParent = NULL);   // standard constructor
	EditPixMapDlg1();   // standard constructor

// Dialog Data
	//{{AFX_DATA(EditPixMapDlg1)
	enum { IDD = IDB_EDITPIXMAP };
	CString	m_nPixelCount;
	CString	m_nRows;
	CString	m_nColumns;
	CString	m_nLines;
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(EditPixMapDlg1)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{{AFX_MSG(EditPixMapDlg1)
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EDITPIXMAPDLG1_H__32012004_3D66_4926_B51E_592053790141__INCLUDED_)



Dialog bar creation code in MainFrm.cpp:

BOOL CMainFrame::CreatePMEditDialog()
{
	if (!m_wndPMEDlgBar.Create(this, IDB_EDITPIXMAP, CBRS_FLYBY, IDB_EDITPIXMAP))
	{
		TRACE0("Failed to create PixMapEdit dialog bar\n");
		return FALSE;      // fail to create
	}
	m_wndPMEDlgBar.SetWindowText(_T("Pixel Map Editor"));//title also used in CSunFlowerApp::PreTranslateMessage
	m_wndPMEDlgBar.EnableDocking(0);

	// Get previous position of PME toolbar
	CPoint pt;
	pt.x = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window7"), -1);
	pt.y = AfxGetApp()->GetProfileInt(_T("Settings"), _T("Window8"), -1);
	if ( (pt.x<0) || (pt.x>(GetSystemMetrics(SM_CXSCREEN)-50)) )
		pt.x = GetSystemMetrics(SM_CXSCREEN) - 300;
	if ( (pt.y<0) || (pt.y>(GetSystemMetrics(SM_CYSCREEN)-200)) )
		pt.y = 50;
	FloatControlBar(&m_wndPMEDlgBar, pt);

	CString szEdit;
	szEdit.Format("");
	SetPixelMapEditText(szEdit);

	return TRUE;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ied168i

ASKER

That is the clarification I was after.  And it works now!!

Thanks for all of your help!
You're welcome - I'm glad I could help ...

Have a nice day,

best regards,

ZOPPO