计算机二级辅导:如何自绘ListView表头
来源:优易学  2011-12-9 21:13:10   【优易学:中国教育考试门户网】   资料下载   IT书店

  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. 请参看示例代码
  具体代码
  .h文件
  // ---------------------------------------------------------------------------
  #ifndef Unit1H
  #define Unit1H
  // ---------------------------------------------------------------------------
  #include
  #include
  #include
  #include
  #include
  // ---------------------------------------------------------------------------
  class TForm1 : public TForm
  {
  __published: // IDE-managed Components
  TListView *ListView1;
  private: // User declarations
  public: // User declarations
  __fastcall TForm1(TComponent* Owner);
  __fastcall~TForm1();
  };
  // ---------------------------------------------------------------------------
  extern PACKAGE TForm1 *Form1;
  // ---------------------------------------------------------------------------
  #endif
  .cpp文件
  // ---------------------------------------------------------------------------
  #include
  #pragma hdrstop
  #include "Unit1.h"
  // ---------------------------------------------------------------------------
  #pragma package(smart_init)
  #pragma resource "*.dfm"
  TForm1 *Form1;
  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 ={ 0 };
  RECT rect = { 0 };
  HDC hPen = NULL;
  HDC hBrush = NULL;
  int iCount = 0;
  int i1 = 0;
  BYTE red0 = 115, green0 = 154, blue0 = 206;
  BYTE red1 = 255, green1 = 255, blue1 = 255;
  BYTE red, green, blue;
  int j, m, n;
  switch(uMsg)
  {
  case WM_PAINT:
  BeginPaint(g_hListViewHeader,
  hPen = SelectObject(ps.hdc, GetStockObject(DC_PEN));
  iCount = Header_GetItemCount(g_hListViewHeader); // 获取表头数目
  SetDCPenColor(ps.hdc, ColorToRGB((TColor)(0x00EFDBCE)));
  red = GetRValue((TColor)(0x00EFDBCE));
  green = GetGValue((TColor)(0x00EFDBCE));
  blue = GetBValue((TColor)(0x00EFDBCE));
  for (int i = 0; i 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,
  break;
  default:
  return CallWindowProc((FARPROC)g_oldListViewWndProc, g_hListViewHeader,
  uMsg, wParam, lParam);
  }
  return 0;
  }
  // ---------------------------------------------------------------------------
  __fastcall TForm1::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));
  }
  // ---------------------------------------------------------------------------
  __fastcall TForm1::~TForm1()
  {
  SetWindowLong(g_hListViewHeader, GWL_WNDPROC, (long)g_oldListViewWndProc);
  }

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训