Solved

Text color of Child dialog editbox for MFC 6

Posted on 2010-11-09
13
745 Views
Last Modified: 2012-05-10
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.
0
Comment
Question by:ied168i
  • 7
  • 6
13 Comments
 
LVL 30

Expert Comment

by:Zoppo
ID: 34100797
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

0
 

Author Comment

by:ied168i
ID: 34104128
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.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34109551
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
0
 

Author Comment

by:ied168i
ID: 34124896
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

0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34134278
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?
0
 

Author Comment

by:ied168i
ID: 34138152
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

0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 30

Expert Comment

by:Zoppo
ID: 34139712
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
0
 

Author Comment

by:ied168i
ID: 34140996
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

0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34144320
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

0
 

Author Comment

by:ied168i
ID: 34147638
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

0
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 34152836
>> I am not clear about your statement

I meant you'll have to use this class instead of CDialogBar in CMainFrame's declaration, i.e. if there's a line like this:

> CDialogBar m_wndPMEDlgBar;

you have to replace it with

> EditPixMapDlg1 m_wndPMEDlgBar;
0
 

Author Comment

by:ied168i
ID: 34157763
That is the clarification I was after.  And it works now!!

Thanks for all of your help!
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 34161971
You're welcome - I'm glad I could help ...

Have a nice day,

best regards,

ZOPPO
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
In Easy String Encryption Using CryptoAPI in C++ (http://www.experts-exchange.com/viewArticle.jsp?aid=1193) I described how to encrypt text and recommended that the encrypted text be stored as a series of hexadecimal digits -- because cyphertext may…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now