Hi,
2009/4/26 Daniel Berger <djberg96 at gmail.com>:> Hi,
>
> I already made a change since 0.5.0. The Clipboard.register_format now
> returns the format number returned by the RegisterClipboardFormat()
> function. This change is in CVS.
>
> It works fine, but one thing I wasn''t sure of was how to register
multiple
> clipboard formats simultaneously. Specifically, I was looking at this
> article:
>
> http://www.codeguru.com/cpp/w-p/clipboard/print.php/c3015
>
> Where he registers both RTF and Csv formats, and when he copies and pastes
> to Word or Excel, it just does the right thing.
>
Here is both CF_HTML and CF_TEXT format handling sample code:
require ''win32/clipboard''
include Win32
module Win32
class HtmlClipboard < Clipboard
MARKER_BLOCK_OUTPUT "Version:1.0\r\n" \
"StartHTML:%09d\r\n" \
"EndHTML:%09d\r\n" \
"StartFragment:%09d\r\n" \
"EndFragment:%09d\r\n" \
"StartSelection:%09d\r\n" \
"EndSelection:%09d\r\n" \
"SourceURL:%s\r\n"
MARKER_BLOCK_EX ''Version:(\S+)\s+'' \
''StartHTML:(\d+)\s+'' \
''EndHTML:(\d+)\s+'' \
''StartFragment:(\d+)\s+'' \
''EndFragment:(\d+)\s+'' \
''StartSelection:(\d+)\s+'' \
''EndSelection:(\d+)\s+'' \
''SourceURL:(\S+)''
MARKER_BLOCK_EX_RE = Regexp.new(MARKER_BLOCK_EX,Regexp::MULTILINE)
MARKER_BLOCK ''Version:(\S+)\s+'' \
''StartHTML:(\d+)\s+'' \
''EndHTML:(\d+)\s+'' \
''StartFragment:(\d+)\s+'' \
''EndFragment:(\d+)\s+'' \
''SourceURL:(\S+)''
MARKER_BLOCK_RE = Regexp.new(MARKER_BLOCK,Regexp::MULTILINE)
DEFAULT_HTML_BODY "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML
4.0 Transitional//EN\">\r\n" \
"<HTML><BODY><!--StartFragment-->%s<!--EndFragment--></BODY></HTML>"
CF_HTML = RegisterClipboardFormat("HTML Format")
def initialize
@html = nil
@fragment = nil
@selection = nil
@source = nil
@version = nil
end
def self.has_html_format?
format_available?(CF_HTML)
end
def self.data
begin
self.open
if IsClipboardFormatAvailable(CF_HTML)
handle = GetClipboardData(CF_HTML)
clip_data = 0.chr * GlobalSize(handle)
memcpy(clip_data, handle, clip_data.size)
clip_data.strip!
clip_data = decode_data(clip_data)
else
clip_data = ''''
end
ensure
self.close
end
clip_data
end
def self.decode_data(src)
if (matches = MARKER_BLOCK_EX_RE.match(src))
@prefix = matches[0]
@version = matches[1]
@html = src[matches[2].to_i ... matches[3].to_i]
@fragment = src[matches[4].to_i ... matches[5].to_i]
@selection = src[matches[6].to_i ... matches[7].to_i]
@source = matches[8]
elsif (matches = MARKER_BLOCK_RE.match(src))
@prefix = matches[0]
@version = matches[1]
@html = src[matches[2].to_i ... matches[3].to_i]
@fragment = src[matches[4].to_i ... matches[5].to_i]
@source = matches[6]
@selection = @fragment
end
@fragment
end
def self.dump_data
clip_data = data
puts "prefix=>>>#{@prefix}<<<END"
puts "version=>>>#{@version}<<<END"
puts "selection=>>>#{@selection}<<<END"
puts "fragment=>>>#{@fragment}<<<END"
puts "html=>>>#{@html}<<<END"
puts "source=>>>#{@source}<<<END"
end
def
self.encode_data(html,fragment_start,fragment_end,selection_start,selection_end,source)
dummy_prefix = MARKER_BLOCK_OUTPUT % [0,0,0,0,0,0,source]
len_prefix = dummy_prefix.length
prefix = MARKER_BLOCK_OUTPUT % [len_prefix, html.length + len_prefix,
fragment_start+len_prefix,fragment_end+len_prefix,
selection_start+len_prefix,selection_end+len_prefix,
source]
prefix + html
end
def self.set_data(fragment,selection=nil,html=nil,source=nil)
selection ||= fragment
html ||= DEFAULT_HTML_BODY % fragment
source ||= ''file://''+__FILE__
fragment_start = html.index(fragment)
fragment_end = fragment_start + fragment.length
selection_start = html.index(selection)
selection_end = selection_start + selection.length
clip_data =
encode_data(html,fragment_start,fragment_end,selection_start,selection_end,source)
self.open
EmptyClipboard()
# Global Allocate a movable piece of memory.
hmem = GlobalAlloc(GHND, clip_data.length + 4)
mem = GlobalLock(hmem)
memcpy(mem, clip_data, clip_data.length)
clip_data2 = fragment.gsub(/<[^>]+?>/,'''')
hmem2 = GlobalAlloc(GHND, clip_data2.length + 4)
mem2 = GlobalLock(hmem2)
memcpy(mem2, clip_data2, clip_data2.length)
# Set the new data
begin
if SetClipboardData(CF_HTML, hmem) == 0
raise Error, "SetClipboardData() failed: " + get_last_error
end
if SetClipboardData(CF_TEXT, hmem2) == 0
raise Error, "SetClipboardData() failed: " + get_last_error
end
ensure
GlobalFree(hmem)
GlobalFree(hmem2)
self.close
end
self
end
end
end
if $0 == __FILE__
data = "<p>Writing to the clipboard is
<strong>easy</strong> with
this code.</p>"
HtmlClipboard.set_data(data)
if HtmlClipboard.data == data
puts "passed"
else
puts "failed"
end
end
> I''m also wondering if we need to modify the Clipboard.set_data
method so
> that it accepts a nil argument. According to MSD, the
''hMem'' parameter can
> be NULL, indicating that the window provides data in the specified
clipboard
> format (renders the format) upon request. If a window delays rendering, it
> must process the WM_RENDERFORMAT and WM_RENDERALLFORMATS messages.
>
> I''m debating what sort of interface we could provide for this. Any
> suggestions?
>
I think, in real world applications, delayed rendering is unreliable
and useless feature.
Can you guarantee the clipboard owner is always active?
Regards,
Park Heesob