Win32 C Как обрабатывать LVM_SETCOLUMNWIDTH в подклассе ListView?

#c #listview #winapi #subclass #win32gui

#c #listview #winapi #подкласс #win32gui

Вопрос:

У меня есть ListView, столбцы которого я хотел бы изменить в зависимости от размера самого ListView (размер которого зависит от размера окна). ListView имеет отдельный подкласс WNDPROC , в котором WM_NOTIFY используется для обработки других сообщений.

Для определения размера столбцов заголовка, которые я использую ListView_SetColumnWidth() , однако это работает только тогда, когда я деактивирую отдельный ListView WNDPROC или удаляю из него WM_NOTIFY обработку.

Я пробовал обрабатывать LVM_SETCOLUMNWIDTH вручную как WNDPROC для ListView, так и для его заголовка, чтобы узнать, передается ли сообщение, но безрезультатно.

Я не совсем уверен, как поступить; любая помощь будет с благодарностью.

Для справки, WM_NOTIFY в моем ListView 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;
    }
  

Комментарии:

1. Вызывает ли ваша пользовательская WNDPROC процедура окна по умолчанию для сообщений, которые она не обрабатывает вручную? Нравится LVM_SETCOLUMNWIDTH ?

2. CallWindowProc() для случая по умолчанию из ListView WNDPROC переходит в main WNDPROC , а из заголовка WNDPROC — в ListView.

3. Это работает, когда вы удаляете обработку WM_NOTIFY, поэтому очевидно, что задействовано сообщение WM_NOTIFY, и оно работает, когда вы меняете то, что вы делаете с этим сообщением. Что вы изменили?

4. Я обрабатываю только HDN_BEGINTRACK в ListView WNDPROC . Когда я добавляю LVM_SETCOLUMNWIDTH некоторый код, ничего не происходит.

5. Вы должны передавать все сообщения, которые вы не обрабатываете, в окно подкласса. Включая WM_NOTIFY LVM_SETCOLUMNWIDTH.

Ответ №1:

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

Ответ №2:

У меня есть ListView, столбцы которого я хотел бы изменить в зависимости от размера самого ListView (размер которого зависит от размера окна).

Итак, в главном окне вам нужно изменить размер Listview SetWindowPos и изменить размер столбцов ListView ListView_SetColumnWidth .

Например, следующий код:

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

Затем в WNDPROC функции ListView 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 triggeredn");
        break;
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
  

Наконец, это работает для меня:

введите описание изображения здесь