У меня есть несколько элементов управления списком (TListView), которые используются для отображения данных. Все эти списки имеют режим «Подробный», и все они имеют TImageList, присвоенные их свойствам «SmallIcons».Как правильно установить размер столбца ListView в соответствии с его содержимым?
Я пытаюсь установить ширину этого столбца на основе их содержимого точно так же, как если бы пользователь дважды нажал на ползунок разделителя в конце каждого заголовка столбца.
Во-первых, я попытался установить ширину столбца на «-1» и «-2» для их автоматической калибровки: это не только отлично работало (некоторые столбцы, содержащие локальные символы), я использую D6 и это означает, что строки ANSI - слишком низки), но он также сделал отображение столбца чрезвычайно медленным (до 30 секунд, чтобы отобразить представление списка с 6 столбцами и 150 элементами, когда оно мгновенно с фиксированной шириной).
Я попытался использовать GetTextExtent в каждой ячейке, чтобы получить ожидаемую ширину текста, добавив некоторый запас (от 2 до 10 пикселей) и расширив ширину столбца, если он меньше расчетной ширины текста. Специальная обработка применяется к первому столбцу (Items.caption), чтобы учесть отображение значка (я добавляю ширину значка плюс маржа к ширине текста ячейки).
Это также не работает: во многих случаях (например, отображение даты в формате «yyyy/mm/dd hh: nn: ss» приводит к слишком большому тексту, чтобы соответствовать столбцу).
Думаю, что проблема может возникнуть из движка темы окна, я переключился на использование GetThemeTextExtent вместо GetTextExtent, но получил тот же результат.
Единственное, что, кажется, работает, это добавить произвольный большой запас (20 пикселей) к каждой ширине столбца, но, конечно, он создает столбцы, которые больше, чем они должны быть.
Итак, есть ли альтернативная стратегия? Мне не нужно ничего, кроме того, что будет вычислять правильную ширину один раз: когда список сначала заполняется. Код, стоящий за «щелчком разделителя столбцов», работает просто отлично, но я не могу найти, как его запускать с помощью кода (ну, я думаю, я мог бы отправлять сообщения двойного щелчка в заголовок непосредственно как взломать)
Для уточнения , вот что я попробовал следующий код:
(в случае вызова есть звонок, сделанный в ListView.canvas.Font.Assign(ListView.font)
. Он не находится в функции тезисов, потому что одного назначения достаточно, но петли кода на всех неавторизованных столбцах списка).
Редактировать
Моя первая попытка с помощью Windows Theme API:
function _GetTextWidth1(AText: widestring; IsHeader: boolean = false): Integer;
var
ATheme: HTheme;
rValue: TRect;
iPartID: integer;
AWidetext: WideString;
const
LVP_GROUPHEADER = 6;
begin
// try to get text width using theme API
ZeroMemory(@rValue, SizeOf(rValue));
ATheme := OpenThemeData(ListView.Handle, 'LISTVIEW');
try
if not IsHeader then
iPartID := LVP_LISTITEM
else
iPartID := LVP_GROUPHEADER;
AWidetext := AText;
GetThemeTextExtent(ATheme,
ListView.Canvas.Handle,
iPartID,
LIS_NORMAL,
PWideChar(AWidetext),
-1,
DT_LEFT or DT_SINGLELINE or DT_CALCRECT,
nil,
rValue
);
finally // wrap up
CloseThemeData(ATheme);
end; // try/finally
result := rValue.Right;
end;
следующую попытку с помощью DrawText/DrawTextW:
function _GetTextWidth2(AText: widestring; IsHeader: boolean = false): Integer;
var
rValue: TRect;
lFlags: Integer;
begin
// try to get text width using DrawText/DrawTextW
rValue := Rect(0, 0, 0, 0);
lFlags := DT_CALCRECT or DT_EXPANDTABS or DT_NOPREFIX or DT_LEFT or DT_EXTERNALLEADING;
DrawText(ListView.canvas.Handle, PChar(AText), Length(AText), rValue, lFlags);
//DrawTextW(ListView.canvas.Handle, PWideChar(AText), Length(AText), rValue, lFlags);
result := rValue.Right;
end;
функция TextWidth
Третья попытка с использованием Делфи
function _GetTextWidth3(AText: widestring; IsHeader: boolean = false): Integer;
begin
// try to get text width using delphi wrapped around GetTextExtentPoint32
result := ListView.canvas.TextWidth(Atext);
end;
Во всех случаях я добавляю маржу к полученной ширине: я пробовал значения до 20 пикселей. Я также учитываю возможность использования значков с изображением (в этом случае я добавляю ширину значка плюс поле снова в первый столбец).
Это можно сделать с помощью 'DrawText', используя флаг' DT_CALCRECT', например: http://stackoverflow.com/questions/16343147/how-do-i-use-drawtext-dt-calcrect-properly –
Спасибо но я просто попробовал это и используя DrawText дает * точно * тот же результат, что и с использованием GetTextExtent. – Stephane