Jump to content

Copy two different formats to the clipboard?


Recommended Posts

Wouldn't that work to use _GUICtrlRichEdit_PasteSpecial() to paste the RTF file content into a homebrew RichEdit control, after registering it temporarily as a new RTF viewer?

If that works maybe you can then get a genuine RTF content (and no more the raw RTF test) using the _ClipBoard* functions. Don't take my word for that, this is off the top of ... the new year.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

6 hours ago, jchd said:

Wouldn't that work to use _GUICtrlRichEdit_PasteSpecial() to paste the RTF file content into a homebrew RichEdit control, after registering it temporarily as a new RTF viewer?

I'll give it a try, but it may be beyond my capabilities. I'm not clear on whether that would produce both Text and RTF clipboard formats, which is the goal of all this.

Link to comment
Share on other sites

As I get it, once you fill the clipboard with RTF object, it contains the text format as well (and Unicode also). But don't sue me should that fail.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

7 hours ago, jchd said:

As I get it, once you fill the clipboard with RTF object, it contains the text format as well (and Unicode also). But don't sue me should that fail.

I won't sue you, but that is not in fact what happens. The different formats all get copied separately. Try it and see for yourself!

Link to comment
Share on other sites

This is what I came up with, even easier than I thought. Run this from Scite and watch in the console the various clipboard formats available when it's filled with genuine RTF content put in RichEdit control from reading raw RTF from file.

From ther I bet you can do whatever you want with the clipboard, provided you don't _Clipboard_Close early or the user doesn't reuse the clipboard.

#include <GuiRichEdit.au3>
#include <Clipboard.au3>

Local $hGUI = GUICreate("RTF viewer", 1000, 1000, 200, 100)
Local $hRTF = _GUICtrlRichEdit_Create($hGUI, "", 20, 20, 980, 980)
GUISetState(@SW_SHOW)
Local $sText = FileRead(@ScriptDir & "\test.rtf")
_GUICtrlRichEdit_SetText($hRTF, $sText)
_GUICtrlRichEdit_SetSel($hRTF, 0, -1)
ControlSend($hGUI, "", $hRTF, "^C")
_ClipBoard_Open($hGUI)
Local $iFmt, $iFmtCnt = 1
Do
    $iFmt = _ClipBoard_EnumFormats($iFmt)
    ConsoleWrite("Format " & $iFmtCnt & " = " & _ClipBoard_FormatStr($iFmt) & @LF)
    $iFmtCnt += 1
Until $iFmt = 0

; here select the format(s) you want pasted elsewhere, one at a time.
; the clipboard won't change until closed.

Local $iMsg
While True
        $iMsg = GUIGetMsg()
        Select
            Case $iMsg = $GUI_EVENT_CLOSE
                _ClipBoard_Close()
                _GUICtrlRichEdit_Destroy($hRTF) ; needed unless script crashes
                GUIDelete()   ; is OK too
                Exit
        EndSelect
WEnd

The interim window can of course be hidden but I left it displayed for watching things at work.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

This is just amazing. It works perfectly. Thank you!

I added three lines, one including <GUIConstantsEx.au3> (it wouldn't work on my system without it), another setting the limit of imported text to a million characters, and another to close the viewer. Also I resized the windows to be easier to use on my laptop when the window is visible for testing purposes; but I also hid the window.

I'm a total beginner at this, and I expect there's a better way to make these changes, but here they are:

#include <GuiRichEdit.au3>
#include <Clipboard.au3>
#include <GuiConstantsEx.au3>  ; added

Local $hGUI = GUICreate("RTF viewer", 800, 800, 200, 100) ; changed to fit my monitor more easily when visible
Local $hRTF = _GUICtrlRichEdit_Create($hGUI, "", 20, 20, 780, 780) ; changed as above
GUISetState(@SW_HIDE)                                               ; changed to hide
Local $sText = FileRead(@ScriptDir & "\testfile.rtf")
_GUICtrlRichEdit_SetLimitOnText($hRTF, 1000000)         ; added
_GUICtrlRichEdit_SetText($hRTF, $sText)
_GUICtrlRichEdit_SetSel($hRTF, 0, -1)
ControlSend($hGUI, "", $hRTF, "^C")
ControlSend($hGUI, "", $hRTF, "!{F4}")                  ; added to close viewer
_ClipBoard_Open($hGUI)
Local $iFmt, $iFmtCnt = 1
Do
    $iFmt = _ClipBoard_EnumFormats($iFmt)
    ConsoleWrite("Format " & $iFmtCnt & " = " & _ClipBoard_FormatStr($iFmt) & @LF)
    $iFmtCnt += 1
Until $iFmt = 0

; here select the format(s) you want pasted elsewhere, one at a time.
; the clipboard won't change until closed.

Local $iMsg
While True
        $iMsg = GUIGetMsg()
        Select
            Case $iMsg = $GUI_EVENT_CLOSE
                _ClipBoard_Close()
                _GUICtrlRichEdit_Destroy($hRTF) ; needed unless script crashes
                GUIDelete()   ; is OK too
                Exit
        EndSelect
WEnd

Again, I'm amazed and impressed by this, and very grateful!

Edited by emendelson
Link to comment
Share on other sites

Glad it helps. To be honest I never used the _Clipboard_* functions before but found them very effective and easy to use.

Once the dust has settled you can remove the loop with consolewrites, as there is no point listing those format strings.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

13 minutes ago, jchd said:

Once the dust has settled you can remove the loop with consolewrites, as there is no point listing those format strings.

Done already - when I realized that it was only for information! Thank you. This really is very effective and I don't think anyone has done this before.

Link to comment
Share on other sites

  • 5 months later...

Quite a bump, but I too want to copy data to the clipboard in multiple formats. And it looks like the Auto clipboard functions that can handIe specifying the data format (_ClipBoard_SetData and _ClipBoard_SetDataEx) will first clear the clipboard before storing their data in the specified format. Meaning you can not set more than 1 format in the clipboard using AutoIt.

While the OP wanted to copy both RTF and text formats, this was accomplished through a workaround (using a RichEdit component) rather than copying the various data formats straight into the clipboard using AutoIt. Can this at all be done?

Link to comment
Share on other sites

Apparently, according to Microsoft, we need to use the DataObject class or an IDataObject implementation to place data on the Clipboard in multiple formats:

Quote

To add data to the Clipboard in one or multiple formats, use the SetDataObject method. (...) you must first add the data to a separate object designed to work with multiple formats. Typically, you will add your data to a DataObject, but you can use any type that implements the IDataObject interface.

In .NET Framework 2.0, you can add data directly to the Clipboard by using new methods designed to make basic Clipboard tasks easier. Use these methods when you work with data in a single, common format such as text.

I'm hoping this can be achieved in AutoIt using ObjCreate, but so far I'm not having any luck finding the appropriate classname. I see the interface in OLE/COM Object Viewer referencing System_Windows_Forms, but ObjCreate("System.Windows.Forms.DataObject") doesn't seem to work:

Local $oClipboard = ObjCreate("System.Windows.Forms.DataObject")
    ConsoleWrite('@error value is: '&@error)
    If IsObj($oClipboard) Then ConsoleWrite("YES")
    Exit

I would really appreciate an insight into this, anyone?

Link to comment
Share on other sites

Bouvrie, Welcome to the AutoIt forum. What you want to achieve can certainly be accomplished. But the functions in the .NET Framework is not the proper way to do it. The proper way to do it is to use the Windows API functions. This is the documentation you need: Clipboard documentation, the Shell Data Object and the IDataObject interface.

The difficult part of your project seems to be understanding the Microsoft documentation. Once you understand the documentation, implementing the code in AutoIt should be more or less straightforward. The main AutoIt commands you need are the DLLStruct-commands to create the necessary data structures, the DllCall function to implement the Windows API functions and ObjCreateInterface for the interfaces.

A note about the documentation of ObjCreateInterface in the help file. In top of the help file there is a big warning about the function. This warning seems to be wrong from first to last. The function is not experimental, it does work, it contains no bugs, and it's not going to be changed or removed. The function was introduced in AutoIt 3.8.0 more than five years ago. There are hundreds of examples that shows that the function works. There are no examples that documents that it does not work or contains bugs. And it's the fundamental function in some of the most interesting examples and projects in recent years eg. the UI Automation Framework, Accessing AutoIt Variables (I'm not modest) and the .NET Framework. I find it very hard to believe that such a valuable function should be removed. I think you can be pretty relaxed about this warning.

Link to comment
Share on other sites

This goes beyond anything I've done with Autoit in the past.  I currently have the following code that doesn't quite work:

Local Const $tagSTRUCT1 = "struct;byte var1[8];endstruct"
    Local Const $tagSTRUCT2 = "struct;char var1[16];endstruct"
    Local $tSTRUCT1 = DllStructCreate($tagSTRUCT1)
    Local $tSTRUCT2 = DllStructCreate($tagSTRUCT2)
    DllStructSetData($tSTRUCT1, "var1", 0xC8151A0000000000)
    DllStructSetData($tSTRUCT2, "var1", 'Hello World')

    ; Display the structures
    MsgBox($MB_SYSTEMMODAL, "", "Structs Size: " & DllStructGetSize($tSTRUCT1) & ' / '&DllStructGetSize($tSTRUCT2) & @CRLF & _
            "Struct pointer: " & DllStructGetPtr($tSTRUCT1) & ' / '&DllStructGetPtr($tSTRUCT2)&@CRLF & _
            "Data:" & @CRLF & _
            DllStructGetData($tSTRUCT1, 1) &' / '&DllStructGetData($tSTRUCT2, 1) & @CRLF)

    ClipPut('A') ;Fill clipboard with 0x4100 first

    $owner = DllCall("user32.dll", "HWND", "GetClipboardOwner")
    $open = DllCall("user32.dll", "BOOLEAN", "OpenClipboard", "HWND", $owner[0])
    If not $open[0] Then ConsoleWriteError("error open clip")
    ConsoleWrite('Copying structs to Windows clipboard'&@CRLF)
    $datahandle = DllCall("user32.dll", "HANDLE", "SetClipboardData", "UINT", 3, "STRUCT", $tSTRUCT1);
    $datahandle = DllCall("user32.dll", "HANDLE", "SetClipboardData", "UINT", 1, "STRUCT", $tSTRUCT2);
    DllCall("user32.dll", "int", "CloseClipboard")


    $owner = DllCall("user32.dll", "HWND", "GetClipboardOwner")
    $open = DllCall("user32.dll", "BOOLEAN", "OpenClipboard", "HWND", $owner[0])
    If not $open[0] Then ConsoleWriteError("error open clip")
   $format = DllCall("user32.dll", "UINT", "EnumClipboardFormats", "UINT", 0)
   ;https://msdn.microsoft.com/en-us/library/windows/desktop/ms649039(v=vs.85).aspx
   While ($format[0]<>0)
      $datahandle = DllCall("user32.dll", "HANDLE", "GetClipboardData", "UINT", $format[0]);
      $size= DllCall("Kernel32.dll", "INT", "GlobalSize", "ptr", $datahandle[0]);"SIZE_t==>ULONG_PTR
      $struct=DLLStructCreate("struct;BYTE var1["&$size[0]&"];endstruct",$datahandle[0])
      $results = DllStructGetData($struct, "var1")
      ConsoleWrite('[CLIPBOARD] Found '&$size[0]&' bytes in format '&$format[0]&': '&$results&@CRLF)
      if $results=0x0041 Then ConsoleWriteError("ERROR, copying seems to have failed..."&@CRLF)

      ;Check to see if there's more
      $format = DllCall("user32.dll", "UINT", "EnumClipboardFormats", "UINT", $format[0])
      If @error Then ConsoleWriteError('ERROR '&@error)
   WEnd
   DllCall("user32.dll", "int", "CloseClipboard")
   ConsoleWrite('End.'&@CRLF)

This code:

  1. Copies the string 'A' (0x0041) to the clipboard using plain Autoit
  2. Tries to copy the multiple formats using WinAPI DLLCall
  3. Dumps the clipboard contents to stdout

#1 and #3 work, #2 still has me puzzled. I wonder whether the "Shell Data Object" and the "IDataObject" interface creation would need to come in here, though I have no clue why those would be a requirement; can't I just push the actual data on the clipboard once in a fire-and-forget way?

P.S. I also found that '{1C3B4210-F441-11CE-B9EA-00AA006B1A69}' is the CLSID for the Microsoft Forms DataObject. (how) does this fit into the IDataObject picture?

Edited by Bouvrie
Link to comment
Share on other sites

If you want to implement clipboard functionality that can handle all formats and multiple formats at once, you also need to implement all of the code. You cannot get all of the functionality by only implementing a small part of the code.

You also need to correctly implement the code as described in the Microsoft documentation. It's not easy just to put some different pieces of code together and make it work properly.

If you don't want to implement all the code, your best option is to implement clipboard functionality for a format at a time like it's done in the old posts.

Link to comment
Share on other sites

Well, I am used to just checking a function's documentation & have it work. That's what good, concise documentation is for. :)

In that sense, I got GetClipboardData working from just looking at GetClipboardData on MSDN. Looking at its counterpart SetClipboardData on MSDN, there's no mention of it requiring an interface. So in my view, I know which function to call, and its parameters. The 1st parameter (format) is correct, so I'm deducing the issue is with the 2nd parameter; the hMem handle reference. 

From the docs: "If NULL, the window provides data in the specified clipboard format (renders the format) upon request". I would assume your IDataObject interface would come into play there. But this does not apply in my case, as I do not want to delayed render the clipboard data; I want to provide/put the full data on the clipboard upon the SetClipboardData call, and not upon request from another app. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...