为什么树形控件(treeview)自绘不成功?问题出在哪儿?

screen12 2014-05-19 10:07:41
我有一个树形控件,希望有的项目颜色以灰色显示,于是不得不采用自绘的方式,代码如下:

case NM_CUSTOMDRAW:
pcd = (NMCUSTOMDRAW*)lParam;
if(wParam == IDC_TREE1)
{
ptvcd = (NMTVCUSTOMDRAW*)lParam;
if(ptvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
{
return CDRF_NOTIFYITEMDRAW; //多次进入该循环
}
else if(ptvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
newfont = (HFONT)GetStockObject(ANSI_FIXED_FONT); //从不进入该循环
SelectObject(ptvcd->nmcd.hdc, newfont);
ptvcd->clrText = RGB(255, 0, 0);
ptvcd->clrTextBk = RGB(0, 150, 50);
return CDRF_NEWFONT;
}
}
return FALSE;
default:
return FALSE;


可是结果发现,树形控件并未象我希望的那样改变字体颜色和背景色。而是显示和标准树形控件一样。

经调试,发现程序多次进入上面一个分支(if)(在代码中标出),却从未进入下面真正进行自绘的分支(else if)(也在代码中标出)。

请问问题出在哪儿?
...全文
315 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2014-06-21
  • 打赏
  • 举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了疑难问题汇总帖 并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面界面版关于版主结帖工作的具体办法
schlafenhamster 2014-05-21
  • 打赏
  • 举报
回复
看图 好像 Style 与 标准tree 差 不 少。 是不是 style 有 问题, 引起的 ? 先 按 标准 style 搞 试试。
screen12 2014-05-21
  • 打赏
  • 举报
回复
我的程序中,在左边树形控件中点击某一个项目,右边会显示出相应的图形。但是我希望做到这样:就是有图片的选项以正常状态显示,没有图片的选项以灰色显示,这样可以一目了然的看出哪些有图片,哪些没有,可以作对应的导入。 其实我只希望某些项目“灰化”显示而已,没有过多的要求,然后这一要求好象只能用自绘的方式。
screen12 2014-05-21
  • 打赏
  • 举报
回复
已经插入Item了,这是我的效果图:

schlafenhamster 2014-05-21
  • 打赏
  • 举报
回复
pcd = (NMCUSTOMDRAW*)lParam; if( pcd ->code == IDC_TREE1)
screen12 2014-05-21
  • 打赏
  • 举报
回复
引用 15 楼 schlafenhamster 的回复:
看图 好像 Style 与 标准tree 差 不 少。
是不是 style 有 问题, 引起的 ?
先 按 标准 style 搞 试试。

这个不是新风格,只是我取消了连线,并在每个项目前面加了一个图片,以便把它们分组而已。

我取消了这些图片,并把连线加上,结果还是一样,没有显示出我需要的效果,并且调试时,永远进入if(ptvcd->nmcd.dwDrawStage == CDDS_PREPAINT)这个分支里。

修改后的控件如下:



谢谢你的帮助,这个问题有点奇怪,看来暂时难以索解。先放下,忙程序中别的部分,有时候过一段时间再回来,说不定找到问题所在了。
schlafenhamster 2014-05-20
  • 打赏
  • 举报
回复
"我的是SDK方式" 晚上 我 再 查查。
screen12 2014-05-20
  • 打赏
  • 举报
回复
回楼上,我仔细看了其中一段: if (pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT) { *pResult = CDRF_NOTIFYITEMDRAW; } 我也确实这样做了,我程序中的代码是(我的是SDK方式): if(ptvcd->nmcd.dwDrawStage == CDDS_PREPAINT) { return CDRF_NOTIFYITEMDRAW; } 和你给出的代码是一样的。我调试了一下,程序每次进入,都是:ptvcd->nmcd.dwDrawStage == CDDS_PREPAINT,没有别的数值,所以别的分支的返回值没有用。 但这个分支,我确实让它的返回值和代码中的一样了。可是从道理上讲,它应该发送ptvcd->nmcd.dwDrawStage等于别的值的消息,可是却总是收不到。
schlafenhamster 2014-05-20
  • 打赏
  • 举报
回复
schlafenhamster 2014-05-20
  • 打赏
  • 举报
回复
插入Item 没有 ?
screen12 2014-05-20
  • 打赏
  • 举报
回复
我按照你的代码修改了一下,还是没用。我的代码修改如下:

case NM_CUSTOMDRAW:
pcd = (NMCUSTOMDRAW*)lParam;
if(wParam == IDC_TREE1)
{
ptvcd = (NMTVCUSTOMDRAW*)lParam;
if((ptvcd->nmcd.dwDrawStage & CDDS_ITEM) && (ptvcd->nmcd.uItemState & CDIS_HOT))//CDIS_SELECTED))
{
SetTextColor(ptvcd->nmcd.hdc, RGB(255,255,255));//white
SetBkColor(ptvcd->nmcd.hdc, RGB(255,0,0));
return CDRF_NOTIFYITEMDRAW;
}
else
{
SetTextColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOW));
return CDRF_NOTIFYITEMDRAW;
}
return CDRF_DODEFAULT;
}
return CDRF_DODEFAULT;
default:
return FALSE;
}
return FALSE;


基本上和你的代码一致了,可是我发现,仍然和以前一样,树形控件没有按照我的设想改变字体颜色。调试发现:每次进入NM_CUSTOMDRAW以后,其ptvcd->nmcd.dwDrawStage的值总是1,也就是说,它总是进入下面的else分支。从不进入上面的分支。

不知道是怎么回事。
schlafenhamster 2014-05-20
  • 打赏
  • 举报
回复
找到了

LRESULT TreeViewNotify (HWND hWnd, LPARAM lParam)
{
	char prompt[80];
	LPNMHDR lpnmh = (LPNMHDR) lParam; // Contains data from a notification 
	switch (lpnmh->code)
	{
	case NM_CLICK:
		sprintf(prompt,"Ctrl ID %d \r\n",lpnmh->idFrom);
		OutputDebugString(prompt);
		break;
	case NM_DBLCLK:
		OutputDebugString("NM_DBLCLK\n");
		break;
	case NM_RETURN://??
		OutputDebugString("NM_RETURN\n");
		break;
	case NM_RCLICK:
		OutputDebugString("NM_RCLICK\n");
		break;
	case NM_RDBLCLK://??
		OutputDebugString("NM_RDBLCLK\n");
		break;
	case NM_SETFOCUS:
//		OutputDebugString("NM_SETFOCUS\n");
		break;
	case NM_KILLFOCUS:
//		OutputDebugString("NM_KILLFOCUS\n");
		break;
	case NM_HOVER:// ?? 
		OutputDebugString("NM_HOVER\n");
		break;
	case NM_CUSTOMDRAW:
//		OutputDebugString("NM_CUSTOMDRAW\n");
		break;
	case TVN_SELCHANGED:
		OutputDebugString("TVN_SELCHANGED\n");
		break;
	}
//	if(GetFocus() != m_hTreeView) return 0;
//	
	if(lpnmh->code==NM_CUSTOMDRAW)
	{//
		LPNMTVCUSTOMDRAW pDraw=(LPNMTVCUSTOMDRAW)lParam;
		DWORD dwDrawStage=pDraw->nmcd.dwDrawStage;
		UINT  uItemState =pDraw->nmcd.uItemState;
		HDC   hdc=pDraw->nmcd.hdc;
		//RECT rc;
		//HTREEITEM hItem=(HTREEITEM) pDraw->nmcd.dwItemSpec;
		//TreeView_GetItemRect(m_hTreeView,hItem,&rc,TRUE);
		//HBRUSH brsh=0; // 0x00010000                    0x0001
		//char txt[260];
		//TVITEM tvi;
		if((dwDrawStage & CDDS_ITEM) && (uItemState & CDIS_HOT))//CDIS_SELECTED))
		{// 
			//brsh=CreateSolidBrush(RGB(255,0,0));//red
			//FillRect(hdc,&rc,brsh);
			//DeleteObject(brsh);
			//set colors
			SetTextColor(hdc,RGB(255,255,255));//white
			SetBkColor(hdc,RGB(255,0,0));
			//
			//memset(txt,0,sizeof(txt));
			//tvi.mask= TVIF_HANDLE | TVIF_TEXT;
			//tvi.hItem=hItem;
			//tvi.pszText=txt;
			//tvi.cchTextMax=sizeof(txt);
			//TreeView_GetItem(m_hTreeView,&tvi);
			//TextOut(hdc,rc.left+2,rc.top+2,txt,strlen(txt));//not sizeof(txt) !
			//????
			//OutputDebugString(txt);
			//OutputDebugString("\n");
			return CDRF_NOTIFYITEMDRAW;// | CDRF_SKIPDEFAULT);
		}
		else 
		{// without these ,1st blue !
			SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
			SetBkColor(hdc,GetSysColor(COLOR_WINDOW));
			//
			return CDRF_NOTIFYITEMDRAW;
		}
	}
	return 0;
}
/*
      ptvcd=(NMTVCUSTOMDRAW*)lParam;
      if(ptvcd->nmcd.dwDrawStage==CDDS_PREPAINT)//Before the painting cycle begins
      {
       //the control will send NM_CUSTOMDRAW notification messages to the parent,before and after drawing items 
       return CDRF_NOTIFYITEMDRAW;
      }
      if(ptvcd->nmcd.dwDrawStage==CDDS_ITEMPREPAINT)//Before an item is drawn
      {
       newfont=(HFONT)GetStockObject(ANSI_FIXED_FONT);
       SelectObject(ptvcd->nmcd.hdc,newfont);
       ptvcd->clrText=RGB(255,0,0);
       ptvcd->clrTextBk=RGB(0,150,50);
       return CDRF_NEWFONT;
      }


*/

// WndProc 里: LRESULT APIENTRY WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) ......... case WM_NOTIFY: if(wParam==IDC_LISTVIEW) { return (ListViewCustomDraw(m_hListView, lParam)); } else if (wParam==IDC_TREEVIEW) { //OutputDebugString("WM_NOTIFY parant\n"); return (TreeViewNotify(hwnd, lParam)); } else if(wParam==IDC_PICK) { PickerNotify(m_hPick, lParam); } break;
screen12 2014-05-19
  • 打赏
  • 举报
回复
引用 2 楼 lis2012 的回复:
http://bbs.csdn.net/topics/330111099
这个文章我仔细看了一下,找不到我需要的答案。
lis2012 2014-05-19
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/330111099
screen12 2014-05-19
  • 打赏
  • 举报
回复
我数了一下,发现程序进入case NM_CUSTOMDRAW:一共12次,均从if(ptvcd->nmcd.dwDrawStage == CDDS_PREPAINT)这个分支走。真不知是哪里出了问题了。
schlafenhamster 2014-05-19
  • 打赏
  • 举报
回复
给个list的tree 没找到:

// OnCustomDraw
void CXListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
	NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);

	// Take the default processing unless we set this to something else below.
	*pResult = CDRF_DODEFAULT;

	// First thing - check the draw stage. If it's the control's prepaint
	// stage, then tell Windows we want messages for every item.

	if (pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT)
	{
		*pResult = CDRF_NOTIFYITEMDRAW;
	}
	else if (pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
	{
		// This is the notification message for an item.  We'll request
		// notifications before each subitem's prepaint stage.

		*pResult = CDRF_NOTIFYSUBITEMDRAW;
	}
	else if (pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
	{
		// This is the prepaint stage for a subitem. Here's where we set the
		// item's text and background colors. Our return value will tell
		// Windows to draw the subitem itself, but it will use the new colors
		// we set here.

		int nItem = static_cast<int> (pLVCD->nmcd.dwItemSpec);
		int nSubItem = pLVCD->iSubItem;

		XLISTCTRLDATA *pXLCD = (XLISTCTRLDATA *) pLVCD->nmcd.lItemlParam;
		ASSERT(pXLCD);

		COLORREF crText  = m_crWindowText;
		COLORREF crBkgnd = m_crWindow;

		if (pXLCD)
		{
			crText  = pXLCD[nSubItem].crText;
			crBkgnd = pXLCD[nSubItem].crBackground;

			if (!pXLCD[0].bEnabled)
				crText = m_crGrayText;
		}

		// store the colors back in the NMLVCUSTOMDRAW struct
		pLVCD->clrText = crText;
		pLVCD->clrTextBk = crBkgnd;

		CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
		CRect rect;
		GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);

		if (pXLCD && (pXLCD[nSubItem].bShowProgress))
		{
			DrawProgress(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);

			*pResult = CDRF_SKIPDEFAULT;	// We've painted everything.
		}
#ifndef DO_NOT_INCLUDE_XCOMBOLIST
		else if (pXLCD && (pXLCD[nSubItem].bCombo))
		{
			if (GetItemState(nItem, LVIS_SELECTED))
				DrawComboBox(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);
			else
				DrawText(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);

			*pResult = CDRF_SKIPDEFAULT;	// We've painted everything.
		}
#endif
		else if (pXLCD && (pXLCD[nSubItem].nCheckedState != -1))
		{
			DrawCheckbox(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);

			*pResult = CDRF_SKIPDEFAULT;	// We've painted everything.
		}
		else
		{
			rect.left += DrawImage(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);

			DrawText(nItem, nSubItem, pDC, crText, crBkgnd, rect, pXLCD);

			*pResult = CDRF_SKIPDEFAULT;	// We've painted everything.
		}
	}
}

tree 的 意思差不多. 主要是CDRF 要对.
screen12 2014-05-19
  • 打赏
  • 举报
回复
引用 4 楼 schlafenhamster 的回复:
return FALSE; 改 return CDRF_DEFAULT;
两个都改了,还是不行。还是显示一个正常的树形控件而没有按照我的自绘要求来改变。并且调试的时候,if(ptvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)这个分支从未进入过。
schlafenhamster 2014-05-19
  • 打赏
  • 举报
回复
return FALSE; 改 return CDRF_DEFAULT;

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧