我遵循了使用WM_SETREDRAW而不是LockWindowUpdate()的建议,以在填充项目时抑制listview更新。在发送带有true的WM_SETREDRAW消息后,我发现我的标题行没有显示。 InvalidateRect()和UpdateWindow()组合或RedrawWindow()无法显示所有者绘制的标题。要显示标题行,我需要通过调整列表视图大小或滚动列表视图来手动强制新的WM_PAINT消息。 此行为仅限于所有者绘制的标题。如果我没有继承Header过程,则在使用true发送WM_SETREDRAW消息后,本机Window过程只显示标题行。 任何人都可以建议我的代码中缺少什么吗?
注意:
以下是子类化的代码:
static LONG_PTR DefaultHeaderProc ;
static char* HeaderText[] = {"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T"} ;
LRESULT CALLBACK ListDlgProc (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
static HWND hwndHeader ;
static HWND hwndListView ;
switch (msg) {
case WM_INITDIALOG :
hwndListView = GetDlgItem (hDlg,IDC_LISTVIEW) ;
hwndHeader = ListView_GetHeader (hwndListView) ;
ListView_SetExtendedListViewStyle (hwndListView,LVS_EX_GRIDLINES |
LVS_EX_TRANSPARENTBKGND |LVS_EX_FULLROWSELECT) ;
SendMessage (hwndListView,LVM_SETBKCOLOR,0,(LPARAM) 0xE0E0E0) ;
SendMessage (hwndListView,LVM_SETTEXTCOLOR,0,(LPARAM) 0xC00000) ;
// Initialize the LVCOLUMN structure.
LVCOLUMN LvColumn ;
ZeroMemory (&LvColumn,sizeof (LVCOLUMN)) ;
LvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT ;
LvColumn.fmt = LVCFMT_LEFT ;
LvColumn.cx = 63 ;
// Add the columns
for (int i = 0 ; i < COLUMNS ; i++) {
LvColumn.pszText = HeaderText[i] ;
LvColumn.iSubItem = i ;
if (ListView_InsertColumn(hwndListView,i,&LvColumn) == -1)
return false ;
} /* for (int i = 0 ; i < COLUMNS ; i++) */
DefaultHeaderProc = SetWindowLongPtr (hwndHeader,GWLP_WNDPROC,
(LONG_PTR) HeaderSubclassProc) ;
SendMessage (hwndHeader,IDM_INIT,0,0L) ;
return true ;
case WM_DESTROY :
SetWindowLongPtr (hwndHeader,GWLP_WNDPROC,(LONG_PTR) DefaultHeaderProc) ;
SetWindowLongPtr (hwndListView,GWLP_WNDPROC,(LONG_PTR) DefaultListViewProc) ;
ListView_DeleteAllItems (hwndListView) ;
return 0 ;
;
以下是WM_PAINT处理的代码:
case WM_PAINT :
PAINTSTRUCT ps ;
hDC = BeginPaint (hwnd,&ps) ;
int DefDC = SaveDC (hDC) ;
SelectObject (hDC,Font) ;
SelectObject (hDC,Pen) ;
SelectObject (hDC,Brush) ;
SetBkMode (hDC,TRANSPARENT) ;
for (int Btn = 0 ; Btn < 20 ; Btn++) {
if (Btn == HBtn)
continue ;
Header_GetItemRect (hwnd,Btn,&rc) ;
Rectangle (hDC,rc.left,rc.top,rc.right + 1,rc.bottom) ;
DrawText (hDC,HeaderText[Btn],-1,&rc,DT_CENTER | DT_VCENTER) ;
} /* for (int Btn = 0 ; Btn < 20 ; Btn++) */
if (HBtn > -1 ) {
Header_GetItemRect (hwnd,HBtn,&rc) ;
SelectObject (hDC,HPen) ;
SelectObject (hDC,HBrush) ;
Rectangle (hDC,rc.left + 1,rc.top + 1,rc.right,rc.bottom - 1) ;
DrawText (hDC,HeaderText[HBtn],-1,&rc,DT_CENTER | DT_VCENTER) ;
} /* if (HLBtn > -1 ) */
RestoreDC (hDC,DefDC) ;
EndPaint (hwnd,&ps) ;
return 0 ;
HBtn是&#34; hot&#34;的热度指数。鼠标悬停在标题
上时的标题列答案 0 :(得分:0)
我尝试使用wParam = SIZE_RESTORED和lParam =自己的大小将WM_SIZE发送到Header窗口,发现Header行显示正确。
感谢Remy Lebeau,我用WM_SETREDRAW替换了LockWindowUpdate()并改进了大型列表的性能。我阅读了关于LockWindowUpdate()的Raymond Chen文章,并了解WM_SETREDRAW对于listview控件的性能提升来自于绕过“复杂的屏幕计算”。使用子类程序,需要重做一些计算。发送WM_SIZE与调整窗口大小的工作相同。控件显示完美,无需调用InvalidateRect()/ UpdateWindow()。
注意:我使用SetWindowLongPtr()将子类化方法更改为使用SetWindowSubclass(),但对我的Header显示问题没有影响。 我正在使用所有20个子项对列表进行排序,因此使用虚拟列表不是一种选择。