Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ListView CustomDraw issues (no mfc)

181 views
Skip to first unread message

Dan Miller

unread,
Jan 14, 2009, 4:48:32 PM1/14/09
to
I've got an application with a working ListView control in it. I want to
change the background color on a couple of fields, to indicate device
status. I'm using Benji's color-listview code from CodeProject
(http://www.codeproject.com/KB/combobox/listview.aspx)
as a reference point, but for some reason I don't get the results that he
gets. (i.e., I don't get colored fields). I'll extract (what I think
is) the relevant code below.

I implemented some debug functions (the syslog calls below just map to
OutputDebugString, which I monitor with DebugView). What seems to happen
is that I get CDDS_PREPAINT messages, but I never get CDDS_ITEMPREPAINT
or (CDDS_SUBITEM | CDDS_ITEMPREPAINT) messages, so the color-selection
code never gets executed. I saw a message somewhere which claimed that
this symptom will occur if the OWNERDRAW flag is set in the ListView, but
as you can see below, I don't set that flag.

The only difference that I can *see* is that my listview is inserted in a
regular window, while his is on a dialog. Is that the problem, or
something else that I don't understand??

//*********************************************************************
HWND CreateListView(int x, int y, int width, int height,
int identifier, HWND hwnd, HINSTANCE g_hInst)
{
return CreateWindowEx(WS_EX_CLIENTEDGE,
"SysListView32", NULL,
WS_CHILD | WS_VISIBLE |
LVS_REPORT | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,
x, y, width, height,
hwnd, (HMENU) identifier, g_hInst, NULL);
}

// creating the ListView, in WM_CREATE:
// dx,dy don't matter, because it will get resized in WM_SIZE
hwndLVtop = CreateListView(0, LV_Y, 100, 100, IDC_LISTVIEW1, hwnd,
g_hinst) ;
if (hwndLVtop == NULL)
syslog("CreateWindow (ListView) : %s\n", get_system_message()) ;

// in WM_SIZE, additional options are set:
SendMessage (hwndLVtop, LVM_SETEXTENDEDLISTVIEWSTYLE,
LVS_EX_SUBITEMIMAGES, LVS_EX_SUBITEMIMAGES);
SendMessage (hwndLVtop, LVM_SETEXTENDEDLISTVIEWSTYLE,
LVS_EX_GRIDLINES, LVS_EX_GRIDLINES);

// a timer is used to add fields to the ListView

// in WM_NOTIFY:
switch (LOWORD (wParam)) {
case IDC_LISTVIEW1:
LPNMLISTVIEW pnm = (LPNMLISTVIEW) lParam;

if (pnm->hdr.hwndFrom == hwndLVtop &&
pnm->hdr.code == (unsigned) NM_CUSTOMDRAW) {
SetWindowLong (hwnd, DWL_MSGRESULT,
(LONG) ProcessCustomDraw (lParam));
}
break;
}

// finally, ProcessCustomDraw() :
//****************************************************************
LRESULT ProcessCustomDraw (LPARAM lParam)
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW) lParam;

switch (lplvcd->nmcd.dwDrawStage) {
case CDDS_PREPAINT: //Before the paint cycle begins
syslog("CDDS_PREPAINT\n") ; // I see this, repeatedly
//request notifications for individual listview items
return CDRF_NOTIFYITEMDRAW;
// I tried some other return values,
// but none made any difference:
// return (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW);
// return CDRF_NOTIFYSUBITEMDRAW;

case CDDS_ITEMPREPAINT: //Before an item is drawn
syslog("CDDS_ITEMPREPAINT\n") ; // but I never see this
return CDRF_NOTIFYSUBITEMDRAW;

case CDDS_SUBITEM | CDDS_ITEMPREPAINT: //Before a subitem is drawn
{ // nor do I see either of these
if (lplvcd->nmcd.dwDrawStage == CDDS_SUBITEM)
syslog("CDDS_SUBITEM\n") ;
else
syslog("CDDS_ITEMPREPAINT\n") ;
}
return CDRF_NEWFONT;

default: // and I never see this
syslog("Unknown CDDS code %u\n", lplvcd->nmcd.dwDrawStage) ;
break;
}
return CDRF_DODEFAULT;
}

Norman Bullen

unread,
Jan 14, 2009, 8:57:32 PM1/14/09
to
If you're calling CreateListView() from within the WM_CREATE handler of
its parent window, it is likely that the (probably) global variable hwnd
which should contain the handle of the parent window has not yet been set.

(WM_CREATE is sent before CreateWindow() returns.)

--
Norm

To reply, change domain to an adult feline.

Jerome

unread,
Jan 15, 2009, 2:13:00 AM1/15/09
to
Dan Miller wrote:
>
> SetWindowLong (hwnd, DWL_MSGRESULT,
> (LONG) ProcessCustomDraw (lParam));

This has no sense if not in a dialog box.

Fred

unread,
Jan 15, 2009, 2:27:51 AM1/15/09
to

"Dan Miller" <dere...@mt2009.com> wrote in message
news:Xns9B938C78D198...@216.196.97.131...


> // in WM_NOTIFY:
> switch (LOWORD (wParam)) {
> case IDC_LISTVIEW1:
> LPNMLISTVIEW pnm = (LPNMLISTVIEW) lParam;
>
> if (pnm->hdr.hwndFrom == hwndLVtop &&
> pnm->hdr.code == (unsigned) NM_CUSTOMDRAW) {
> SetWindowLong (hwnd, DWL_MSGRESULT,
> (LONG) ProcessCustomDraw (lParam));
> }
> break;

Yes, this code is fir dialog boxes
BTW, never copy code from codeproject (not professional, many bugs)
Always use MSDN code (several ones for Listviews)
Custom draw is well explained
http://msdn.microsoft.com/en-us/library/bb761817(VS.85).aspx


Dan Miller

unread,
Jan 15, 2009, 12:05:37 PM1/15/09
to
"Fred" <fr...@gmail.com> wrote in news:gkmohr$aj5$1...@news.motzarella.org:

Ahhh... yes, I wasn't thinking carefully...
DWL_MSGRESULT is specifically for dialogs.
Unfortunately, if I change my top-level application from Window to
Dialog, I get other problems, but I'll broach that in a separate topic
(after I do a little more research).

Thanks for the responses!!

0 new messages