Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

I want to use measurement studio in ASP.net. I want to ask, how i can treat graph activex control as server side control?

Our application is basically web browser based. We want to show graphs of data in web browser using measurement studio. I want to ask how we can achieve this in asp.net without helpof client script?
0 Kudos
Message 1 of 7
(6,411 Views)
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
Message 2 of 7
(6,411 Views)
I suggested doing this with .aspx pages because it was easy, but after I posted this I realized that a custom HTTP handler, which is a better solution, isn't really any harder. For more information about HTTP handlers, see Creating HttpHandlers and Registering HttpHandlers.

For example, here's how to convert the last example above to an HTTP handler:

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 DynamicImageHandler : IHttpHandler
{
public bool IsReusable
{
get
{
return false;
}
}

public void ProcessRequest(HttpContext context)
{
WriteImage(context, ImageType.Png);
}

private static void WriteImage(HttpContext context, ImageType imageType)
{
if (context == null)
throw new ArgumentNullException("context");

if (imageType == null)
throw new ArgumentException("imageType");

HttpResponse response = context.Response;
response.ContentType = imageType.ContentType;
response.BufferOutput = false;

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);
}
}
}
}

You can then register the HTTP handler as described in the article linked above and reference it in the <img/> tag as mentioned in my previous post. The ideal solution would be ASP.NET server controls, but this is a good workaround with the ActiveX/Windows Forms controls.

- Elton
Message 3 of 7
(6,411 Views)
Elton,

The response is awesome!, I ported the Measurement studio 7 option to work with VB and ASP.NET. But in my application we need to display the data in the browser with minimal or no flickering. I am using java script and webservices to get the data to the browser with out doing a server side page refresh, so I already have the data in the browser that need to be plotted.

What is the best way to continually update the plot data in the browser? Is there a client side equivalent to the solution you explained.

Thanks a bunch in advance
0 Kudos
Message 4 of 7
(6,411 Views)
There was another post earlier today where someone asked a similar question, but it sounds like you're already implementing some of the suggestions that I made there.

I haven't tried these options yet, but off the top of my head ... one option might be to have a separate page that has the image, put that page in an iframe, then refreshing that inner page will just refresh the iframe portion of the page rather than the entire page. Another option might be to make a call to your web service, generate an image and cache it on t
he server (i.e., save it to a file or put it in the ASP.NET cache), and then return something to the client that will let you get back to the image (i.e., a path to the file or a parameter you can pass to a page or HTTP handler that will get the image out of the ASP.NET cache and send it to the client), then use script to update the image on the client.

I'm curious to hear what you end up with. Please give these options a shot and post a reply with how it worked out or if you came up with something else. Thanks.

- Elton
0 Kudos
Message 5 of 7
(6,411 Views)
Sir, the code you have given, worked fine for waveformgraph but it didn't worked for scatter graph. Can we implement solution on similar line for scatter graph?
Also on which graph controls this code works and on which it doesn't.
0 Kudos
Message 6 of 7
(6,411 Views)
Please see the response that was posted to the new thread about this. Thanks.

- Elton
0 Kudos
Message 7 of 7
(6,411 Views)