container control to picture

I’d like to be able to share the contents of a container control (more specifically a iOSCustomTableCell) as a picture.

Is there something like DrawInto that I can use?

I’m assuming someone’s done a declare that will cover this as well.

Thanks in advance.

IOSKit has a ScreenShot function. You could extract a portion of the image corresponding to your TableCell by getting its bounds. I don’t think there is a way to do this directly in Xojo. You might be able to modify the screenshot function to just draw the table cell, I don’t remember.

I believe the iOSKit screenshot function could be adapted to only output the TableCell contents.

Yeah it can definitely be adapted. Let me know if you would like me to put it together for you and I can do so tomorrow.

May I request iOSCanvas -> iOSImage while you’re at it? :slight_smile:

I’m not sure the canvas acts the same way but it’s worth a try.
Will have a look at it Sunday evening

Untested but should be something like this. Please let me know if this works and I can add it to iOSKit this weekend (not at my main dev machine for the week so I don’t have access to Xojo):

Function PictureOfView(viewRef as Ptr) As iOSImage
#if Target32Bit
    declare function bounds lib UIKitLib selector "bounds" (obj_id as Ptr) as CGRect32
#Elseif Target64Bit
    declare function bounds lib UIKitLib selector "bounds" (obj_id as Ptr) as CGRect64
#Endif

#if Target32Bit
    dim sz as CGSize32 = bounds(viewRef).rsize
#Elseif Target64Bit
    dim sz as CGSize64 = bounds(viewRef).rsize
#Endif

#if Target32Bit
    declare sub UIGraphicsBeginImageContext lib UIKitLib (mSize as CGSize32)
#Elseif Target64Bit
    declare sub UIGraphicsBeginImageContext lib UIKitLib (mSize as CGSize64)
#Endif
UIGraphicsBeginImageContext(sz)

declare function layer lib UIKitLib selector "layer" (obj_id as ptr) as ptr
declare sub renderInContext lib UIKitLib selector "renderInContext:" (obj_id as ptr, ctx as ptr)
declare function UIGraphicsGetCurrentContext lib UIKitLib () as ptr
renderInContext(layer(viewRef), UIGraphicsGetCurrentContext())

declare function UIGraphicsGetImageFromCurrentImageContext lib UIKitLib () as ptr
dim newUIImage as Ptr = UIGraphicsGetImageFromCurrentImageContext()

declare sub UIGraphicsEndImageContext lib UIKitLib ()
UIGraphicsEndImageContext()

Return iOSImage.FromHandle(newUIImage)
End Function

You’ll pass in the view hande to this function.

FYI… from what I can tell… that above code could be modified ever so slightly to create a fully functional PDF document generator

Mr, King… good news, good news, and bad news.

Good news… it works.
Good news… I’m pretty sure I can qualify for the Boston Marathon this year :slight_smile:
Bad news… sharing by method of saving the image crashes the app. I don’t know yet if this is a Xojo issue or something odd with the image, but I’m presuming the former.

Thanks for the code. This is a huge help!

If you are saving the image to PhotoLibrary without NS…Description in the app’s plist then it will crash.
Unless you are saving somewhere else ?

Hi Chris have you been able to confirm that the crashing issue was due to the entitlements like Jeremie suggested, and not something wrong with the function I put together?

Verified.

Your function was perfect out of the box.
The PLIST entry fixed it.

Thanks again!

Jason, a couple years later… this function is now not working right. I think it’s failing to recognize the scaling of the container control. Any ideas?

Untested

[code]Function PictureOfView(viewRef as Ptr) As iOSImage

declare function bounds lib UIKitLib selector "bounds" (obj_id as Ptr) as CGRect64


dim sz as CGSize64 = bounds(viewRef).rsize


//declare sub UIGraphicsBeginImageContext lib UIKitLib (mSize as CGSize64)

declare sub UIGraphicsBeginImageContextWithOptions lib UIKitLib (mSize as CGSize64, opaque as boolean, scale as CGFloat)

UIGraphicsBeginImageContextWithOptions(sz, true, 0.0) //0.0 uses current screen scale

declare function layer lib UIKitLib selector “layer” (obj_id as ptr) as ptr
declare sub renderInContext lib UIKitLib selector “renderInContext:” (obj_id as ptr, ctx as ptr)
declare function UIGraphicsGetCurrentContext lib UIKitLib () as ptr
renderInContext(layer(viewRef), UIGraphicsGetCurrentContext())

declare function UIGraphicsGetImageFromCurrentImageContext lib UIKitLib () as ptr
dim newUIImage as Ptr = UIGraphicsGetImageFromCurrentImageContext()

declare sub UIGraphicsEndImageContext lib UIKitLib ()
UIGraphicsEndImageContext()

Return iOSImage.FromHandle(newUIImage)
End Function[/code]

Thank you Jeremie,
I’m getting very strange results. It looks like the X and Y don’t scale the same, and the text element scale differently.
I need to investigate.

Depending on when you call that function, the bounds of the View might be wrong.

So here’t the deal…

I’m trying to get all the cells in a given iOSTable.
If I reference the table, I get all the white space (empty rows), which won’t work for me.
If I get individual rows (to combine later) the scale is badly mixed up.

When referencing the table do you still get the cells at the top + whitespace at the bottom?

If you do, you could then crop the iOSImage given the fact that you know how many cells there are and the height of each cell.

I just tested that. It only gives me what is visible at the current time.
I am going to have to figure out the scaling issue.

OK, I figured out the source of the problem, but I can’t figure out an elegant solution
To get the cell I call rowData
When I do this on a table with a custom source, it created a new cell. That cell hasn’t been displayed yet, and I’m guessing that’s why it has incorrect sizes.

The ugly hack I can think of is to keep a reference to each cell that I put in the table and keep them updated every time RowData is changed.

Is there a better way?