Obsługa komunikatów przez formę utworzoną dynamicznie

0

Lazarus 2.0.10


type
  TMojaClasa = class
  private
    procedure WmLButtonDown(var Msg : TMessage); message WM_LBUTTONDOWN;
  public
    function  MojaFunkcja(<parametry>): <typ_zwracany>;
  end;

var
  MojaForma : TForm;

implementation

procedure TMojaClasa.WmLButtonDown(var Msg : TMessage); 
begin
...
end;

function TMojaClasa.MojaFunkcja(<parametry>): <typ_zwracany>;
begin
  MojaForma := TForm.Create ...
end

po utworzeniu instancji MojaForma chciałbym przypisać jej procedurę obsługi w/w komunikatu
(aby reagowała ona na jego wystąpienie) tylko .... nie mam pojęcia jak to zrobić.

Proszę o pomoc

2

masakra tworzysz klasę (TMyClass), w której tworzysz formę, której chcesz przypisać procedurę z tej klasy (TMyClass) ... masło maślane.

Jeśli dobrze Cię zrozumiałem to masz swoją klasę TMyClass, w której coś się będzie działo. Gdy to się wydarzy to na MojaForma ma się coś zadziać samoistnie. Jeśli o to chodzi to prawdopodobnie chcesz zrobić swojego rodzaju eventa. Nie jestem pewien jak w lazarusie ale w Delphi robi się to poprzez procedure of object. Musisz zatem do swojej klasy TMyClass stworzyć property do którego przypiszesz fizycznie metodę z formatki lub na odwrót gdy coś się na formatce zdarzy to tworzysz property na formie i do niej przypisujesz procedurę z TMyClass Przykład dla formy:

type
  TOnPlayChange = procedure(const pStart, pStop, pPlay: Int64) of object;

TMyClass = class(TForm)
strict private
        FOnPlayChange: TOnPlayChange;
public
        property OnPlayingChange: TOnPlayChange read fOnPlayChange write fOnPlayChange;
end;

Przy tworzeniu instancji formy robisz tak:

varMyForm := TMyForm.Create(Self);
varMyForm.OnPlayingChange :=  OnCopyProcedure 

i wywołanie

if assigned(FOnPlayChange) then
   FOnPlayChange(0,10,2);
1

Jeśli chodzi o obsługę komunikatów, to schemat zastosowany przez Ciebie — @jw_developer — wykorzystuje się wtedy, gdy obsługa danego komunikatu nie jest zaimplementowana w klasie kontrolki. Załóżmy, że jest sobie komunikat LM_RECEIVEDATA (zmyślony) i chcesz dodać kod jego obsługi oraz zdarzenie z nim powiązane. Szablon dla tego wszystkiego wygląda tak:

type
  TOnReceiveData = procedure(ASender: TObject; const AData: Integer) of object;

type
  TMyForm = class(TForm)
  private
    FOnReceiveData: TOnReceiveData;
  private
    procedure DoReceiveData(AData: Integer);
  protected
    procedure LMReceiveData(const AMessage: TLMessage); message LM_RECEIVEDATA;
  public
    property OnReceiveData: TOnReceiveData read FOnReceiveData write FOnReceiveData;
  end;

  procedure TMyForm.DoReceiveData(AData: Integer);
  begin
    if Assigned(FOnReceiveData) then
      FOnReceiveData(Self, AData);
  end;

  procedure TMyForm.LMReceiveData(const AMessage: TLMessage);
  begin
    DoReceiveData(AMessage.lParam);
  end;

W skrócie. LMReceiveData otrzymuje paczkę komunikatu i dane w niej zawarte wykorzystuje do dalszych operacji. W tym przypadku przekazuje liczbę zawartą w polu lParam do procedury wywołującej zdarzenie, czyli do DoReceiveData. Ta z kolei sprawdza czy zdarzenie jest w ogóle przypisane i jeśli tak, wywołuje je, przekazując własną referencję oraz dane w parametrach. I to wszystko.

Tak więc jeśli chodzi o obsługę własnego komunikatu lub takiego, którego obsługa w danej klasie nie istnieje, wykorzystuje się podany wyżej szablon. W Twoim przypadku, taki zabieg nie jest konieczny, dlatego że klasa formularza posiada już pełną obsługę komunikatu wciśnięcia lewego przycisku myszy, a także posiada zdarzenie wywoływane po otrzymaniu takiego komunikatu.

Implementacja obsługi zawarta jest w klasie bazowej (dokładnie w klasie TControl) pod postacią zdarzenia OnMouseDown, które oprócz dostarczenia informacji na temat tego, który przycisk został przyciśnięty, dorzuca także zestaw dodatkowych przycisków (takich jak Shift, Ctrl, Alt itd.) oraz współrzędne kursora. Tak więc jeśli chesz podłączyć własną metodę do klasy okna i przechwytywać kliknięcia, to zadeklaruj metodę zgodną parametrami z typem TMouseEvent i podłącz ją pod zdarzenie OnMouseDown, tuż po utworzeniu instancji klasy okna:

type
  TMyForm = class(TForm)
  {..}
  end;

type
  TMainForm = class(TForm)
  private
    procedure HandleMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  private
    procedure CreateMyForm();
  end;

  procedure TMainForm.CreateMyForm();
  var
    MyForm: TMyForm;
  begin
    MyForm := TMyForm.Create(Self);
    MyForm.OnMouseDown := @HandleMouseDown;
  end;

Pisane z palca, jakby co. ;)

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