伊布SKY

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理


{
example:
Copy:
  EmbeddedWB1.Copy;
  NDClipboard.CopyNDDataToClipboard;
Cut:
  EmbeddedWB1.Cut;
  NDClipboard.CopyNDDataToClipboard;
Paste:
  if NDClipboard.HasFormat(CF_NDCONTENT) then
  begin
    NDClipboard.CopyNDDataFromClipboard;//从剪贴板取出数据,并进行解壳操作
    EmbeddedWB1.Paste;//粘贴到目标中去
    NDClipboard.CopyNDDataToClipboard; //再将剪贴板里的数据重新加壳
  end
  else
    EmbeddedWB1.Paste;
}


unit uNDClipboardClass;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Clipbrd;

const
  NDClipboardFormatStr = 'CF_NDCONTENT';

type
  TNDClipboard = class(TClipboard)
  public
    procedure SetNdData;
    procedure GetNdData;
    procedure CopyNDDataToClipboard;
    procedure CopyNDDataFromClipboard;

    procedure SaveClipDataToStream(var AMem: TMemoryStream);
    procedure LoadClipDataFromStream(var AMem: TMemoryStream);

  end;

  TDataIdnet = array[0..2] of Char;
  TClipboardFileHead = packed record
    rIdent: TDataIdnet;
    rCount: Word;
  end;

  TClipboardFileItem = packed record
    rFormat: Word;
    rSize: Longword;
    rData: Pointer;
  end;

const rDataIdnet: TDataIdnet = 'cbf';



var
  CF_NDCONTENT: Word;

function NDClipboard: TNDClipboard;
function ClipboardSaveToStream(mStream: TStream): Boolean;
function ClipboardLoadFromStream(mStream: TStream): Boolean;

procedure CopyStreamToClipboard(fmt: Cardinal; S: TStream);
procedure CopyStreamFromClipboard(fmt: Cardinal; S: TStream);
procedure SaveClipboardFormat(fmt: Word; writer: TWriter);
procedure LoadClipboardFormat(reader: TReader);
procedure SaveClipboard(S: TStream);
procedure LoadClipboard(S: TStream);



implementation

function ClipboardSaveToStream(mStream: TStream): Boolean;
var
  vClipboardFileHead: TClipboardFileHead;
  vClipboardFileItem: TClipboardFileItem;
  I: Integer;
  vData: THandle;
begin
  Result := False;
  if not Assigned(mStream) then Exit;
  vClipboardFileHead.rIdent := rDataIdnet;
  vClipboardFileHead.rCount := Clipboard.FormatCount;
  mStream.Write(vClipboardFileHead, SizeOf(vClipboardFileHead));
  try
    Clipboard.Open;
    for I := 0 to Clipboard.FormatCount - 1 do begin
      vData := GetClipboardData(Clipboard.Formats[I]);
      vClipboardFileItem.rFormat := Clipboard.Formats[I];
      vClipboardFileItem.rSize := GlobalSize(vData);
      vClipboardFileItem.rData := GlobalLock(vData);
      try
        mStream.Write(vClipboardFileItem, SizeOf(vClipboardFileItem) -
          SizeOf(vClipboardFileItem.rData));
        mStream.Write(vClipboardFileItem.rData^, vClipboardFileItem.rSize);
      finally
        GlobalUnlock(vData);
      end;
    end;
  finally
    Clipboard.Close;
  end;
  Result := True;
end; { ClipboardSaveToStream }

procedure CopyStreamToClipboard(fmt: Cardinal; S: TStream);
var
  hMem: THandle;
  pMem: Pointer;
begin
  Assert(Assigned(S));
  S.Position := 0;
  hMem := GlobalAlloc(GHND or GMEM_DDESHARE, S.Size);
  if hMem <> 0 then
  begin
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      try
        S.Read(pMem^, S.Size);
        S.Position := 0;
      finally
        GlobalUnlock(hMem);
      end;
      Clipboard.Open;
      try
        Clipboard.SetAsHandle(fmt, hMem);
      finally
        Clipboard.Close;
      end;
    end { If }
    else
    begin
      GlobalFree(hMem);
      OutOfMemoryError;
    end;
  end { If }
  else
    OutOfMemoryError;
end; { CopyStreamToClipboard }

procedure CopyStreamFromClipboard(fmt: Cardinal; S: TStream);
var
  hMem: THandle;
  pMem: Pointer;
begin
  Assert(Assigned(S));
  hMem := Clipboard.GetAsHandle(fmt);
  if hMem <> 0 then
  begin
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      try
        S.Write(pMem^, GlobalSize(hMem));
        S.Position := 0;
      finally
        GlobalUnlock(hMem);
      end;
    end { If }
    else
      raise Exception.Create('CopyStreamFromClipboard: could not lock global handle ' +
        'obtained from clipboard!');
  end; { If }
end; { CopyStreamFromClipboard }

procedure SaveClipboardFormat(fmt: Word; writer: TWriter);
var
  fmtname: array[0..128] of Char;
  ms: TMemoryStream;
begin
  Assert(Assigned(writer));
  if 0 = GetClipboardFormatName(fmt, fmtname, SizeOf(fmtname)) then
    fmtname[0] := #0;
  ms := TMemoryStream.Create;
  try
    CopyStreamFromClipboard(fmt, ms);
    if ms.Size > 0 then
    begin
      writer.WriteInteger(fmt);
      writer.WriteString(fmtname);
      writer.WriteInteger(ms.Size);
      writer.Write(ms.Memory^, ms.Size);
    end; { If }
  finally
    ms.Free
  end; { Finally }
end; { SaveClipboardFormat }

procedure LoadClipboardFormat(reader: TReader);
var
  fmt: Integer;
  fmtname: string;
  Size: Integer;
  ms: TMemoryStream;
begin
  Assert(Assigned(reader));
  fmt := reader.ReadInteger;
  fmtname := reader.ReadString;
  Size := reader.ReadInteger;
  ms := TMemoryStream.Create;
  try
    ms.Size := Size;
    reader.Read(ms.memory^, Size);
    if Length(fmtname) > 0 then
      fmt := RegisterCLipboardFormat(PChar(fmtname));
    if fmt <> 0 then
      CopyStreamToClipboard(fmt, ms);
  finally
    ms.Free;
  end; { Finally }
end; { LoadClipboardFormat }

procedure SaveClipboard(S: TStream);
var
  writer: TWriter;
  i: Integer;
begin
  Assert(Assigned(S));
  writer := TWriter.Create(S, 4096);
  try
    Clipboard.Open;
    try
      writer.WriteListBegin;
      for i := 0 to Clipboard.formatcount - 1 do
        SaveClipboardFormat(Clipboard.Formats[i], writer);
      writer.WriteListEnd;
    finally
      Clipboard.Close;
    end; { Finally }
  finally
    writer.Free
  end; { Finally }
end; { SaveClipboard }

procedure LoadClipboard(S: TStream);
var
  reader: TReader;
begin
  Assert(Assigned(S));
  reader := TReader.Create(S, 4096);
  try
    Clipboard.Open;
    try
      clipboard.Clear;
      reader.ReadListBegin;
      while not reader.EndOfList do
        LoadClipboardFormat(reader);
      reader.ReadListEnd;
    finally
      Clipboard.Close;
    end; { Finally }
  finally
    reader.Free
  end; { Finally }
end; { LoadClipboard }

function ClipboardLoadFromStream(mStream: TStream): Boolean;
var
  vClipboardFileHead: TClipboardFileHead;
  vClipboardFileItem: TClipboardFileItem;
  I: Integer;
  vData: THandle;
begin
  Result := False;
  if not Assigned(mStream) then Exit;
  if mStream.Size <= SizeOf(vClipboardFileHead) then Exit;
  mStream.Read(vClipboardFileHead, SizeOf(vClipboardFileHead));
  if vClipboardFileHead.rIdent <> rDataIdnet then Exit;
  Clipboard.Clear;
  Clipboard.Open;
  try
    for I := 0 to vClipboardFileHead.rCount - 1 do begin
      mStream.Read(vClipboardFileItem, SizeOf(vClipboardFileItem) -
        SizeOf(vClipboardFileItem.rData));
      vData := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE,
        vClipboardFileItem.rSize);
      try
        vClipboardFileItem.rData := GlobalLock(vData);
        try
          mStream.Read(vClipboardFileItem.rData^, vClipboardFileItem.rSize);
          SetClipboardData(vClipboardFileItem.rFormat, vData);
        finally
          GlobalUnlock(vData);
        end;
      finally
        GlobalFree(vData);
      end;
    end;
  finally
    Clipboard.Close;
  end;
  Result := True;
end; { ClipboardLoadFromStream }



procedure TNDClipboard.SetNdData;
var
  Data: THandle;
  DataPtr: Pointer;
  MemStream: TMemoryStream;
begin
  Open;
  try
    Data := NDclipboard.Handle;
    if Data = 0 then Exit;
    DataPtr := GlobalLock(Data);
    if DataPtr = nil then Exit;
    try
      MemStream := TMemoryStream.Create;
      try
        MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
        MemStream.Position := 0;
        SetBuffer(CF_NDCONTENT, MemStream.Memory^, MemStream.Size);
      finally
        MemStream.Free;
      end;
    finally
      GlobalUnlock(Data);
    end;
  finally
    Close;
  end;
end;

procedure TNDClipboard.GetNdData;
var
  Data: THandle;
  DataPtr: Pointer;
  MemStream: TMemoryStream;
begin
  Open;
  try
    Data := GetClipboardData(CF_NDCONTENT);
    if Data = 0 then Exit;
    DataPtr := GlobalLock(Data);
    if DataPtr = nil then Exit;
    try
      MemStream := TMemoryStream.Create;
      try
        MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
        MemStream.Position := 0;
      finally
        MemStream.Free;
      end;
    finally
      GlobalUnlock(Data);
    end;
  finally
    Close;
  end;
end;

var
  FNDClipboard: TNDClipboard;

function NDClipboard: TNDClipboard;
begin
  if FNDClipboard = nil then
    FNDClipboard := TNDClipboard.Create;
  Result := FNDClipboard;
end;

procedure TNDClipboard.CopyNDDataFromClipboard;
var
  hbuf: THandle;
  bufptr: Pointer;
  mstream: TMemoryStream;
begin
  hbuf := Clipboard.GetAsHandle(CF_NDCONTENT);
  if hbuf <> 0 then begin
    bufptr := GlobalLock(hbuf);
    if bufptr <> nil then begin
      try
        mstream := TMemoryStream.Create;
        try
          mstream.WriteBuffer(bufptr^, GlobalSize(hbuf));
          mstream.Position := 0;
          //-- 处理流的代码 --
          //ClipboardLoadFromStream(mstream)
          //LoadClipDataFromStream(mstream);
          LoadClipboard(mstream);
        finally
          mstream.Free;
        end;
      finally
        GlobalUnlock(hbuf);
      end;
    end;
  end;

end;

procedure TNDClipboard.CopyNDDataToClipboard;
var
  hbuf: THandle;
  bufptr: Pointer;
  mstream: TMemoryStream;
begin
  mstream := TMemoryStream.Create;
  try
    //-- 处理流的代码 --
    //ClipboardSaveToStream(mstream);
    //SaveClipDataToStream(mstream);
    SaveClipboard(mstream);
    //mstream.SaveToFile('test');
    hbuf := GlobalAlloc(GMEM_MOVEABLE, mstream.size);
    try
      bufptr := GlobalLock(hbuf);
      try
        Move(mstream.Memory^, bufptr^, mstream.size);
        Clipboard.SetAsHandle(CF_NDCONTENT, hbuf);
      finally
        GlobalUnlock(hbuf);
      end;
    except
      GlobalFree(hbuf);
      raise;
    end;
  finally
    mstream.Free;
  end;
end;


procedure TNDClipboard.LoadClipDataFromStream(var AMem: TMemoryStream);
var
  MemStream, DataStream: TMemoryStream;
  i, FormatListLen, DataStreamLen: Integer;
  tmpStrings: TStringList;
begin
  DataStream := TMemoryStream.Create;
  tmpStrings := TStringList.Create;
  try
    clipbrd.Clipboard.Open;
    Clipboard.Clear;
    AMem.Position := 0;
    AMem.ReadBuffer(FormatListLen, SizeOf(Integer));
    AMem.ReadBuffer(DataStreamLen, SizeOf(Integer));
    DataStream.CopyFrom(AMem, FormatListLen);
    DataStream.position := 0;
    tmpStrings.LoadFromStream(DataStream);
    DataStream.Clear;

    DataStream.CopyFrom(AMem, DataStreamLen);
    DataStream.position := 0;

    if DataStream.Size <> 0 then DataStream.Position := 0;

    for i := 0 to tmpStrings.Count - 1 do
    begin
      FormatListLen := StrToInt(tmpStrings.Names[i]);
      DataStreamLen := StrToInt(tmpStrings.Values[tmpStrings.Names[i]]);

      MemStream := TMemoryStream.Create;
      try
        MemStream.CopyFrom(DataStream, DataStreamLen);
        MemStream.Position := 0;

        SetBuffer(FormatListLen, MemStream.Memory^, DataStreamLen);
      finally
        MemStream.Free;
      end;
    end;
  finally
    clipbrd.Clipboard.Close;
    tmpStrings.Free;
    DataStream.Free;
  end;

end;

procedure TNDClipboard.SaveClipDataToStream(var AMem: TMemoryStream);
var
  Data: THandle;
  DataPtr: Pointer;
  MemStream, DataStream: TMemoryStream;
  i, tmpInt: Integer;
  tmpStrings: TStringList;
begin
  DataStream := TMemoryStream.Create;
  tmpStrings := TStringList.Create;
  try
    clipbrd.Clipboard.Open;
    for i := 0 to Clipboard.FormatCount - 1 do
    begin
      Data := GetClipboardData(Clipboard.Formats[i]);
      if Data = 0 then Continue;
      DataPtr := GlobalLock(Data);
      try
        if DataPtr = nil then Continue;
        MemStream := TMemoryStream.Create;
        try
          tmpInt := GlobalSize(Data);
          if tmpInt = 0 then
            beep;
          MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));
          MemStream.Position := 0;
          tmpStrings.Add(IntToStr(Clipboard.Formats[i]) + '=' + IntToStr(GlobalSize(Data)));
          DataStream.WriteBuffer(MemStream.Memory^, MemStream.Size);
        finally
          MemStream.Free;
        end;
      finally
        GlobalUnlock(Data);
      end;
    end;
    if tmpStrings.Count <> 0 then
    begin
      AMem.Clear;
      tmpInt := Length(tmpStrings.Text);
      AMem.WriteBuffer(tmpInt, SizeOf(Integer));
      tmpInt := DataStream.size;
      AMem.WriteBuffer(tmpInt, Sizeof(Integer));
      MemStream := TMemoryStream.Create;
      try
        tmpStrings.SaveToStream(MemStream);
        AMem.WriteBuffer(MemStream.Memory^, MemStream.Size);
      finally
        MemStream.Free;
      end;
      AMem.WriteBuffer(DataStream.Memory^, DataStream.Size);
    end;
  finally
    clipbrd.Clipboard.Close;
    tmpStrings.Free;
    DataStream.Free;
  end;
end;

initialization
  CF_NDCONTENT := RegisterClipboardFormat(NDClipboardFormatStr);
  FNDClipboard := nil;
finalization
  FNDClipboard.Free;

end.

posted on 2009-04-23 11:58  伊布  阅读(355)  评论(0编辑  收藏  举报