Re: Copying objects to clipboard



On Tue, 6 Jan 2009 20:23:29 -0800 (PST), Arun wrote:

2) copy an image file like image1.jpg located in say c: by a right
click->copy and paste it onto the canvas. Twapi does not work for this

Some months ago I posted a script to c.l.t which uses TWAPI to do that sort
of thing. I've included a slightly modified version here. *IF* you know
that the filename will be pure ASCII, you can use this script as is, like
this:

# There can be several types data in the clipboard so we have to
# make sure that a name has already been pasted to the clipboard
# Type 15 is CF_HDROP
if {[is_format 15] == 0} {
puts "Clipboard does not contain a filename"
return
}
# Get the first name in the list
set filename [read_format 15]

If the filename isn't ASCII or you want to pick up more than one filename,
you'll have to modify the script to suit your situation.
The script also has a function to do the inverse - copy a name to the
clipboard so that some other function (or the user) can paste the file.
The other two functions (list_formats and enum_formats) are mostly for
debugging.


Here's the script:

# Try copy/paste files via clipboard

# INFO
# From winuser.h
# /*
# * Predefined Clipboard Formats
# */
# #define CF_TEXT 1
# #define CF_BITMAP 2
# #define CF_METAFILEPICT 3
# #define CF_SYLK 4
# #define CF_DIF 5
# #define CF_TIFF 6
# #define CF_OEMTEXT 7
# #define CF_DIB 8
# #define CF_PALETTE 9
# #define CF_PENDATA 10
# #define CF_RIFF 11
# #define CF_WAVE 12
# #define CF_UNICODETEXT 13
# #define CF_ENHMETAFILE 14
# #if(WINVER >= 0x0400)
# #define CF_HDROP 15 # Filename copied to clipboard
# #define CF_LOCALE 16
# #define CF_MAX 17
# #endif /* WINVER >= 0x0400 */

# and from shlobj.h
# // format of CF_HDROP and CF_PRINTERS, in the HDROP case the data that
follows
# // is a double null terinated list of file names, for printers they are
printer
# // friendly names
# //
# typedef struct _DROPFILES {
# DWORD pFiles; // offset of file list
# POINT pt; // drop point (client coords)
# BOOL fNC; // is it on NonClient area
# // and pt is in screen coords
# BOOL fWide; // WIDE character switch
# } DROPFILES, FAR * LPDROPFILES;

# This was returned by "read_format 15" when the file C:\tcl\bin\clip.tcl
# was copied to the clipboard
# 14000000000000000000000000000000
# 0100000043003a005c00540063006c00
# 5c00620069006e005c0063006c006900
# 70002e00740063006c0000000000

# The 14000000 at the beginning of the first line is
# the offset (which is 20 decimal) because it points to the first
# byte after the structure (and therefore you could
# also interpret this first struct entry as being the length
# of the structure in bytes).
# The 01000000 at the beginning of the second line (above) is the
# BOOL fWide in the structure, so in this case it is on (set)
# which is why there are two bytes per ASCII char in the remaining data
# When sending files to the clipboard you can
# pass their pathnames as plain ASCII by setting fWide
# to zero

package require twapi

proc is_format {format} {
return [twapi::clipboard_format_available $format]
}
proc list_formats {} {
twapi::open_clipboard
set list [twapi::get_clipboard_formats]
twapi::close_clipboard
return $list
}
# Enumerate the currently available clipboard formats sorted
# numerically
proc enum_formats {} {
set known_formats {CF_TEXT CF_BITMAP CF_METAFILEPICT CF_SYLK CF_DIF CF_TIFF
CF_OEMTEXT CF_DIB CF_PALETTE CF_PENDATA CF_RIFF CF_WAVE CF_UNICODETEXT
CF_ENHMETAFILE CF_HDROP CF_LOCALE}

set lf [lsort [list_formats]]
if {$lf == ""} return
twapi::open_clipboard
foreach i $lf {
if {$i < 17} {
puts "[format "%6d" $i] [lindex $known_formats $i]"
continue
}

puts "[format "%6d" $i] [twapi::get_registered_clipboard_format_name $i]"
}
twapi::close_clipboard
}

# If the format is 15 (CF_HDROP) this returns the ASCII pathname of
# the first file in the list, otherwise it returns a hex dump of
# the _DROPFILES structure returned by reading the clipboard
proc read_format {format} {
if {[twapi::clipboard_format_available $format] == 0} {
puts "No files on the clipboard"
return ""
}
twapi::open_clipboard
set list [twapi::read_clipboard $format]
twapi::close_clipboard
# puts [string length $list]
binary scan $list H* hex_list

# If the format isn't CF_HDROP (==15) return the hex
if {$format != 15} {return $hex_list}

# Otherwise assume that the pathname is PURE ASCII and
# return the FIRST name in the list
# If you need to handle multiple names copied to the clipboard
# and/or to handle non-ASCII names, this will have to be modified
set il [string range $list 20 end]
set ol ""
while {1} {
set c [string index $il 0]
if {$c == "\0"} break
append ol $c
set il [string range $il 2 end]
}
return $ol
}

puts "Usage: is_format format_number"
puts "Usage: list_formats"
puts "Usage: read_format format_number"


# Copy a file *name* to the clipboard so that it can be
# pasted by e.g. Windows Explorer to a different directory
# Currently the name MUST be plain ASCII
# The filename must be a fully qualified pathname and don't
# forget to use, and escape, backslashes e.g.
# copy_file "C:\\Tcl\\bin\\clip.tcl"

proc copy_file {fname} {
# The header for a DROPFILES list in hex
set fheader "1400000000000000000000000000000000000000"

# Convert the filename to a hex string and append
# to the drop list
binary scan [binary format a* $fname] H* hlist
append fheader $hlist

# This is the nulls required if sending a wide string but
# it will also terminate plain ASCII
append fheader "00000000"

# Convert the hex string to binary
set bin_header [binary format H* $fheader]
binary scan $bin_header H* hlist
# puts $hlist

# Now do the clipboard "copy" operation
# Once this is done you can use the "Paste" operation
# in Windows Explorer to paste the file to another
# directory
twapi::open_clipboard
set list [twapi::write_clipboard 15 $bin_header]
twapi::close_clipboard
return
}


Pete
--
NN->01
.



Relevant Pages

  • [Dialog] Script to convert clipboard to ASCII
    ... I recall there was a script to read the clipboard and convert certain ... non-ASCII characters to ASCII. ... example, to simple ASCII equivalents. ...
    (news.software.readers)
  • Re: Dragonfly macro/script recorder
    ... and sending the script to the clipboard... ... no movement at start of script records correctly. ... bool AfterFirstUpstroke=false; ... {//UNUSEABLE KEYBOARD MESSAGE ...
    (comp.lang.beta)
  • Re: Tinyurl.com and my clip board
    ... useful option, but IMO, the user should be informed that a script will write ... to the clipboard, preparing the user for a possible warning. ... IMO, the default of 'Warn' is appropriate in the Internet Zone, but if one ... Better for the website to ...
    (misc.news.internet.discuss)
  • Re: Copy Pathname Script?
    ... default value: YourProgramPath %1 ... then send the path to the Clipboard. ... whether that will work for a script. ... > the bits I want to add, just I don't know if its open source or a ...
    (microsoft.public.scripting.wsh)
  • Re: Inserting OLE Bitmap into Word document
    ... Access is telling me it doesn't recognise the variable type tagOPENFILENAME, ... > copy its contents to the Clipboard. ... instead of them having to type a filename in. ... >>> You can programmatically copy the contents of the OLE field to the ...
    (microsoft.public.access.formscoding)