Thursday, October 22, 2009

Copy & Paste Form Controls

My previous post worked with the chart controls in VS. While working on my own project I realized a need for the ability to copy the chart control and place it into another program such as Excel or Powerpoint.

I tried many combinations of things, but they just weren't working. Then I stumbled upon this article by Scott Lysle (http://www.a1vbcode.com/app-3902.asp) which made the whole thing easy. His method creates a .bmp image and saves it, I have adjusted it in two ways to accomplish my goal. First I turned it into a function that returned the image instead of saving it, and then I put it in the clipboard for ease of movement.

His code uses a datagridview as a source, but as he mentions in the write-up, it is easily adaptable for most any control by just changing the control type.

Here is the code to copy the datagridview that accompanies my chart:

Public Function Convertdg2BMP(ByVal dg As DataGridView)

dg.Refresh()
dg.Select()

Dim g As Graphics = dg.CreateGraphics
Dim ibitMap As New Bitmap(dg.ClientSize.Width, _
dg.ClientSize.Height, g)
Dim iBitMap_gr As Graphics = Graphics.FromImage(ibitMap)
Dim iBitMap_hdc As IntPtr = iBitMap_gr.GetHdc
Dim me_hdc As IntPtr = g.GetHdc

BitBlt(iBitMap_hdc, 0, 0, dg.ClientSize.Width, _
dg.ClientSize.Height, me_hdc, 0, 0, SRC)
g.ReleaseHdc(me_hdc)
iBitMap_gr.ReleaseHdc(iBitMap_hdc)

Return ibitMap
End Function

And here it is with the chart:


Public Function ConvertCH2BMP(ByVal ch As Chart)

ch.Refresh()
ch.Select()

Dim g As Graphics = ch.CreateGraphics
Dim ibitMap As New Bitmap(ch.ClientSize.Width, _
ch.ClientSize.Height, g)
Dim iBitMap_gr As Graphics = Graphics.FromImage(ibitMap)
Dim iBitMap_hdc As IntPtr = iBitMap_gr.GetHdc
Dim me_hdc As IntPtr = g.GetHdc
BitBlt(iBitMap_hdc, 0, 0, ch.ClientSize.Width, _
ch.ClientSize.Height, me_hdc, 0, 0, SRC)
g.ReleaseHdc(me_hdc)
iBitMap_gr.ReleaseHdc(iBitMap_hdc)

Return ibitMap
End Function

**You will need to add an imports:

Imports System.Drawing.Imaging

And then you will need this function pasted within your class:

Private Declare Auto Function BitBlt Lib "gdi32.dll" _
(ByVal pHdc As IntPtr, ByVal iX As Integer, _
ByVal iY As Integer, ByVal iWidth As Integer, _
ByVal iHeight As Integer, ByVal pHdcSource As IntPtr, _
ByVal iXSource As Integer, ByVal iYSource As Integer, _
ByVal dw As System.Int32) As Boolean
Private Const SRC As Integer = &HCC0020

Then just call the function you need based on the control (you could use just one, yes, but that is beyond the scope of this I think):

Clipboard.SetImage(ConvertCH2BMP(Me.Chart1))

I set mine up in a context menu so a right-click -> copy fires the code and then I go paste where I like.

No comments: