Компонент-нащадок TListView з можливістю показу стрілочки в заголовку (як у Провідника Windows), Різне, Програмування, статті

Автор: Дмитро Савченко, Королівство Delphi 

При роботі над одним проектом мені знадобилося в заголовку компонента TListView відображати стрілочку, яка вказує напрямок сортування. Стандартний компонент такої можливості не надавав. Першим справою я звернувся до пошуку на Круглому столі, але не зміг знайти там підказки, як таке реалізувати. Численні пошуки в Мережі дозволили знайти тільки один безкоштовний нащадок TListView з исходниками, вміє в числі іншого і малювати потрібну стрілку (Про це компоненті буде згадано трохи нижче). “Підглянувши” реалізацію промальовування в цьому компоненті я і написав свій TatwListView.


Використання компонента

Отже, TatwListView – прямий нащадок класу TListView, в якому додано лише одне опубліковане властивість:










{Тип стрілки вгору-вниз}
TArrowType = (atUp, atDown);
{Тип нового властивості компонента}
TArrowOptions = record
SortColumnIndex: Integer;
ArrowType: TArrowType;
end;
{Само властивість}
property ArrowOptions: TArrowOptions;

Тут, думаю, все зрозуміло. Програміст змінює ця властивість в будь-якому місці коду – і потрібна стрілочка відображається в потрібній колонці. Якщо ArrowOptions.SortColumnIndex має від’ємне значення, то стрілка не відображається взагалі. ArrowOptions.ArrowType має за замовчуванням значення atUp.


Як це було зроблено

Я не буду сдесь переписувати исходник компонента – все це можна подивитися у доданих файлах з коментарями. Опишу тільки ту частину коду, де безпосередньо прорисовується стрілка.

Але спочатку слід зауважити, що, починаючи з Windows XP, ОС сама вміє малювати стрілочки. Тому для XP і вище достатньо лише вказати системі, де її малювати. А от для більш старих версій Windows намалювати стрілочку доведеться самим. Багато хто, можливо, скажуть, що тоді простіше для будь-якої версії ОС включаючи XP і Vista здійснювати власну промальовування, але у мене є на це пара заперечень:



  1. Компонент TListView є надбудовою над стандартним об’єктом Windows. Тому весь функціонал (і навіть більше, як і в нашому випадку), закладений в операційній системі, яка все ж краще знає як і де малювати ту чи іншу частину об’єкта. Не дуже раціонально, по-моєму вчити систему робити те, що вона і так вміє.

  2. Починаючи з XP, Windows можна прикрасити (хоча, може навпаки, спотворити) купою різноманітних стилів, і ніхто не може знати, як в такому-то стилі буде виглядати наша власна стрілка. А в Vista ця стрілка взагалі малюється не справа від тексту, а зверху, точно посередині колонки. Але ж ми хочемо, щоб було “також як у Провіднику”.

Тому, компонент містить два приватних методу SetColumnArrow і SetColumnArrowNonXP, які й відповідають за установку стрілки. Ось їх код:










procedure TatwListView.SetColumnArrow(ColumnIndex: Integer);
var
HeaderHndl: HWND;
Item: THDItem;
begin
{Отримуємо дескриптор заголовка нашого ListView “а}
HeaderHndl := ListView_GetHeader(Handle);
FillChar(Item, SizeOf(Item), 0);
{Значення цього оператора можна знайти в довідці від Microsoft}
Item.Mask := HDI_FORMAT;
{Отримуємо інформацію про зазначену колонці в заголовку для подальшого її зміни}
Header_GetItem(HeaderHndl, ColumnIndex, Item);
if (ColumnIndex = FArrowOptions.SortColumnIndex) then
begin
{Попередньо прибираємо обидві стрілки з прапорів параметра fmt}
Item.fmt:= Item.fmt and not (HDF_SORTDOWN or HDF_SORTUP);
{Вказуємо системі промальовувати необхідну стрілку додаванням соотв. прапора}
if FArrowOptions.ArrowType = atUp then
Item.fmt:= Item.fmt or HDF_SORTUP
else
Item.fmt:= Item.fmt or HDF_SORTDOWN;
end
{На цій колонці не треба малювати стрілку – повідомляємо про це системі}
else
Item.fmt := Item.fmt and not({HDF_BITMAP or HDF_BITMAP_ON_RIGHT or} HDF_SORTDOWN
or HDF_SORTUP);
{Застосовуємо встановлені атрибути – система сама намалює колонку}
Header_SetItem(HeaderHndl, ColumnIndex, Item);
end;
procedure TatwListView.SetColumnArrowNonXP(ColumnIndex: Integer);
var
hdr: HWND;
Item: THDItem;
begin
{Тут все так само як і в SetColumnArrow – див. вище}
hdr := Listview_GetHeader(Handle);
FillChar(Item, sizeof(Item), 0);
Item.Mask := HDI_FORMAT;
Header_GetItem(hdr, ColumnIndex, Item);
if (ColumnIndex = FArrowOptions.SortColumnIndex) then
begin
{Малюємо бітмап – цей код промальовування був запозичений з TListViewEx}
Item.Mask := Item.Mask or HDI_BITMAP;
Item.fmt := Item.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT;
if FArrowOptions.ArrowType = atUp then
Item.hbm:= FUpArrow.Handle
else
Item.hbm := FDownArrow.Handle;
end
else
Item.fmt := Item.fmt and not(HDF_BITMAP or HDF_BITMAP_ON_RIGHT);
Header_SetItem(hdr, ColumnIndex, Item);
end;

Де і як викликаються ці методи дивіться в исходниках.


Використані матеріали

Компонент TListViewEx (home.hccnet.nl/p.zylstra). Я частково використав код цього компонента. В Copyright частини модуля ListViewEx.pas зазначено, що цей компонент безкоштовний і може бути використаний в комерційних / некомерційних цілях.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*