Solved

OnCtlColor problem...

Posted on 2000-02-23
9
1,292 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
  • 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
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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 100 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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

840 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