【问题标题】:Win32 C++ How to handle LVM_SETCOLUMNWIDTH in a ListView subclass?Win32 C++ 如何处理 ListView 子类中的 LVM_SETCOLUMNWIDTH?
【发布时间】:2021-01-31 04:18:49
【问题描述】:

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

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

我尝试在 WNDPROC 中手动处理 ListView 及其标题的 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;
    }

【问题讨论】:

  • 您的自定义WNDPROC 是否为它不手动处理的消息调用默认窗口过程?喜欢LVM_SETCOLUMNWIDTH
  • CallWindowProc() 的默认情况从 ListView WNDPROC 转到主 WNDPROC 和从标题的 WNDPROC 到 ListView 的。
  • 当您删除 WM_NOTIFY 处理时它起作用,因此显然涉及 WM_NOTIFY 消息,并且当您更改对该消息的处理时它起作用。你改变了什么?
  • 我只在 ListView WNDPROC 中处理 HDN_BEGINTRACK。当我用一些代码添加LVM_SETCOLUMNWIDTH 时,什么也没有发生。
  • 您必须将您不处理的所有消息传递给子类窗口。包括 WM_NOTIFY + LVM_SETCOLUMNWIDTH。

标签: c listview winapi subclass win32gui


【解决方案1】:

我有一个 ListView,我想根据 ListView 本身的大小(根据窗口大小调整大小)调整其列的大小。

所以在主窗口需要通过SetWindowPos修改Listview的大小,通过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);
}

最后,它对我有用:

【讨论】:

    【解决方案2】:

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 2013-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-23
      相关资源
      最近更新 更多