Since you specified that you want to use the graph as a server-side control, I'm assuming that you do not want any controls actually running on the client, so what you want is to send an image of the control to the client. To do this, you need to a.) determine a mechanism for sending dynamic images to the client, and b.) actually create the dynamic images and send them to them to the client via however you decided to implement a.).
There are different approaches to a.), but one easy one is to create a separate .aspx page where the page has nothing but the page directive and the structure of the code behind looks like this:
class MyPage : Page
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Response.Clear();
Response.ContentType = /* specify the MIME type of the image */
// Handle dynamic image creation details, and then write the image to
// the response stream via Response.BinaryWrite or
// Response.OutputStream.
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
}
}
You can then create an <img/> tag that points to the page that serves dynamic images like this:
<img src="MyPage.aspx">
You could also implement the page so that it can take parameters and pass those parameters via a URL query string.
To generate images of the CWGraph ActiveX control, you will need to first add AspCompat="true" to the page that's generating the dynamic image. This is because we will be dynamically creating the graph ActiveX control and AspCompat="true" will ensure that the page runs on an STA thread. Next, run aximp.exe on cwui.ocx and add both the generated AxCWUIControlsLib and CWUIControlsLib interop assemblies to your project. You must manually run aximp.exe and add the references - if you just add a reference via the COM tab in the Add Reference dialog, only CWUIControlsLib will be generated and added to the project. You will also need to add a reference to System.Windows.Forms since the ActiveX control host derives from AxHost, which is in the Windows Forms assembly. Also note that you will have to get a license string for the ActiveX control and set the license string. You can get more information on how to do this from the Microsoft KB article
HOW TO: Dynamically Add ActiveX Controls that Require Run-Time Licenses in Visual Basic .NET and the NI KB article
Dynamically Add Activex controls that require run-time licences in C#. Here's the code behind to generate an image from a graph ActiveX control:
using AxCWUIControlsLib;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Windows.Forms;
namespace DynamicImageExample
{
public class DynamicImageActiveX : Page
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
WriteImage(ImageFormat.Png, "image/png");
}
private void WriteImage(ImageFormat format, string contentType)
{
if (format == null)
throw new ArgumentNullException("format");
if (contentType == null)
throw new ArgumentException("contentType");
Response.Clear();
Response.ContentType = contentType;
using (AxCWGraph graph = new AxCWGraph())
{
// Set the license for the ActiveX graph. See Microsoft KB Q326651.
FieldInfo fi = typeof(AxHost).GetField("licenseKey", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(graph, "[Enter your license string here]");
graph.CreateControl();
using (Image controlImage = graph.ControlImage())
using (MemoryStream stream = new MemoryStream())
{
// Some codecs require seekable memory streams and others don't.
// Therefore, we need to write to a seekable memory stream, then
// transfer the memory stream to the output stream.
controlImage.Save(stream, format);
Response.BinaryWrite(stream.ToArray());
stream.Close();
}
}
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
}
}
}
This is a little easier with the Windows Forms .NET graph controls in Measurement Studio 7.0. Here's the code behind:
using NationalInstruments;
using NationalInstruments.UI;
using NationalInstruments.UI.WindowsForms;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
using System.Web.UI;
namespace DynamicImageExample
{
public class DynamicImageMStudio70 : Page
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
WriteImage(ImageFormat.Png, "image/png");
}
private void WriteImage(ImageFormat format, string contentType)
{
if (format == null)
throw new ArgumentNullException("format");
if (contentType == null)
throw new ArgumentException("contentType");
Response.ClearContent();
Response.ContentType = contentType;
using (WaveformGraph graph = new WaveformGraph())
using (XAxis xAxis = new XAxis())
using (YAxis yAxis = new YAxis())
using (WaveformPlot plot = new WaveformPlot(xAxis, yAxis))
using (Bitmap bmp = new Bitmap(graph.Width, graph.Height, PixelFormat.Format32bppPArgb))
using (Graphics g = Graphics.FromImage(bmp))
using (MemoryStream stream = new MemoryStream())
{
graph.XAxes.Add(xAxis);
graph.YAxes.Add(yAxis);
graph.Plots.Add(plot);
Rectangle bounds = new Rectangle(0, 0, graph.Width, graph.Height);
graph.Draw(new ComponentDrawArgs(g, bounds));
// Some codecs require seekable memory streams and others don't.
// Therefore, we need to write to a seekable memory stream, then
// transfer the memory stream to the output stream.
bmp.Save(stream, format);
Response.BinaryWrite(stream.ToArray());
stream.Close();
}
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
}
}
}
Measurement Studio 7.1, which will be available very soon, makes this much easier with convenient control image exporting methods:
using NationalInstruments;
using NationalInstruments.UI;
using NationalInstruments.UI.WindowsForms;
using System;
using System.Drawing;
using System.Web;
using System.Web.UI;
namespace DynamicImageExample
{
public class DynamicImageMStudio71 : Page
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
WriteImage(ImageType.Png);
}
private void WriteImage(ImageType imageType)
{
if (imageType == null)
throw new ArgumentException("imageType");
Response.ClearContent();
Response.ContentType = imageType.ContentType;
using (WaveformGraph graph = new WaveformGraph())
using (XAxis xAxis = new XAxis())
using (YAxis yAxis = new YAxis())
using (WaveformPlot plot = new WaveformPlot(xAxis, yAxis))
{
graph.XAxes.Add(xAxis);
graph.YAxes.Add(yAxis);
graph.Plots.Add(plot);
graph.ToStream(Response.OutputStream, imageType);
}
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
}
}
}
Hope this helps.
- Elton