?
Solved

OnCtlColor problem...

Posted on 2000-02-23
9
Medium Priority
?
1,354 Views
Last Modified: 2013-11-20
Basically, here goes:

CGraphicalComponent derives from CDialog
CColorStatic derives from CStatic

I want to change the foreground and background colors of a dialog box derived from CGraphicalComponent. CGraphicalComponent has two member variables (m_crefBackground and m_crefForeground) containing the appropriate colors to be used. It also creates a brush called m_brushBackground using CreateSolidBrush(m_crefBackground).

I have trapped WM_CTLCOLOR within CGraphicalComponent:

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

    return m_brushBackground;

//    return hbr;
}

This works ok with most controls (I had to write some more code for my push buttons but that is correct as push buttons do behave differently). However, my particular problem lies in the fact that one of my dialog's controls is a CColorStatic object (derived from CStatic) which needs to have its own background/foreground color.

Thus, I trapped the WM_CTLCOLOR_REFLECT message in the following handler:

HBRUSH CColorStatic::CtlColor(CDC* pDC, UINT nCtlColor)
{
    pDC->SetTextColor(m_crefForeground);
    pDC->SetBkColor(m_crefBackground);

    return (HBRUSH)m_brushBackground;
}

* Note that those m_crefForeground and m_crefBackground members are NOT the same as the ones from CGraphicalComponent - and their values are set through CColorStatic member functions in their parent dialog's WM_INITDIALOG handler.

--

The problem is, obviously, that the calling order is as follows:

1. CGraphicalComponent::OnCtlColor calls CDialog::OnCtlColor
2. CDialog::OnCtlColor reflects the message to the control
3. CColorStatic::CtlColor does its thing
4. CDialog::OnCtlColor returns the brush from CColorStatic::CtlColor if the reflection was trapped - otherwise it returns the default system brush for background painting (gray)
5. CGraphicalComponent::OnCtlColor ignores all of this and returns a custom background brush

---

Basically, here's what I want:

I want all my controls to use the custom brush from CGraphicalComponent BUT not the CColorStatic ones, which have their own background brush.

The only way I was able to make this work was by adding the following check at the beginning of CGraphicalComponent::OnCtlColor :

if(hbr == (HBRUSH)Default()) {
    return m_brushBackground;
}
else {
    return hbr;
}

..and although that solves the background brush problem, it does not help as far as textcolor/textbackground go (in the CColorStatic). The two SetTextColor and SetBkColor commands in CColorStatic::CtlColor are simply useless and my text defaults to typical black on gray.
0
Comment
Question by:bbousquet
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 2
  • 2
9 Comments
 
LVL 23

Expert Comment

by:naveenkohli
ID: 2552504
Why didn't you make check on nCtlColor parameter...

if (nCtlColor == CTLCOLOR_STATIC) {
// Do the didley for static control
}
else {
// go homer
}

Hope it helps.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 2552530
Here is sample code from my application.. I am setting the text color only for static control.. You can return a differetn color brush for background.


HBRUSH COptionsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
      HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
      
      switch (nCtlColor) {
            case CTLCOLOR_EDIT:
                  if (pWnd == &m_HorizNumEdit) {
                        pDC->SetTextColor (RGB (255, 255, 0));
                  }
                  break;
            case CTLCOLOR_STATIC:
                  pDC->SetTextColor (RGB(255, 255, 0));
                  break;
            default:
                  break;
      }
      
      // TODO: Return a different brush if the default is not desired
      return hbr;
}
0
 
LVL 2

Author Comment

by:bbousquet
ID: 2552552
Thanks but it doesn't solve my problem. CGraphicalComponent has absolutely no idea of the CColorStatic's colors. I have been able to get my desired behavior using the following:

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

    CBrush *pBrush = CBrush::FromHandle(hbr);
    if(pBrush != NULL) {
        LOGBRUSH logBrush;
        if(pBrush->GetLogBrush(&logBrush)) {
            if((logBrush.lbStyle == BS_SOLID                  ) &&
               (logBrush.lbColor == GetSysColor(COLOR_BTNFACE))   ) {
                pDC->SetBkColor  (m_crefBackground);
                pDC->SetTextColor(m_crefForeground);
                return m_brushBackground;
            }
        }
    }

    return hbr;
}

[I find this horrible but it is, in my own opinion, nicer than a dynamic_cast]

Any ideas, anyone?

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 2

Author Comment

by:bbousquet
ID: 2552624
Thanks but it doesn't solve my problem. CGraphicalComponent has absolutely no idea of the CColorStatic's colors. I have been able to get my desired behavior using the following:

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

    CBrush *pBrush = CBrush::FromHandle(hbr);
    if(pBrush != NULL) {
        LOGBRUSH logBrush;
        if(pBrush->GetLogBrush(&logBrush)) {
            if((logBrush.lbStyle == BS_SOLID                  ) &&
               (logBrush.lbColor == GetSysColor(COLOR_BTNFACE))   ) {
                pDC->SetBkColor  (m_crefBackground);
                pDC->SetTextColor(m_crefForeground);
                return m_brushBackground;
            }
        }
    }

    return hbr;
}

[I find this horrible but it is, in my own opinion, nicer than a dynamic_cast]

Any ideas, anyone?

0
 
LVL 2

Author Comment

by:bbousquet
ID: 2552627
Oops. Sorry for the double-comment.
0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 400 total points
ID: 2552804
How about this...

HBRUSH CGraphicalComponent::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
  LRESULT lResult;
  if (pWnd->SendChildNotifyLastMsg(&lResult)) {
    return (HBRUSH)lResult;
  }
  // do whatever you want for
  // everything else
  //
}
0
 
LVL 2

Author Comment

by:bbousquet
ID: 2553274
That's a pretty good idea. That looks a lot like what the CDialog does internally and I hadn't thought of moving that up to CGraphicalComponent.

I'll try this tomorrow and I'll get back to you after that. But I'm pretty sure you'll get your points!

Thanks!
0
 
LVL 2

Author Comment

by:bbousquet
ID: 2555120
RONSLOW,

I just tested your proposed answer and it works perfectly.

Thank you very much for an accurate and prompt answer.

Grade A awarded.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2556185
Thank you .. it often helps to see what MFC does itself.
0

Featured Post

Learn how to optimize MySQL for your business need

With the increasing importance of apps & networks in both business & personal interconnections, perfor. has become one of the key metrics of successful communication. This ebook is a hands-on business-case-driven guide to understanding MySQL query parameter tuning & database perf

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month9 days, 13 hours left to enroll

762 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