码迷,mamicode.com
首页 > 其他好文 > 详细

TListView Header重绘和高度设置

时间:2016-06-09 18:28:36      阅读:295      评论:0      收藏:0      [点我收藏+]

标签:

TListView 的 Header 部分默认 BtnFace 颜色,高度也不能改变。我们可以通过编写一些代码来实现这些功能;

 

  • 获得TListView 的Header 的句柄;

    TListView的Header其实是一个 HeaderContorl 控件。要获得他的句柄需要调用下面的代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

static HWND hListViewHeader = NULL;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
//获得ListView Header的句柄
    hListViewHeader = ListView_GetHeader(ListView1->Handle);
}
//---------------------------------------------------------------------------

 

其实还有许多ListView_XXXX 这样的windows API ,需要查看MSDN;

 

  • 改变Header的高度

Header的高度,是在一个处理一个叫 HDM_LAYOUT 的消息的时候进行设置。

msdn的原话如下:

技术分享

 

那么我们就用SetWindowLong 来改变 Header的 消息过程。

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


static HWND hListViewHeader = NULL;

//Header原来的窗口过程
static WNDPROC oldHeaderWindowProc = NULL;

//Header的新窗口过程
LRESULT CALLBACK NewHeaderWindowProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
//先要用原来的窗口过程处理
    LRESULT result = oldHeaderWindowProc(hwnd,uMsg,wParam,lParam);
//再处理HDM_LAYOUT消息
    if (HDM_LAYOUT == uMsg)
    {
        LPHDLAYOUT phdmlayout = (LPHDLAYOUT)lParam;
        //改变header的高度
        phdmlayout->pwpos->cy = 27;
        //改变listview表格部分的高度
        phdmlayout->prc->top  = phdmlayout->pwpos->cy;
    }

return result; } __fastcall TForm1::TForm1(TComponent
* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { hListViewHeader = ListView_GetHeader(ListView1->Handle); oldHeaderWindowProc = (WNDPROC)SetWindowLong( hListViewHeader,GWL_WNDPROC,(LONG)NewHeaderWindowProc); ListView1->Invalidate(); } //---------------------------------------------------------------------------

 

我们会看到这样的效果

 

技术分享

 

  • 处理Header的背景色

可以在Header的窗口过程中编写WM_PAINT 消息处理函数。但是这样写,你会发现无法在Header上输出文字。准确的说,你绘制上去的文字

会莫名其妙的不见,比如,拉宽一下Header 中的某一列,文字就会消失边检。使得这种重绘不好控制;

 

正确的做法是这样

  1. 调用 Header_SetItem 函数(其实是一个macro) 将ListView的Header 的 format 属性,设置为 HDF_OWNERDRAW (默认是 HDF_STRING).
  2. 重写ListView 的消息过程。(不是Header的消息过程);
  3. 在ListView的消息过程中处理 WM_DRAWITEM 消息;(WM_DRAWITEM消息会包含要重绘的 区域,hdc,index,状态等等)
  4. 在Header 的 HDM_LAYOUT 消息处理过程,也要调用 Header_SetItem,将format消息设置为 HDF_OWERDRAW (否则,每次改变列宽,format属性就又变成HDF_STRING,导致无法重绘)

下面是实现的代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


static HWND hListViewHeader = NULL;

//Header原来的窗口过程
static WNDPROC oldHeaderWindowProc = NULL;

//listView 原来的窗口过程
static WNDPROC oldListViewProc = NULL;

//Header的新窗口过程
LRESULT CALLBACK NewHeaderWindowProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
//先要用原来的窗口过程处理
    LRESULT result = oldHeaderWindowProc(hwnd,uMsg,wParam,lParam);
//再处理HDM_LAYOUT消息
    if (HDM_LAYOUT == uMsg)
    {
        LPHDLAYOUT phdmlayout = (LPHDLAYOUT)lParam;
        //改变header的高度
        phdmlayout->pwpos->cy = 27;
        //改变listview表格部分的高度
        phdmlayout->prc->top  = phdmlayout->pwpos->cy;
    }

    return result;
}


LRESULT CALLBACK NewListViewWindowProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
    if (uMsg == WM_DRAWITEM)
    {
        DRAWITEMSTRUCT* drawItemStruct = (DRAWITEMSTRUCT*)lParam;
        HDC hdc = drawItemStruct->hDC;
        int index = drawItemStruct->itemID;
        RECT rect = drawItemStruct->rcItem;

        TBrush* brush = new TBrush();
        TColor fontColor = clBlack;
        if (index == 0)
        {
            brush->Color = clRed;
            fontColor    = clWhite;
        }

        if (index == 1)
        {
            brush->Color = clYellow;
            fontColor    = clBlue;
        }

        if (index == 2)
        {
            brush->Color = clBlue;
            fontColor    = clWhite;
        }

        if (index == 3)
        {
            brush->Color = clLime;
            fontColor    = clBlue;
        }

        FillRect(hdc,&rect,brush->Handle);
        delete brush;

        SetTextColor(hdc,fontColor);
        SetBkMode(hdc,TRANSPARENT);
        //获取文本
        HDITEM hditem= {0};
        char buf[100] = {0};
        hditem.mask = HDI_TEXT;
        hditem.pszText = buf;
        hditem.cchTextMax = 100;
        Header_GetItem(hListViewHeader,index,&hditem);

        DrawText(hdc,hditem.pszText,strlen(hditem.pszText),&rect,
        DT_CENTER |DT_VCENTER |DT_SINGLELINE);


    }

    return oldListViewProc(hwnd,uMsg,wParam,lParam);
}

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void SetHDItem()
{
    if (hListViewHeader == NULL)
    {
        return;
    }

    HDITEM hditem;
    hditem.mask = HDI_FORMAT;
    hditem.fmt  = HDF_OWNERDRAW; //默认是 HDF_STRING

    int count = Header_GetItemCount(hListViewHeader);
    for (int i = 0; i < count ;i++)
    {
        Header_SetItem(hListViewHeader,i,&hditem);
    }
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    hListViewHeader = ListView_GetHeader(ListView1->Handle);
    
    oldHeaderWindowProc = (WNDPROC)SetWindowLong(
        hListViewHeader,GWL_WNDPROC,(LONG)NewHeaderWindowProc);

    oldListViewProc = (WNDPROC)SetWindowLong(
        ListView1->Handle,GWL_WNDPROC,(LONG)NewListViewWindowProc);

    SetHDItem();

    ListView1->Invalidate();
}
//---------------------------------------------------------------------------

 

显示效果如下

技术分享

但是,一旦拖动列头会变成这样

技术分享

所以需要有上述步骤中第4步,在HDM_LAYOUT消息中加入SetHDItem 函数调用

最终代码

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


static HWND hListViewHeader = NULL;

//Header原来的窗口过程
static WNDPROC oldHeaderWindowProc = NULL;

//listView 原来的窗口过程
static WNDPROC oldListViewProc = NULL;


void SetHDItem()
{
    if (hListViewHeader == NULL)
    {
        return;
    }

    HDITEM hditem;
    hditem.mask = HDI_FORMAT;
    hditem.fmt  = HDF_OWNERDRAW; //默认是 HDF_STRING

    int count = Header_GetItemCount(hListViewHeader);
    for (int i = 0; i < count ;i++)
    {
        Header_SetItem(hListViewHeader,i,&hditem);
    }
}

//Header的新窗口过程
LRESULT CALLBACK NewHeaderWindowProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
//先要用原来的窗口过程处理
    LRESULT result = oldHeaderWindowProc(hwnd,uMsg,wParam,lParam);
//再处理HDM_LAYOUT消息
    if (HDM_LAYOUT == uMsg)
    {
        LPHDLAYOUT phdmlayout = (LPHDLAYOUT)lParam;
        //改变header的高度
        phdmlayout->pwpos->cy = 27;
        //改变listview表格部分的高度
        phdmlayout->prc->top  = phdmlayout->pwpos->cy;
        //将HDF_STRING 重新设置为 HDF_OWNERDRAW
        SetHDItem();
    }

    return result;
}


LRESULT CALLBACK NewListViewWindowProc(
      HWND hwnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam)
{
    if (uMsg == WM_DRAWITEM)
    {
        DRAWITEMSTRUCT* drawItemStruct = (DRAWITEMSTRUCT*)lParam;
        HDC hdc = drawItemStruct->hDC;
        int index = drawItemStruct->itemID;
        RECT rect = drawItemStruct->rcItem;

        TBrush* brush = new TBrush();
        TColor fontColor = clBlack;
        if (index == 0)
        {
            brush->Color = clRed;
            fontColor    = clWhite;
        }

        if (index == 1)
        {
            brush->Color = clYellow;
            fontColor    = clBlue;
        }

        if (index == 2)
        {
            brush->Color = clBlue;
            fontColor    = clWhite;
        }

        if (index == 3)
        {
            brush->Color = clLime;
            fontColor    = clBlue;
        }

        FillRect(hdc,&rect,brush->Handle);
        delete brush;

        SetTextColor(hdc,fontColor);
        SetBkMode(hdc,TRANSPARENT);
        //获取文本
        HDITEM hditem= {0};
        char buf[100] = {0};
        hditem.mask = HDI_TEXT;
        hditem.pszText = buf;
        hditem.cchTextMax = 100;
        Header_GetItem(hListViewHeader,index,&hditem);

        DrawText(hdc,hditem.pszText,strlen(hditem.pszText),&rect,
        DT_CENTER |DT_VCENTER |DT_SINGLELINE);


    }

    return oldListViewProc(hwnd,uMsg,wParam,lParam);
}

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormCreate(TObject *Sender)
{
    hListViewHeader = ListView_GetHeader(ListView1->Handle);
    
    oldHeaderWindowProc = (WNDPROC)SetWindowLong(
        hListViewHeader,GWL_WNDPROC,(LONG)NewHeaderWindowProc);

    oldListViewProc = (WNDPROC)SetWindowLong(
        ListView1->Handle,GWL_WNDPROC,(LONG)NewListViewWindowProc);

    SetHDItem();

    ListView1->Invalidate();
}
//---------------------------------------------------------------------------

 

TListView Header重绘和高度设置

标签:

原文地址:http://www.cnblogs.com/songr/p/5572536.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!