HTMLviewer image to canvas question.

HTMLviewer image to canvas question.

I have a page with a HTMLviewer on it. Is it possible to store the image
in the HTMLviewer to a canvas ?

I am trying to store the image in the HTMLviewer to a database to be viewed
later as an image file.

It can be done by using some of MBS plugins

something like this;

[code] Dim NSImage As NSImageMBS=HTMLViewer1.RenderWebsiteImageMBS
If NSImage<>Nil Then
URLPicture = NSImage.CopyPictureWithMask

  Canvas1.Invalidate
End If[/code]

where URLPicture is an image you draw in Canvas1.Paint event. Or you can store the image in a database if thats desired.

I use the code from the first post on Mac OS X with no issues (and no plugins)…
http://forums.realsoftware.com/viewtopic.php?f=1&t=43288

that’s not the same as draw into…
RenderWebsiteImageMBS gives whole website, not just what’s visible in window.

I just want what is visible in the HTMLviewer window. What I am doing is getting maps that show up in the window
and save them as a .png or .jpg file.

Using the code in that thread works for Mac OS X and will just capture the visible portion of the HTMLViewer…

If you are open to using MBS plugins, maybe ScreenshotMBS would do what you want. It will create an in-memory picture which you could then display in a canvas, save as an image file, etc.

For Windows It can be done with:

  #If TargetWin32 Then
 //Declare all the Windows Junk
  Declare Function GetDC Lib "User32" (HWND As Integer) As Integer
  Declare Function BitBlt Lib "GDI32" (DCdest As Integer, xDest As Integer, yDest As Integer, nWidth As Integer, nHeight As Integer, _
  DCdource As Integer, xSource As Integer, ySource As Integer, rasterOp As Integer) As Boolean
  Declare Function ReleaseDC Lib "User32" (HWND As Integer, DC As Integer) As Integer
  
//Let's get two constants...winxp and under didn't have captureblt so we'll hafta use srccopy :-)
  Const CAPTUREBLT = &h40000000
  Const SRCCOPY = &HCC0020
  
  //Create a Picture object to hold our hooked screenshot
  Dim screenCap As New Picture(HTMLViewer1.Width, HTMLViewer1.Height, 24)
  //Get the "Real" HTMLViewer Handle for Capture..Xojo returns a bogus 'pseudo handle'
  Dim HTMLViewerDC as Integer = GetDC(HTMLViewer1.Handle)
  
//Grab that snapshot of the HTMLViewer
  Call BitBlt(screenCap.Graphics.Handle(1),0,0,HTMLViewer1.Width , HTMLViewer1.Height , HTMLViewerDC, -2, -2, SRCCOPY or CAPTUREBLT)
  //Function may be called again..so lets release the object to prevent memory leak...
  Call ReleaseDC(HTMLViewer1.Handle, HTMLViewerDC)
  //Return our "Snapshot"
  Return screenCap
#elseif TargetMacOS Then
//Mac way...
#endif

I Don’t have my mac available to use the system API declares to replicate but here’s the Obj C of it… can translate to Xojo later if needed
https://developer.apple.com/library/mac/samplecode/SonOfGrab/Introduction/Intro.html

Avoiding plugins and without translating API, I might add that you can use a Shell Class and

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/screencapture.1.html

open the image in a function…get the cordinates of your htmlviewer and crop that portion out of the resulting screenshot? :slight_smile:

@Matthew Combatti

I have used your routine and see that it stores the htmlviewer image in another
windows backdrop. How do I store that as a image file ?

http://documentation.xojo.com/index.php/Picture.Save

The function above returns a Picture object. You can use the Picture.Save function built-in to Xojo to save the file or, if its being saved into a database as the recordset.picturevalue.

Thanks guys for the help. I got the windows to work as needed but am still having problems with the Mac routine.
Below is the code that I am working with. The Windows part works fine but I need help with the mac code.
I need to get the image in the HTMLviewer1 into the canvas1 as this works in windows.
Keep in mind that I am using RS version 2012r2.1. I do have XOJO but just to much database recoding to use it.

This code is in a button/action

[code] #If TargetWin32 Then
// Set up the varables for screen Width/Height
Dim htmlwinwidth As Integer
Dim htmlwinheigth As Integer
htmlwinwidth = self.Width
htmlwinheigth = self.Height
// Set the canvas1 to the same size as the road map screen
Canvas1.Width = HTMLViewer1.Width
Canvas1.Height = HTMLViewer1.Height
// Fill the canvas backdrop with the map from the htmlviewer
Canvas1.Backdrop = GetMapFromHTMLViewer(htmlwinwidth,htmlwinheigth,HTMLViewer1)

// Canvas 1 routine
Dim f as FolderItem
Dim imageData as String
Dim bs as BinaryStream
Dim FileNameNoExtension As String

// Creates a date/time stamp for a new map
Dim today as New Date
Dim vDateStamp1 as String
Dim vDateStamp2 as String

// Creates the time stamp for a new filename
vDateStamp1=today.LongTime
vDateStamp2=today.SQLDate

// Remove the Colons and Spaces from the time string
vDateStamp1=ReplaceAll(vDateStamp1,":","") 
vDateStamp1=ReplaceAll(vDateStamp1," ","")
vDateStamp1=ReplaceAll(vDateStamp1,"PM","")
vDateStamp2=ReplaceAll(vDateStamp2,"-","")  
// Create the file name for the map
FileNameNoExtension = ReplaceAll(gCGName, "/", "-")
FileNameNoExtension = FileNameNoExtension + "_" + vDateStamp2 + "_" + vDateStamp1    //' + "."

// Now we save the canvas backdrop to a file
If Canvas1.Backdrop <> NIL then
  // Get a temporary file to save the image to
  'f = gdbFolderTA.Child( str(gCGID) + FileNameNoExtension + "Jpg")
  f = gdbFolderTA.Child(FileNameNoExtension + ".Jpg")
  // Save the image out to the file as a .jpg
  Canvas1.Backdrop.Save(f,Picture.SaveAsJPEG)
  // Open the file as a BinaryStream and read the data in
  bs=BinaryStream.Open(f,False)
  If bs <> NIL then
    imageData = bs.read( bs.length )
    bs.close
  End if
End If

#elseif TargetMacOS Then
// Mac Routine
Dim g As Graphics
Dim Pic As Picture
mP = new Picture(htmlviewer1.Width, htmlviewer1.Height, 32)
Pic = new Picture(LocationMapPage.Width, LocationMapPage.Height, 32)
g = Pic.Graphics

//mP ia global picture property
//323 and 17 are respectively the left and the top properties of the htmlviewer control
//we must use the DrawInto method of the windows because the DrawInto method of the htmlviewer does'nt work

LocationMapPage.DrawInto(g, 17, 323)
    
mp.Graphics.DrawPicture pic,0,0,htmlviewer1.Width,htmlviewer1.Height,323,17,htmlviewer1.Width,htmlviewer1.Height

LocationMapPage.canvas1.Backdrop = mp
#endif

[/code]
Below is the windows method. Part of this code is by Matthew Combatti. Thanks for this great chunk of code.

METHOD NAME GetMapFromHTMLViewer
Parameters MapWidth as Integer, MapHeight as Integer, MapViewer as HTMLViewer
Return Type Picture

[code] #If TargetWin32 Then
//Declare all the Windows Junk
Declare Function GetDC Lib “User32” (HWND As Integer) As Integer
Declare Function BitBlt Lib “GDI32” (DCdest As Integer, xDest As Integer, yDest As Integer, nWidth As Integer, nHeight As Integer, _
DCdource As Integer, xSource As Integer, ySource As Integer, rasterOp As Integer) As Boolean
Declare Function ReleaseDC Lib “User32” (HWND As Integer, DC As Integer) As Integer

//Let's get two constants...winxp and under didn't have captureblt so we'll hafta use srccopy :-)
Const CAPTUREBLT = &h40000000
Const SRCCOPY = &HCC0020

//Create a Picture object to hold our hooked screenshot
Dim screenCap As New Picture(LocationMapPage.HTMLViewer1.Width, LocationMapPage.HTMLViewer1.Height, 24)
//Get the "Real" HTMLViewer Handle for Capture..Xojo returns a bogus 'pseudo handle'
Dim HTMLViewerDC as Integer = GetDC(LocationMapPage.HTMLViewer1.Handle)

//Grab that snapshot of the HTMLViewer
Call BitBlt(screenCap.Graphics.Handle(1),0,0,LocationMapPage.HTMLViewer1.Width ,   LocationMapPage.HTMLViewer1.Height , HTMLViewerDC, -2, -2, SRCCOPY or CAPTUREBLT)
//Function may be called again..so lets release the object to prevent memory leak...
Call ReleaseDC(LocationMapPage.HTMLViewer1.Handle, HTMLViewerDC)
//Return our "Snapshot"
Return screenCap

#elseif TargetMacOS Then
//Mac way…
Dim g As Graphics
Dim Pic As Picture
mP = new Picture(htmlviewer1.Width, htmlviewer1.Height, 32)
Pic = new Picture(LocationMapPage.Width, window_main.Height, 32)
g = Pic.Graphics

//mP ia global picture property
//323 and 17 are respectively the left and the top properties of the htmlviewer control
//we must use the DrawInto method of the windows because the DrawInto method of the htmlviewer does'nt work

LocationMapPage.DrawInto(g, 17, 323)


mp.Graphics.DrawPicture pic,0,0,htmlviewer1.Width,htmlviewer1.Height,323,17,htmlviewer1.Width,htmlviewer1.Height

LocationMapPage.canvas1.Backdrop = mp

#endif[/code]

I decided to take the liberty to complete the function for you. If you need linux as well, would be glad to complete that as well…but I think with the following Mac example could complete it on your own using the linux command line

import -window root" + SpecialFolder.Temporary.Child(TimeStamp(tStamp, true) + ".png")

A more efficient TimeStamp method…Unix accepted…Mac/Windows friendly :slight_smile:

Function TimeStamp(theDate As date, unix As boolean) As string
  ' Returns Unis time stamp [if unix = true] or ISO date time.
  dim s(1), result As string
  
  if unix then ' Use no separators to create a Unix time stamp.
    s(0) = ""
    s(1) = ""
  else ' Use separators that create an ISO date time.
    s(0) = "-"
    s(1) = ":"
  end if
  
  result = format( theDate.year, "0000" ) + s(0)
  result = result + format( theDate.month, "00" ) + s(0)
  result = result + format( theDate.day, "00" ) + "T"
  result = result + format( theDate.hour, "00" ) + s(1)
  result = result + format( theDate.minute, "00" ) + s(1)
  result = result + format( theDate.second, "00" )
  
  return result
  
End Function

and I don’t have my mac up and running, so I haven’t tested the following…if any correction is needed, should be very minimal changes…but it should work as is…

Mac Snapshot of HTMLViewer:

Function MacSnap() As Picture
  Dim takeSnap as new Shell
  Dim tStamp as new Date
  Dim SnapShotFile as FolderItem
  Dim SnapImage as Picture
  Dim HTMLPortion as Picture = New Picture(HTMLViewer1.Width, HTMLViewer1.Height, 32)
  
  SnapShotFile =  SpecialFolder.Temporary.Child(TimeStamp(tStamp,true) +".png")
  
  //-x will supress the camera snapshot sound
  //we could have used "screencapture -c" and read the image from the Clipboard,
  //but this would be inefficient, especially if the user happens to copy an image to the clipboard...
  takeSnap.Execute "screencapture -x " +SnapShotFile
  
  if SnapShotFile.Exists then
    //Load our SnapShot
    SnapImage = Picture.Open(SnapShotFile)
    //Draw our Mac SnapShot
    //323 Could be Screen.Width - HTMLViewer1.Left
    //17 could be Screen.Height - HTMLViewer1.Top
    HTMLPortion.Graphics.DrawPicture(SnapImage,0,0,HTMLViewer1.Width,HTMLViewer1.Height,323,17,HTMLViewer1.Width,HTMLViewer1.Height)
    //Delete the snapshot file to prevent massive collection in our Temp Dir
    SnapShotFile.Delete
    //Return the Snapshot of the HTMLViewer ONLY
    Return HTMLPortion
  else
    //Something happened or the directory isn't Writeable
    //Should never occur, but just in case...
    Return Nil
  end if
  
End Function

Have a Great Night :slight_smile:

Just a final thought…but the Mac function I gave could be Mac/Linux universally friendly if you replace part of the code with:

SnapShotFile = SpecialFolder.Temporary.Child(TimeStamp(tStamp,true) +".png")

#if targetMacOS then
takeSnap.Execute "screencapture -x " + SnapShotFile
#elseif TargetLinux then
takeSnap.Execute “import -window root” + SnapShotFile
#endif

Although…add a space after root and before the end-quote…

@Matthew Combatti

I tried the routine above but it does not work. I created the timestamp and macsnap methods
but I’m not sure how to call macsnap as I get an error (you must use the value returned by this function)

In the macsnap function the line of code that gives an error of (you have used an operator that is not
compatible with the data types specified)

takeSnap.Execute "screencapture -x " +SnapShotFile

The function returns a picture object of the htmlviewer just as the windows function does, so wherever you are wanting to obtain the image and save it,

Dim SnapShotToSave as picture
SnapshotTosave = MacSnap
SnapShotToSave.Save (just like picture.save for the windows function. If you put the windows function in the MacSnap function with targetwin32 directive, only a single function is necessary for cross-platform usage.

Oops…replace the “+ Snapshotfile” with “+ SnapShotFile.ShellPath” for both the Mac and Linux functions. Apologies, it was a tiring evening and the function remained untested.

Hope that helps.

Matthew

I have been playing with the mac code and though it works it captures the whole screen.
All I want is just whats in the HTMLviewer1 and copy that to canvas1. Once there I know how to to create
the image file from the canvas1 (assuming it works as windows does) and do what I need from there.
I’m sorry to keep pestering you but I really don’t know Mac’s very well and get a little confused with the
way it works compared to windows. You are giving me one hell of a lesson though and thank you for help.
I do try to manipulate the code to make it work but I am really lost at the moment.
I did add this code //Mac Routine. Dim SnapShotToSave as picture SnapshotTosave = MacSnap Canvas1.Backdrop = snapshottosave
and it does show in the canvas1 but it shows a full screen shot not just whats in the htmlviewer1

I think he mentioned that early on. Just grab the portion of the image you’re interested in.