Solved

OnCtlColor problem...

Posted on 2000-02-23
9
1,302 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
has22 challenge 11 106
sum28 challenge 31 117
fizzArray2 challenge 1 101
ShiftLeft challenge 21 88
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…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
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.
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

713 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