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

Вниз

OwnerDraw в KOLListView   Найти похожие ветки 

 
Dimaxx ©   (2003-07-16 23:33) [0]

Прошу не пинать, если повторюсь - времени мало. Как отрисовывать элементы в listview в режиме Detail. Меня интересует рисование курсора-полоски, выделение выбранных элементов цветом. Как пользоваться drawstate и itemstate? Можно с примером... Сенькс!


 
Кладов   (2003-07-17 15:54) [1]


function TForm2.LVStackLVCustomDraw(Sender: PControl; DC: HDC;
 Stage: Cardinal; ItemIdx, SubItemIdx: Integer; const Rect: TRect;
 ItemState: TDrawState; var TextColor, BackColor: Integer): Cardinal;
   procedure ProvideColors;
   begin
     if odsSelected in ItemState then
     begin
       if LVStack.Focused then
       begin
         Sender.Canvas.Brush.Color := clHighlight;
         Sender.Canvas.Font.Color := clHighlightText;
       end
         else
       begin
         Sender.Canvas.Brush.Color := Color2RGB( clBtnFace );
         Sender.Canvas.Font.Color := clWindowText;
       end;
     end
       else
     begin
       Sender.Canvas.Brush.Color := clWindow;
       Sender.Canvas.Font.Color := clWindowText;
     end;
     Sender.Canvas.DeselectHandles;
   end;

var StartAddr, ItemAddr: Integer;
   Txt: String;
   R: TRect;
   SubItem: Integer;
   SI: Integer;
begin
 if Stage and CDDS_PREERASE = CDDS_PREERASE then
 begin
   ProvideColors;
   Result := CDRF_NOTIFYITEMDRAW;
 end
   else
 if LongBool(Stage and CDDS_PREPAINT) and (ItemIdx >= 0) then
 begin
   ProvideColors;
   StartAddr := EmuZ.rSP and 1;
   ItemAddr := StartAddr + ItemIdx * 2;
   R := Sender.LVItemRect( ItemIdx, lvipBounds );
   R.Right := R.Left;
   for SI := 0 to 3 do
   begin
     CASE SI OF
     0: SubItem := ColSP;
     1: SubItem := ColAddr;
     2: SubItem := ColValue;
     else SubItem := ColChars;
     END;
     CASE SubItem OF
     ColSP: if EmuZ.rSP = ItemAddr then Txt := "SP"
                                   else Txt := "";
     ColAddr:  Txt := Int2Dig( ItemAddr, 4 );
     ColValue: Txt := Int2Dig( EmuZ.PeekWord( ItemAddr ), 4 );
     ColChars: Txt := ByteToChar( EmuZ.PeekByte( ItemAddr + 1 ) ) +
                   ByteToChar( EmuZ.PeekByte( ItemAddr ) );
     END;
     R.Left := R.Right;
     R.Right := R.Left + Sender.LVColWidth[ SubItem ];
     Sender.Canvas.TextRect( R, R.Left, R.Top, Txt );
   end;
   Result := CDRF_SKIPDEFAULT;
 end
   else
   Result := CDRF_NOTIFYITEMDRAW;
end;


 
Gandalf ©   (2003-07-17 22:48) [2]

Я пожалуй в FAQ занесу.


 
Dimaxx ©   (2003-07-17 23:32) [3]

Спасибо!!


 
Dimaxx ©   (2003-07-19 00:03) [4]

В моем приложении есть TabControl. На нем динамически создаются вкладки, а на вкладках - KOLListView в режиме Detail.

var
 LVS: array[0..15] of PControl;    // Массив динамических ListView


Мои проблемы с KOLListView:


1) После создания мне нужно прицепить на OnLVCustomDraw создаваемого ListView функцию LVDraw. Определяю эту самую функцию LVDraw:

function TMain.LVDraw(Sender: PControl; DC: HDC; Stage: cardinal; ItemIdx,SubItemIdx: integer; const Rect: TRect; ItemState: TDrawState; var TextColor,BackColor: integer): cardinal;
begin
 ...
 ...    // Отрисовка элементов
 ...
end;


далее в процедуре создания ListView пишу:

...
LVS[<индекс>].OnLVCustomDraw:=TOnLVCustomDraw(MakeMethod(LVS[<индекс>],@LVDraw));
...


А компилятор ругается на @LVDraw, типа, нужна переменная. Какая, к чертям, переменная??!! Как правильно динамически прикрутить событие?


2) Далее. Мне нужно, чтобы при активации какой-либо вкладки фокус переходил на соответствующий ListView (с выбором элемента 0), который на ней лежит. Пишу в событии OnChange (также динамически этот ListView уже заполнен необходимой информацией):

...
LVS[<индекс>].CurItem:=0;
...


Получаю Access violation...!!!!! По идее, ListView должен получить фокус и выбрать самый верхний элемент! Шиш!!! Так где я не прав?

Спасибо!


 
Gandalf ©   (2003-07-19 10:31) [5]


> LVS[<индекс>].OnLVCustomDraw:=TOnLVCustomDraw(MakeMethod(LVS[<индекс>],@LVDraw));


А LVDraw то твонму что? LVS[<индекс>].OnLVCustomDraw:=VDraw;

> LVS[<индекс>].CurItem:=0;


Разве трудно запомнить что для ListView - все фишки начинаются с LV? Попробуй LVS[<индекс>].LVCurItem:=0;


 
Кладов   (2003-07-19 11:37) [6]

Это уже метод, зачем же его через MakeMethod пытаться в метод превращать. Чтобы не ошибаться, проще всего сделать так. Положить в design-time на формы TKOLListView, обычным способом создать обработчик события (достаточно между begin и end вставить комментарий //). Событие можно в ObjectInspector"е переименовать по вкусу. Теперь ненужный list view с формы можно удалить. Присваивать событие обычным :=, без всяких премудростей. Это метод формы, при вызове он получает первый (невидимый) параметр Self - объект формы, второй у него Sender, и дальше как объявлено.

По 2), разберитесь, что такое LVS[ ], и чем оно заполнено. И что за CutItem. В list view LVCurItem - это первая или единственная строка. У вас же есть возможность остановиться в нужном месте и исследовать, что в этот момент чему равно.


 
Dimaxx ©   (2003-07-19 23:44) [7]

С событием разобрался - все навешивается. Спасибо!

2 Gandalf: LVS[<индекс>].LVCurItem:=0 не помогает - все равно Access violation...


 
Dimaxx ©   (2003-07-22 01:15) [8]

Что-то опять не пойму со своим массивом ListView!

Элемент массива с индексом 0 содержит PControl от ListView, созданного в design-time. Далее я написал процедуру динамического создания новых ListView:

procedure CreateListView(Parent: PControl; P: array of PControl);
var I: integer;
begin
 //
 // Переменная I содержит индекс первого свободного в массиве PControl (<>nil)
 //
 P[I]:=NewListView(Parent,lvsDetail,[lvoIconLeft,lvoEditLabel,lvoMultiselect,lvoRowSelect,lvoOwnerDrawFixed],nil,nil,nil);
 P[I].Align:=caClient;
 P[I].Font.FontStyle:=[fsBold];
 P[I].LVColAdd("AAA",taLeft,242);
 P[I].LVColAdd("BBB",taLeft,39);
 P[I].LVColAdd("CCC",taRight,67);
 P[I].LVColAdd("DDD",taLeft,99);
 P[I].LVColAdd("EEE",taLeft,34);
 P[I].LVBkColor:=clBtnFace;
 P[I].LVTextBkColor:=clBtnFace;
 P[I].OnLVCustomDraw:=LVDraw;

 // Далее идет заполнение элементов по умолчанию первичной информацией - это не интересно

 P[I].LVControl.Visible:=True;
end;


Вызываю ее из другой процедуры:

var NP: PControl;
begin
 ...
 NP:=TabControl.TC_Insert(TabControl.Count,"ABC",-1);
 // Передаем тот самый массив PControl
 CreateListView(NP,LVS);
 ...
end;


Далее. Если поставить бряк на последнюю команду в процедуре создания и посмотреть содержимое массива Р, то оказывается следующее:

Элемент 0 - не изменился (он был занесен при создании формы)
Элемент 1 - новый, только что созданный ListView. Все вроде бы о"кэй.
Остальные равны nil, так как не заполнены еще.

Дальше - самое интересное! На форме (то бишь на вкладке TabControl"а) ListView отображается, данные в него занесены при создании правильно (присутствуют и редактируются, так как включен режим редактирования), но режим OwnerDraw не действует. Смотрю в массив после завершения всех этих операций, а там исчез только что созданный ListView!!!!! Вместо него стоит nil! Как быть? Может, кто посоветует другой способ хранения информации о динамически создаваемых контролах? Нужна возможность удалять и создавать динамически.


 
Dimaxx ©   (2003-07-24 23:29) [9]

Ответ нашелся сам собой. Я несколько упростил вопрос: у меня PControl лежат не в массиве, а в массиве записей как элемент записи:

var LVS: array[0..31] of record
     ...
     LV: PControl;
     ...
   end;


Оказывается, в этом случае и происходит сброс. А если записано array of PControl, то все в порядке и ничего не теряется.



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

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

Наверх




Память: 0.5 MB
Время: 0.033 c
1-1079528045
Andrey_ck
2004-03-17 15:54
2004.04.04
Работа со строками


6-1075220897
*partizan*
2004-01-27 19:28
2004.04.04
Сетевые компоненты в Delphi7


7-1072072538
Ilkhom
2003-12-22 08:55
2004.04.04
Лицинзионные программы


14-1078751910
Undert
2004-03-08 16:18
2004.04.04
Весна ...


1-1079614201
WebErr
2004-03-18 15:50
2004.04.04
SystemBorder := false ==> Big trouble!!!