我有一个带有MDI框架窗口的Win32应用程序(没有mfc)。
主MDI框架窗口会产生MDICLIENT窗口。但在我的应用程序中,主框架窗口有另一个tabctrl子窗口,它在主框架的底部显示一些listview wnds:
//create the tab first, as a child of main MDI frame with 800px width and 300px height, at point (0, 600) of main frame window.
HWND hWndTabCtrl = CreateWindow(WC_TABCONTROL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | TCS_BOTTOM, 0, 600, 800, 300, hWndMainFrame, NULL, hInstance, NULL);
//add one tab item for test:
TCITEM item;
item.mask = TCIF_TEXT;
item.pszText = L"Test List View";
TabCtrl_InsertItem(hWndTabCtrl , 0, &item);
//And then create a listview, this list view is a child window of tab ctrl (hWndTabCtrl)
HWND hWndListView = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS | WS_VISIBLE, 0, 0,800, 280, hWndTabCtrl , NULL, hInstance, NULL);
//Now insert two columns:
LVCOLUMN column;
column.mask = LVCF_WIDTH | LVCF_TEXT;
column.cx = 200;
column.pszText = L"Column 0";
ListView_InsertColumn(hWndListView , 0, &column); //column for sub item 0
column.pszText = L"Column 1";
ListView_InsertColumn(hWndListView , 1, &column); //column for sub item 1
现在我想更改子项目1的文字颜色。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message){
case WM_NOTIFY:
if (((LPNMHDR)lParam)->hwndFrom == hWndListView && ((LPNMHDR)lParam)->code == NM_CUSTOMDRAW){
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
switch (lplvcd->nmcd.dwDrawStage){
case CDDS_PREPAINT:
//I can receive this value
return CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
//I cann't receive this value:
return CDRF_NOTIFYSUBITEMDRAW;
break;
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
//I cann't receive this value:
lplvcd->clrText = RGB(255,0, 0);
return CDRF_NEWFONT;
break;
}
return CDRF_DODEFAULT;
}
break;
case ...
...
break;
default:
return DefFrameProc(hWnd, hWndMainFrame, message, wParam, lParam);
}
}
在WM_NOTIFY代码块的情况下,我只能接收lplvcd-> nmcd.dwDrawStage一次,其值为CDDS_PREPAINT。我相信这是因为返回值CDRF_NOTIFYITEMDRAW没有返回正确的" parent"。
是TabCtrl的问题还是MDI窗口的问题?
答案 0 :(得分:0)
尽管文档说的是,返回值实际上是一个位掩码,因此您可以一次返回多个值。同样,dwDrawingStage
也是一个位掩码,所以你应该寻找你感兴趣的特定位。
尝试更像这样的事情:
LPNMHDR pnmhdr = (LPNMHDR) lParam;
if ((pnmhdr->hwndFrom == hWndListView) && (pnmhdr->code == NM_CUSTOMDRAW))
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW) lParam;
if (lplvcd->nmcd.dwDrawStage & CDDS_ITEM)
{
if (lplvcd->nmcd.dwDrawStage & CDDS_ITEMPREPAINT)
{
if (lplvcd->nmcd.dwDrawStage & CDDS_SUBITEM)
{
lplvcd->clrText = RGB(255,0, 0);
...
return CDRF_DODEFAULT | CDRF_NEWFONT;
}
else
{
...
return CDRF_DODEFAULT | CDRF_NOTIFYSUBITEMDRAW;
}
}
...
}
else
{
switch (lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
{
...
return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYSUBITEMDRAW;
}
...
}
}
return CDRF_DODEFAULT;
}
答案 1 :(得分:0)
我有一个类似的问题(Dialog中的ListView),有一个共同的因素:没有MFC。 相同的结果:接收CDDS_PREPAINT,但不接收CDDS_ITEMPREPAINT及其组合(CDDS_SUBITEM | CDDS_PREPAINT和CDDS_ITEM | CDDS_SUBITEM | CDDS_PREPAINT)。 经过3天的挖掘后,我在https://www.codeproject.com/Articles/2890/Using-ListView-control-under-Win-API找到了答案。
在我的DialogProc中,我将NM_CUSTOMDRAW的结果返回给WM_NOTIFY,如下所示:
case WM_NOTIFY:
NMHDR* pHdr = (NMHDR*) lParam;
if (pHdr->idFrom == IDC_LIST_RESULTS && pHdr->code == NM_CUSTOMDRAW)
{
SetWindowLong(hDlg, DWL_MSGRESULT, (LONG)HandleCustomDraw((NMLVCUSTOMDRAW*)pHdr));
return TRUE;
}
break;
但正确的行为是将结果发送给所有者:
Comparator
希望它有所帮助!
编辑:当然现在我在另一个stackoverflow问题中找到了相同的答案:-) Virtual listview doesn't get CDDS_ITEMPREPAINT c++