[ Pobierz całość w formacie PDF ]
.Ancestor))elseResult := not Empty;end;begininherited DefineProperties(Filer);Filer.DefineBinaryProperty('Data', ReadData, WriteData, DoWrite);end;Jak widaæ, definiowana jest tu porcja danych identyfikowana przez nazwê Data,obs³ugiwana przez procedury transmisyjne ReadData() i WriteData(); jej obecnoœæw strumieniu zale¿na jest od wyniku zwracanego przez funkcjê DoWrite(), któr¹zajmiemy siê za chwilê.Dzia³anie ReadData i WriteData ogranicza siê do (odpowiednio) odczytu danychkomponentu ze strumienia i zapisu danych w strumieniu:procedure TddgWaveFile.ReadData(Stream: TStream);{ odczytuje dane ze strumienia }beginLoadFromStream(Stream);end;procedure TddgWaveFile.WriteData(Stream: TStream);{ zapisuje dane komponentu do strumienia }beginSaveToStream(Stream);end;Metoda LoadFromStream() sprawdza wpierw, czy do komponentu zosta³y ju¿za³adowane jakieœ dane; je¿eli jest tak istotnie, zwalnia przydzielon¹ dla nichpamiêæ, przydziela j¹ ponownie w rozmiarze odpowiadaj¹cym rozmiarowi strumieniai wczytuje do niej dane zawarte w strumieniu:procedure TddgWaveFile.LoadFromStream(S: TStream);{Wczytuje dane ze strumienia, zwalniaj¹c pamiêæ zajêt¹ przezew.dane za³adowane wczeœniej}beginif not Empty thenFreeMem(FData, FDataSize);FDataSize := 0;FData := AllocMem(S.Size);FDataSize := S.Size;S.Read(FData^, FDataSize);end;Metoda SaveToStream() jest nieco prostsza: zapisuje dane w strumieniu,sprawdziwszy jednak uprzednio, czy w ogóle jest co zapisywaæ:procedure TddgWaveFile.SaveToStream(S: TStream);{ Zapisuje dane do strumienia }beginif not EmptythenS.Write(FData^, FDataSize);end;Funkcja DoWrite(), decyduj¹ca o tym, czy dane maj¹ byæ w ogóle zapisywane,rozwi¹zuje tu pewien problem, który pojawi³ siê wraz z mo¿liwoœci¹dziedziczenia formularzy (Visual Form Inheritance), na przyk³ad z repozytorium,za pomoc¹ opcji Inherit.Nie mo¿na wykluczyæ sytuacji, i¿ komponentTddgWaveFile jest czêœci¹ formularza macierzystego i jako taki jestdziedziczony przez formularz projektu.Je¿eli dziedziczenie takie istotnie mamiejsce, a ponadto dane komponentu w formularzu macierzystym s¹ identyczne zdanymi komponentu w formularzu projektu, to najprawdopodobniej niemodyfikowaliœmy jeszcze zawartoœci komponentu w projekcie.Je¿eli terazzamknêlibyœmy projekt i zmienili zawartoœæ komponentu w formularzumacierzystym, to mielibyœmy prawo oczekiwaæ, i¿ po ponownym otwarciu projektuzmiany te uwidoczni¹ siê w komponencie znajduj¹cym siê na formularzu tegoprojektu.Innymi s³owy — dopóki nie dokonamy ¿adnej zmiany w komponencieznajduj¹cym siê w formularzu projektu, mamy prawo oczekiwaæ pe³nej jegozgodnoœci z komponentem w formularzu macierzystym; komponent ma wówczasdziedziczyæ sw¹ wartoœæ z formularza macierzystego, nie zaœ odczytywaæ j¹ zestrumienia.Funkcja DoWrite() rozpoczyna wiêc od sprawdzenia, czy komponent TddgWaveFilezosta³ odziedziczony z formularza macierzystego — w takiej sytuacji komponentten jest wskazywany przez w³aœciwoœæ Ancestor obiektu TFiler.Je¿eli komponentw formularzu macierzystym równie¿ jest komponentem klasy TddgWaveFile i je¿elijego zawartoœæ jest identyczna z zawartoœci¹ podlegaj¹c¹ zapisowi do strumieniato przyjmuje siê, i¿ komponent w projekcie nie by³ jeszcze modyfikowany (choæwcale nie musi to byæ prawda, lecz dla prostoty przyjmijmy tak¹ uproszczon¹wersjê).Warto przy tym zwróciæ uwagê na to, w jaki sposób metoda Equal()porównuje zawartoœæ obydwu komponentów.Te i inne szczegó³y wyczytaæ mo¿na z kodu Ÿród³owego komponentu, któryprezentujemy na wydruku 12.8.Wydruk 12.8.Modu³ implementuj¹cy komponent TddgWaveFileunit Wavez;interfaceusesSysUtils, Classes;type{ rozró¿nienie typów z punktu widzenia edytora w³aœciwoœci }TWaveFileString = type string;EWaveError = class(Exception);TWavePause = (wpAsync, wpsSync);TWaveLoop = (wlNoLoop, wlLoop);TddgWaveFile = class(TComponent)privateFData: Pointer;FDataSize: Integer;FWaveName: TWaveFileString;FWavePause: TWavePause;FWaveLoop: TWaveLoop;FOnPlay: TNotifyEvent;FOnStop: TNotifyEvent;procedure SetWaveName(const Value: TWaveFileString);procedure WriteData(Stream: TStream);procedure ReadData(Stream: TStream);protectedprocedure DefineProperties(Filer: TFiler); override;publicdestructor Destroy; override;function Empty: Boolean;function Equal(Wav: TddgWaveFile): Boolean;procedure LoadFromFile(const FileName: String);procedure LoadFromStream(S: TStream);procedure Play;procedure SaveToFile(const FileName: String);procedure SaveToStream(S: TStream);procedure Stop;publishedproperty WaveLoop: TWaveLoop read FWaveLoop write FWaveLoop;property WaveName: TWaveFileString read FWaveName write SetWaveName;property WavePause: TWavePause read FWavePause write FWavePause;property OnPlay: TNotifyEvent read FOnPlay write FOnPlay;property OnStop: TNotifyEvent read FOnStop write FOnStop;end;implementationuses MMSystem, Windows;{ TddgWaveFile }destructor TddgWaveFile.Destroy;{ zapewnia zwolnienie przydzielonej pamiêci }beginif not Empty thenFreeMem(FData, FDataSize);inherited Destroy;end;function StreamsEqual(S1, S2: TMemoryStream): Boolean;beginResult := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size);end;procedure TddgWaveFile
[ Pobierz całość w formacie PDF ]
Darmowy hosting zapewnia PRV.PL