'Add texts with line breaks in Win32 API ListView
I am using the WC_LISTVIEW control to create a table that is filled with data at runtime. The table is working fine. However, I cannot display multiple lines in one cell.
Is there a way to use line breaks (e.g. with \n
)?
This is how I create the table:
HWND listViewErrors = CreateWindow(WC_LISTVIEW, L"",
WS_VISIBLE | WS_BORDER | WS_CHILD | LVS_REPORT | LVS_SINGLESEL,
17, 27, errorsRect.Width() - 12, errorsRect.Height() - 25,
GetWindowHandle(), (HMENU)ID_LIST_ERRORS, NULL, 0);
I add rows like this:
LVITEM lvi = { 0 };
lvi.mask = LVIF_TEXT;
lvi.pszText = L"Label of an entry";
int ret = ListView_InsertItem(hwndList, &lvi); // Main item
if (ret >= 0)
{
ListView_SetItemText(
hwndList,
ret,
1,
L"A description containing\nline breaks, but the\nline breaks will be\nignored."); // Sub item
}
return ret;
The result is that the line break character (\n
) is not visible anymore, but the text is still in a single line.
Solution 1:[1]
Unless you use custom draw or owner-draw, a LISTVIEW window never supports multi-line entries in report mode.
Even when using use custom draw or owner-draw, all rows will have the same height.
Solution 2:[2]
What @xMRi said is right.
To make WC_LISTVIEW support multi-line text:
you should set it have LVS_OWNERDRAWFIXED style. After this, you could see the ListView's content is invisible, although its header and grid line is visible.
At this time, ListView's parent window will receive WM_MEASUREITEM message. In my test, this message is received only one time. When received it, set the row height like this:
LRESULT DialogMain::OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LPMEASUREITEMSTRUCT lp = (LPMEASUREITEMSTRUCT)lParam;
//3 times of origin text height
lp->itemHeight *= 3;
return 0;
}
- When repaint, ListView's parent window will receive WM_DRAWITEM message. Each row is corresponding one message.
In WM_DRAWITEM message, draw the text manually like this:
LRESULT DialogMain::OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
if (lpdis->CtlID != IDC_LISTVIEW)
return 0;
HDC hdc = lpdis->hDC;
int index = lpdis->itemID;
for (int col = 0; col < listView.GetColumnCount(); ++col)
{
string s = listView.GetItem(index, col);
RECT rc = listView.GetGridRect(index, col);
DrawText(hdc, (LPSTR)s.c_str(), s.length(), &rc, 0);
}
return 0;
}
Notice: my method can only make ListView's every row height be fixed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Cody Gray |
Solution 2 | Tom Willow |