Фильтр столбцов в ListView на Win API - PullRequest
2 голосов
/ 05 марта 2020

Я провожу некоторые исследования и хотел бы узнать, как я могу реализовать фильтр столбцов в ListView, используя чисто win32 API.

Примерно так:

enter image description here

Я написал простой тестовый код, чтобы сгенерировать представление списка для отображения содержимого CSV.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <commctrl.h>
#include <string.h>

#define WND_CLASS_NAME "CSVVIEW"

char* filename;
HWND  hList;

int rgb(int r, int g, int b) { return r + (g << 8) + (b << 16); }

void onCreate(HWND hWnd, LPARAM lParam) {
    LVCOLUMN col;
    LVITEM item;
    int iCol, iCount, dwStyle;
    CREATESTRUCT* lp = (CREATESTRUCT*)lParam;
    FILE* fp;
    char buf[256];
    char* field;

    memset(&item, 0, sizeof(item));
    hList = CreateWindowEx(0, WC_LISTVIEW, 0,
        WS_CHILD | WS_VISIBLE | LVS_REPORT,
        0, 0, 100, 100, hWnd, (HMENU)1, lp->hInstance, NULL);
    dwStyle = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
    dwStyle = dwStyle | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT |
        LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP;
    SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
    col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;

    fp = fopen(filename, "r");
    if (fp == NULL) {
        sprintf(buf, "Fail to open the file...", filename);
        MessageBox(hWnd, buf, "Error", MB_OK);
        exit(1);
    }
    fgets(buf, 255, fp);
    field = strtok(buf, ",");
    for (iCol = 0; field != NULL; iCol++) {
        if (field[1] != ':') { col.fmt = LVCFMT_LEFT; }
        else if (field[0] == 'l') { col.fmt = LVCFMT_LEFT;   field += 2; }
        else if (field[0] == 'c') { col.fmt = LVCFMT_CENTER; field += 2; }
        else if (field[0] == 'r') { col.fmt = LVCFMT_RIGHT;  field += 2; }
        col.cx = strlen(field) * 13;
        col.iSubItem = iCol;
        col.pszText = field;
        SendMessage(hList, LVM_INSERTCOLUMN, iCol, (LPARAM)&col);
        field = strtok(NULL, ",\n");
    }

    item.mask = LVIF_TEXT;
    for (iCount = 0; fgets(buf, 255, fp) != NULL; iCount++) {
        item.pszText = strtok(buf, ",");
        item.iItem = iCount;
        item.iSubItem = 0;
        SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&item);
        for (iCol = 1; (field = strtok(NULL, ",\n")) != NULL; iCol++) {
            item.pszText = field;
            item.iItem = iCount;
            item.iSubItem = iCol;
            SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&item);
        }
    }
}

void onSize(HWND hwnd, WPARAM wp, LPARAM lp) {
    RECT rc;
    GetClientRect(hwnd, &rc);
    MoveWindow(hList, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

int onNotify(HWND hwnd, WPARAM wp, LPARAM lp) {
    NMHDR* pnmhdr = (NMHDR*)lp;
    if (pnmhdr->code == NM_CUSTOMDRAW) {
        NMLVCUSTOMDRAW* lpCustomDraw = (NMLVCUSTOMDRAW*)pnmhdr;
        switch (lpCustomDraw->nmcd.dwDrawStage) {
        case CDDS_PREPAINT:
            return CDRF_NOTIFYITEMDRAW;
        case CDDS_ITEMPREPAINT:
            if (lpCustomDraw->nmcd.dwItemSpec % 2 == 1)
                lpCustomDraw->clrTextBk = rgb(209, 240, 179);
            else
                lpCustomDraw->clrTextBk = rgb(250, 250, 250);
            return CDRF_NEWFONT;
        }
    }
    return DefWindowProc(hwnd, WM_NOTIFY, wp, lp);
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_CREATE:  onCreate(hWnd, lParam);  break;
    case WM_SIZE:    onSize(hWnd, wParam, lParam);  break;
    case WM_NOTIFY:  return onNotify(hWnd, wParam, lParam);
    case WM_DESTROY: PostQuitMessage(0);  break;
    default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    char buf[256];
    HWND hWnd;
    WNDCLASS wcl;
    MSG msg;

    filename = lpCmdLine;
    if (filename == NULL) return FALSE;
    InitCommonControls();

    memset(&wcl, 0, sizeof(wcl));
    wcl.hInstance = hInstance;
    wcl.lpszClassName = WND_CLASS_NAME;
    wcl.lpfnWndProc = WindowProc;
    wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcl.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    if (!RegisterClass(&wcl)) return FALSE;

    wsprintf(buf, "%s - %s", "CSV View", lpCmdLine);
    hWnd = CreateWindowEx(0, WND_CLASS_NAME, buf,
        WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 900, 300, NULL, NULL, hInstance, NULL);
    if (!hWnd) return FALSE;

    while (GetMessage(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

Файл теста CSV:

COL 1,COL 2,COL 3,COL 4
CA_002,CB_002,CB_002,CB_002
CA_003,CB_003,CB_003,CB_003

Что необходимо изменить в коде, чтобы можно было создавать поля поиска в заголовке представления списка?

Как захватить события для каждого текстового поля в заголовке?

...