705 lines
23 KiB
ObjectPascal
705 lines
23 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvClipbrd.PAS, released on 2003-05-18.
|
|
|
|
The Initial Developer of the Original Code is Olivier Sannier
|
|
[obones att altern dott org]
|
|
Portions created by Olivier Sannier are Copyright (C) 2003 Olivier Sannier.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s): none to date.
|
|
|
|
You may retrieve the latest version of this file at the Connection Manager
|
|
home page, located at http://cnxmanager.sourceforge.net
|
|
|
|
Known Issues: none to date.
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvClipbrd.pas 10612 2006-05-19 19:04:09Z jfudickar $
|
|
|
|
unit JvClipbrd;
|
|
|
|
{$I jvcl.inc}
|
|
{$I windowsonly.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
Windows, Messages, Classes, Clipbrd;
|
|
|
|
type
|
|
// the type of the event fired when a format has been added with delayed
|
|
// rendering and needs rendering because an application asked for it.
|
|
// Parameters are :
|
|
// Sender The object triggering the event. Cleary, will always
|
|
// be the value returned by JvClipboard, unless you
|
|
// call the event yourself
|
|
// Format The format needing rendering
|
|
// buffer The buffer where the rendered data has to be or
|
|
// has been put
|
|
// You may change the value of the buffer parameter to
|
|
// point on a memory that will survive the exit of your
|
|
// handler. Clearly, you can't give a pointer to a local
|
|
// variable or use a PChar() conversion.
|
|
// Alternatively, you can allocate some memory with
|
|
// GetMem(), copy your data in the buffer and set the
|
|
// mustFree parameter to True to ask the clipboard to
|
|
// free the memory for you (done using FreeMem)
|
|
// Setting buffer to nil will make the system remove this
|
|
// format from the clipboard, even if it is not a
|
|
// documented behaviour
|
|
// size the size in bytes of the data available in the buffer
|
|
// Setting size to 0 will make the system remove this
|
|
// format from the clipboard, even if it is not a
|
|
// documented behaviour
|
|
// mustFree set to False by default. If you set this to True, the
|
|
// clipboard will call FreeMem(buffer) after having copied
|
|
// the data in the system clipboard. This is useful only
|
|
// if you allocated the buffer using GetMem()
|
|
TJvRenderFormatEvent = procedure(Sender: TObject; Format: Word;
|
|
var Buffer: Pointer; var Size: Cardinal; var MustFree: Boolean) of object;
|
|
|
|
// the new clipboard object, with added power !
|
|
// clearly, it now allows to use delayed rendering through the
|
|
// OnRenderFormat event.
|
|
// All methods have been overriden to allow specifying delayed
|
|
// rendering. See their documentation for details.
|
|
// However, SetAsHandle has not been overriden as it is enough
|
|
// to set its second parameter to 0 to get delayed rendering
|
|
TJvClipboard = class(TClipboard)
|
|
private
|
|
function GetAsWideText: WideString;
|
|
procedure SetAsWideText(const Value: WideString);
|
|
protected
|
|
// the pointer to the user procedure to call for the event
|
|
// see the declaration of TOnRenderFormat
|
|
FOnRenderFormat: TJvRenderFormatEvent;
|
|
|
|
// the list of formats that have been added using delayed rendering
|
|
// we need to keep track of them because we must be able to render
|
|
// them when the WM_RENDERALLFORMATS event is fired.
|
|
// And we can't simply loop through the Formats property as this
|
|
// is not a good thing to call RenderFormat for formats not put
|
|
// by the user in the clipboard (for instance, adding CF_TEXT will
|
|
// make the system add a CF_OEMTEXT and a CF_UNICODETEXT automatically)
|
|
// Moreover, to ensure that the delayed rendering formats will
|
|
// survive the death of the application, we must ask for their value
|
|
// from the DestroyHandle method
|
|
// If the formats are quite big, which may cause memory problems,
|
|
// you should ask the user if he wants to keep them and if not,
|
|
// call the clear method before destroying the handle
|
|
// This list will actually only contain Words (Format Ids)
|
|
FDelayedFormats: TList;
|
|
|
|
// the handle to the window processing the messages
|
|
FClipboardWindow: THandle;
|
|
|
|
// This flag is used to determine wether or not the RenderFormat
|
|
// method should be called as a result of the WM_RENDERALLFORMATS
|
|
// message. It will be set to True from within DestroyHandle,
|
|
// thus ensuring a delayed rendering format is only rendered once
|
|
FFromDestroyHandle: Boolean;
|
|
|
|
// overridden wndproc to handle WM_RENDERFORMAT and
|
|
// WM_RENDERALLFORMATS messages
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure WndProc(var Message: TMessage); override;
|
|
{$ELSE}
|
|
procedure WndProc(var Message: TMessage); virtual;
|
|
procedure MainWndProc(var Message: TMessage);
|
|
|
|
// SetBuffer is not protected in the VCL shipped with D5 and BCB5.
|
|
// We need to access it anyway and this is done using direct memory
|
|
// access to the correct procedure. However this method cannot be
|
|
// called SetBuffer because under BCB the Buffer parameter will be
|
|
// output as a void* for both Pointer and Untyped types.
|
|
procedure SetBufferVCL5(Format: Word; var Buffer; Size: Integer);
|
|
{$ENDIF COMPILER6_UP}
|
|
|
|
// This function calls the user event handler and does the
|
|
// rendering the way windows expects it
|
|
// it will trigger an exception if no OnRenderFormat event
|
|
// handler is given
|
|
procedure RenderFormat(Format: Word); virtual;
|
|
|
|
// returns the window handle (the value of FClipboardWindow)
|
|
function GetHandle: THandle;
|
|
public
|
|
// creates the list
|
|
constructor Create; virtual;
|
|
|
|
// destroys the list and the window (only if needed, see below)
|
|
destructor Destroy; override;
|
|
|
|
// To ensure that the formats using delayed rendering are
|
|
// saved when the application terminates, it is necessary
|
|
// that we get their values before actually destroying the
|
|
// underlying window (which handle is given by the Handle property)
|
|
// As a result, the OnRenderFormat event will be fired for every
|
|
// format with delayed rendering still in the clipboard.
|
|
// This could lead to memory problems if the format is quite big.
|
|
// You should then asks the user if he wants to keep the big objects
|
|
// available for other programs
|
|
// If you don't call this method and some formats are in the
|
|
// clipboard with delayed rendering, it will be called upon
|
|
// destruction of the clipboard, which is likely to happen after the
|
|
// destruction of the object where the event is set.
|
|
// I let you imagine the consequences...
|
|
// So you should call this function from the destructor (or the
|
|
// OnDestroy event) of the component where the OnRenderFormat event
|
|
// handler is set (eg, the main form) as this component is likely
|
|
// to be destroyed before the clipboard itself.
|
|
procedure DestroyHandle;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
// forced to override Open to be able to use our own
|
|
// window handle
|
|
procedure Open; override;
|
|
|
|
// Close is overriden but simply calls the inherited Close
|
|
// method. It is still there if you want to tweak around
|
|
procedure Close; override;
|
|
|
|
// forced to override Clear to keep track of the delayed
|
|
// formats in the delayedFormats list
|
|
procedure Clear; override;
|
|
{$ELSE}
|
|
procedure Open; virtual;
|
|
procedure Close; virtual;
|
|
procedure Clear; virtual;
|
|
{$ENDIF COMPILER6_UP}
|
|
|
|
// registers a format of that name with the system and returns
|
|
// its identifier. You may as well call RegisterClipboardFormat
|
|
// directly
|
|
function RegisterFormat(const Name: string): Word;
|
|
|
|
// add a format that uses delayed rendering
|
|
// if you do so, you MUST provide an OnRenderFormat event handler
|
|
procedure AddDelayed(Format: Word);
|
|
|
|
// overriden method to allow setting buffer to nil and thus
|
|
// asking to use delayed rendering. If you do so, you MUST provide
|
|
// an OnRenderFormat event handler
|
|
// if buffer <> nil then the inherited method is called
|
|
procedure SetBuffer(Format: Word; Buffer: Pointer; Size: Integer); overload;
|
|
|
|
// get a buffer of the given format
|
|
// the format must be present in the clipboard. If not the function
|
|
// returns False.
|
|
// The buffer and the size parameters must be set to the correct size
|
|
// for the specified format. If they are too small, the data will be
|
|
// truncated, resulting in corrupted values on your side (but you're
|
|
// the one who knows what to do with that).
|
|
// If they are too large, the application will crash as it will be
|
|
// asking the system for more data than available
|
|
// Returns True if data was successfuly retrieved, else use
|
|
// Windows.GetLastError to get the error code
|
|
function GetBuffer(Format: Word; Buffer: Pointer; Size: Cardinal): Boolean;
|
|
|
|
// overloaded version of the same procedure in TClipboard that
|
|
// now allows you to specify delayed rendering.
|
|
// If delayed is set to False, the inherited method is called
|
|
// else, the format is simply added in the clipboard and you MUST
|
|
// provid an OnRenderFormat event;
|
|
procedure SetComponent(Component: TComponent; Delayed: Boolean); overload;
|
|
|
|
// overloaded version of the same procedure in TClipboard that
|
|
// now allows you to specify delayed rendering.
|
|
// If delayed is set to False, the inherited method is called
|
|
// else, the format is simply added in the clipboard and you MUST
|
|
// provid an OnRenderFormat event;
|
|
procedure SetTextBuf(Buffer: PChar; Delayed: Boolean); overload;
|
|
|
|
// the handle to the underlying window handling the delayed
|
|
// rendering messages
|
|
property Handle: THandle read GetHandle;
|
|
{$IFDEF COMPILER5}
|
|
private
|
|
function GetOpenRefCount: Integer;
|
|
protected
|
|
property OpenRefCount: Integer read GetOpenRefCount;
|
|
{$ENDIF COMPILER5}
|
|
published
|
|
// the event fired when a format has been added with delayed
|
|
// rendering and needs rendering because an application (or the
|
|
// DestroyHandle method) asked for it
|
|
property OnRenderFormat: TJvRenderFormatEvent read FOnRenderFormat
|
|
write FOnRenderFormat;
|
|
property AsWideText: WideString read GetAsWideText write SetAsWideText;
|
|
end;
|
|
|
|
// global function to get access to a TJvClipboard object
|
|
function JvClipboard: TJvClipboard;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvClipbrd.pas $';
|
|
Revision: '$Revision: 10612 $';
|
|
Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils, Consts,
|
|
JvTypes, JvJVCLUtils, JvResources;
|
|
|
|
{$IFDEF COMPILER5}
|
|
|
|
// Delphi 5 implementation
|
|
type
|
|
TPrivateClipboard = class(TPersistent)
|
|
private
|
|
FOpenRefCount: Integer;
|
|
end;
|
|
|
|
var
|
|
Clipboard_SetBuffer: procedure(Instance: TClipboard; Format: Word; var Buffer;
|
|
Size: Integer);
|
|
|
|
{$ENDIF COMPILER5}
|
|
|
|
constructor TJvClipboard.Create;
|
|
begin
|
|
inherited Create;
|
|
// create the list used to keep track of delayed formats
|
|
// in the clipboard
|
|
FDelayedFormats := TList.Create;
|
|
|
|
// if a WM_RENDERALLFORMATS message is fired, then
|
|
// it is not yet as a result of a call to DestroyHandle
|
|
FFromDestroyHandle := False;
|
|
end;
|
|
|
|
destructor TJvClipboard.Destroy;
|
|
begin
|
|
// ensure handle is destroyed, but see remark where
|
|
// DestroyHandle is declared
|
|
DestroyHandle;
|
|
|
|
// free the list
|
|
FDelayedFormats.Free;
|
|
|
|
// and let the rest be done
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{$IFDEF COMPILER5}
|
|
|
|
procedure TJvClipboard.SetBufferVCL5(Format: Word; var Buffer; Size: Integer);
|
|
var
|
|
P: PByte;
|
|
begin
|
|
if not Assigned(Clipboard_SetBuffer) then
|
|
begin
|
|
P := @TClipboard.SetTextBuf;
|
|
while P^ <> $E8 do
|
|
Inc(P); // StrLen
|
|
Inc(P);
|
|
while P^ <> $E8 do
|
|
Inc(P); // SetBuffer
|
|
Inc(P);
|
|
Clipboard_SetBuffer := Pointer(Integer(P) + 4 + PInteger(P)^);
|
|
end;
|
|
if Assigned(Clipboard_SetBuffer) then
|
|
Clipboard_SetBuffer(Self, Format, Buffer, Size);
|
|
end;
|
|
|
|
function TJvClipboard.GetOpenRefCount: Integer;
|
|
begin
|
|
Result := TPrivateClipboard(Self).FOpenRefCount;
|
|
end;
|
|
|
|
{$ENDIF COMPILER5}
|
|
|
|
procedure TJvClipboard.Clear;
|
|
begin
|
|
// call the inherited method, will do its job
|
|
inherited Clear;
|
|
// no more delayed formats available
|
|
FDelayedFormats.Clear;
|
|
end;
|
|
|
|
function TJvClipboard.GetBuffer(Format: Word; Buffer: Pointer;
|
|
Size: Cardinal): Boolean;
|
|
var
|
|
Data: THandle;
|
|
DataPtr: Pointer;
|
|
begin
|
|
// retrieve data of the given format
|
|
|
|
// first, open clipoard
|
|
Open;
|
|
|
|
// ask for data
|
|
Data := GetClipboardData(Format);
|
|
|
|
// was data retrieved ?
|
|
if Data <> 0 then
|
|
begin
|
|
// if some data retrieved, get a Pointer to it
|
|
DataPtr := GlobalLock(Data);
|
|
|
|
// did we get a valid Pointer ?
|
|
if DataPtr <> nil then
|
|
begin
|
|
// if yes, copy from global pointer to user supplied pointer
|
|
CopyMemory(Buffer, DataPtr, Size);
|
|
// and retrieval was a success
|
|
Result := True;
|
|
end
|
|
else
|
|
begin
|
|
// else, retrieval has failed
|
|
Result := False;
|
|
end;
|
|
|
|
// unlock global memory
|
|
GlobalUnlock(Data);
|
|
end
|
|
else
|
|
begin
|
|
// if no data retrieved, then retrieval failed
|
|
Result := False;
|
|
end;
|
|
|
|
// finally, close clipoard
|
|
Close;
|
|
end;
|
|
|
|
procedure TJvClipboard.Open;
|
|
begin
|
|
// call the inherited open method to force the inherited
|
|
// private FOpenRefCount to be greater than 0. This is the
|
|
// result of a bad design, because FOpenRefCount should be
|
|
// protected in the TClipboard class, allowing us to access
|
|
// it directly, rather than tweaking around
|
|
// Having the inherited FOpenRefCount greater than 0 is
|
|
// required for the inherited method that put data in the
|
|
// clipboard to work. Indeed, they call the private method
|
|
// Adding which calls Clear only if FOpenRefCount is not 0.
|
|
// And calling Clear is required for the window to get the
|
|
// clipboard ownership.
|
|
// Another good decision would have been to make the Adding
|
|
// method protected rather than private. This would have
|
|
// allowed to easily add other methods to put other types
|
|
// in the clipboard.
|
|
// But it seems the people in charge of that part didn't
|
|
// have reusability in mind when they designed the
|
|
// TClipboard class
|
|
inherited Open;
|
|
|
|
// if we were just opened (the inherited FOpenRefCount
|
|
// just turned to 1)
|
|
if OpenRefCount = 1 then
|
|
begin
|
|
// then, if we need a window to handle delayed rendering
|
|
if FClipboardWindow = 0 then
|
|
begin
|
|
// then we create one, passing MainWndProc rather than
|
|
// WndProc as MainWndProc will call WndProc but in a
|
|
// try except statement ensuring good exception handling
|
|
FClipboardWindow := AllocateHWndEx(MainWndProc);
|
|
end;
|
|
|
|
// we must now close the clipboard as it was opened
|
|
// with an incorrect window handle (most likely the
|
|
// application window handle)
|
|
CloseClipboard;
|
|
|
|
// and we finally open the clipboard with our window handle
|
|
// to ensure that we can process delayed rendering messages
|
|
if not OpenClipboard(FClipboardWindow) then
|
|
raise EJVCLException.CreateRes(@SCannotOpenClipboard);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvClipboard.Close;
|
|
begin
|
|
// call the inherited close method to force update of the
|
|
// inherited FOpenRefCount and to close the clipboard if
|
|
// needed
|
|
inherited Close;
|
|
end;
|
|
|
|
function TJvClipboard.RegisterFormat(const Name: string): Word;
|
|
var
|
|
Tmp: PChar;
|
|
begin
|
|
GetMem(Tmp, Length(Name) + 1); // don't forget +1 for trailing #0
|
|
try
|
|
StrPCopy(Tmp, Name);
|
|
Result := RegisterClipboardFormat(Tmp);
|
|
finally
|
|
FreeMem(Tmp);
|
|
end;
|
|
// Note : Yes, we could have used PChar(name) as an argument to
|
|
// RegisterClipboardFormat, but this only works under Delphi 6
|
|
// and this code have to work under older versions
|
|
end;
|
|
|
|
procedure TJvClipboard.RenderFormat(Format: Word);
|
|
var
|
|
Buffer: Pointer;
|
|
Size: Cardinal;
|
|
hglb: HGLOBAL;
|
|
GlobalPtr: Pointer;
|
|
MustFree: Boolean;
|
|
begin
|
|
// by default, we must not free the given buffer
|
|
MustFree := False;
|
|
|
|
// if user gave us an event
|
|
if Assigned(FOnRenderFormat) then
|
|
// then ask user to render the format
|
|
FOnRenderFormat(Self, Format, Buffer, Size, MustFree)
|
|
else
|
|
// else, trigger an exception, how could we guess the
|
|
// size and data to put in the buffer ?
|
|
raise EJVCLException.CreateRes(@RsENoRenderFormatEventGiven);
|
|
|
|
// now render the way windows wants it
|
|
|
|
// first allocate a global memory
|
|
hglb := GlobalAlloc(GMEM_DDESHARE or GMEM_MOVEABLE, Size);
|
|
if hglb <> 0 then
|
|
begin
|
|
// if allocation was successful
|
|
// then lock global memory to get access to it
|
|
GlobalPtr := GlobalLock(hglb);
|
|
|
|
// copy user supplied data
|
|
CopyMemory(GlobalPtr, Buffer, Size);
|
|
|
|
// unlock global memory
|
|
GlobalUnlock(hglb);
|
|
|
|
// finally, place the content in the clipboard
|
|
SetClipboardData(Format, hglb);
|
|
end;
|
|
|
|
// if user asked us to free his buffer
|
|
if MustFree then
|
|
// then we free it
|
|
FreeMem(Buffer);
|
|
end;
|
|
|
|
procedure TJvClipboard.WndProc(var Message: TMessage);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
case Message.Msg of
|
|
// if asked to render a particular format
|
|
WM_RENDERFORMAT:
|
|
begin
|
|
// then render it
|
|
RenderFormat(Message.WParam);
|
|
// and tell windows so
|
|
Message.Result := 0;
|
|
end;
|
|
// if asked to render all available formats
|
|
WM_RENDERALLFORMATS:
|
|
begin
|
|
// then if it is not the result of a call
|
|
// to DestroyHandle
|
|
if not FFromDestroyHandle then
|
|
begin
|
|
// then we render all the delayed formats
|
|
// we are aware of
|
|
for I := 0 to FDelayedFormats.Count - 1 do
|
|
RenderFormat(Word(FDelayedFormats[I]));
|
|
end;
|
|
// tell windows we handled the message
|
|
Message.Result := 0;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
// in any case let the ancestor do its stuff
|
|
inherited WndProc(Message);
|
|
{$ELSE}
|
|
with Message do
|
|
Result := DefWindowProc(Handle, Msg, WParam, LParam);
|
|
{$ENDIF COMPILER6_UP}
|
|
end;
|
|
|
|
{$IFDEF COMPILER5}
|
|
procedure TJvClipboard.MainWndProc(var Message: TMessage);
|
|
begin
|
|
try
|
|
WndProc(Message);
|
|
except
|
|
ShowException(ExceptObject, ExceptAddr);
|
|
end;
|
|
end;
|
|
{$ENDIF COMPILER5}
|
|
|
|
procedure TJvClipboard.DestroyHandle;
|
|
var
|
|
I: Integer;
|
|
Format: Word;
|
|
Buffer: Char;
|
|
begin
|
|
// if we have a window handle, hence, meaning that it is
|
|
// the first time DestroyHandle is called
|
|
if FClipboardWindow <> 0 then
|
|
begin
|
|
// to ensure persistance of the private formats, we
|
|
// must get them before destroying the window
|
|
// this is rather strange as destroying the window fires
|
|
// the WM_RENDERALLFORMATS message but it seems the system
|
|
// forgets the results.
|
|
// so we do the job ourselves and ask for the data
|
|
// Of course, this will not work for formats that the user
|
|
// put in the clipboard using delayed rendering through direct
|
|
// API calls
|
|
for I := 0 to FDelayedFormats.Count - 1 do
|
|
begin
|
|
// get the format id
|
|
Format := Word(FDelayedFormats[I]);
|
|
|
|
// ask to get this format from the clipboard, will
|
|
// in turn trigger a WM_RENDERFORMAT message
|
|
// we only ask for one byte as we don't know what to
|
|
// do with the format and clearly won't use it
|
|
// Asking for one byte ensures that windows will
|
|
// effectively give us something
|
|
GetBuffer(Format, @Buffer, 1);
|
|
end;
|
|
|
|
// Having done that will not prevent the WM_RENDERALLFORMATS
|
|
// message from being fired so me must ensure the RenderFormat
|
|
// method is not called twice for all delayed rendering formats
|
|
FFromDestroyHandle := True;
|
|
|
|
// we can now safely destroy the window
|
|
DeallocateHWndEx(FClipboardWindow);
|
|
|
|
// and we no longer have a window
|
|
FClipboardWindow := 0;
|
|
end;
|
|
end;
|
|
|
|
function TJvClipboard.GetHandle: THandle;
|
|
begin
|
|
Result := FClipboardWindow;
|
|
end;
|
|
|
|
procedure TJvClipboard.SetComponent(Component: TComponent; Delayed: Boolean);
|
|
begin
|
|
if Delayed then
|
|
// add as delayed
|
|
AddDelayed(CF_COMPONENT)
|
|
else
|
|
inherited SetComponent(Component);
|
|
end;
|
|
|
|
procedure TJvClipboard.SetTextBuf(Buffer: PChar; Delayed: Boolean);
|
|
begin
|
|
if Delayed then
|
|
// add as delayed
|
|
AddDelayed(CF_TEXT)
|
|
else
|
|
inherited SetTextBuf(Buffer);
|
|
end;
|
|
|
|
procedure TJvClipboard.SetBuffer(Format: Word; Buffer: Pointer; Size: Integer);
|
|
begin
|
|
// if buffer is nil
|
|
if Buffer = nil then
|
|
// then add the format using delayed rendering
|
|
AddDelayed(Format)
|
|
else
|
|
begin
|
|
// else call inherited method
|
|
{$IFDEF COMPILER6_UP}
|
|
inherited SetBuffer(Format, Buffer^, Size);
|
|
{$ELSE}
|
|
SetBufferVCL5(Format, Buffer^, Size);
|
|
{$ENDIF COMPILER6_UP}
|
|
end;
|
|
end;
|
|
|
|
procedure TJvClipboard.AddDelayed(Format: Word);
|
|
begin
|
|
// add as delayed
|
|
inherited SetAsHandle(Format, 0);
|
|
// and we keep track of that format
|
|
FDelayedFormats.Add(Pointer(Format));
|
|
end;
|
|
|
|
function TJvClipboard.GetAsWideText: WideString;
|
|
var
|
|
Data: THandle;
|
|
begin
|
|
Open;
|
|
Data := GetClipboardData(CF_UNICODETEXT);
|
|
try
|
|
if Data <> 0 then
|
|
Result := PWideChar(GlobalLock(Data))
|
|
else
|
|
Result := '';
|
|
finally
|
|
if Data <> 0 then
|
|
GlobalUnlock(Data);
|
|
Close;
|
|
end;
|
|
if (Data = 0) or (Result = '') then
|
|
Result := AsText
|
|
end;
|
|
|
|
procedure TJvClipboard.SetAsWideText(const Value: WideString);
|
|
begin
|
|
Open;
|
|
try
|
|
AsText := Value; {Ensures ANSI compatiblity across platforms.}
|
|
{$IFDEF COMPILER6_UP}
|
|
SetBuffer(CF_UNICODETEXT, PWideChar(Value)^, (Length(Value) + 1) * SizeOf(WideChar));
|
|
{$ELSE}
|
|
SetBufferVCL5(CF_UNICODETEXT, PWideChar(Value)^, (Length(Value) + 1) * SizeOf(WideChar));
|
|
{$ENDIF COMPILER6_UP}
|
|
finally
|
|
Close;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
GlobalClipboard: TJvClipboard;
|
|
|
|
// global function to call to get access to the clipboard
|
|
|
|
function JvClipboard: TJvClipboard;
|
|
begin
|
|
if GlobalClipboard = nil then
|
|
GlobalClipboard := TJvClipboard.Create;
|
|
Result := GlobalClipboard;
|
|
end;
|
|
|
|
initialization
|
|
{$IFDEF UNITVERSIONING}
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
finalization
|
|
FreeAndNil(GlobalClipboard);
|
|
{$IFDEF UNITVERSIONING}
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|
|
|