<br>{*******************************************************}<br>{ }<br>{ Borland Delphi Visual Component Library }<br>{ }<br>{ Copyright (c) 1995-2001 Borland Software Corporation }<br>{ }<br>{*******************************************************}<br><br>unit Clipbrd;<br><br>{$R-,T-,H+,X+}<br><br>interface<br><br>uses Windows, Messages, Classes, Graphics;<br><br>var<br> CF_PICTURE: Word;<br> CF_COMPONENT: Word;<br><br>{ TClipboard }<br><br>{ The clipboard object encapsulates the Windows clipboard.<br><br> Assign - Assigns the given object to the clipboard. If the object is<br> a TPicture or TGraphic desendent it will be placed on the clipboard<br> in the corresponding format (e.g. TBitmap will be placed on the<br> clipboard as a CF_BITMAP). Picture.Assign(Clipboard) and<br> Bitmap.Assign(Clipboard) are also supported to retrieve the contents<br> of the clipboard.<br> Clear - Clears the contents of the clipboard. This is done automatically<br> when the clipboard object adds data to the clipboard.<br> Close - Closes the clipboard if it is open. Open and close maintain a<br> count of the number of times the clipboard has been opened. It will<br> not actually close the clipboard until it has been closed the same<br> number of times it has been opened.<br> Open - Open the clipboard and prevents all other applications from changeing<br> the clipboard. This is call is not necessary if you are adding just one<br> item to the clipboard. If you need to add more than one format to<br> the clipboard, call Open. After all the formats have been added. Call<br> close.<br> HasFormat - Returns true if the given format is available on the clipboard.<br> GetAsHandle - Returns the data from the clipboard in a raw Windows handled<br> for the specified format. The handle is not owned by the application and<br> the data should be copied.<br> SetAsHandle - Places the handle on the clipboard in the given format. Once<br> a handle has been given to the clipboard it should *not* be deleted. It<br> will be deleted by the clipboard.<br> GetTextBuf - Retrieves<br> AsText - Allows placing and retrieving text from the clipboard. This property<br> is valid to retrieve if the CF_TEXT format is available.<br> FormatCount - The number of formats in the Formats array.<br> Formats - A list of all the formats available on the clipboard. }<br><br>type<br> TClipboard = class(TPersistent)<br> private<br> FOpenRefCount: Integer;<br> FClipboardWindow: HWND;<br> FAllocated: Boolean;<br> FEmptied: Boolean;<br> procedure Adding;<br> procedure AssignGraphic(Source: TGraphic);<br> procedure AssignPicture(Source: TPicture);<br> procedure AssignToBitmap(Dest: TBitmap);<br> procedure AssignToMetafile(Dest: TMetafile);<br> procedure AssignToPicture(Dest: TPicture);<br> function GetAsText: string;<br> function GetClipboardWindow: HWND;<br> function GetFormatCount: Integer;<br> function GetFormats(Index: Integer): Word;<br> procedure SetAsText(const Value: string);<br> protected<br> procedure AssignTo(Dest: TPersistent); override;<br> procedure SetBuffer(Format: Word; var Buffer; Size: Integer);<br> procedure WndProc(var Message: TMessage); virtual;<br> procedure MainWndProc(var Message: TMessage);<br> property Handle: HWND read GetClipboardWindow;<br> property OpenRefCount: Integer read FOpenRefCount;<br> public<br> procedure Assign(Source: TPersistent); override;<br> procedure Clear; virtual;<br> procedure Close; virtual;<br> function GetComponent(Owner, Parent: TComponent): TComponent;<br> function GetAsHandle(Format: Word): THandle;<br> function GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;<br> function HasFormat(Format: Word): Boolean;<br> procedure Open; virtual;<br> procedure SetComponent(Component: TComponent);<br> procedure SetAsHandle(Format: Word; Value: THandle);<br> procedure SetTextBuf(Buffer: PChar);<br> property AsText: string read GetAsText write SetAsText;<br> property FormatCount: Integer read GetFormatCount;<br> property Formats[Index: Integer]: Word read GetFormats;<br> end;<br><br>function Clipboard: TClipboard;<br>function SetClipboard(NewClipboard: TClipboard): TClipboard;<br><br>implementation<br><br>uses SysUtils, Forms, Consts;<br><br>procedure TClipboard.Clear;<br>begin<br> Open;<br> try<br> EmptyClipboard;<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.Adding;<br>begin<br> if (FOpenRefCount <> 0) and not FEmptied then<br> begin<br> Clear;<br> FEmptied := True;<br> end;<br>end;<br><br>procedure TClipboard.Close;<br>begin<br> if FOpenRefCount = 0 then Exit;<br> Dec(FOpenRefCount);<br> if FOpenRefCount = 0 then<br> begin<br> CloseClipboard;<br> if FAllocated then<br> Classes.DeallocateHWnd(FClipboardWindow);<br> FClipboardWindow := 0;<br> end;<br>end;<br><br>procedure TClipboard.Open;<br>begin<br> if FOpenRefCount = 0 then<br> begin<br> FClipboardWindow := Application.Handle;<br> if FClipboardWindow = 0 then<br> begin<br> FClipboardWindow := Classes.AllocateHWnd(MainWndProc);<br> FAllocated := True;<br> end;<br> if not OpenClipboard(FClipboardWindow) then<br> raise Exception.CreateRes(@SCannotOpenClipboard);<br> FEmptied := False;<br> end;<br> Inc(FOpenRefCount);<br>end;<br><br>procedure TClipboard.WndProc(var Message: TMessage);<br>begin<br> with Message do<br> Result := DefWindowProc(FClipboardWindow, Msg, wParam, lParam);<br>end;<br><br>function TClipboard.GetComponent(Owner, Parent: TComponent): TComponent;<br>var<br> Data: THandle;<br> DataPtr: Pointer;<br> MemStream: TMemoryStream;<br> Reader: TReader;<br>begin<br> Result := nil;<br> Open;<br> try<br> Data := GetClipboardData(CF_COMPONENT);<br> if Data = 0 then Exit;<br> DataPtr := GlobalLock(Data);<br> if DataPtr = nil then Exit;<br> try<br> MemStream := TMemoryStream.Create;<br> try<br> MemStream.WriteBuffer(DataPtr^, GlobalSize(Data));<br> MemStream.Position := 0;<br> Reader := TReader.Create(MemStream, 256);<br> try<br> Reader.Parent := Parent;<br> Result := Reader.ReadRootComponent(nil);<br> try<br> if Owner <> nil then<br> Owner.InsertComponent(Result);<br> except<br> Result.Free;<br> raise;<br> end;<br> finally<br> Reader.Free;<br> end;<br> finally<br> MemStream.Free;<br> end;<br> finally<br> GlobalUnlock(Data);<br> end;<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.SetBuffer(Format: Word; var Buffer; Size: Integer);<br>var<br> Data: THandle;<br> DataPtr: Pointer;<br>begin<br> Open;<br> try<br> Data := GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE, Size);<br> try<br> DataPtr := GlobalLock(Data);<br> try<br> Move(Buffer, DataPtr^, Size);<br> Adding;<br> SetClipboardData(Format, Data);<br> finally<br> GlobalUnlock(Data);<br> end;<br> except<br> GlobalFree(Data);<br> raise;<br> end;<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.SetComponent(Component: TComponent);<br>var<br> MemStream: TMemoryStream;<br>begin<br> MemStream := TMemoryStream.Create;<br> try<br> MemStream.WriteComponent(Component);<br> SetBuffer(CF_COMPONENT, MemStream.Memory^, MemStream.Size);<br> finally<br> MemStream.Free;<br> end;<br>end;<br><br>function TClipboard.GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;<br>var<br> Data: THandle;<br>begin<br> Open;<br> Data := GetClipboardData(CF_TEXT);<br> if Data = 0 then Result := 0 else<br> begin<br> Result := StrLen(StrLCopy(Buffer, GlobalLock(Data), BufSize - 1));<br> GlobalUnlock(Data);<br> end;<br> Close;<br>end;<br><br>procedure TClipboard.SetTextBuf(Buffer: PChar);<br>begin<br> SetBuffer(CF_TEXT, Buffer^, StrLen(Buffer) + 1);<br>end;<br><br>function TClipboard.GetAsText: string;<br>var<br> Data: THandle;<br>begin<br> Open;<br> Data := GetClipboardData(CF_TEXT);<br> try<br> if Data <> 0 then<br> Result := PChar(GlobalLock(Data))<br> else<br> Result := '';<br> finally<br> if Data <> 0 then GlobalUnlock(Data);<br> Close;<br> end;<br>end;<br><br>function TClipboard.GetClipboardWindow: HWND;<br>begin<br> if FClipboardWindow = 0 then<br> Open;<br> Result := FClipboardWindow;<br>end;<br><br>procedure TClipboard.SetAsText(const Value: string);<br>begin<br> SetBuffer(CF_TEXT, PChar(Value)^, Length(Value) + 1);<br>end;<br><br>procedure TClipboard.AssignToPicture(Dest: TPicture);<br>var<br> Data: THandle;<br> Format: Word;<br> Palette: HPALETTE;<br>begin<br> Open;<br> try<br> Format := EnumClipboardFormats(0);<br> while Format <> 0 do<br> begin<br> if TPicture.SupportsClipboardFormat(Format) then<br> begin<br> Data := GetClipboardData(Format);<br> Palette := GetClipboardData(CF_PALETTE);<br> Dest.LoadFromClipboardFormat(Format, Data, Palette);<br> Exit;<br> end;<br> Format := EnumClipboardFormats(Format);<br> end;<br> raise Exception.CreateRes(@SInvalidClipFmt);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.AssignToBitmap(Dest: TBitmap);<br>var<br> Data: THandle;<br> Palette: HPALETTE;<br>begin<br> Open;<br> try<br> Data := GetClipboardData(CF_BITMAP);<br> Palette := GetClipboardData(CF_PALETTE);<br> Dest.LoadFromClipboardFormat(CF_BITMAP, Data, Palette);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.AssignToMetafile(Dest: TMetafile);<br>var<br> Data: THandle;<br> Palette: HPALETTE;<br>begin<br> Open;<br> try<br> Data := GetClipboardData(CF_METAFILEPICT);<br> Palette := GetClipboardData(CF_PALETTE);<br> Dest.LoadFromClipboardFormat(CF_METAFILEPICT, Data, Palette);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.AssignTo(Dest: TPersistent);<br>begin<br> if Dest is TPicture then<br> AssignToPicture(TPicture(Dest))<br> else if Dest is TBitmap then<br> AssignToBitmap(TBitmap(Dest))<br> else if Dest is TMetafile then<br> AssignToMetafile(TMetafile(Dest))<br> else inherited AssignTo(Dest);<br>end;<br><br>procedure TClipboard.AssignPicture(Source: TPicture);<br>var<br> Data: THandle;<br> Format: Word;<br> Palette: HPALETTE;<br>begin<br> Open;<br> try<br> Adding;<br> Palette := 0;<br> Source.SaveToClipboardFormat(Format, Data, Palette);<br> SetClipboardData(Format, Data);<br> if Palette <> 0 then SetClipboardData(CF_PALETTE, Palette);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.AssignGraphic(Source: TGraphic);<br>var<br> Data: THandle;<br> Format: Word;<br> Palette: HPALETTE;<br>begin<br> Open;<br> try<br> Adding;<br> Palette := 0;<br> Source.SaveToClipboardFormat(Format, Data, Palette);<br> SetClipboardData(Format, Data);<br> if Palette <> 0 then SetClipboardData(CF_PALETTE, Palette);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.Assign(Source: TPersistent);<br>begin<br> if Source is TPicture then<br> AssignPicture(TPicture(Source))<br> else if Source is TGraphic then<br> AssignGraphic(TGraphic(Source))<br> else inherited Assign(Source);<br>end;<br><br>function TClipboard.GetAsHandle(Format: Word): THandle;<br>begin<br> Open;<br> try<br> Result := GetClipboardData(Format);<br> finally<br> Close;<br> end;<br>end;<br><br>procedure TClipboard.SetAsHandle(Format: Word; Value: THandle);<br>begin<br> Open;<br> try<br> Adding;<br> SetClipboardData(Format, Value);<br> finally<br> Close;<br> end;<br>end;<br><br>function TClipboard.GetFormatCount: Integer;<br>begin<br> Result := CountClipboardFormats;<br>end;<br><br>function TClipboard.GetFormats(Index: Integer): Word;<br>begin<br> Open;<br> try<br> Result := EnumClipboardFormats(0);<br> while Index > 0 do<br> begin<br> Dec(Index);<br> Result := EnumClipboardFormats(Result);<br> end;<br> finally<br> Close;<br> end;<br>end;<br><br>function TClipboard.HasFormat(Format: Word): Boolean;<br><br> function HasAPicture: Boolean;<br> var<br> Format: Word;<br> begin<br> Open;<br> try<br> Result := False;<br> Format := EnumClipboardFormats(0);<br> while Format <> 0 do<br> if TPicture.SupportsClipboardFormat(Format) then<br> begin<br> Result := True;<br> Break;<br> end<br> else Format := EnumClipboardFormats(Format);<br> finally<br> Close;<br> end;<br> end;<br><br>begin<br> Result := IsClipboardFormatAvailable(Format) or ((Format = CF_PICTURE) and<br> HasAPicture);<br>end;<br><br><br>var<br> FClipboard: TClipboard;<br><br>function Clipboard: TClipboard;<br>begin<br> if FClipboard = nil then<br> FClipboard := TClipboard.Create;<br> Result := FClipboard;<br>end;<br><br>function SetClipboard(NewClipboard: TClipboard): TClipboard;<br>begin<br> Result := FClipboard;<br> FClipboard := NewClipboard;<br>end;<br><br>procedure TClipboard.MainWndProc(var Message: TMessage);<br>begin<br> try<br> WndProc(Message);<br> except<br> if Assigned(ApplicationHandleException) then<br> ApplicationHandleException(Self)<br> else<br> raise;<br> end;<br>end;<br><br>initialization<br> { The following strings should not be localized }<br> CF_PICTURE := RegisterClipboardFormat('Delphi Picture');<br> CF_COMPONENT := RegisterClipboardFormat('Delphi Component');<br> FClipboard := nil;<br>finalization<br> FClipboard.Free;<br>end.<br><br>