问题
I'm trying to customize a treeview control using NM_CUSTOMDRAW messages. I simply want to draw every other visible item with a grey color. Here is code to draw:
INT CResourceOutliner::On_WM_NOTIFY( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
HWND hTree = GetDlgItem( hDlg, IDC_TREE1 );
switch( ( ( LPNMHDR )lParam )->code )
{
...
case NM_CUSTOMDRAW:
{
LPNMTVCUSTOMDRAW pCustomDraw = ( LPNMTVCUSTOMDRAW )lParam;
switch( pCustomDraw->nmcd.dwDrawStage )
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
{
switch ( pCustomDraw->iLevel )
{
// painting all 0-level items blue,
// and all 1-level items red (GGH)25.
case 0:
{
if( pCustomDraw->nmcd.uItemState == ( CDIS_FOCUS | CDIS_SELECTED ) )
pCustomDraw->clrTextBk = RGB( 255, 255, 255 );
else
pCustomDraw->clrTextBk = RGB( 128, 128, 128 );
break;
}
case 1:
{
if( pCustomDraw->nmcd.uItemState == ( CDIS_FOCUS | CDIS_SELECTED ) )
pCustomDraw->clrTextBk = RGB( 255, 255, 255 );
else
pCustomDraw->clrTextBk = RGB( 128, 128, 128 );
break;
}
default:
break;
}
return CDRF_SKIPDEFAULT;
}
default:
break;
}
}
...
}
}
This code is from here .
The problem is that after returning CDRF_NOTIFYITEMDRAW on CDDS_PREPAINT notification message, the CDDS_ITEMPREPAINT message never comes...Is there an option to set in order to enable custom drawing..? I imagine that there isn't because the CDDS_PREPAINT message is sent by the control...
...also the code above is not meant to draw every other item...its just a demo from codeguru.com
here is message handling implementation...
int CResourceOutliner::DoModal( int resID, RECT rct, HWND hParent )
{
// Set properties
m_dwpSaveThis = ( DWORD_PTR )this; /// store this pointer
m_nResId = resID;
m_hParent = hParent;
m_hWindow = CreateDialog( GetModuleHandle( NULL ), MAKEINTRESOURCE( m_nResId ), m_hParent, ( DLGPROC )MsgProcStatic );
// Set window position
SetWindowPos( m_hWindow, 0, rct.left, rct.top, rct.right, rct.bottom, 0 );
ShowWindow( m_hWindow, SW_HIDE );
if( m_hWindow )
return 1;
return 0;
}
INT CALLBACK CResourceOutliner::MsgProcStatic( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if( !m_hWindow )
m_hWindow = hWnd;
CResourceOutliner *pDlg = ( CResourceOutliner* )m_dwpSaveThis;
if( pDlg )
return pDlg->MsgProc( hWnd, uMsg, wParam, lParam );
else
return 0;
}
INT CALLBACK CResourceOutliner::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
On_WM_INITDIALOG( hWnd, wParam, lParam );
break;
case WM_COMMAND:
On_WM_COMMAND( hWnd, wParam, lParam );
break;
case WM_NOTIFY:
{
return On_WM_NOTIFY( hWnd, wParam, lParam );
}
case WM_LBUTTONDOWN:
On_WM_LBUTTONDOWN( hWnd, wParam, lParam );
break;
case WM_LBUTTONUP:
On_WM_LBUTTONUP( hWnd, wParam, lParam );
break;
case WM_MOUSEMOVE:
On_WM_MOUSEMOVE( hWnd, wParam, lParam );
break;
case WM_PAINT:
On_WM_PAINT( hWnd, wParam, lParam );
break;
case WM_CLOSE:
On_WM_CLOSE( hWnd, wParam, lParam );
break;
default:
return 0;
}
return 0;
}
回答1:
Most return codes from the dialog procedure need to be set via DWLP_MSGRESULT
, for example:
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
There are very few exceptions to this rule (WM_CTLCOLORSTATIC
is one example that returns directly) as a dialog procedure is generally defined as returning TRUE
or FALSE
depending on whether the message was handled or not.
来源:https://stackoverflow.com/questions/18805801/win32-custom-draw-treeview-control