Jump to content

WD_Screenshot to Clipboard for Copy and Paste?


Go to solution Solved by Nine,

Recommended Posts

Hello,

I am trying to use the _WD_Screenshot function to capture an element in a webpage. My starting point is the following:

; Take screenshot
$sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "/html/body/form")
$bImage = _WD_Screenshot($sSession, $sElement, 2)
$hFileOpen = FileOpen("Element.jpg", $FO_BINARY + $FO_OVERWRITE)
FileWrite($hFileOpen, $bImage)
FileClose($hFileOpen)

This is pretty much taken directly from the help file and seems to be working because an "element.jpg" image of my element gets created in the script directory that I am able to open successfully.

The next step(s) that I am trying to accomplish include some way to get this screenshot into the clipboard so that I can paste the image into an email or document. I've done some digging around the forums and found the following topics that seem to indicate in one way or another that this is possible and has been done, but each time I've tried to mirror the examples (in addition with my lines above) I end up either pasting binary data or nothing at all.

Some of these posts are also older, so I'm not sure what relevance they might still have, if any.

What I am making this post for is to basically see if there is a general consensus or approach of how to accomplish what I am attempting. Ultimately, at some point I'm most likely going to try to take some of the information from whatever works from this method and apply it to taking screenshots not using web driver, so any insight on simply taking screenshots and being able to copy/paste their images would be helpful as well!

Link to post
Share on other sites

You could use something like:

#include <Clipboard.au3>
#include <ScreenCapture.au3>

Local $hTray = ControlGetHandle('[CLASS:Shell_TrayWnd]', '', 'TrayNotifyWnd1')

_ScreenShot($hWnd)

Func _ScreenShot($_hWnd, $_sFilePath = "", $_iLeft = 0, $_iTop = 0, $_iRight = -1, $_iBottom = -1, $_bCursor = False)
    Local $hBitmap = _ScreenCapture_CaptureWnd($_sFilePath, $_hWnd, $_iLeft, $_iTop, $_iRight, $_iBottom, $_bCursor)
    _ClipBoard_Open("")
    _ClipBoard_Empty()
    _ClipBoard_SetDataEx($hBitmap, $CF_BITMAP)
    _ClipBoard_Close()
EndFunc

 

Link to post
Share on other sites

If you want to use WD, here a way that is working for me :

Local $sElem = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='line1']")
  Local $vScreen = _WD_Screenshot($sSession, $sElem, 2)
  _GDIPlus_Startup()
  Local $hBit = _GDIPlus_BitmapCreateFromMemory($vScreen)
  _GDIPlus_ImageSaveToFile($hBit, "Element.bmp")
  _GDIPlus_ImageDispose($hBit)
  _GDIPlus_Shutdown()

  Local $hHbit = _WinAPI_LoadImage(0, "Element.bmp", $IMAGE_BITMAP, 0, 0, $LR_LOADFROMFILE)
  
  _ClipBoard_Open("")
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hHbit, $CF_BITMAP)
  _ClipBoard_Close()
  _WinAPI_DeleteObject($hHbit)

I do not know why creating HBitmap format from GDI+ is not compatible with _ClipBoard.  This is the reason I needed to go thru a file to make it worked.

Link to post
Share on other sites

According to the help, _GDIPlus_BitmapCreateFromMemory will return a hbitmap if you pass True for the 2nd parameter. I wonder if it would work without saving to disk if you did it like this --

GDIPlus_Startup()
  Local $hBit = _GDIPlus_BitmapCreateFromMemory($vScreen, True)

  _ClipBoard_Open("")
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hBit, $CF_BITMAP)
  _ClipBoard_Close()
  
  _GDIPlus_ImageDispose($hBit)
  _GDIPlus_Shutdown()

 

Link to post
Share on other sites
Posted (edited)
Link to post
Share on other sites
On 6/3/2022 at 5:28 PM, Subz said:

You could use something like:

#include <Clipboard.au3>
#include <ScreenCapture.au3>

Local $hTray = ControlGetHandle('[CLASS:Shell_TrayWnd]', '', 'TrayNotifyWnd1')

_ScreenShot($hWnd)

Func _ScreenShot($_hWnd, $_sFilePath = "", $_iLeft = 0, $_iTop = 0, $_iRight = -1, $_iBottom = -1, $_bCursor = False)
    Local $hBitmap = _ScreenCapture_CaptureWnd($_sFilePath, $_hWnd, $_iLeft, $_iTop, $_iRight, $_iBottom, $_bCursor)
    _ClipBoard_Open("")
    _ClipBoard_Empty()
    _ClipBoard_SetDataEx($hBitmap, $CF_BITMAP)
    _ClipBoard_Close()
EndFunc

 

@SubzI'm focusing on trying to get this to work using webdriver first and foremost as what I need to capture are specific elements within Chrome, but I will take a look at this when I go and test gathering screen captures from non-browser applications! As a side note - I'm not sure why I didn't think of this before, but I was curious and wanted to see if I could capture a window (instead of the whole screen) by also using Send("^!{PRINTSCREEN}") and that worked!

20 hours ago, Nine said:

If you want to use WD, here a way that is working for me :

Local $sElem = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='line1']")
  Local $vScreen = _WD_Screenshot($sSession, $sElem, 2)
  _GDIPlus_Startup()
  Local $hBit = _GDIPlus_BitmapCreateFromMemory($vScreen)
  _GDIPlus_ImageSaveToFile($hBit, "Element.bmp")
  _GDIPlus_ImageDispose($hBit)
  _GDIPlus_Shutdown()

  Local $hHbit = _WinAPI_LoadImage(0, "Element.bmp", $IMAGE_BITMAP, 0, 0, $LR_LOADFROMFILE)
  
  _ClipBoard_Open("")
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hHbit, $CF_BITMAP)
  _ClipBoard_Close()
  _WinAPI_DeleteObject($hHbit)

I do not know why creating HBitmap format from GDI+ is not compatible with _ClipBoard.  This is the reason I needed to go thru a file to make it worked.

@NineThis seems to work for me! I embeded this into one of my existing projects and added a few lines to test pasting into something simple like a Word document and then deleting the file afterwards and it's perfect (thus far lol)!

Quick question regarding this method: I'm presuming that this only works using the bmp image format, correct? I did try to save the element as jpg and it didn't work, so while it isn't necessarily a complete deal breaker I'm curious if there is a way to convert the bmp to another image format?

Link to post
Share on other sites
  • Solution

@kornholeking

Finally found a way to copy the element to clipboard without saving it to a temp file.

$sElem = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='line1']")
  Local $vScreen = _WD_Screenshot($sSession, $sElem, 2)
  _GDIPlus_Startup()
  Local $hHbit = _GDIPlus_BitmapCreateFromMemory($vScreen, True)
  _GDIPlus_Shutdown()
  Local $hHBitmap = _WinAPI_CopyImage($hHbit, 0, 0, 0, $LR_COPYDELETEORG + $LR_COPYRETURNORG)
  _WinAPI_DeleteObject($hHbit)
  _ClipBoard_Open("")
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hHBitmap, $CF_BITMAP)
  _ClipBoard_Close()
  _WinAPI_DeleteObject($hHBitmap)

I knew there should be a way... :)

Link to post
Share on other sites
2 hours ago, Nine said:

@kornholeking

Finally found a way to copy the element to clipboard without saving it to a temp file.

$sElem = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='line1']")
  Local $vScreen = _WD_Screenshot($sSession, $sElem, 2)
  _GDIPlus_Startup()
  Local $hHbit = _GDIPlus_BitmapCreateFromMemory($vScreen, True)
  _GDIPlus_Shutdown()
  Local $hHBitmap = _WinAPI_CopyImage($hHbit, 0, 0, 0, $LR_COPYDELETEORG + $LR_COPYRETURNORG)
  _WinAPI_DeleteObject($hHbit)
  _ClipBoard_Open("")
  _ClipBoard_Empty()
  _ClipBoard_SetDataEx($hHBitmap, $CF_BITMAP)
  _ClipBoard_Close()
  _WinAPI_DeleteObject($hHBitmap)

I knew there should be a way... :)

@NineWorks flawlessly! Thanks for making this even smoother than before!

Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...