Using MSChart COM Component in VB.net

I have successfully used other some 'Com' components in VB.net, eg 'Flexgrid', but have failed to get 'MSChart' to work, without bringing up an Operation Exception, the details of which are:
"Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.".
I think I understand what it means, but how do I fix it?
[382 byte] By [Prius] at [2007-12-25]
# 1
Prius,
Did you ever get an answer to this? I'm running into exactly the same problem now, using C#, VS .NET 2005 B2, .NET 2.0.
Any suggestions?
Thanks in advance,
Joel
J.W. at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 2
Prius,
I found the answer in another forum. This worked for me:
Mike Harsh wrote:
This sounds like a known issue with the Visual Studio hosting process. The Visual Studio hosting process starts up a main thread and then creates a new UI thread that the application is run on. Some ActiveX controls do not support running on a UI thread that is not the main thread, hence this exception is being thrown.
The workaround is to disable the Visual Studio hosting process. To do this, open the project proeprty designer and selet the Debug tab. Then uncheck the "Enable the Visual Studio hosting process" checkbox.
VS host gives a performance boost to the F5 scenario and also enables the debug in security zone functionality. You will not be able to access these features if VS host is disabled.
Hope this helps.
- mike
J.W. at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 3
Uh-oh.....

I'm having the same problem. I disabled the hosting process and ran my program. In my case the alternate thread is started by a timer or is a timer thread updatting a listview control.

I ran the program with for a couple of passes and it worked - then it failed with the same error.

The host process is definitely turned off.

I've tried fooling it and it doesn't seem to be foolable.

ReneeC at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 4

Dealing with this requires a delegate routine and is needed at runtime regardless of whether a host process is present or not.

I do have code but the code is rather esoteric and I don't think it's too illustrative. :(

ReneeC at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 5
Hi,
I am facing a similar problem of cross thread access. Can you please post the code?
Thanks,
Hemanth
Hemanth at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 6
Hi.
I saw the problem within my printing function. I was trying to print an MSChart object (using MSChart20.ocx) embedded in a .NET Windows Form. The principle was to copy the chart graphics to the clipboard, then pass that Bitmap to the PrintPageEventArgs object in the PrintPage event of a System.Drawing.Printing.PrintDocument object.
Here's a clip from the PrintPage event handler:

/// <summary>
/// This is the event handler for the <c>PrintPageEventHandler<c> of the <c>PrintDocument<c>.
/// This method displays the default printer dialog then prints a Bitmap containing the chart image.
/// </summary>
private void pdPrintDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
// get the MSChart object that is currently selected
// (ChartManager is my own code, and irrelevant in this example.)
AxMSChart20Lib.AxMSChart achart = ChartManager.SelectedChart;

try
{
// EditCopy() is a native MSChart method. It places the bitmap of the chart on the clipboard.
// **** THIS IS WHERE THE EXCEPTION OCCURS ****
achart.EditCopy();
Cursor = Cursors.AppStarting;

// Get the bitmap from the clipboard as a general data object, but treat it like a bitmap
IDataObject drawing = (IDataObject)(Clipboard.GetDataObject());

if (drawing.GetDataPresent(DataFormats.Bitmap))
{
Bitmap bm = (Bitmap)(Clipboard.GetDataObject().GetData(DataFormats.Bitmap));
// Not sure how, but this prints the Bitmap.
e.Graphics.DrawImage(bm, e.Graphics.VisibleClipBounds);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
Cursor = Cursors.Default;
}
}
}

Good luck!
Joel

J.W. at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 7

I found the error actually occurs in the line:

IDataObject drawing = (IDataObject)(Clipboard.GetDataObject());

Pasting the data into Paint after a failure worked. To get arround this, I created a small application that copied the contents from the clipboard, then proceded to print it. This code worked fine for me. I hope this helps!

Note that I had no such problems with VB 2003.

MikeMonteith at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 8
I had the same problem and had to use Win32 API calls to solve the problem.
The following C# code worked for me:

using System.Runtime.InteropServices;
...

//copy the chart bitmap to the clipboard
MSChart1.EditCopy();

Application.DoEvents();

//open the clipboard
if (Win32ClipboardAPI.OpenClipboard(IntPtr.Zero))
{
//check that it has recognized the bitmap
if (Win32ClipboardAPI.IsClipboardFormatAvailable(Win32ClipboardAPI.CF_BITMAP))
{
//Get the pointer for the current Clipboard Data
IntPtr bmptr = Win32ClipboardAPI.GetClipboardData(Win32ClipboardAPI.CF_BITMAP);

if (bmptr != IntPtr.Zero)
{
//retrieve the bitmap
Bitmap chartCapture = Bitmap.FromHbitmap(bmptr);
.....

//tidy up
chartCapture.Dispose();
}
}

//Close the clipboard and release unused resources
Win32ClipboardAPI.CloseClipboard();
}

private class Win32ClipboardAPI
{
public const uint CF_BITMAP = 2;

[DllImport("user32.dll")]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll")]
public static extern IntPtr GetClipboardData(uint uFormat);

[DllImport("user32.dll")]
public static extern bool CloseClipboard();

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool IsClipboardFormatAvailable(uint format);
}

MikeAjao at 2007-9-3 > top of Msdn Tech,Visual Basic,Visual Basic General...