Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 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]


> Где, как отловить/перекрыть момент заполнения списка поля
> 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.
Естествено, данный редактор свойства нужен зарегестрировать соотвествующим образом.


 
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.083 c
15-1186931345
rtQew
2007-08-12 19:09
2007.09.09
Посоветуйте...


4-1174345185
Vlad-Q
2007-03-20 01:59
2007.09.09
Открытие окна броузера с заданным url


15-1186930128
Dimka Maslov
2007-08-12 18:48
2007.09.09
Вот интересно почему


15-1186570167
Reindeer Moss Eater
2007-08-08 14:49
2007.09.09
Эксель и счет


15-1185177914
Mystic
2007-07-23 12:05
2007.09.09
В продолжение шахматной темы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский