TlistView 控件是vcl 对windows公用控件库的一个封装用户TlistView控件并未提供自绘表头的事件 一般情况下 要想自绘表头比较困难 但是windows 所有控件的绘制都是由于消息WM_PAINT的产生而由窗口过程来绘制的 这样我们似乎就有可能通过WM_PAINT消息能够绘制TlistView表头 经过分析发现TlistView 的组成实际上包括了两部分 一部分是TlistView本省 另外一部分就是TlistView的表头 该表头实际上是一个嵌入TlistView里面的独立的窗口 该窗口的类名为SysHeader(可以使用ccrun写的窗口探测工具spywin观察的到) 综合上述依据 实现TlistView表头的自绘可以分为一下几个步骤: 查找TlistView的表头窗口句柄 替换表头窗口的窗口过程 表头的WM_PAINT消息 在窗口过程中编写绘制代码 这样就能绘制TlistView 的表头了具体实现方式如下 : 查找表头有三种方式 一 使用FindWindowEx : 以类名SysHeader来查找TlistView的子窗口 由于TlistView只有一个名为SysHeader的子窗口(就是表头) 所以一定能够获取到表头窗口的句柄 二 使用windows提供的帮助宏ListView_GetHeader 这种方式实际上是通过发送消息来获取表头句柄 返回值即表头句柄 替换表头的窗口过程 使用SetWindowLong这个API 就可以替换掉一个窗口的窗口过程(详细步骤请参看MSDN) 请参看示例代码 请参看示例代码 具体代码 h文件 // #ifndef UnitH #define UnitH // #include #include #include #include #include // class TForm : public TForm { __published: // IDEmanaged Components TListView *ListView; private: // User declarations public: // User declarations __fastcall TForm(TComponent* Owner); __fastcall~TForm(); }; // extern PACKAGE TForm *Form; // #endif cpp文件 // #include #pragma hdrstop #include Unith // #pragma package(smart_init) #pragma resource *dfm TForm *Form; typedef LRESULT(CALLBACK * TCallBack)(HWND UINT WPARAM LPARAM); TCallBack g_oldListViewWndProc; HWND g_hListViewHeader; LRESULT CALLBACK ListViewWindowProc(HWND hwnd UINT uMsg WPARAM wParam LPARAM lParam) { PAINTSTRUCT ps ={ }; RECT rect = { }; HDC hPen = NULL; HDC hBrush = NULL; int iCount = ; int i = ; BYTE red = green = blue = ; BYTE red = green = blue = ; BYTE red green blue; int j m n; switch(uMsg) { case WM_PAINT: BeginPaint(g_hListViewHeader hPen = SelectObject(pshdc GetStockObject(DC_PEN)); iCount = Header_GetItemCount(g_hListViewHeader); // 获取表头数目 // 本文转自 C++Builder研究 ?i= SetDCPenColor(pshdc ColorToRGB((TColor)(xEFDBCE))); red = GetRValue((TColor)(xEFDBCE)); green = GetGValue((TColor)(xEFDBCE)); blue = GetBValue((TColor)(xEFDBCE)); for (int i = ; i Font>Handle); i = ((rectbottom recttop) abs(Form>Font>Height)) / ; hBrush = SelectObject(pshdc GetStockObject(NULL_BRUSH)); SetBkMode(pshdc TRANSPARENT); // 这是设置背景为透明的 TextOut(pshdc rectleft + recttop + i Form>ListView>Columns>Items[i]>Captionc_str() Form>ListView>Columns>Items[i]>CaptionLength()); SelectObject(pshdc hBrush); } hPen = SelectObject(pshdc hPen); EndPaint(g_hListViewHeader break; default: return CallWindowProc((FARPROC)g_oldListViewWndProc g_hListViewHeader uMsg wParam lParam); } return ; } // __fastcall TForm::TForm(TComponent* Owner) : TForm(Owner) { g_hListViewHeader = FindWindowEx(ListView>Handle NULL SysHeader NULL); g_oldListViewWndProc = (TCallBack)GetWindowLong (g_hListViewHeader GWL_WNDPROC); SetWindowLong(g_hListViewHeader GWL_WNDPROC long(ListViewWindowProc)); } // __fastcall TForm::~TForm() { SetWindowLong(g_hListViewHeader GWL_WNDPROC (long)g_oldListViewWndProc); } |