Delphi - Egyedi formátumú adat elhelyezése vágólapon

forráskód letöltése
Vágólapon általában szöveget szoktunk elhelyezni, amit ezután vagy ugyanabban az alkalmazásban, vagy egy másikban használunk fel.

A szöveg mellett perszer mást is helyezhetünk a vágólapra. Ennek tartalma lehet kép, hang, Delphi komponens, stb.

Megoldható viszont az is, hogy egy teljesen egyedi formátumú adatot helyezzünk el a vágólapon.

Mellékelt példában az alábbi struktúrájú adat kerül a vágólapra:
  TRec=record
    num: integer;
    date: TDateTime;
  end;
Ennek megvalósításához először regisztrálnunk kell egy saját formátumot, amit a RegisterClipboardFormat függvény hívásával tehetünk meg. Paraméterként egy tetszőleges szöveget adhatunk, mely az új formátum leírása lehet. A visszatérési értéket eltároljuk, később még szükségünk lesz rá.
procedure TForm1.FormCreate(Sender: TObject);
begin
  CF_NEWFORMAT:=RegisterClipboardFormat('Animare Clipboard Format');
end;
Létrehozunk egy ClipboardSetData eljárást, mely a fenti rekordot helyezi el vágólapon. Paraméterként egy ilyen típusú változót kell átadnunk, aminek előtte természetesen értéket adunk.
procedure TForm1.Button1Click(Sender: TObject);
var
  a: TRec;
begin
  a.num:=TrackBar1.Position;
  a.date:=MonthCalendar1.Date;
  ClipboardSetData(a);
end;
A ClipboardSetData működése a következő: első lépésként egy memória stream-re másolja a kapott változó tartalmát, így lehetőségünk nyílik egy egységes memória területként, akár bájtonként is elérni a változó tartalmát.

A GlobalAlloc-al memória területet foglalunk a globális memóriából és a stream-ból ide másoljuk az adatokat. Végül már csak annyi a teendő, hogy a TClipboard SetAsHandle metódusával erre a memória területre állítsuk a vágólapot.
procedure TForm1.ClipboardSetData(rec: TRec);
var
  st: TMemoryStream;
  h: THandle;
  p: Pointer;
begin
  st:=TMemoryStream.Create;
  try
    st.Write(rec, SizeOf(TRec));
    st.Position:=0;
    h:=GlobalAlloc(GMEM_MOVEABLE and GMEM_DDESHARE,
         st.Size);
    if h<>0 then begin
      p:=GlobalLock(h);
      try
        st.Read(p^, st.Size);
      finally
        GlobalUnlock(h);
      end;
      ClipBoard.SetAsHandle(CF_NEWFORMAT, h);
    end;
  finally
    st.Free;
  end;
end;
Ezek után a kérdéses adat vágólapon megtalálható, de mivel formátumát valószínűleg saját alkalmazásainkon kívül más program nem fogja ismerni, így felhasználni is csak saját programjaink tudják.

Ehhez viszont olvasni is tudni kell a vágólapról. Ehhez hozzuk létre a ClipboardGetData függvényt, mely az egyetlen paraméterében fogja szolgáltatni a vágólapon lévő adathalmazt. Ha esetleg időközben már más kerülne a vágólapra és ott nem a saját formátumú adatunk található, akkor a függvény hamis értékkel tér vissza. Ezt nem árt minden esetben ellenőrizni.

A függvény működése megegyezik az előbbi ClipboardSetData eljárással, csupán itt nem írunk, hanem olvasunk.
function TForm1.ClipboardGetData(var rec: TRec): boolean;
var
  h: THandle;
  p: Pointer;
  st: TMemoryStream;
begin
  result:=false;
  ClipBoard.Open;
  try
    h:=GetClipboardData(CF_NEWFORMAT);
    if h<>0 then begin
      p:=GlobalLock(h);
      if p<>nil then begin
        try
          st:=TMemoryStream.Create;
          try
            st.WriteBuffer(p^, GlobalSize(h));
            st.Position:=0;
            st.Read(rec, SizeOf(TRec));
            result:=true;
          finally
            st.Free;
          end;
        finally
          GlobalUnlock(h);
        end;
      end;
    end;
  finally
    ClipBoard.Close;
  end
end;