![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Добавление published свойства
RASkov © (2006-09-10 05:27:00)Подскажите пожалуйста как при написании компанента добавить ему паблишед свойство чтобы в инспекторе объектов, значение свойства выбиралось из выподающего списка. В список должны добавляться компаненты имеющиеся на форме и имеющие Canvas. В написании компанент опыта мало т.е. нет.
TMyCompanent = class(TCompanent)
private
FCanvas: TCanvas;
....
published
property Canvas: TCanvas ....?????...
....
end;
Можно кусок примера как это делается. Т.е. если "кинуть" мой компанент на читую("голую") форму то в Инсп.Объектов у моего компанента в списке свойства Canvas должна быть Form1. Бросили на форму Image1 - и его в список. Ну и так всех у кого есть канва.
RASkov (2006-10-02 16:33:00) [41]
> DimaBr (02.10.06 16:10) [79]
Спасибо за индех. То что надо.
> Лучше всего организовать правильно, иначе плохо будет работать
> :)))
Это понятно.... :) я имел ввиду обработать OnMove и PtInRect() или еще как? и на 5 - ?
DimaBr (2006-10-02 16:10:00) [42]
> можно какимнить образом из элемента TPicMenuCollectionItem
> свой индекс в коллекции передать в TPicMenus
Легко
TPicMenus = class(TGraphicControl)
private
procedure ChangeRect(IndexCollection: integer);
end;
procedure TPicMenuCollectionItem.SetMenuHeight(const Value: Integer);
begin
FMenuHeight := Value;
GetPicMenus.ChangeRect(Index);
end;
> И как работу с мышью лучше организовать?
Лучше всего организовать правильно, иначе плохо будет работать :)))
RASkov (2006-10-02 14:39:00) [43]
> DimaBr (02.10.06 09:59) [77]
> function TPicMenuCollectionItem.GetPicMenus: TPicMenus;
> begin
> Result := TPicMenus(Collection.Owner);
> end;
Уже сделал...
1 - 50 на 50 - в данном коде реализована общая прорисовка элементов меню, потом хотел сделать что то типа:
procedure TPicMenuCollectionItem.DrawItems;
var N: Integer;
begin
...
for N:=0 to FCountMenu-1 do begin
DrawItem(N, ItemState);
end;
end;
2 - реолизовал
3 - спорный вопрос - ближе к концу решится, есть некоторые факты в пользу alClient - пока оставим так.
4 - спасибо. удалю нафик всю :)
5 - Чем лучше? Т.е. чем мне здесь может это помочь? Хотя уже вроде начал вникать в эти коллекции может сам допру.
И мне бы хотелось узнать - можно какимнить образом из элемента TPicMenuCollectionItem свой индекс в коллекции передать в TPicMenus?
т.е при пересчете Rect'ов передать в TPicMenus номер изменившегося TPicMenuCollectionItem? И как работу с мышью лучше организовать?
Спасибо.
DimaBr (2006-10-02 09:59:00) [44]
> Меня вот интересуют нотификации (Notification)
Нотификация нужна для уведомления о добавлении/удалении компонентов формы. Если вы обрабатываете это движение в компоненте - то нужны. Искуственно можно передать нотификацию в коллекцию и вложенные компоненты/персистенты
1. Как достучатся?
function TPicMenuCollectionItem.GetPicMenus: TPicMenus;
begin
Result := TPicMenus(Collection.Owner);
end;
По поводу кода:
1. В принципе нет необходимости рисовать в элементах коллекции (тогда речь шла о двух компонентах), можно рисовать в методе Paint используя свойства коллекции.
2. Во все методы Set.. элементов коллекции добавить GetPicMenus.Invalidate для перерисовки родителя при изменении свойства элемента коллекции
3. Строчка "Align:=alClient" с конструкторе мне не нравится, потому что не хочу чтобы компонент занимал всю область. Повысить видимость Align до Published.
4. В нотификации необходимости нет.
5. TMenuCollection = class(TCollection); лучше заменить на TMenuCollection = class(TOwnedCollection);
RASkov (2006-10-01 16:59:00) [45]> (это ни суть, здесь придумаю как их туда засунуть)
Пока не придумал :)
RASkov (2006-09-30 22:39:00) [46]Вот вернулся к своему компаненту и задумался - сюда запостить или в новую ветку... решил пока сюда.
Вот что получилось (код компанента ниже), на данный момент пока "скелет" компанета. Код "рабочий", по крайней мере без явных ошибок работает в дизайнтайме т.е. без AV.
Я вот в таком виде его хочу показать Вам, и если Вам не трудно, посмотрите, на правильном я направлении или нет. Меня вот интересуют нотификации (Notification) - у меня они походу для понта здесь. Вот мне хочется узнать нужны ли они в данных моих компанентах? Я в них(Notification) чето никак не въеду:(.
И если нетрудно, ответьте на вопросы:
1)Как из объектов TPicMenuCollectionItem достучаться до TPicMenus? (хотелось бы вызывать перерисовку (Invalidate) при изменении свойств);
2)Каким образом лучше обрабатывать мышь (Enter/Leave/Click элементов меню)? Элементы меню планирую хранить как TRect в поле FItemsMenu в его Object, т.е. сейчас пока присваение так FItemsMenu.Assign(Value); потом хочу переделать с добавлением областей (Rect'ов), ченить типа так (только что здесь придумал, пока писАл)
R:=Rect(<расчитываем область>);
FItemsMenu.AddObject(Value[i], TObject(@R));
(это ни суть, здесь придумаю как их туда засунуть)
Вопрос наверное кем эфективнее обрабатывать - TPicMenuCollectionItem или TPicMenus? Я сам склоняюсь к TPicMenus, т.к. кое-какие махинации с мышью уже реализованы ГрафикКонтролом... И ченить типа
for N:=0 to FItemsMenu-1 do
if PtInRect(TRect(FItemsMenu.Object(N)), Point(X,Y)) then ..
end;
на TPicMenus.MouseMove но... как-то некрасиво... низнаю пока.
Ну вот пока вроде все, следом код (хотел повырезать ненужное но на всяк оставил целиком)
RASkov (2006-09-30 22:39:00) [47]
unit PicMenu;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Dialogs;
type
TPicMenus = class;
TMenuCollection = class(TCollection);
TOrientationMenu = (omVert, omHoriz);
TPicMenuCollectionItem = class(TCollectionItem)
private
FPicture: TPicture;
FBitMap: TBitMap;
// FCanvas: TCanvas;
FCountMenu: Integer;
FShowCaptions: Boolean;
FItemsMenu: TStrings;
FMenuTop: Integer;
FMenuWidth: Integer;
FMenuLeft: Integer;
FMenuHeight: Integer;
FSpacing: Byte;
FOrientation: TOrientationMenu;
function GetCountMenu: Integer;
procedure SetMenuHeight(const Value: Integer);
procedure SetItemsMenu(const Value: TStrings);
procedure SetMenuLeft(const Value: Integer);
procedure SetMenuTop(const Value: Integer);
procedure SetMenuWidth(const Value: Integer);
procedure SetPicture(const Value: TPicture);
procedure SetShowCaptions(const Value: Boolean);
procedure SetCountMenu(const Value: Integer);
procedure SetSpacing(const Value: Byte);
procedure SetOrientation(const Value: TOrientationMenu);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); dynamic;
function GetPicMenus: TPicMenus;
procedure DrawItems(Cnv: TCanvas);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
published
property CountMenu: Integer read GetCountMenu write SetCountMenu;
property ItemsMenu: TStrings read FItemsMenu write SetItemsMenu;
property MenuHeight: Integer read FMenuHeight write SetMenuHeight default 14;
property MenuWidth: Integer read FMenuWidth write SetMenuWidth default 50;
property MenuLeft: Integer read FMenuLeft write SetMenuLeft default 10;
property MenuTop: Integer read FMenuTop write SetMenuTop default 10;
property Orientation: TOrientationMenu read FOrientation write SetOrientation default omVert;
property Picture: TPicture read FPicture write SetPicture;
property ShowCaptions: Boolean read FShowCaptions write SetShowCaptions default True;
property Spacing: Byte read FSpacing write SetSpacing default 5;
end;
TPicMenus = class(TGraphicControl)
private
FMenuCollection: TMenuCollection;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property MenuCollection: TMenuCollection read FMenuCollection write FMenuCollection;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Stnd', [TPicMenus]);
end;
{ TPicMenuCollectionItem }
constructor TPicMenuCollectionItem.Create(Collection: TCollection);
begin
inherited Create(Collection);
FPicture:=TPicture.Create;
FBitMap:=TBitMap.Create;
FItemsMenu:=TStringList.Create;
FMenuHeight:=14;
FMenuTop:=10;
FMenuLeft:=10;
FMenuWidth:=50;
//FCanvas:=ACanvas;
FShowCaptions:=True;
FSpacing:=5;
end;
destructor TPicMenuCollectionItem.Destroy;
begin
FPicture.Free;
FBitMap.Free;
FItemsMenu.Free;
inherited;
end;
procedure TPicMenuCollectionItem.DrawItems(Cnv: TCanvas);
var N: Integer; R: TRect;
begin
Cnv.Pen.Style:=psSolid;
Cnv.Pen.Width:=1;
for N:=0 to FCountMenu-1 do begin
case Orientation of
omVert: R:=Rect(FMenuLeft, FMenuTop+N*(FMenuHeight+FSpacing), FMenuLeft+FMenuWidth, FMenuTop+FMenuHeight+N*(FMenuHeight+FSpacing));
omHoriz: R:=Rect(FMenuLeft+N*(FMenuWidth+FSpacing), FMenuTop, FMenuLeft+FMenuWidth+N*(FMenuWidth+FSpacing), FMenuTop+FMenuHeight);
end;
Cnv.Rectangle(R);
{ if csDesigning in ComponentState then Cnv.TextRect(R, R.Left, R.Top, ItemsMenu[N]+'dsgmode')
else Cnv.TextRect(R, R.Left, R.Top, ItemsMenu[N]);}
if FShowCaptions then Cnv.TextRect(R, R.Left, R.Top, ItemsMenu[N]);
end;
end;
function TPicMenuCollectionItem.GetCountMenu: Integer;
begin
FCountMenu:=FItemsMenu.Count;
Result:=FCountMenu;
end;
function TPicMenuCollectionItem.GetPicMenus: TPicMenus;
begin
Result:=nil;
end;
procedure TPicMenuCollectionItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
end;
procedure TPicMenuCollectionItem.SetCountMenu(const Value: Integer);
begin
FCountMenu := FItemsMenu.Count;
end;
procedure TPicMenuCollectionItem.SetMenuHeight(const Value: Integer);
begin
FMenuHeight := Value;
end;
procedure TPicMenuCollectionItem.SetItemsMenu(const Value: TStrings);
begin
FItemsMenu.Assign(Value);
end;
procedure TPicMenuCollectionItem.SetMenuLeft(const Value: Integer);
begin
FMenuLeft := Value;
end;
procedure TPicMenuCollectionItem.SetMenuTop(const Value: Integer);
begin
FMenuTop := Value;
end;
procedure TPicMenuCollectionItem.SetMenuWidth(const Value: Integer);
begin
FMenuWidth := Value;
end;
procedure TPicMenuCollectionItem.SetPicture(const Value: TPicture);
begin
FPicture := Value;
end;
procedure TPicMenuCollectionItem.SetShowCaptions(const Value: Boolean);
begin
FShowCaptions := Value;
end;
procedure TPicMenuCollectionItem.SetSpacing(const Value: Byte);
begin
FSpacing := Value;
end;
procedure TPicMenuCollectionItem.SetOrientation(const Value: TOrientationMenu);
begin
FOrientation := Value;
end;
{ TPicMenus }
constructor TPicMenus.Create(AOwner: TComponent);
begin
inherited;
FMenuCollection := TMenuCollection.Create(TPicMenuCollectionItem);
Align:=alClient;
end;
destructor TPicMenus.Destroy;
begin
FMenuCollection.Free;
inherited
end;
procedure TPicMenus.Notification(AComponent: TComponent; Operation: TOperation);
var N: Integer;
begin
inherited Notification(AComponent, Operation);
if (FMenuCollection <> nil) and not (csDestroying in ComponentState) then
for N := 0 to FMenuCollection.Count -1 do
TPicMenuCollectionItem(MenuCollection.Items[N]).Notification(AComponent, Operation);
end;
procedure TPicMenus.Paint;
var N: Integer;
begin
Canvas.Font := Font;
Canvas.Brush.Color := Color;
if csDesigning in ComponentState then
with Canvas do begin
Pen.Width:=1;
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
end;
for N := 0 to FMenuCollection.Count -1 do
TPicMenuCollectionItem(MenuCollection.Items[N]).DrawItems(Self.Canvas);
end;
end.
Спасибо тому, кто это дело не пропустит... пусть даже будет критик... обаснованный:)
ЗЫ Очень надеюсь на Ваши "пинки".
RASkov (2006-09-29 13:34:00) [48]Короче, Спасибо Вам всем. На данный момент попробовать чего либо не могу так как нахожусь в другом нас. пункте. завтра к вечеру буду и обязательно попробую разные варианты. Учиться... учиться... и еще раз учиться © Ленин
[70] DimaBr (29.09.06 08:44) - если обидел чем извеняюсь. Трудно на форуме изложить свои мысли, чёбы другие поняли и высказать правильно :)
Наиль (2006-09-29 09:37:00) [49]
> Где, как отловить/перекрыть момент заполнения списка поля
> CanvasControls
Type
TMyPropertyEditor=class(TComponentProperty)
private
InspectorProc:TGetStrProc;
procedure MyProc(const S: string);
public
procedure GetValues(Proc: TGetStrProc); override;
End;
{ TMyPropertyEditor }
procedure TMyPropertyEditor.GetValues(Proc: TGetStrProc);
begin
InspectorProc:=Proc;
Designer.GetComponentNames(GetTypeData(GetPropType), MyProc);
end;
procedure TMyPropertyEditor.MyProc(const S: string);
Var
Compon:TComponent;
begin
Compon:=Designer.GetComponent(S);
if Compon=nil then Exit;
if not (Compon is TControl) then Exit;
if (Compon as TControl).Width<200 then InspectorProc(S)
end;
Этот код не точный, возможно не верный. Предназначен лишь для того, чтобы показать, как фильтруются списки в свойствах. В данном случае в список должны попасть лишь те контролы, которые имеют ширину меньше 200.
Естествено, данный редактор свойства нужен зарегестрировать соотвествующим образом.
Наиль (2006-09-29 09:13:00) [50]> TCollectionMenu = class(TCollection);
>
> TPicMenu = class(TPaintBox)
> FCollectMenu: TCollectionMenu;
> .....
> end;
Здесь notification не нужен.
> Ну типа как у TTable свойство Fields. Если грохнуть таблицу
> то и Field'ы все умрут....
А здесь нужен. Fields - NonVisual-компоненты. Присутствуют в dfm и pas файлах. Откуда их легко удалить. Со всеми вытекающими последствиями.
В общем нотификация нужна всегда, если компонент на который имеется ссылка может быть удалён без твоего ведома.
DimaBr (2006-09-29 08:44:00) [51]
> А я планировал сделать все в одном компаненте на основе ПаинтБокса
Тогда просто супер !!! А я всё живу прошлой жизнью, где присутствовало два компонента - рисующий и подопытный.
RASkov (2006-09-28 23:57:00) [52]> [68] Юрий Зотов © (28.09.06 20:17)
Юрий, извеняюсь, но мне попап вооще не нужен был:)
> Юзер хочет привязать к контролу не меню
Вообще хотел привязать к контролу свой компанент т.е. наоборот, контрол к моему компаненту но пункты меню рисовать самому т.е. выводить их ввиде картинок в определенном TRect'е. И надобность в контроле, насителе канвы, вроде отпала уже. Спасибо [50] DimaBr.
Извеняюсь еще раз, если что не в тему.
Юрий Зотов (2006-09-28 20:17:00) [53]> DimaBr (28.09.06 10:58) [60]
Ничего жестокого. Юзер хочет привязать к контролу не меню, а коллекцию меню - он ее и привязывает. Что хочет - то и получает.
RASkov (2006-09-28 17:24:00) [54]> Если этот второй компонент удалить, куда будет ссылаться
> элемент коллекции PaintBoxa ?
Т.е. при добавлении элемента, ему подсовывается канвас того ПаинтБокса, которому и добавляем этот элемент. И усе... удалили элемент, перерисовали паинт и ок:) ИМХО.
RASkov (2006-09-28 17:19:00) [55]
> У вас два компонента
Воо как... А я планировал сделать все в одном компаненте на основе ПаинтБокса, добавить ему этих итемов, которые на нем (ПаинтБоксе) и будут рисовать. Ну типа как у TTable свойство Fields. Если грохнуть таблицу то и Field'ы все умрут.... Или мы разговариваем на разных языках :( Или я воопще тупю :(
У вас два компонента - PaintBox и тот который на нём рисует- как понять эту строку - в IDE устанавливаются два самостоятельных компанента, или же ПаинтБокс содержит в себе "тот который на нём"
> Если этот второй компонент удалить, куда будет ссылаться
> элемент коллекции PaintBoxa ?
Я же так понимаю элемент коллекции и будет рисовать на паинте... и при его удалении нужно только перерисовать паинт.
Или я никак не вникну в Коллекции и их КоллектионИтемы, к сожалению :(
Ухх.. нелегкая эта работа.....:)
DimaBr (2006-09-28 16:33:00) [56]Всё опять неверно. У вас два компонента - PaintBox и тот который на нём рисует. В PaintBox-e ссылка в коллекции на внешний компонент и в методе Paint мы предоставляем свою канву дря рисования второму компоненту. Если этот второй компонент удалить, куда будет ссылаться элемент коллекции PaintBoxa ?
RASkov (2006-09-28 16:24:00) [57]Смысл этих строк
> P/S Если чего нибудь не получится, ничего если я в этой
> ветке буду спрашивать...
Ничо... :)))
в том, что отказавшись от дополнительно контрола в свойстве компанента, я немного ушел от темы (сабжа) и поидее нужно создовать новую тему, и поэтому так спросил.
Ничо... :))) сенькс ;)
RASkov (2006-09-28 16:15:00) [58]
> DimaBr (28.09.06 13:49) [62]
> Вы не так поняли. Это нужно для удаления компонента на который
> ссылается ваш PaintBox. Удалили компонент, PaintBox получил
> сообщение об удалении и передал сообщение каждому элементу
> коллекции, которые и проверяют не порали удалить битую ссылку.
>
Чето я туплю :( извеняюсь.... может неправильно написал
> так как при удалении этого контрола - удалится и вся "коллекция"
> рисующая на нем :)
Контрол на котором будут рисовать CollectionItems'ы - это же все один компанент (TNewPaintBox), и цитату выше читать следует так: так как при удалении этого моего компанента - удалится и вся "коллекция"
Если удалить "контейнер" ( Контрол на котором находится мой TNewPaintBox:) с моим компанентом то, я так понимаю, он (контейнер, например TPanel или TForm) автоматом грохнет мой компанент, а тот в свою очередь поубивает и итемы из коллекции...
Т.е. другими словами у меня теперь в компаненте нет ссылки на другие контролы... Единственное, теперь нужно как то передавать канву Обладателя КоллектионИтемов (TNewPaintBox - разр. комп.) самим итемам, что бы те, в свою очередь, рисовали на ней. Попробую дома разобраться с этим. Вот вроде так... Сами же предложили отказаться от внешнего холста :)... Или я опять непонял [62] :( Спасибо.
DimaBr (2006-09-28 13:49:00) [59]
> Похоже сдесь тоже проблема решена, так как при удалении
> этого контрола - удалится и вся "коллекция" рисующая на
> нем :)
Вы не так поняли. Это нужно для удаления компонентана который ссылается ваш PaintBox. Удалили компонент, PaintBox получил сообщение об удалении и передал сообщение каждому элементу коллекции, которые и проверяют не порали удалить битую ссылку.
> P/S Если чего нибудь не получится, ничего если я в этой
> ветке буду спрашивать...
Ничо... :)))
RASkov (2006-09-28 13:26:00) [60]Спасибо Вам огромное.
С предложением DimaBr [50] и примером из [52] совсем отпала необходимость использования стороннего контрола для отрисовки элементов меню. Вы наверное не уловили ход моих мыслей, за что мои извинения. Дело в том что, теперь ни надо свойство из сабжа. Т.е. берем за основу TGaphicControl или TPaintBox (на мой взгляд даже лучше), добавляем некоторые свойства и в их числе будет CollectionMenu : TCollection, элементами которой (коллекции) будут непосредственно "мои первоночальные компаненты" т.е. теперь просто класс используемый новым компанентом.
Т.е. примерно должно получится нечто вроде этого: кидаю на форму новый "мой" компанент - он приобретает Align - alClient по отношению к Parent'у, добавляю в коллекцию CollectionMenu необходимое кол-во элементов (не элементов меню) и соответственно их настраиваю, что бы они рисовали свои пункты (рисунками, картинками или просто разным цветом) меню в определенных координатах и при необходимости (будет опционально, что то типа ShowCaptions) выводили текст и все это на владельце CollectionMenu т.е. на PaintBox если от него плясать (грубо на этом новом компаненте).
Код Ю. Зотова наверное не совсем подходит, но там очень много полезного, огромное спасибо Вам, Юрий.
> [56] DimaBr (28.09.06 08:44)
>
> > Что будет если убрать эти методы из моих классов?
>
> Если убрать метод нотификации, то при удалении компонента
> на который будет ссылаться ваш контрол получим битую ссылку.
Похоже сдесь тоже проблема решена, так как при удалении этого контрола - удалится и вся "коллекция" рисующая на нем :)
Я вот подумал, что тот код, который привел в [53], немного переделать и сделать Мой первоначальный компанент в качестве TCollectionItem
Т.е. нечто так:
TMyClick = procedure MyClick(Sender: TObject; var NItem: Integer) of object; //не уверен, что написал верно, приду вечером домой в Delph'ях разберусь.Ну вот вроде и все... вечером приду домой буду пробовать.
TPicMenuItem = class(TCollectionItem )
....
published
property OnClick: TMyClick;
end;
//это не 1 пункт меню, а одно меню со своими элементами меню.
TCollectionMenu = class(TCollection);
TPicMenu = class(TPaintBox)
FCollectMenu: TCollectionMenu;
.....
end;
вот как будет выглядеть это все:
----------------------------------------------------------------
|
| 1111111 11111111 1111111 11111111
|
|
| 222222 33333 33333 33333
| 222222
| 222222
| 222222 44444
|
где в моем компаненте в свойстве CollectMenu будут четыре меню каждый будет рисовать свои пункты первый - 1, второй - 2 и т.д.
Еще раз спасибо Вам огромное.
P/S Если чего нибудь не получится, ничего если я в этой ветке буду спрашивать...