?
Solved

can not get CDDS_ITEMPREPAINT message with ListView control

Posted on 2003-03-06
8
Medium Priority
?
2,014 Views
Last Modified: 2013-12-03
My code will break at the return of CDDS_PREPAINT, but I never seem to get the CDDS_ITEMPREPAINT I expect.  Any ideas why this would happen?

  case NM_CUSTOMDRAW:
    {
      LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
      switch(lplvcd->nmcd.dwDrawStage)
      {
      case CDDS_PREPAINT:
        return CDRF_NOTIFYITEMDRAW;
      case CDDS_ITEMPREPAINT:
        lplvcd->clrText = RGB(0,255,0);
        lplvcd->clrTextBk = RGB(255,255,0);
        return CDRF_NEWFONT;
      case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
        return CDRF_DODEFAULT;
      }
      return CDRF_DODEFAULT;
    }
    return CDRF_DODEFAULT;
0
Comment
Question by:Kalvyn
[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
  • 4
  • 4
8 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 8090764
Are you getting any NM_CUSTOMDRAW notifs?  
Are you sure you called InitCommonControlsEx() correctly?
Show the code you use to create the control.
-- Dan
0
 

Author Comment

by:Kalvyn
ID: 8091013
Yes, I get the CDDS_PREPAINT as expected.  I don't get any other NM_CUSTOMDRAW messages after that, as if the CDRF_NOTIFYITEMDRAW is ignored.

  hWndListbox = CreateWindow(WC_LISTVIEW,"Orders",
    WS_CHILD|LVS_REPORT,
    0,0,0,0,
    hWnd, NULL, hInstance, NULL
    );
  if (hWndListbox == NULL)
  {
    app.MB("failed");
    return;
  }
ListView_SetExtendedListViewStyle(hWndListbox,LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
  if (!InitListViewColumns(hWndListbox))
  {
    DestroyWindow(hWndListbox);
    return;
  }
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8092012
You are not checking for other notifc.  I think you may be getting SubItem notifs and not detecting them.  If you ever send CDRF_DODEFAULT, that ends the sequence.  I'd add code like:

case NM_CUSTOMDRAW:
   {
     LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
     switch(lplvcd->nmcd.dwDrawStage)
     {
...
     default: //unexpected value in dwDrawStage
         ::MessageBox(0,"woops","bummer", IDOK );
         return CDRF_DODEFAULT;
     } // end of switch (dwDrawStage)
...

-- Dan
0
Get your Disaster Recovery as a Service basics

Disaster Recovery as a Service is one go-to solution that revolutionizes DR planning. Implementing DRaaS could be an efficient process, easily accessible to non-DR experts. Learn about monitoring, testing, executing failovers and failbacks to ensure a "healthy" DR environment.

 

Author Comment

by:Kalvyn
ID: 8092871
I tested for that with this code.  I only ever receive one NM_CUSTOMDRAW message altho I asked for CDRF_NOTIFYITEMDRAW.  Stepping the code I verified that CDDS_PREPAINT is executed, but no other messages are received.

  case NM_CUSTOMDRAW:
    lplvcd = (LPNMLVCUSTOMDRAW)lParam;
    app.debug(ltoa(lplvcd->nmcd.dwDrawStage,app.tmp,10));
    switch(lplvcd->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
      return CDRF_NOTIFYITEMDRAW;
    case CDDS_ITEMPREPAINT:
      lplvcd->clrText = RGB(0,255,0);
      lplvcd->clrTextBk = RGB(255,255,0);
      return CDRF_NEWFONT;
    case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
      lplvcd->clrText = RGB(0,255,0);
      lplvcd->clrTextBk = RGB(255,255,0);
      return CDRF_NEWFONT;
    default:
      app.debug(ltoa(lplvcd->nmcd.dwDrawStage,app.tmp,10));
    }
    return CDRF_DODEFAULT;

0
 
LVL 49

Accepted Solution

by:
DanRollins earned 750 total points
ID: 8094735
Is the code you posted directly in your WinProc?  The reason I ask is that with MFC, or some home-brewed foundation class, the actual return value must be stored into an external variable and the actual return value is a BOOL.  For instance, with MFC, we use:

BOOL CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
   ....
   *lResult= CDRF_NOTIFYITEMDRAW;
   return(1);

-- Dan
0
 

Author Comment

by:Kalvyn
ID: 8096139
I'm not using MFC.  It isn't in WinProc directly, however the ListView is a child control of a MDI window.  I have written a test case that works as expected when the ListView is a child windows of WinProc.  It does get the CDDS_PREPAINT so I would expected it to get the CDDS_ITEMPREPAINT as well.  It gets other messages required for the ListView such as NL_DBLCLK, NM_RCLICK, LVN_ITEMCHANGED, LVN_COLUMNCLICK, LVN_DELTEITEM and LVN_GETDISPINFO.  The ListView control draws correctly, I just can't change the font color or background.  
0
 

Author Comment

by:Kalvyn
ID: 8096238
Your comments led me to the problem in my code.  I was trapping WM_NOTIFY and then calling a class method.  The class method returned CDRF_NOTIFYITEMDRAW to the original call without passing the value on to WM_NOTIFY. I now use

  case NM_CUSTOMDRAW:
    lplvcd = (LPNMLVCUSTOMDRAW)lParam;
  //app.debug(ltoa(lplvcd->nmcd.dwDrawStage,app.tmp,10));
    switch(lplvcd->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
      result = CDRF_NOTIFYITEMDRAW;
      break;
    case CDDS_ITEMPREPAINT:
      lplvcd->clrText = RGB(255,0,255);
      lplvcd->clrTextBk = RGB(92,0,82);
      result = CDRF_NEWFONT;
      break;
    case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
      lplvcd->clrText = RGB(0,255,0);
      lplvcd->clrTextBk = RGB(255,255,0);
      result = CDRF_NEWFONT;
      break;
    default:
      app.debug(ltoa(lplvcd->nmcd.dwDrawStage,app.tmp,10));
    }
    return result;

...and then return result to WM_NOTIFY.

Thank you so much for your prompt and insightfull contributions to my issue.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8096422
>>Thank you so much for your prompt and insightfull contributions to my issue.

The best way to thank a person is to award them with an A (it cost you nothing).  If only I had been even MORE prompt and even MORE insightful, and if only I had been able to read your code and your mind, then I could have eeked out an A.  I'll just have to learn to try harder :)

-- Dan
0

Featured Post

Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

Question has a verified solution.

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

This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

770 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