Although I had used some of the procedures in the component I sent
you, basically the area I was having problems with is this:
DataBuffer := GlobalLock(Data);
try
DataSize := GlobalSize(Data);
OutFile.Write(DataSize, SizeOf(DataSize));
OutFile.Write(DataBuffer^, DataSize);
finally
GlobalUnlock(Data);
end;
I'm going to have to spend a couple of days and really study up on
pointers. I've never had a reason to use them until now! I know that's
hard to believe, but true! Also, exactly what is the purpose of the
GlobalLock? I was referring to specially registered formats, but I found in
the SDK some functions that should be able to give me that information.
Just for simplicity's sake I would probably like to store the formats in a
separate field. I've used Widestrings ONLY as required by a few API calls
without truly understanding why. What type could I use to store them...as
TStrings? Is there anyway to make use of them without converting them from
their integer values first? I couldn't find any but that doesn't mean it
isn't possible! Thanx much for the code examples. It's much easier for me
to understand yours!
>From "Robert Meek"
Personal e-mail: [EMAIL PROTECTED]
dba / "Tangentals Design"
Visit us at: www.TangentalsDesign.com
Home of "The Keep"!
Member of: "Association of Shareware Professionals"
Moderator for: "The Delphi", "Delphi-DB", and "Delphi-Talk" programming
lists at elists.org,
and proud to be a donator to the Jedi VCL 3.0.
-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf
Of Rob Kennedy
Sent: Tuesday, April 12, 2005 3:48 PM
To: Borland's Delphi Discussion List
Subject: Re: Oh boy...need pointer help...addendum!
Robert Meek wrote:
> Yes I asked the wrong question! What I meant to ask was as I
> obviously have to place things back on the clipboard that are in a
specially
> registered format, how do I do that not knowing what the format is?
But you *do* know the format. You had to know the format in order to get
the data off the clipboard in the first place. When you store the data
to a file, also store the name of the format.
> I
> haven't found anyway to use the numeric constants for these special
> types...it seems you need to know the CF_ constant type? And there is no
> listing I can find to use for converting from one to the other! Also, how
> can I save what is on the clipboard to a stream so it can be loaded into a
> blob along with it's format type so I can then load it back into the
> clipboard later? There's nothing in the Clipbrd unit that I can use for
> that.
If I wanted to save the contents of the clipboard in all available
formats to a single file, this is the code I would use:
function GetFormatName(const Format: UInt): WideString;
var
Len: Integer;
begin
if Format < $c000 then begin
Result := SysUtils.Format('#%u', [Format]);
end else begin
Len := 400;
SetLength(Result, Len);
Len := GetClipboardFormatNameW(Format, PWideChar(Result), Len);
Win32Check(Len <> 0);
SetLength(Result, Len);
end;
end;
procedure SaveClipboardToFile(const FileName: WideString);
var
OutHandle: THandle;
OutFile: TStream;
Format: DWord;
FormatName: WideString;
NameLen: LongWord;
Data: THandle;
DataBuffer: Pointer;
DataSize: LongWord;
begin
Win32Check(OpenClipboard(0));
try
OutHandle := CreateFileW(PWideChar(FileName), Generic_Write, 0,
nil, Create_Always, File_Attribute_Archive or File_Flag_Sequential_Scan, 0);
Win32Check(OutHandle <> Invalid_Handle_Value);
try
OutFile := THandleStream.Create(Integer(OutHandle));
try
Format := EnumClipboardFormats(0);
while Format <> 0 do try
FormatName := GetFormatName(Format);
NameLen := Length(FormatName);
if NameLen = 0 then continue;
OutFile.Write(NameLen, SizeOf(NameLen));
if NameLen > 0 then OutFile.Write(FormatName[1], NameLen *
SizeOf(FormatName[1]));
Data := GetClipboardData(Format);
Win32Check(Data <> 0);
DataBuffer := GlobalLock(Data);
try
DataSize := GlobalSize(Data);
OutFile.Write(DataSize, SizeOf(DataSize));
OutFile.Write(DataBuffer^, DataSize);
finally
GlobalUnlock(Data);
end;
finally
Format := EnumClipboardFormats(Format);
end;
Assert(Format = 0);
if GetLastError <> Error_Success then RaiseLastOSError;
// Use 0 to designate end of data
OutFile.Write(Format, SizeOf(Format));
finally
OutFile.Free;
end;
finally
CloseHandle(OutHandle);
end;
finally
CloseClipboard;
end;
end;
It's naive. It doesn't account for private clipboard formats, and it
also doesn't make any effort to detect and skip synthesized clipboard
formats.
The procedure saves the clipboard data in a list. First it writes the
name of the format, and then it writes the data. Both the name and the
data get prefixed by their lengths first so that they can be read back
correctly later. Below is a procedure that should be able to read the
data and put it back on the clipboard.
function GetFormatNumber(const Name: WideString): UInt;
begin
if Name[1] = '#' then begin
Result := StrToInt(Copy(Name, 2, MaxInt));
end else begin
Result := RegisterClipboardFormatW(PWideChar(Name));
end;
end;
procedure LoadClipboardFromFile(const FileName: WideString);
var
InHandle: THandle;
InFile: TStream;
Format: DWord;
FormatName: WideString;
NameLen: LongWord;
Data: THandle;
DataBuffer: Pointer;
DataSize: LongWord;
begin
Win32Check(OpenClipboard(0));
try
Win32Check(EmptyClipboard);
InHandle := CreateFileW(PWideChar(FileName), Generic_Read, 0, nil,
Open_Existing, File_Attribute_Archive or File_Flag_Sequential_Scan, 0);
Win32Check(InHandle <> Invalid_Handle_Value);
try
InFile := THandleStream.Create(Integer(InHandle));
try
InFile.ReadBuffer(NameLen, SizeOf(NameLen));
while NameLen <> 0 do begin
SetLength(FormatName, NameLen);
InFile.ReadBuffer(FormatName[1], NameLen *
SizeOf(FormatName[1]));
Format := GetFormatNumber(FormatName);
InFile.ReadBuffer(DataSize, SizeOf(DataSize));
Data := GlobalAlloc(GMem_Moveable or GMem_DDEShare, DataSize);
Win32Check(Data <> 0);
try
DataBuffer := GlobalLock(Data);
Win32Check(Assigned(DataBuffer));
try
InFile.ReadBuffer(DataBuffer^, DataSize);
SetClipboardData(Format, Data);
finally
GlobalUnlock(Data);
end;
except
GlobalFree(Data);
raise;
end;
InFile.ReadBuffer(NameLen, SizeOf(NameLen));
end;
finally
InFile.Free;
end;
finally
CloseHandle(InHandle);
end;
finally
CloseClipboard;
end;
end;
I use a special format for clipboard format names because the documentat
for GetClipboardFormatName suggests that the built-in formats don't have
names.
--
Rob
_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi
_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi