如何自绘ListView表头

时间:2021-05-02

TlistView 控件是vcl 对windows公用控件库的一个封装.用户TlistView控件并未提供自绘表头的事件, 一般情况下, 要想自绘表头比较困难. 但是windows 所有控件的绘制都是由于消息WM_PAINT的产生,而由窗口过程来绘制的, 这样我们似乎就有可能通过WM_PAINT消息能够绘制TlistView表头. 经过分析发现TlistView 的组成实际上包括了两部分, 一部分是TlistView本省, 另外一部分就是TlistView的表头, 该表头实际上是一个嵌入TlistView里面的独立的窗口, 该窗口的类名为”SysHeader32”.(可以使用ccrun写的窗口探测工具spy4win观察的到). 综合上述依据, 实现TlistView表头的自绘可以分为一下几个步骤:

1. 查找TlistView的表头窗口句柄.2. 替换表头窗口的窗口过程3. 表头的WM_PAINT消息4. 在窗口过程中编写绘制代码

这样就能绘制TlistView 的表头了.具体实现方式如下 :1. 查找表头有三种方式 一. 使用FindWindowEx :以类名”SysHeader32”来查找TlistView的子窗口, 由于TlistView只有一个名为”SysHeader32”的子窗口(就是表头), 所以一定能够获取到表头窗口的句柄二. 使用windows提供的帮助宏ListView_GetHeader这种方式实际上是通过发送消息来获取表头句柄, 返回值即表头句柄2. 替换表头的窗口过程使用SetWindowLong这个API 就可以替换掉一个窗口的窗口过程.(详细步骤请参看MSDN)3. 请参看示例代码4. 请参看示例代码

示例代码 :开发者 : 死牛之祭(A-Few)2009-08-25说明 :该代码可以zi you引用, 包括商业应用. 希望转载时尊重作者的署名权利.学习交流请来信a-few@netease.com.

.h文件//---------------------------------------------------------------------------#ifndefUnit1H#defineUnit1H//---------------------------------------------------------------------------#include<Classes.hpp>#include<Controls.hpp>#include<StdCtrls.hpp>#include<Forms.hpp>#include<ComCtrls.hpp>//---------------------------------------------------------------------------classTForm1:publicTForm{__published://IDE-managedComponents TListView*ListView1;private://Userdeclarationspublic://Userdeclarations __fastcallTForm1(TComponent*Owner); __fastcall~TForm1();};//---------------------------------------------------------------------------externPACKAGETForm1*Form1;//---------------------------------------------------------------------------#endif

.cpp文件//---------------------------------------------------------------------------#include<vcl.h>#pragmahdrstop#include"Unit1.h"//---------------------------------------------------------------------------#pragmapackage(smart_init)#pragmaresource"*.dfm"TForm1*Form1;typedefLRESULT(CALLBACK*TCallBack)(HWND,UINT,WPARAM,LPARAM);TCallBackg_oldListViewWndProc;HWNDg_hListViewHeader;LRESULTCALLBACKListViewWindowProc(HWNDhwnd,UINTuMsg,WPARAMwParam, LPARAMlParam){ PAINTSTRUCTps={ 0 }; RECTrect= { 0 }; HDChPen=NULL; HDChBrush=NULL; intiCount=0; inti1=0; BYTEred0=115,green0=154,blue0=206; BYTEred1=255,green1=255,blue1=255; BYTEred,green,blue; intj,m,n; switch(uMsg) { caseWM_PAINT: BeginPaint(g_hListViewHeader,&ps); hPen=SelectObject(ps.hdc,GetStockObject(DC_PEN)); iCount=Header_GetItemCount(g_hListViewHeader);//获取表头数目// 本文转自 C++Builder研究 - http:///article.asp?i=1069&d=uq3568 SetDCPenColor(ps.hdc,ColorToRGB((TColor)(0x00EFDBCE))); red=GetRValue((TColor)(0x00EFDBCE)); green=GetGValue((TColor)(0x00EFDBCE)); blue=GetBValue((TColor)(0x00EFDBCE)); for(inti=0;i<iCount;i++) { Header_GetItemRect(g_hListViewHeader,i,&rect);//获取Item的高度 m=rect.bottom-rect.top; n=m/2+1; for(j=0;j<n;j++) { red=red0*(j+1)/n+red1*(n-j-1)/n; green=green0*(j+1)/n+green1*(n-j-1)/n; blue=blue0*(j+1)/n+blue1*(n-j-1)/n; SetDCPenColor(ps.hdc,RGB(red,green,blue)); MoveToEx(ps.hdc,rect.left+1,rect.top+j,NULL); LineTo(ps.hdc,rect.right,rect.top+j); MoveToEx(ps.hdc,rect.left+1,rect.bottom-j-1,NULL); LineTo(ps.hdc,rect.right,rect.bottom-j-1); } SetDCPenColor(ps.hdc,ColorToRGB(clBtnFace)); MoveToEx(ps.hdc,rect.right,rect.top+1,NULL); LineTo(ps.hdc,rect.right,rect.bottom-1); SelectObject(ps.hdc,Form1->Font->Handle); i1=((rect.bottom-rect.top)-abs(Form1->Font->Height))/2; hBrush=SelectObject(ps.hdc,GetStockObject(NULL_BRUSH)); SetBkMode(ps.hdc,TRANSPARENT);//这是设置背景为透明的 TextOut(ps.hdc,rect.left+10,rect.top+i1, Form1->ListView1->Columns->Items[i]->Caption.c_str(), Form1->ListView1->Columns->Items[i]->Caption.Length()); SelectObject(ps.hdc,hBrush); } hPen=SelectObject(ps.hdc,hPen); EndPaint(g_hListViewHeader,&ps); break; default: returnCallWindowProc((FARPROC)g_oldListViewWndProc,g_hListViewHeader, uMsg,wParam,lParam); } return0;}//---------------------------------------------------------------------------__fastcallTForm1::TForm1(TComponent*Owner):TForm(Owner){ g_hListViewHeader=FindWindowEx(ListView1->Handle,NULL,"SysHeader32", NULL); g_oldListViewWndProc=(TCallBack)GetWindowLong (g_hListViewHeader,GWL_WNDPROC); SetWindowLong(g_hListViewHeader,GWL_WNDPROC,long(ListViewWindowProc));}//---------------------------------------------------------------------------__fastcallTForm1::~TForm1(){ SetWindowLong(g_hListViewHeader,GWL_WNDPROC,(long)g_oldListViewWndProc);}

本文源自:翔宇亭——IT乐园(http://),转载请保留此信息!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章