Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.09.04;
Скачать: CL | DM;

Вниз

отрисовка Items в tlistbox   Найти похожие ветки 

 
stay unknown   (2011-05-12 15:57) [0]

Нужно рисовать айтемы листбокса.

Кажды айтем должен получится вида:

Тип:           Телевизор ЖК \ ТВ
Производитель: Samsung
Модель:        UE37C6540SW

Слева еще иконка товара будет. Вопрос: как лучше организовать отрисовку:

- написать функцию, что-то типа:


function DrawBlockProductDescription(Canvas: TCanvas; X, Y: Int; Margins: TMargins; Bitmap: TBitmap): TRect;


- написать класс.

Что посоветуете?


 
Kerk ©   (2011-05-12 15:58) [1]

Да функции хватит. Зачем тут целый класс.


 
b z   (2011-05-12 16:02) [2]


> Что посоветуете?
ListView


 
Лукошко   (2011-05-12 16:31) [3]

Есс-но, это - простой пример на скорую руку, сделай нормально.

Класс товара:


type
TItem=class
 public
   tp:string;
   ds:string;
   md:string;
 end;


В коде:


{заполнение листбокса товаром}
procedure TForm1.Button1Click(Sender:TObject);
var
 i:integer;
 item:TItem;
begin
 for i:=1 to 10 do begin
   item:=TItem.Create;
   item.tp:="Тип продукции: "+IntToStr(i)+" DFG";
   item.ds:="Производитель продукции: "+IntToStr(i)+" manufacture";
   item.md:="Модель: "+IntToStr(i)+" serial";
   ListBox1.AddItem(item.tp,item);
 end;
end;

{отрисовка}
procedure TForm1.ListBox1DrawItem(Control:TWinControl; Index:Integer; Rect:TRect; State:TOwnerDrawState);
var
 LoadIndex:integer;
 Bitmap:TBitmap;
 BMPRect:TRect;
 ColorRect:TRect;
begin
 with TListBox(Control),Canvas do begin
   {выделяем выделение :o)}
   if odSelected in State then Brush.Color:=$00FAEADC
   else Brush.Color:=clWindow;
   FillRect(Rect);
   {рисуем разделители}
   Pen.Style:=psDot;
   Pen.Color:=clGray;
   MoveTo(128,Rect.Top);
   LineTo(128,Rect.Bottom);
   MoveTo(Rect.Left,Rect.Bottom-1);
   LineTo(Rect.Right,Rect.Bottom-1);
   {левая строка}
   Font.Color:=clNavy;
   Font.Size:=8;
   Font.Style:=[fsBold];
   TextOut(Rect.Left+20,Rect.Top+2,TItem(Items.Objects[index]).md);
   {верхняя строка}
   Font.Color:=clBlack;
   Font.Size:=8;
   Font.Style:=[fsBold];
   TextOut(Rect.Left+150,Rect.Top+2,TItem(Items.Objects[index]).tp);
   {нижняя строка}
   Font.Color:=clMaroon;
   Font.Size:=7;
   Font.Style:=[];
   TextOut(Rect.Left+166,Rect.Top+17,TItem(Items.Objects[index]).ds);
   {убираем рамку}
   if odFocused in State then DrawFocusRect(Rect);
 end;
end;


 
Лукошко   (2011-05-12 16:37) [4]

Рисовка иконки из иконлиста:

BlaBlaImageList.Draw(TListBox(Control).Canvas,10,Rect.Top+5,IconIndex,true);


Рисовка иконки из битмапа:

   {рисуем иконку}
var
 Bitmap:TBitmap;
 BMPRect:TRect;
begin
   Bitmap:=TBitmap.Create;
   try
     Bitmap.LoadFromFile({путь к файлу, к примеру});
     if Bitmap<>nil then begin
       BMPRect:=Bounds(36,Rect.Top+7,16,16);
       BrushCopy(BMPRect,Bitmap,Bounds(0,0,Bitmap.Width,Bitmap.Height),Bitmap.Canvas.Pi xels[15,0]);
     end;
   finally
     Bitmap.Free;
   end;
end;


 
Лукошко   (2011-05-12 16:39) [5]

У листбокса должен быть style=lbOwnerDrawVariable или lbOwnerDrawFixed.
Первый - для разных по высоте итемов, если мне не изменяет память.


 
KilkennyCat ©   (2011-05-12 17:12) [6]


> type
> TItem=class
>  public
>    tp:string;
>    ds:string;
>    md:string;
>  end;
>

из пушки по воробьям.


 
clickmaker ©   (2011-05-12 17:39) [7]

> из пушки по воробьям

почему? У него же реальный объект "Телевизор" с параметрами, как раз тянет на класс


 
Лукошко   (2011-05-12 17:45) [8]


> KilkennyCat ©   (12.05.11 17:12) [6]

Так удобнее же.
Хотя можно и рекорд, и вообще строку с разделителями :o)


 
stay unknown   (2011-05-12 18:05) [9]

с отрисовкой разобрался, теперь сложность в другом. айтем может быть 3 видов:

Тип:           Телевизор ЖК \ ТВ
Производитель: Samsung
Модель:        UE37C6540SW

Тип:         не найден (<ID типа>)

Модель:      не найдена (<ID модели>)

Размер айтема напрямую зависит от высоты блока рисуемой информации в событии OnDrawItem. Как динамически менять его размер. Знаю что размер можно менять в OnMeasureItem, но как из события узнать высоту нарисованного блока.


 
clickmaker ©   (2011-05-12 18:09) [10]

> как из события узнать высоту нарисованного блока

Canvas.TextHeight


 
stay unknown   (2011-05-12 18:27) [11]

Я про другое

у меня размер блока выводимой информации рассчитывается на момент отрисовки (не для всех Items он одинаковый). Сам блок представляет собой несколько TextOut"ов разделенных между собой.

Все возможные варианты.

(1)

Тип:           Телевизор ЖК \ ТВ
Производитель: Samsung
Модель:        UE37C6540SW

(2)

Тип:           Телевизор ЖК \ ТВ
Производитель: Samsung

(3)

Производитель: Samsung
Модель:        UE37C6540SW

(4)

Тип:           Телевизор ЖК \ ТВ
Модель:        UE37C6540SW

(5)

Тип:           Телевизор ЖК \ ТВ

(6)

Производитель: Samsung

(7)

Модель:        UE37C6540SW

Блок 1 - одного размера, 2, 3, 4 - другого, 5,6,7 - третьего

Как из OnMeasureItem получить высоту отрисованного блока для I-ого айтема


 
KilkennyCat ©   (2011-05-12 18:32) [12]


> clickmaker ©   (12.05.11 17:39) [7]

потому, что тут достаточно

> Лукошко   (12.05.11 17:45) [8]


как-то привык, что в переменных хранятся данные того же типа, что и переменная (а не использование, например, строковых для чисел). Это удобно. При виде класса я буду предполагать наличие гораздо большего, чем пара переменных.


 
Игорь Шевченко ©   (2011-05-12 18:34) [13]


> Как из OnMeasureItem получить высоту отрисованного блока
> для I-ого айтема


item же передается, по нему и вычислить


 
KilkennyCat ©   (2011-05-12 18:35) [14]


> Как из OnMeasureItem получить высоту отрисованного блока
> для I-ого айтема

высчитать сразу при отрисовке.


 
Лукошко   (2011-05-12 18:46) [15]

Меняем условие:

{заполнение листбокса товаром}
procedure TForm1.Button1Click(Sender: TObject);
var
 i:integer;
 item:TItem;
begin
 for i:=1 to 10 do begin
   item:=TItem.Create;
   item.tp:="Тип продукции: "+IntToStr(i)+" DFG";
   if (i mod 2)=0 then item.ds:="Производитель продукции: "+IntToStr(i)+" manufacture"
   else item.ds:="";
   item.md:="Модель: "+IntToStr(i)+" serial";
   ListBox1.AddItem(item.ds,item); //обрати внимание - передаю другой итем
 end;
end;


Вычисление высоты:

{меняем высоту итема}
procedure TForm1.ListBox1MeasureItem(Control:TWinControl; Index:Integer; var Height:Integer);
begin
 if TListBox(Control).Items[Index]="" then Height:=20;
end;


ЗЫ: Обрати внимание, объект item в AddItem добавляется ПОСЛЕ вызова MeasureItem


 
Лукошко   (2011-05-12 18:50) [16]


> KilkennyCat ©   (12.05.11 18:32) [12]

Ну так-то согласен, рекорд понятнее.


> Игорь Шевченко ©   (12.05.11 18:34) [13]

В том-то и дело, что ещё не передался Item, только после OnMeasureItem добавляется ссылка. Ну или ткните меня носом :o)


 
clickmaker ©   (2011-05-12 18:58) [17]

> Ну так-то согласен, рекорд понятнее

вообще, объектную модель не гуй должен диктовать. Сегодня листбокс, а завтра разноцветный суперпупергридвью какой-нить с хедерами и футерами.


 
Игорь Шевченко ©   (2011-05-12 19:10) [18]


> В том-то и дело, что ещё не передался Item, только после
> OnMeasureItem добавляется ссылка. Ну или ткните меня носом
> :o)


http://msdn.microsoft.com/en-us/library/bb775925(v=vs.85).aspx


 
Лукошко   (2011-05-12 19:18) [19]


> clickmaker ©   (12.05.11 18:58) [17]

Дык я и не настаивал. Для данного примера вообще пофигу, как объявить, это жыж просто пример для автора топика.


> Игорь Шевченко ©   (12.05.11 19:10) [18]

Прочитал.


 
Игорь Шевченко ©   (2011-05-12 19:24) [20]

Лукошко   (12.05.11 19:18) [19]


> Прочитал.


Там написано, что сообщение посылается в зависимости от стиля, если стиль с элементами фиксированной высоты, то один раз для контрола, если стиль с элементами разной высоты, то для каждого элемента.
Поэтому фраза

> только после OnMeasureItem добавляется ссылка

в этом контексте звучит слегка некорректно


 
Лукошко   (2011-05-12 19:37) [21]


> Игорь Шевченко ©   (12.05.11 19:24) [20]

Я понял, что там написано :o)
Да, согласен, немного не так. Ну так у автора как раз вэриэйбл высота, сообщение посылается каждый раз. Но ещё до добавления ссылки на объект в AddObject"е.


 
Игорь Шевченко ©   (2011-05-12 21:16) [22]

Лукошко   (12.05.11 19:37) [21]

Все, сообразил.

TListBoxStrings.Add посылает LB_ADDSTRING, а Object к этому моменту еще не установлен, потому что TStrings.AddObject сначала выполняет Add, а потом PutObject

Я бы в таком случае хранил список объектов отдельно и использовал бы виртуальный ListBox


 
Лукошко   (2011-05-12 21:32) [23]


> Игорь Шевченко ©   (12.05.11 21:16) [22]

Я именно так и сделал, виртуальный ListBox. Вообще, не очень удобно сделано в генофонде, много лишнего надо писать.

Автор топика, думаю, может обойтись > Лукошко   (12.05.11 18:46) [15]


 
Dimka Maslov ©   (2011-05-12 22:13) [24]

Что мешает воспользоваться компонентом TListView, у которого уже есть возможность отрисовки иконок?


 
Германн ©   (2011-05-13 02:47) [25]


> Dimka Maslov ©   (12.05.11 22:13) [24]
>
> Что мешает воспользоваться компонентом TListView, у которого
> уже есть возможность отрисовки иконок?
>

А при чем тут "возможность отрисовки иконок"?


 
Лукошко   (2011-05-13 15:12) [26]

Так вот старался-старался, писал, собирал у себя готовый код, а автор даже спасибо не сказал :o(
У вас тут все студенты неблагодарные?


 
KilkennyCat ©   (2011-05-13 18:10) [27]


> Лукошко   (13.05.11 15:12) [26]

настоящие герои плюют на признание толпы.


 
Лукошко   (2011-05-13 19:10) [28]


> KilkennyCat ©   (13.05.11 18:10) [27]

Хыхы
Мне до героя далекоооо... :o)



Страницы: 1 вся ветка

Текущий архив: 2011.09.04;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.009 c
2-1305269551
ixen
2011-05-13 10:52
2011.09.04
DBGridEh и отображение содержимого BLOB поля


1-1265825105
Дмитрий Белькевич
2010-02-10 21:05
2011.09.04
Особенность создания компонентных врапперов OLE


2-1305899107
Leon-Z
2011-05-20 17:45
2011.09.04
ADOTable.LoadFromFile(...)


4-1248422295
Dmitriy
2009-07-24 11:58
2011.09.04
как определить соединение


8-1215423834
Лол
2008-07-07 13:43
2011.09.04
Выввод изображения в подсказке хинт