#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()
для случая по умолчанию из ListViewWNDPROC
переходит в mainWNDPROC
, а из заголовкаWNDPROC
— в ListView.3. Это работает, когда вы удаляете обработку WM_NOTIFY, поэтому очевидно, что задействовано сообщение WM_NOTIFY, и оно работает, когда вы меняете то, что вы делаете с этим сообщением. Что вы изменили?
4. Я обрабатываю только
HDN_BEGINTRACK
в ListViewWNDPROC
. Когда я добавляю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);
}
Наконец, это работает для меня: