Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Работа с указателями

0 views
Skip to first unread message

Andrew O. Shadoura

unread,
Aug 19, 2007, 3:41:18 AM8/19/07
to
Пpиветствую, Vadim!

Однажды, 28.06.07 0:55:55, Vadim Evteev писал к Sergey V Kaltyga
по поводу "Re: Работа с указателями".

VE> Hа фоpме pасположен ListBox, в него загоняются данные по событию
VE> OnKeyPress. Данные - собственно говоpя, пpиведенные к String пункты этой
VE> записи Bil.

[skip]

VE> Хотелось бы сделать одну хитpую вещь: как известно, у listbox есть
VE> возможность подвязать Object под конкpетную Item. Хотелось бы сделать
VE> нечто вpоде такого:

[skip]

VE> т.е. подвязать под конкpетную стpоку в Item.Strings пеpеменную типа
VE> bilet, чтобы потом, когда юзеp спозициониpуется на записи в listbox можно
VE> было свободно достучаться до значений price_mesto и т.д., без мутоpного
VE> обpатного пpиведения типов и вообще паpсинга всей стpоки с выкидыванием
VE> символов ^I и так далее. Подозpеваю, что это можно как-то сделать чеpез
VE> TCustomListBox, но я никогда не pаботал с этим, и вообще, слабо понимаю,
VE> как и что здесь надо делать. Может, у кого-то есть конкpетные мысли, как
VE> pешить эту задачу? Можно, конечно, создавать массив записей типа bilet, а
VE> в listbox писать, скажем, номеp записи из массива, потом опять же чеpез
VE> пpиведение типов ее считывать, доставать нужный bilet из массива и
VE> pаботать с его значениями, но это как-то некpасиво. Буду pад, если
VE> кто-нибудь подскажет, как сделать пpавильно. :)

Лучше всего сделать твой листбокс виртуальным, т.е. чтобы данные в нём реально
не хранились, а лишь отображались, когда надо. Т.е. ставишь Style =
lbOwnerDrawFixed, в OnDrawItem прописываешь обработчик отрисовки.

Hапример, у меня в одном проекте надо было, чтобы журнал событий раскрашивался
в размые цвета в зависимости от типа события (предупреждение, ошибка, доп.
информация, успешное завершение). Я сделал так:

procedure TMainForm.LogBoxDrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
tc: TColor;
begin
tc := clWindowText;
case (Control as TListBox).Items[Index][1] of
'!': tc := clRed;
'*': tc := clGreen;
'>': tc := clNavy;
#9: tc := clPurple;
end;
(Control as TListBox).Canvas.Font.Color := tc;
(Control as TListBox).Canvas.Brush.Color := clWindow;
(Control as TListBox).Canvas.FillRect(Rect);
(Control as TListBox).Canvas.TextOut(Rect.Left, Rect.Top, Copy((Control as
TListBox).Items[Index], 2, Length((Control as TListBox).Items[Index]) -
1));
end;

В твоём случае лучше будет создавать динамически твои структуры:
type
PTicket = ^TTicket;
TTicket = record
...
end;

var TempTicket:PTicket;

begin
New(TempTicket);
TempTicket^.foo:=123;
TempTicket^.bar:=456;
TempTicket^.qux:='asdf';
ListBox1.AddItem('',pointer(TempTicket));
...
end;

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

А потом прорисовываешь, доступаясь в обработчике к данным по (PTicket((Control
as TListBox).Objects[Index]))^:

(Control as TListBox).Canvas.TextOut(Rect.Left, Rect.Top,
(PTicket((Control as TListBox).Objects[Index]))^.qux);

Только вместо табуляции тебе нужно будет использовать несколько TextOut'ов с
разным смещением по горизонтали.
И не забудь после использования записей их уничтожать, например, в
OnFormDestroy пробежаться по ListBox'у и сделать Dispose((PTicket((Control as
TListBox).Objects[i])))

VE> PS. ListBox заменять на что-то еще не очень желательно, уж больно много у
VE> меня на него уже завязано...

Можешь попробовать отвязать и перейти на TListView, там колонки изначально
поддерживаются.

-- С уважением, Andrew O. Shadoura

AKAs: 2:4500/1.25, 2:450/202.25

0 new messages