zoukankan      html  css  js  c++  java
  • listView表头重绘


    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
    说明 :
    该代码可以自由引用, 包括商业应用. 希望转载时尊重作者的署名权利.
    学习交流请来信a-few@netease.com.

    #ifndef Unit1H
    #define Unit1H
    // ---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ComCtrls.hpp>

    // ---------------------------------------------------------------------------
    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 <vcl.h>
    #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, &ps);
            hPen = SelectObject(ps.hdc, GetStockObject(DC_PEN));
            iCount = Header_GetItemCount(g_hListViewHeader); // 获取表头数目
    // 本文转自 C++Builder研究 - http://www.ccrun.com/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 (int i = 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:
            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);
    }

  • 相关阅读:
    关于OI的文学作品
    HBOI 2020 游记
    从0开始的字符串生活(选手命要没了)
    近两年HBOI选做
    NOI online #3
    2020年“美团杯”程序设计挑战赛题解(目前只有测试赛)
    退群咕咕墙
    JS 获得当前地址栏url
    你了解getBoundingClientRect()?
    字符串与数字相加
  • 原文地址:https://www.cnblogs.com/victoria-c/p/6673372.html
Copyright © 2011-2022 走看看