Łączenie komponentu z innym

0

Hej
po chyba roku przerwy znowu odrodziła się we mnie chęć do programowania i dłubania w kodzie :)

Piszę właśnie komponent i chciałbym połączyć go z innym na formie np zeby dodawac do TMemo jakies teksty.

Chciałbym dodać możliwość wyboru tego komponentu w tym miejscu:

myvisualcomponent_properties11.png
(zdjęcie przykładowe)

Czy podpowiecie mi jak się do tego zabrać albo jak zacząć szukać? Próbowałem odwoływać się do TMemo bezpośrednio z kodu mojego komponentu ale intuicyjnie czuje, że nie jest to najlepsze rozwiązanie i lepiej dać możliwość wskazania i sprawdzenia czy jest w ogóle do czego pisać.

5

dodajesz published property z typem TMemo wtedy możesz w OI wybrać sobie konkretne memo z listy

3

Oprócz stworzenia sobie właściwości połączonej z polem, pasuje też nadpisać metodę Notification, tak aby przyłączony komponent był poprawnie ustawiany i odpinany (jeśli zajdzie taka potrzeba). No i trzeba też napisać setter takiej właściwości z krótką logiką.

Ogólny schemat jest taki:

type
  TMyVisualComponent = class(TSomething)
  private
    FAbout: TMemo;
  private
    procedure SetAbout(AValue: TMemo);
  protected
    procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
  published
    property About: TMemo read FAbout write SetAbout;
  end;

procedure TMyVisualComponent.SetAbout(AValue: TMemo);
begin
  if AValue <> FAbout then
  begin
    if FAbout <> nil then
      FAbout.RemoveFreeNotification(Self);

    FAbout := AValue;

    if AValue <> nil then
      AValue.FreeNotification(Self);
  end;
end;

procedure TMyVisualComponent.Notification(AComponent: TComponent; AOperation: TOperation);
begin
  inherited Notification(AComponent, AOperation);

  if (AComponent = FAbout) and (AOperation = opRemove) then
    FAbout := nil;
end;

I tak dla każdej właściwości, która ma być komponentem. Oczywiście metoda Notification pozostaje jedna, bez względu na liczbę ”komponentowych” właściwości. W takim przypadku wystarczy dorzucić więcej warunków, np.:

procedure TMyVisualComponent.Notification(AComponent: TComponent; AOperation: TOperation);
begin
  inherited Notification(AComponent, AOperation);

  if AOperation = opRemove then
  begin
    if AComponent = FFoo then FFoo := nil;
    if AComponent = FBar then FBar := nil;
    if AComponent = FBaz then FBaz := nil;
  end;
end;
0

Jak zwykle działa bezbłędnie. Dziękuję Ci bardzo!
Oczywiście przed próbą pisania do takiego komponentu trzeba sprawdzić czy jest do czego.

0
karpov napisał(a):

Oczywiście przed próbą pisania do takiego komponentu trzeba sprawdzić czy jest do czego.

Rozwiń, bo nie wiem co masz na myśli.

Szablon który podałem wyżej, zawiera wszystko co potrzeba i jest bezpieczny w użyciu – nie wymaga dodania kolejnych warunków. W razie wątpliwości, zawsze możesz zobaczyć jak to wygląda w standardowych komponentach, np. dla właściwości FocusControl w klasie TLabel.

0
furious programming napisał(a):
karpov napisał(a):

Oczywiście przed próbą pisania do takiego komponentu trzeba sprawdzić czy jest do czego.

Rozwiń, bo nie wiem co masz na myśli.

Czy referencja na to memo jest przypisana i jest ważna.
Bo jeśli nie, to nie ma do czego pisać ;-)

A żeby to działało poprawnie, to trzeba zaprzyjaźnić się i użyć "notyfikacji".
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TComponent.Notification

Szablon który podałem wyżej, zawiera wszystko co potrzeba i jest bezpieczny w użyciu – nie wymaga dodania kolejnych warunków. W razie wątpliwości, zawsze możesz zobaczyć jak to wygląda w standardowych komponentach, np. dla właściwości FocusControl w klasie TLabel.

I od razu podpatrzeć jak poprawnie używa się Notifications;-)

0

@wloochacz: pamiętaj, że LCL choć podobne do VCL, to jednak jest zbudowane inaczej. No i też o tym, że ten wątek dotyczy LCL, a nie VCL, bo najwyraźniej ten fakt przeoczyłeś. ;)


Masz za przykład żywcem wyciągnięty kod z LCL, dotyczący właściwości FocusControl dla komponentu TLabel:

TCustomLabel = class(TGraphicControl)
private
  FFocusControl: TWinControl;
protected
  procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  procedure SetFocusControl(Value: TWinControl);
published
  property FocusControl: TWinControl read FFocusControl write SetFocusControl;
end;

{..}

procedure TCustomLabel.SetFocusControl(Value : TWinControl);
begin
  if Value <> FFocusControl then
  begin
    if FFocusControl <> nil then
      FFocusControl.RemoveFreeNotification(Self);
    FFocusControl:= Value;
    if Value <> nil then
      Value.FreeNotification(Self);
  end;
end;

procedure TCustomLabel.Notification(AComponent : TComponent; Operation : TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (AComponent = FFocusControl) and (Operation = opRemove) then
    FFocusControl := nil;
end;

I to jest wszystko dotyczące notyfikacji, co jest niezbędne do poprawnego działania. Chyba że deweloperzy biblioteki komponentów wg Ciebie nie potrafią poprawnie używać kodu, który sami napisali?

Jeśli o mnie chodzi, to notyfikacje są oprogramowane poprawnie i nic więcej (prócz powyższego) nie potrzeba.

1 użytkowników online, w tym zalogowanych: 0, gości: 1