Home All Groups Group Topic Archive Search About

Framework2 Clipboard bitmap problem solved

Author
29 Mar 2007 3:20 PM
Roy Soltoff
I use an MsChrt20.ocx in my Vs 2003 project. To print the chart, I used the
old workaround of using the ocx's EditCopy method to copy the chart image to
the clipboard, then use the Clipboard.GetDataObject method to get the image
from the clipboard using code like the following:
Dim iData As System.Windows.Forms.IDataObject = Clipboard.GetDataObject()

If (iData.GetDataPresent(DataFormats.Bitmap)) Then

    Try

        Dim Img As Image = CType(iData.GetData(DataFormats.Bitmap), Bitmap)

        Dim lMargin As Single = e.MarginBounds.Left

        Dim tMargin As Single = e.MarginBounds.Top

        e.Graphics.DrawImage(Img, lMargin, tMargin)

        Dim myRect As New Rectangle(lMargin, tMargin, Img.Width + 20,
Img.Height)

        e.Graphics.DrawRectangle(Pens.Black, myRect)

    Catch ex As Exception

        PostError(ex)

    End Try

End If

In Vs2005, this fails miserably with a Fatal Engine Error,l in spite of
forcing the program to be <STAThread> with the appropriate attribute on the
Sub Main() as specified in the MSDN on the clipboard class. I rewrote the
code to use the enhanced Clipboard class in the Framework2, but that
generates the same error. Interestingly enough using a test program, if I
invoked 2 instances of the program, I could copy the chart using EditCopy to
the clipboard in one instance, and paste the clipboard bitmap into the other
instance. But accessing the clipboard once the ActiveX control copied a
bitmap to it resulted in crash city.

After research, I discovered that the Framework2 does indeed have some
severe problems with accessing the clipboard for images. Fortunately, the
Win32 clipboard APIs can be used directly in a Vs2005 program. The following
partial code appears to work flawlessly in a VB.Net 2 program. I offer it as
a solution for those that need it:

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Public Class Form2
    <DllImport("user32.dll", EntryPoint:="OpenClipboard", _
       SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="EmptyClipboard", _
       SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EmptyClipboard() As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="SetClipboardData", _
       SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function SetClipboardData(ByVal uFormat As Integer, ByVal
hWnd As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll", EntryPoint:="CloseClipboard", _
       SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function CloseClipboard() As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="GetClipboardData", _
      SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function GetClipBoardData(ByVal uFormat As Integer) As
IntPtr
    End Function
    <DllImport("user32.dll", EntryPoint:="IsClipboardFormatAvailable", _
      SetLastError:=True, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function IsClipboardFormatAvailable(ByVal uFormat As
Integer) As Boolean
    End Function
    '/*
    ' * Predefined Clipboard Formats
    ' */
    Private Const CF_TEXT As Integer = 1
    Private Const CF_BITMAP As Integer = 2
    Private Const CF_METAFILEPICT As Integer = 3
    Private Const CF_SYLK As Integer = 4
    Private Const CF_DIF As Integer = 5
    Private Const CF_TIFF As Integer = 6
    Private Const CF_OEMTEXT As Integer = 7
    Private Const CF_DIB As Integer = 8
    Private Const CF_PALETTE As Integer = 9
    Private Const CF_PENDATA As Integer = 10
    Private Const CF_RIFF As Integer = 11
    Private Const CF_WAVE As Integer = 12
    Private Const CF_UNICODETEXT As Integer = 13
    Private Const CF_ENHMETAFILE As Integer = 14
    Private Const CF_HDROP As Integer = 15
    Private Const CF_LOCALE As Integer = 16
    Private Const CF_MAX As Integer = 17
    Private Const CF_OWNERDISPLAY As Integer = 128
    Private Const CF_DSPTEXT As Integer = 129
    Private Const CF_DSPBITMAP As Integer = 130
    Private Const CF_DSPMETAFILEPICT As Integer = 131
    Private Const CF_DSPENHMETAFILE As Integer = 142

    Private Sub btnCopy_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnCopy.Click
        Try
            AxMSChart1.EditCopy()
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Exclamation)
        End Try
    End Sub

    Private Sub btnPaste_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnPaste.Click
        Try
            If (IsClipBoardFormatAvailable(CF_BITMAP)) Then
                OpenClipboard(Me.Handle)
                Dim hWnd As IntPtr = GetClipBoardData(CF_BITMAP)
                If (Not hWnd.Equals(IntPtr.Zero)) Then
                    Dim img As System.Drawing.Image =
System.Drawing.Image.FromHbitmap(hWnd)
                    picPicture.Image = img
                End If
                CloseClipboard()
            Else
                MsgBox("A bitmap is not available")
            End If
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Exclamation)
        End Try
    End Sub

AddThis Social Bookmark Button