Win32 C++ 如何在 ListView 子类中处理 LVM_SETCOLUMNWIDTH?

Win32 C++ How to handle LVM_SETCOLUMNWIDTH in a ListView subclass?

我有一个 ListView,我想根据 ListView 本身的大小调整其列的大小(根据 window 大小调整大小)。 ListView 是一个单独的 WNDPROC 子类,其中 WM_NOTIFY 用于处理其他消息。

为了调整 header 列的大小,我正在使用 ListView_SetColumnWidth(),但这仅在我停用单独的 ListView WNDPROC 或从中删除 WM_NOTIFY 处理时才有效.

我已经尝试在 ListView 及其 header 的 WNDPROC 中手动处理 LVM_SETCOLUMNWIDTH 以查看消息是否通过,但无济于事。

我不太确定如何进行;任何帮助将不胜感激。

作为参考,我的 ListView 中的 WM_NOTIFY WNDPROC:

    case WM_NOTIFY:
    {
        UINT debugval = (((LPNMHDR)lParam)->code);
        switch (((LPNMHDR)lParam)->code)
        {
            case HDN_BEGINTRACK:
            {
                return TRUE;  //Prevent manual resizing.
                break;
            }
            case LVM_SETCOLUMNWIDTH:
            {
                ::MessageBox(hwnd, L"test", L"test", MB_OK);
                break;
            }
        }
        break;
    }

LVM_SETCOLUMNWIDTH 是它自己的单独消息,它不会像您编码的那样通过 WM_NOTIFY 传递。您需要将 case LVM_SETCOLUMNWIDTH 移动到外部 switch 中。并确保您为所有不想丢弃的消息调用 CallWindowProc()DefSubclassProc()(取决于您创建子类的方式)。

试试像这样的东西:

switch (uMsg)
{
    case WM_NOTIFY:
    {
        UINT code = (((LPNMHDR)lParam)->code);
        switch (code)
        {
            case HDN_BEGINTRACK:
            {
                return TRUE;  //Prevent manual resizing.
            }
        }
        break;
    }

    case LVM_SETCOLUMNWIDTH:
    {
        ...
        break;
    }
}

return CallWindowProc(..., hwnd, uMsg, wParam, lParam);
or
return DefSubclassProc(hwnd, uMsg, wParam, lParam);

I have a ListView whose columns I'd like to resize in relation to the size of the ListView itself (which is sized based on the window size).

所以在mainwindow中需要通过SetWindowPos, and modify the size of the ListView columns through ListView_SetColumnWidth修改Listview的大小。

喜欢下面的代码:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_SIZE:
    {
        int cxClient = LOWORD(lParam);
        int cyClient = HIWORD(lParam);
        SetWindowPos(Instructions_ListView, NULL, cxClient / 3, cyClient / 4, cxClient / 5, cyClient / 2, SWP_SHOWWINDOW);
        ListView_SetColumnWidth(Instructions_ListView, 0, cxClient / 10);
        return 0;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

那么在ListView的WNDPROC函数中,LVM_SETCOLUMNWIDTH是自己独有的消息,不属于WM_NOTIFY。其他默认消息通过DefSubclassProc处理。

所以可以参考下面的代码:

LRESULT CALLBACK ListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case WM_NOTIFY:
    {
        UINT debugval = (((LPNMHDR)lParam)->code);
        switch (debugval)
        {
        case HDN_BEGINTRACK:
            return true;
        }
        break;
    }
    case LVM_SETCOLUMNWIDTH:
        OutputDebugString(L"LVM_SETCOLUMNWIDTH triggered\n");
        break;
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

终于对我有用了: