ListView_HitTest 函数是 Windows API 中用于执行鼠标点击测试(hit testing)的函数,特别是用于在列表视图控件中确定指定坐标下的子项和子项的部分。该函数定义在 Commctrl.h 头文件中,用于操作 Windows 上的列表视图控件。

以下是 ListView_HitTest 函数的一般格式:
int ListView_HitTest(
  HWND     hwnd,
  LVHITTESTINFO *pinfo
);

  •  参数 hwnd 是列表视图控件的句柄。

  •  参数 pinfo 是一个指向 LVHITTESTINFO 结构的指针,用于指定测试坐标并接收测试结果。


LVHITTESTINFO 结构的定义如下:
typedef struct tagLVHITTESTINFO {
  POINT pt;
  UINT  flags;
  int   iItem;
  int   iSubItem;
  int   iGroup;
} LVHITTESTINFO, *LPLVHITTESTINFO;

  •  pt 是一个 POINT 结构,用于指定测试坐标。

  •  flags 是一个表示测试结果的标志集。

  •  iItem 是子项的索引。

  •  iSubItem 是子项的子项索引(在详细信息视图中使用)。

  •  iGroup 是组的索引(在分组的列表视图中使用)。


函数返回一个整数,表示测试的结果,可以是以下常量之一:

  •  LVHT_NOWHERE:测试坐标不在列表视图的任何位置。

  •  LVHT_ONITEMICON:测试坐标在子项图标上。

  •  LVHT_ONITEMLABEL:测试坐标在子项标签上。

  •  LVHT_ONITEMSTATEICON:测试坐标在子项状态图标上。

  •  LVHT_ONITEM:测试坐标在子项的任何部分。

  •  LVHT_ONITEMINDENT:测试坐标在子项的缩进部分(在详细信息视图中使用)。

  •  LVHT_ONITEMBUTTON:测试坐标在子项的按钮上。

  •  LVHT_ONITEMRIGHT:测试坐标在子项的右侧。

  •  LVHT_ONITEMSTATEICON:测试坐标在子项的状态图标上。

  •  LVHT_ABOVE:测试坐标在列表视图的上方。

  •  LVHT_BELOW:测试坐标在列表视图的下方。

  •  LVHT_TORIGHT:测试坐标在列表视图的右侧。

  •  LVHT_TOLEFT:测试坐标在列表视图的左侧。


下面是一个简单的示例代码,演示如何使用 ListView_HitTest 函数:
#include <windows.h>
#include <commctrl.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_LBUTTONDOWN: {
            // 获取鼠标坐标
            POINT pt;
            GetCursorPos(&pt);
            ScreenToClient(hwnd, &pt);

            // 执行点击测试
            LVHITTESTINFO hitTestInfo;
            hitTestInfo.pt = pt;
            int hitResult = ListView_HitTest(hwnd, &hitTestInfo);

            // 处理测试结果
            if (hitResult & LVHT_ONITEM) {
                MessageBox(NULL, L"Click on item!", L"Hit Test Result", MB_OK);
            } else {
                MessageBox(NULL, L"Click outside items!", L"Hit Test Result", MB_OK);
            }
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

int main() {
    // 初始化 Common Controls Library
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&icex);

    // 创建主窗口
    HWND hwndMain = CreateWindowEx(0, WC_LISTVIEW, L"ListView_HitTest Example",
        WS_OVERLAPPEDWINDOW | LVS_REPORT | LVS_SINGLESEL, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL, NULL, GetModuleHandle(NULL), NULL);

    // 添加一列以便能够看到列表视图的显示
    LVCOLUMN lvColumn;
    lvColumn.mask = LVCF_TEXT | LVCF_WIDTH;
    lvColumn.pszText = L"Column 1";
    lvColumn.cx = 200;
    ListView_InsertColumn(hwndMain, 0, &lvColumn);

    // 添加一些项以便能够点击测试
    LVITEM lvItem;
    lvItem.mask = LVIF_TEXT;
    lvItem.iItem = 0;
    lvItem.iSubItem = 0;
    lvItem.pszText = L"Item 1";
    ListView_InsertItem(hwndMain, &lvItem);

    lvItem.iItem = 1;
    lvItem.pszText = L"Item 2";
    ListView_InsertItem(hwndMain, &lvItem);

    // 设置窗口过程
    SetWindowLongPtr(hwndMain, GWLP_WNDPROC, (LONG_PTR)WindowProc);

    // 显示窗口
    ShowWindow(hwndMain, SW_SHOWNORMAL);
    UpdateWindow(hwndMain);

    // 进入消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

在这个示例中,当用户在列表视图中单击鼠标左键时,将执行点击测试,检查鼠标位置是否在列表视图的子项上。然后根据测试结果显示相应的消息框。


转载请注明出处:http://www.zyzy.cn/article/detail/24739/Win32 API/Commctrl.h/ListView_HitTest