unit Unit1;

interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Clipbrd,
  {   }
  Unit2;


Type

MojSchowek = class(TObject)
private
   CF_DDGDATA : Word;
   ob_osoba   : Osoba;

public
   procedure   SetOsoba(par_osoba : Osoba);

   procedure   CopyToClipboard();
   procedure   GetFromClipboard();

   constructor Create();
   destructor  Destroy(); override;
end;

implementation
Uses
   Main;
{------------------------------------------------------------------------------}
constructor MojSchowek.Create();
begin
   // tutaj trzymamy dane o osobie
   ob_osoba := Osoba.Create();

	// zerejestru niestandardowy format danych w Schowku Windows
   CF_DDGDATA := RegisterClipboardFormat('CF_DDGDATA');

   if CF_DDGDATA = 0 then
   begin
      Form1.Memo1.Lines.Add('Nie udało się zarejestrować nowego formatu danych dla schowka');
   end;
end;

destructor MojSchowek.Destroy();
begin
   if Assigned(ob_osoba) then
   begin
   	FreeAndNil(ob_osoba);
   end;

	inherited;
end;

procedure MojSchowek.SetOsoba(par_osoba: Osoba);
begin
   ob_osoba.set_nazwisko(par_osoba.get_nazwisko());
   ob_osoba.set_imie(par_osoba.get_imie());
   ob_osoba.set_ulica(par_osoba.get_ulica());
   ob_osoba.set_kodp(par_osoba.get_kodp());
   ob_osoba.set_miasto(par_osoba.get_miasto());
end;

procedure MojSchowek.CopyToClipboard();
var
	nazwisko : String;
	imie     : String;
	ulica    : String;
	kodp     : String;
	miasto   : String;

	Data     : HGLOBAL;
	DataPtr  : Pointer;
	iSize    : Integer;

begin
	nazwisko := '';
	imie     := '';
	ulica    := '';
	kodp     := '';
	miasto   := '';
   Data     := 0;
	DataPtr  := Nil;

   iSize := ob_osoba.InstanceSize();

	// przydziel pamięć dla bloku pamięci
	Data := GlobalAlloc(GMEM_MOVEABLE, iSize);

	try
   	// uzyskaj wskaźnik do pierwszego bajtu przydzielonej pamięci:
		DataPtr := GlobalLock(Data);

		try
			// skopiuj dane osoby do przydzielonej pamięci
         CopyMemory(DataPtr, ob_osoba, iSize);

         // sprawdzamy czy na prawdę w DataPtr jest to co trzeba
         nazwisko := Osoba(DataPtr).get_nazwisko();
         imie     := Osoba(DataPtr).get_imie();
         ulica    := Osoba(DataPtr).get_ulica();
         kodp     := Osoba(DataPtr).get_kodp();
         miasto   := Osoba(DataPtr).get_miasto();

			Form1.Memo1.Lines.Add('Do schowka:');
			Form1.Memo1.Lines.Add(nazwisko);
			Form1.Memo1.Lines.Add(imie);
			Form1.Memo1.Lines.Add(ulica);
			Form1.Memo1.Lines.Add(kodp);
			Form1.Memo1.Lines.Add(miasto);

      	// wyczyść schowek Windows
			Clipboard.Clear();
			// Clipboard Open musi być wywołane w sytuacji, gdy kopiowane są dane w kilku fomatach jednocześnie
			Clipboard.Open();
			// skopiuj dane w ich specyficznym formacie
			Clipboard.SetAsHandle(CF_DDGDATA, Data);

			Clipboard.Close();

      finally
			// odblokuj globalny fragment pamięci
			GlobalUnlock(Data);
		end;
	except
		// zwolnienie danych wykonywane przez poniższą instrukcję
		// konieczne jest tylko wówczas, gdy wystapi wyjątek
		// w przeciwnym razie Schowek sam zwolni wszystkie związane
		// z nim obszary pamieci globalnej
		GlobalFree(Data);
		ShowMessage('Wystąpił błąd');
	end;
end;

procedure MojSchowek.GetFromClipboard;
var
	nazwisko   : String;
	imie       : String;
	ulica      : String;
	kodp       : String;
	miasto     : String;

	Data       : HGLOBAL;
	DataPtr    : Pointer;
	iSize      : Integer;

   // żeby nie było wątpliwości, ze to tra sama zmienna
   // utworzymy sobie nowy pojemniek na dane
   nowa_osoba : Osoba;

begin
	(*
	procedura wkleja ze Schowka porcję danych w formacie
	reprezentowanym przez zmienną CF_DDGDATA.
	Dane zapisywane są w polu ob_osoba obiektu Osoba
	*)
	nazwisko := '';
	imie     := '';
	ulica    := '';
	kodp     := '';
	miasto   := '';
   Data     := 0;
	DataPtr  := Nil;
   iSize    := 0;

	if Clipboard.HasFormat(CF_DDGDATA) then
	begin
		Form1.Memo1.Lines.Add('Schowek zawiera dane w oczekiwanym fomacie');
	end
	else begin
		Form1.Memo1.Lines.Add('Schowek nie zawiera danych w oczekiwanym fomacie');
      exit;
	end;

	// uzyskaj uchwyt do bloku pamięci w schowku
	Data := Clipboard.GetAsHandle(CF_DDGDATA);

	if Data = 0 then
	begin
      exit;
	end;

	// przekształć uchwyt we wskaźnik
	DataPtr := GlobalLock(Data);

	try
		// określamy wielkość pobieranej porcji danych:
		iSize := GlobalSize(Data);
   	// kopiujemy z bloku pamięci do zm. typu Osoba
      nowa_osoba := Osoba.Create();
      CopyMemory(nowa_osoba, DataPtr, iSize);

      // sprawdzamy co mamy ze schowka
		nazwisko := nowa_osoba.get_nazwisko();
		imie     := nowa_osoba.get_imie();
		ulica    := nowa_osoba.get_ulica();
		kodp     := nowa_osoba.get_kodp();
		miasto   := nowa_osoba.get_miasto();

		Form1.Memo1.Lines.Add(' ');
		Form1.Memo1.Lines.Add('Ze schowka:');
		Form1.Memo1.Lines.Add(nazwisko);
		Form1.Memo1.Lines.Add(imie);
		Form1.Memo1.Lines.Add(ulica);
		Form1.Memo1.Lines.Add(kodp);
		Form1.Memo1.Lines.Add(miasto);
   finally
		// zwolnij wskaźnik do globalnego fragmentu pamięci
		GlobalUnlock(Data);

      FreeAndNil(nowa_osoba);
	end;
end;

end.

