Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1392
  • Last Modified:

OnCtlColor problem...

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
bbousquet
Asked:
bbousquet
  • 5
  • 2
  • 2
1 Solution
 
naveenkohliCommented:
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
 
naveenkohliCommented:
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
 
bbousquetAuthor Commented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
bbousquetAuthor Commented:
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
 
bbousquetAuthor Commented:
Oops. Sorry for the double-comment.
0
 
RONSLOWCommented:
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
 
bbousquetAuthor Commented:
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
 
bbousquetAuthor Commented:
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
 
RONSLOWCommented:
Thank you .. it often helps to see what MFC does itself.
0

Featured Post

Technology Partners: 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!

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now