Форум: "Компоненты";
Текущий архив: 2007.09.09;
Скачать: [xml.tar.bz2];
ВнизДобавление published свойства Найти похожие ветки
← →
DimaBr (2006-09-25 16:53) [40]
TMyComponent = class(TComponent)
private
fCanvasControls: TCustomControls;
procedure SetCanvasControls(const Value: TCustomControl);
published
property CanvasControls: TCustomControl read fCanvasControls write SetCanvasControls;
end;
procedure TMyComponent.SetCanvasControls(const Value: TCustomControl);
begin // процедура срабатывает при изменении свойства CanvasControls
fCanvasControls := Value;
end;
← →
DimaBr (2006-09-25 16:58) [41]Я так и не понял, зачем рисовать изображения на чужих контролах ?
Ваша процедура вывода изображения использует событие формы - решение не подходит, так как не у всех контролов есть OnPaint.
← →
RASkov (2006-09-25 21:02) [42]> [40] DimaBr (25.09.06 16:53)
Это я уже попробовал...:(
Как здесь можно фильтр поставить т.е. "Етого добавить, а Етого нет"?
> Ваша процедура вывода изображения использует событие формы
> - решение не подходит, так как не у всех контролов есть
> OnPaint.
Это тут пару раз мне предложили сделать такую процедуру но я так и не понял что именно нужно и привел этот кусок кода... т.е. так я понял... короче ерунда какая то получается...
> Я так и не понял, зачем рисовать изображения на чужих контролах
> ?
Вроде подробно расписал в [39] вот неполное описание того что хотел сделать. За основу взял TPicClip из RxLib и хотел добавить некоторые свойства и методы:Type
TOrientation = (orVert, orHoriz);
TPicMenu = class(TComponent)
private
FPicture: TPicture;
FCountMenu: Integer;
FBitmap: TBitmap;
FOrientation: TOrientation;
FCanvasControl: TGraphicControl;
.....
published
.......
property MenuHeight: Integer read GetMenuHeight write SetMenuHeight stored False;
property MenuWidth: Integer read GetWidth write SetWidth stored False;
property CountMenu: Integer read FCountMenu write FCountMenu default 1;
property Orientation: TOrientation read FOrientation write SetOrientation default orVert;
property CanvasCtrl: TGraphicControl read FCanvasControl write SetCanvasControl;
end;
Если чесно... то уже желание почти пропало этот компанент делать.
Многое, что понял... многое нет :( И хотелось бы поконкретней услышать про ту процедуру, что имели ввиду Ю.Зотов и GrayFace.
Спасибо всем кто хотел помочь.
← →
RASkov (2006-09-25 21:04) [43]ошибка, так должно:
property MenuWidth: Integer read GetMenuWidth write SetMenuWidth stored False;
← →
DimaBr (2006-09-26 10:27) [44]
> Как здесь можно фильтр поставить т.е. "Етого добавить, а
> Етого нет"?
procedure TMyComponent.SetCanvasControls(const Value: TCustomControl);
begin
if МНЕ ПОДХОДИТ ЭТОТ КОНТРОЛ then fCanvasControls := Value;
end;
Из пункта [39] лично я ничо не понял. Если можно, опишите подробрее (без троеточий) цель Вашего сочинения. Создаётся впечатление что Вас никто не понимает. По крайней мере, цель каждого контрола - корректно отображать свои данные. Вы же предлагаете рисовать поверх него свои, тогда пропадает смысл в использовании этого контрола. Объясните на примерах похожих компонент.
← →
RASkov (2006-09-26 16:40) [45]Прошу прощения, но помоему:
procedure TMyComponent.SetCanvasControls(const Value: TCustomControl);
begin
if МНЕ ПОДХОДИТ ЭТОТ КОНТРОЛ then fCanvasControls := Value;
end;
Таким способом мы ограничиваем выбор свойства т.е. в инспекторе объектов в поле CanvasControls в выподающем списке будут все от TCustomControl но выбрать будет возможно исодя изif МНЕ ПОДХОДИТ ЭТОТ КОНТРОЛ then
- это не совсем то что хотелось.
Хотелось, что бы в инсп. объектов в списке поля CanvasControls были только те контролы которые отвечают условиюif МНЕ ПОДХОДИТ ЭТОТ КОНТРОЛ then
> Из пункта [39] лично я ничо не понял. Если можно, опишите
> подробрее (без троеточий) цель Вашего сочинения. Создаётся
> впечатление что Вас никто не понимает. По крайней мере,
> цель каждого контрола - корректно отображать свои данные.
> Вы же предлагаете рисовать поверх него свои, тогда пропадает
> смысл в использовании этого контрола. Объясните на примерах
> похожих компонент.
Целью моего сочинения было сделать компанент который выводил бы графическое меню на канве выбранного контрола. Т.е. берем ПаинтБокс кидаем на "голую" форму, кидаем туда пару, тройку моих компанентов и в их свойстве указываем один и тот же контрол ПаинтБокс, и вот они (мои компаненты) выводили бы каждый в определенных координатах свои пункты меню. В итоге должно получится такое: контрол (жертва моих компанентов) рисует свою канву и после, поверх уже рисуют мои комп.
Эх... ладно если опять ничего не понятно, то тогда пора закрывать эту тему в связи с тем что нового здесь я уже ничего не узнаю, а как еще понятней объяснить не смогу.
По всей видимости надо свойство сделать жестко, типа TPaintBox и каким то образом заставить инсп. объектов сделать поле с выпадающим списком в котором будут перечислены все ПаинтБоксы на форме. Таким образом ограничить взаимодействие моих компанентов с контролами т.е. привязать их к ПаинтБоксам...
Спасибо всем и отдельное DimaBr за сторание помочь.
← →
RASkov (2006-09-26 16:44) [46]Спасибо всем и отдельное DimaBr за старание помочь.
С русским как и с математикой... трабл:)
← →
DimaBr (2006-09-26 16:55) [47]1. Для ограничения самого списка придётся присать редактор свойства, там уж и будете выбирать какий компоненты подходят, а какие нет. Только в Run-Time этот редактор работать не будет , следовательно ничего не момешает динамически прицепить что угодно.
2. По всей видимости нужно писать как раз таки контрол который отображает, с коллекцией компонентов откуда брать данные, а не наоборот.
← →
GrayFace © (2006-09-26 19:27) [48]RASkov (25.09.06 16:28) [39]
Вроде так что ли?
Ну да. Эта процедура DrawCnvs - в компоненте, а ее вызов при отрисовке какого-то контрола - уже дело пользователя. Как выводить - заботится компонент, куда - пользователь, тут у него и OnPaint, и все что нужно под рукой. Выпадающий список - в топку.
RASkov (25.09.06 16:28) [39]
> RASkov (22.09.06 16:23) [35]
> Где, как отловить/перекрыть момент заполнения списка поля
> CanvasControls
> write SetCanvasControls
Можно объяснить это - я так понимаю здесь можно ограничить выбор кнтролов а не отфильтровать... т.е. в списке будут все а выбрать будет возможно не все...
Да, я тут не понял вопрос.
← →
RASkov (2006-09-26 23:03) [49]> [48] GrayFace © (26.09.06 19:27)
Т.е. получается на OnPaint Controla подсовывать процедуру моего компанентаprocedure TForm1.Form1Paint();
begin
MyCompanent.DrawCnvs(Form1.Canvas);
end;
Если это имелось ввиду... то здесь наверное и смысла нет в компаненте...
Можно просто модуль сделать и таким вот способом рисовать. :)
PS: Я уже плохо сооброжаю чего хочу :)) Сенькс.
← →
DimaBr (2006-09-27 08:33) [50]Ещё раз предлагаю, написать контрол, со свойством - коллекцией управляющих компонентов, который и будет рисовать (предоставлять канву для рисования). Код приблизительно таков
procedure TMyContriol.Paint;
var i: integer;
begin
inherited;
for i := 0 to CompCollection.Count -1 do
CompCollection.Draw(Canvas);
end;
← →
RASkov (2006-09-27 15:04) [51]> [50] DimaBr (27.09.06 08:33)
Спасибо. Мысль понял. Но чето нипойму как это будет выглядеть...
Т.е. как мне в контрол засунуть "много" дуругих. Здесь, наверное, для "нового" контрола нужно будет делать свойство множество для "старых" моих компанентов...
Т.е. примерно так что ли?Type MyOldComp = class (TCompanent)
....
public
Draw(Cnv: TCanvas);
....
end;
TCompCollections = Set of TMyOldComp;
TMyNewComp = class (TGraphicControl);
FPicture: TPicture;
FBitMap: TBitmap;
FCompCollections: TCompCollections;
FCompCollectionCount: Integer;
....
protected
Paint() override;
....
published
property CompCollCount: Integer read FCompCollectionCount;
property CompColletion: TCompCollections read GetCompColl write SetCompColl default [];
property OnPaint; // А это лучше скрыть наверное, но добавить свойство типа "Фон": ТБитМап
......
end;
Вот на "скорую руку накотал". Но, теперь я так понимаю, без редактора свойства никак. Так? Если так, то как он делается, этот редактор..
Можно ли его в одном модуле с компанентом делать, или в одном пакете, или есть какие то правила по их деланию?
Ну вот вроде опять желание появилось "что то хорошее сделать" :)
Если не трудно не могли бы привести простой пример редактора свойства.
Спасибо.
← →
DimaBr (2006-09-27 15:26) [52]немного не так.
TCompCollectionItem = class(TCollectionItem)
private
fComp: TMyOldComp;
public
procedure Notification(AComponent: TComponent; Operation: TOperation);
published
property Comp: TMyOldComp read fComp write fComp;
end;
TMyNewComp = class (TGraphicControl);
fCompCollection: TCollection;
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
published
property CompColletion: TCollections read fCompCollection write fCompCollection;
end;
......
constructor TMyNewComp.Create(AOwner: TComponent);
begin
inherited;
fCompCollection := TOwnedCollectio.Create(Self,TCompCollectionItem);
end;
procedure TMyNewComp.Notification(AComponent: TComponent; Operation: TOperation);
var i: integer;
begin
inherited;
for i := 0 to CompCollection.Count -1
TCompCollectionItem(CompCollection.Items[i]).Notification(AComponent,Operation);
end;
procedure TMyNewComp.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = Comp) then Comp := nil;
end;
end;
← →
RASkov (2006-09-27 23:48) [53]> [52] DimaBr (27.09.06 15:26)
Спасибо большое.
К сожалению, код приведенный выше содержит ошибки, и я, никогда не писавший компаненты, попытался исправить их... Вроде бы, на мой (делитанский в этом плане) взгляд, исправил ошибки... даже скомпилировал... более того установил этот "чудо-новый мой" компанент
но при выборе его и попытки кинуть на форму.... Усе смерть всей IDE.
Значит не те ошибки исправил :) или более того ничего неисправил, а добавил новых... Что не так? И опять вопрос - нужно ли будет делать редактор для свойства CompColletion? (ну незнаю я как он делается)
Даже не смог заставить это заработать... пойду башкой апстену пится :)
Вот это чудо - смерть Delphi - называется :)unit MyPicMenu;
interface
uses
SysUtils, Classes, Controls;
type
//TMyOldComp = class (TComponent);
TCompCollectionItem = class(TCollectionItem)
private
fComp: TComponent; {TMyOldComp}
public
procedure Notification(AComponent: TComponent; Operation: TOperation);
published
property Comp: TComponent read fComp write fComp;
end;
TMyNewComp = class (TGraphicControl)
fCompCollection: TCollection;
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
published
property CompCollection: TCollection read fCompCollection write fCompCollection;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents("Stnd", [TMyNewComp]);
end;
{ TCompCollectionItem }
procedure TCompCollectionItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = Comp) then Comp := nil;
end;
{ TMyNewComp }
constructor TMyNewComp.Create(AOwner: TComponent);
begin
inherited;
fCompCollection := TCollection.Create(TCompCollectionItem);
end;
destructor TMyNewComp.Destroy;
begin
inherited;
end;
procedure TMyNewComp.Notification(AComponent: TComponent; Operation: TOperation);
var N: Integer;
begin
inherited;
for N := 0 to CompCollection.Count -1 do
TCompCollectionItem(CompCollection.Items[N]).Notification(AComponent,Operation);
end;
procedure TMyNewComp.Paint;
begin
inherited;
end;
end.
Подозреваю, что у TCompCollectionItem нужно Create перекрыть, где создавать поле FComp... Но наверное собака в другом месте закопана.
PS DimaBr Огромное, тебе, спасибо за старание помочь
← →
RASkov (2006-09-28 02:13) [54]Методами тыка апстенку :), сделал вывод, что виснет все из-за метода TMyNewComp.Notification, так же понял, что редактр свойства ненужен :)
Отсюда вопрос: для чего нужен Notification? Т.е. как его исправить? Я понял, что он вызывается при вставке/удаления "объектов классов"
и так же понял что ошибка при обращении к CompCollection в методе Notification. И почему, если сделать вот так,procedure TMyNewComp.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
ShowMessage(AComponent.ClassName);
end;
то при добавлении/удалении либого (или многих, на всех не проверял:) компанента вылазит сообщение с именем его класса.
Что будет если убрать эти методы из моих классов?
← →
Юрий Зотов © (2006-09-28 07:43) [55]> берем ПаинтБокс кидаем на "голую" форму, кидаем туда пару, тройку моих
> компанентов и в их свойстве указываем один и тот же контрол ПаинтБокс,
> и вот они (мои компаненты) выводили бы каждый в определенных
> координатах свои пункты меню.
Практически то же самое делают плавающие тулбары. Чем не устраивают?
← →
DimaBr (2006-09-28 08:44) [56]
> Что будет если убрать эти методы из моих классов?
Если убрать метод нотификации, то при удалении компонента на который будет ссылаться ваш контрол получим битую ссылку.
destructor TMyNewComp.Destroy;
begin
FreeAndNil(fCompCollection);
inherited;
end;
procedure TMyNewComp.Notification(AComponent: TComponent; Operation: TOperation);
var N: Integer;
begin
inherited;
if CompCollection <> nil then
for N := 0 to CompCollection.Count -1 do
TCompCollectionItem(CompCollection.Items[N]).Notification(AComponent,Operation);
end;
← →
DimaBr (2006-09-28 08:53) [57]В принципе, возвращаясь к старому, есть такой компонент, который рисует своё виденье мира на любом WinControl-е, естественно этот контрол уже теряет свою функциональность, это чудо называется TMediaPlayer.
← →
Юрий Зотов © (2006-09-28 10:39) [58]
type
TYzMenuManager = class;
TYzMenuCollection = class;
TYzMenuCollectionItem = class(TCollectionItem)
private
FItemCaption: string;
FItemChecked: boolean;
FItemEnabled: boolean;
FItemMenu: TPopupMenu;
FLeft: integer;
FTop: integer;
procedure SetItemCaption(const Value: string);
procedure SetItemChecked(const Value: boolean);
procedure SetItemEnabled(const Value: boolean);
procedure SetItemMenu(const Value: TPopupMenu);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); dynamic;
procedure AssignTo(Dest: TPersistent); override;
function GetDisplayName: string; override;
function GetManager: TYzMenuManager;
public
constructor Create(Collection: TCollection); override;
procedure ShowMenu;
published
property ItemCaption: string read FItemCaption write SetItemCaption;
property ItemChecked: boolean read FItemChecked write SetItemChecked default False;
property ItemEnabled: boolean read FItemEnabled write SetItemEnabled default True;
property ItemMenu: TPopupMenu read FItemMenu write SetItemMenu;
property Left: integer read FLeft write FLeft default 0;
property Top: integer read FTop write FTop default 0;
end;
TYzMenuCollection = class(TOwnedCollection)
protected
procedure Update(Item: TCollectionItem); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); dynamic;
public
function GetManager: TYzMenuManager;
function GetMenuItem(Index: integer): TYzMenuCollectionItem;
end;
TYzMenuManager = class(TComponent)
private
FControl: TControl;
FMenuCollection: TCollection;
FMainMenu: TPopupMenu;
procedure SetControl(const Value: TControl);
procedure SetMenuCollection(const Value: TCollection);
procedure MainMenuItemClick(Sender: TObject);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure UpdateMainMenu;
property MainMenu: TPopupMenu read FMainMenu;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetMenuCollection: TYzMenuCollection;
published
property Control: TControl read FControl write SetControl;
property MenuCollection: TCollection read FMenuCollection write SetMenuCollection;
end;
{ TYzMenuCollectionItem }
procedure TYzMenuCollectionItem.AssignTo(Dest: TPersistent);
begin
if Dest is TYzMenuCollectionItem then
with TYzMenuCollectionItem(Dest) do
begin
Collection.BeginUpdate;
try
ItemCaption := Self.ItemCaption;
ItemMenu := Self.ItemMenu;
Index := Self.Index;
Left := Self.Left;
Top := Self.Top
finally
Collection.EndUpdate
end
end
else
inherited
end;
constructor TYzMenuCollectionItem.Create(Collection: TCollection);
begin
inherited;
FItemEnabled := True
end;
function TYzMenuCollectionItem.GetDisplayName: string;
begin
Result := FItemCaption
end;
function TYzMenuCollectionItem.GetManager: TYzMenuManager;
begin
Result := TYzMenuCollection(Collection).GetManager
end;
procedure TYzMenuCollectionItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = FItemMenu) then
FItemMenu := nil
end;
procedure TYzMenuCollectionItem.SetItemCaption(const Value: string);
begin
if not AnsiSameStr(Value, FItemCaption) then
begin
FItemCaption := Value;
Changed(False)
end
end;
procedure TYzMenuCollectionItem.SetItemChecked(const Value: boolean);
begin
if FItemChecked <> Value then
begin
FItemChecked := Value;
Changed(False)
end
end;
procedure TYzMenuCollectionItem.SetItemEnabled(const Value: boolean);
begin
if FItemEnabled <> Value then
begin
FItemEnabled := Value;
Changed(False)
end
end;
procedure TYzMenuCollectionItem.SetItemMenu(const Value: TPopupMenu);
begin
if FItemMenu <> Value then
begin
if FItemMenu <> nil then
FItemMenu.RemoveFreeNotification(GetManager);
FItemMenu := Value;
if FItemMenu <> nil then
FItemMenu.FreeNotification(GetManager)
end
end;
procedure TYzMenuCollectionItem.ShowMenu;
var
SavePopupComponent: TComponent;
P: TPoint;
begin
if (GetManager.Control <> nil) and (FItemMenu <> nil) then
begin
SavePopupComponent := FItemMenu.PopupComponent;
FItemMenu.PopupComponent := GetManager.Control;
try
P := GetManager.Control.ClientToScreen(Point(Left, Top));
FItemMenu.Popup(P.X, P.Y)
finally
FItemMenu.PopupComponent := SavePopupComponent
end
end
end;
{ TYzMenuCollection }
function TYzMenuCollection.GetManager: TYzMenuManager;
begin
Result := TYzMenuManager(GetOwner)
end;
function TYzMenuCollection.GetMenuItem(Index: integer): TYzMenuCollectionItem;
begin
Result := TYzMenuCollectionItem(Items[Index])
end;
procedure TYzMenuCollection.Notification(AComponent: TComponent; Operation: TOperation);
var
i: integer;
begin
for i := 0 to Count - 1 do
GetMenuItem(i).Notification(AComponent, Operation)
end;
procedure TYzMenuCollection.Update(Item: TCollectionItem);
begin
inherited;
GetManager.UpdateMainMenu
end;
{ TYzMenuManager }
constructor TYzMenuManager.Create(AOwner: TComponent);
begin
inherited;
FMainMenu := TPopupMenu.Create(Self);
FMenuCollection := TYzMenuCollection.Create(Self, TYzMenuCollectionItem)
end;
type
TFriendControl = class(TControl);
destructor TYzMenuManager.Destroy;
begin
if FControl <> nil then
TFriendControl(FControl).PopupMenu := nil;
FMenuCollection.Free;
inherited
end;
function TYzMenuManager.GetMenuCollection: TYzMenuCollection;
begin
Result := TYzMenuCollection(FMenuCollection)
end;
procedure TYzMenuManager.MainMenuItemClick(Sender: TObject);
begin
GetMenuCollection.GetMenuItem(TMenuItem(Sender).MenuIndex).ShowMenu
end;
procedure TYzMenuManager.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (FMenuCollection <> nil) and not (csDestroying in ComponentState) then
begin
if (Operation = opRemove) and (AComponent = FControl) then
FControl := nil;
GetMenuCollection.Notification(AComponent, Operation)
end
end;
procedure TYzMenuManager.SetControl(const Value: TControl);
begin
if FControl <> Value then
begin
if FControl <> nil then
begin
TFriendControl(FControl).PopupMenu := nil;
FControl.RemoveFreeNotification(Self);
end;
FControl := Value;
if FControl <> nil then
begin
FControl.FreeNotification(Self);
TFriendControl(FControl).PopupMenu := FMainMenu
end
end
end;
procedure TYzMenuManager.SetMenuCollection(const Value: TCollection);
begin
FMenuCollection.Assign(Value)
end;
procedure TYzMenuManager.UpdateMainMenu;
var
i: integer;
begin
FMainMenu.Items.Clear;
for i := 0 to FMenuCollection.Count - 1 do
with GetMenuCollection.GetMenuItem(i) do
FMainMenu.Items.Add(NewItem(ItemCaption, 0, ItemChecked, ItemEnabled, MainMenuItemClick, -1, ""))
end;
end.
← →
Юрий Зотов © (2006-09-28 10:41) [59]Забыл - в AssignTo надо добавить присвоение ItemChecked и ItemEnabled.
← →
DimaBr (2006-09-28 10:58) [60]Нет, я думаю что RASkov хочет отрисовывать меню на контроле, а не POPUP.
> TFriendControl(FControl).PopupMenu := nil;
> TFriendControl(FControl).PopupMenu := FMainMenu
Жестоко, как мне кажется.
← →
RASkov (2006-09-28 13:26) [61]Спасибо Вам огромное.
С предложением 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 Если чего нибудь не получится, ничего если я в этой ветке буду спрашивать...
← →
DimaBr (2006-09-28 13:49) [62]
> Похоже сдесь тоже проблема решена, так как при удалении
> этого контрола - удалится и вся "коллекция" рисующая на
> нем :)
Вы не так поняли. Это нужно для удаления компонента на который ссылается ваш PaintBox. Удалили компонент, PaintBox получил сообщение об удалении и передал сообщение каждому элементу коллекции, которые и проверяют не порали удалить битую ссылку.
> P/S Если чего нибудь не получится, ничего если я в этой
> ветке буду спрашивать...
Ничо... :)))
← →
RASkov (2006-09-28 16:15) [63]
> DimaBr (28.09.06 13:49) [62]
> Вы не так поняли. Это нужно для удаления компонента на который
> ссылается ваш PaintBox. Удалили компонент, PaintBox получил
> сообщение об удалении и передал сообщение каждому элементу
> коллекции, которые и проверяют не порали удалить битую ссылку.
>
Чето я туплю :( извеняюсь.... может неправильно написал
> так как при удалении этого контрола - удалится и вся "коллекция"
> рисующая на нем :)
Контрол на котором будут рисовать CollectionItems"ы - это же все один компанент (TNewPaintBox), и цитату выше читать следует так: так как при удалении этого моего компанента - удалится и вся "коллекция"
Если удалить "контейнер" (Контрол на котором находится мой TNewPaintBox:) с моим компанентом то, я так понимаю, он (контейнер, например TPanel или TForm) автоматом грохнет мой компанент, а тот в свою очередь поубивает и итемы из коллекции...
Т.е. другими словами у меня теперь в компаненте нет ссылки на другие контролы... Единственное, теперь нужно как то передавать канву Обладателя КоллектионИтемов (TNewPaintBox - разр. комп.) самим итемам, что бы те, в свою очередь, рисовали на ней. Попробую дома разобраться с этим. Вот вроде так... Сами же предложили отказаться от внешнего холста :)... Или я опять непонял [62] :( Спасибо.
← →
RASkov (2006-09-28 16:24) [64]Смысл этих строк
> P/S Если чего нибудь не получится, ничего если я в этой
> ветке буду спрашивать...
Ничо... :)))
в том, что отказавшись от дополнительно контрола в свойстве компанента, я немного ушел от темы (сабжа) и поидее нужно создовать новую тему, и поэтому так спросил.
Ничо... :))) сенькс ;)
← →
DimaBr (2006-09-28 16:33) [65]Всё опять неверно. У вас два компонента - PaintBox и тот который на нём рисует. В PaintBox-e ссылка в коллекции на внешний компонент и в методе Paint мы предоставляем свою канву дря рисования второму компоненту. Если этот второй компонент удалить, куда будет ссылаться элемент коллекции PaintBoxa ?
← →
RASkov (2006-09-28 17:19) [66]
> У вас два компонента
Воо как... А я планировал сделать все в одном компаненте на основе ПаинтБокса, добавить ему этих итемов, которые на нем (ПаинтБоксе) и будут рисовать. Ну типа как у TTable свойство Fields. Если грохнуть таблицу то и Field"ы все умрут.... Или мы разговариваем на разных языках :( Или я воопще тупю :(У вас два компонента - PaintBox и тот который на нём рисует
- как понять эту строку - в IDE устанавливаются два самостоятельных компанента, или же ПаинтБокс содержит в себе "тот который на нём"
> Если этот второй компонент удалить, куда будет ссылаться
> элемент коллекции PaintBoxa ?
Я же так понимаю элемент коллекции и будет рисовать на паинте... и при его удалении нужно только перерисовать паинт.
Или я никак не вникну в Коллекции и их КоллектионИтемы, к сожалению :(
Ухх.. нелегкая эта работа.....:)
← →
RASkov (2006-09-28 17:24) [67]> Если этот второй компонент удалить, куда будет ссылаться
> элемент коллекции PaintBoxa ?
Т.е. при добавлении элемента, ему подсовывается канвас того ПаинтБокса, которому и добавляем этот элемент. И усе... удалили элемент, перерисовали паинт и ок:) ИМХО.
← →
Юрий Зотов © (2006-09-28 20:17) [68]> DimaBr (28.09.06 10:58) [60]
Ничего жестокого. Юзер хочет привязать к контролу не меню, а коллекцию меню - он ее и привязывает. Что хочет - то и получает.
← →
RASkov (2006-09-28 23:57) [69]> [68] Юрий Зотов © (28.09.06 20:17)
Юрий, извеняюсь, но мне попап вооще не нужен был:)
> Юзер хочет привязать к контролу не меню
Вообще хотел привязать к контролу свой компанент т.е. наоборот, контрол к моему компаненту но пункты меню рисовать самому т.е. выводить их ввиде картинок в определенном TRect"е. И надобность в контроле, насителе канвы, вроде отпала уже. Спасибо [50] DimaBr.
Извеняюсь еще раз, если что не в тему.
← →
DimaBr (2006-09-29 08:44) [70]
> А я планировал сделать все в одном компаненте на основе ПаинтБокса
Тогда просто супер !!! А я всё живу прошлой жизнью, где присутствовало два компонента - рисующий и подопытный.
← →
Наиль © (2006-09-29 09:13) [71]> TCollectionMenu = class(TCollection);
>
> TPicMenu = class(TPaintBox)
> FCollectMenu: TCollectionMenu;
> .....
> end;
Здесь notification не нужен.
> Ну типа как у TTable свойство Fields. Если грохнуть таблицу
> то и Field"ы все умрут....
А здесь нужен. Fields - NonVisual-компоненты. Присутствуют в dfm и pas файлах. Откуда их легко удалить. Со всеми вытекающими последствиями.
В общем нотификация нужна всегда, если компонент на который имеется ссылка может быть удалён без твоего ведома.
← →
Наиль © (2006-09-29 09:37) [72]
> Где, как отловить/перекрыть момент заполнения списка поля
> CanvasControlsType
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.
Естествено, данный редактор свойства нужен зарегестрировать соотвествующим образом.
← →
RASkov (2006-09-29 13:34) [73]Короче, Спасибо Вам всем. На данный момент попробовать чего либо не могу так как нахожусь в другом нас. пункте. завтра к вечеру буду и обязательно попробую разные варианты. Учиться... учиться... и еще раз учиться © Ленин
[70] DimaBr (29.09.06 08:44) - если обидел чем извеняюсь. Трудно на форуме изложить свои мысли, чёбы другие поняли и высказать правильно :)
← →
RASkov (2006-09-30 22:39) [74]Вот вернулся к своему компаненту и задумался - сюда запостить или в новую ветку... решил пока сюда.
Вот что получилось (код компанента ниже), на данный момент пока "скелет" компанета. Код "рабочий", по крайней мере без явных ошибок работает в дизайнтайме т.е. без 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) [75]
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-10-01 16:59) [76]> (это ни суть, здесь придумаю как их туда засунуть)
Пока не придумал :)
← →
DimaBr (2006-10-02 09:59) [77]
> Меня вот интересуют нотификации (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-02 14:39) [78]
> 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 16:10) [79]
> можно какимнить образом из элемента 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 16:33) [80]
> DimaBr (02.10.06 16:10) [79]
Спасибо за индех. То что надо.
> Лучше всего организовать правильно, иначе плохо будет работать
> :)))
Это понятно.... :) я имел ввиду обработать OnMove и PtInRect() или еще как? и на 5 - ?
Страницы: 1 2 3 вся ветка
Форум: "Компоненты";
Текущий архив: 2007.09.09;
Скачать: [xml.tar.bz2];
Память: 0.71 MB
Время: 0.063 c