Showing posts with label Winforms. Show all posts
Showing posts with label Winforms. Show all posts

Sunday, May 24, 2015

C# Winform: Build a R script editor using ScintillaNET

In one of my projects, I was required to create an R editor and scripting interface that communicate between winform and R script interpreter. Part of the task is to create an R editor in C# winform. After some search, I found ScintillaNET. The way to use ScintillaNET in C# winform is pretty straightforward, either download its source from github or the binary from nuget. Drag a copy of the Scintilla into the toolbox of VS IDE and drag a copy of it from toolbox to your winform UI.

The next step is to customize ScintillaNET for R syntax highlighting, auto complete and so on. While earlier version of ScintillaNET does not have R Lexer, the current version downloaded (3.3.0) contains a very easy way for R syntax highlighting and auto-complete. Below is the Source codes (Assuming I put the code in a winform named FrmDummy, and my Scintilla editor component I put in the form is named "txtScript"):


    public partial class FrmDummy : Form
    {
 private List<string> Keywords1 = null;
        private List<string> Keywords2 = null;
        private string AutoCompleteKeywords = null;
        
        public FrmDummy()
        {
            InitializeComponent();

            PrepareKeywords();

            ConfigureRScriptSyntaxHighlight();
            ConfigureRScriptAutoFolding();
            ConifugreRScriptAutoComplete();
   
     txtScript.Text=@"#Some dummy R codes
  print('Hello World')
  x <- c('Hello World', 'Hello World2')";
        }
  
        private void PrepareKeywords()
        {
            Keywords1 = @"commandArgs detach length dev.off stop lm library predict lmer 
            plot print display anova read.table read.csv complete.cases dim attach as.numeric seq max 
            min data.frame lines curve as.integer levels nlevels ceiling sqrt ranef order
            AIC summary str head png tryCatch par mfrow interaction.plot qqnorm qqline".Split(new char[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToList();

            Keywords2 = @"TRUE FALSE if else for while in break continue function".Split(new char[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToList();

            List<string> keywords = Keywords1.ToList();
            keywords.AddRange(Keywords2);
            keywords.Sort();

            AutoCompleteKeywords = string.Join(" ", keywords);
        }

        private void ConfigureRScriptSyntaxHighlight()
        {

            txtScript.StyleResetDefault();
            txtScript.Styles[Style.Default].Font = "Consolas";
            txtScript.Styles[Style.Default].Size = 10;
            txtScript.StyleClearAll();

            txtScript.Styles[Style.R.Default].ForeColor = Color.Brown;
            txtScript.Styles[Style.R.Comment].ForeColor = Color.FromArgb(0, 128, 0); // Green
            txtScript.Styles[Style.R.Number].ForeColor = Color.Olive;
            txtScript.Styles[Style.R.BaseKWord].ForeColor = Color.Purple;
            txtScript.Styles[Style.R.Identifier].ForeColor = Color.Black;
            txtScript.Styles[Style.R.String].ForeColor = Color.FromArgb(163, 21, 21); // Red
            txtScript.Styles[Style.R.KWord].ForeColor = Color.Blue;
            txtScript.Styles[Style.R.OtherKWord].ForeColor = Color.Blue;
            txtScript.Styles[Style.R.String2].ForeColor = Color.OrangeRed;
            txtScript.Styles[Style.R.Operator].ForeColor = Color.Purple;


            txtScript.Lexer = Lexer.R;

            txtScript.SetKeywords(0, string.Join(" ", Keywords1));
            txtScript.SetKeywords(1, string.Join(" ", Keywords2));
        }

        private void ConifugreRScriptAutoComplete()
        {
            txtScript.CharAdded += scintilla_CharAdded;
        }

        private void scintilla_CharAdded(object sender, CharAddedEventArgs e)
        {
            Scintilla scintilla = txtScript;

            // Find the word start
            var currentPos = scintilla.CurrentPosition;
            var wordStartPos = scintilla.WordStartPosition(currentPos, true);

            // Display the autocompletion list
            var lenEntered = currentPos - wordStartPos;
            if (lenEntered > 0)
            {
                scintilla.AutoCShow(lenEntered, AutoCompleteKeywords);
            }
        }

        private void ConfigureRScriptAutoFolding()
        {
            Scintilla scintilla = txtScript;

            // Instruct the lexer to calculate folding
            scintilla.SetProperty("fold", "1");
            scintilla.SetProperty("fold.compact", "1");

            // Configure a margin to display folding symbols
            scintilla.Margins[2].Type = MarginType.Symbol;
            scintilla.Margins[2].Mask = Marker.MaskFolders;
            scintilla.Margins[2].Sensitive = true;
            scintilla.Margins[2].Width = 20;

            // Set colors for all folding markers
            for (int i = 25; i <= 31; i++)
            {
                scintilla.Markers[i].SetForeColor(SystemColors.ControlLightLight);
                scintilla.Markers[i].SetBackColor(SystemColors.ControlDark);
            }

            // Configure folding markers with respective symbols
            scintilla.Markers[Marker.Folder].Symbol = MarkerSymbol.BoxPlus;
            scintilla.Markers[Marker.FolderOpen].Symbol = MarkerSymbol.BoxMinus;
            scintilla.Markers[Marker.FolderEnd].Symbol = MarkerSymbol.BoxPlusConnected;
            scintilla.Markers[Marker.FolderMidTail].Symbol = MarkerSymbol.TCorner;
            scintilla.Markers[Marker.FolderOpenMid].Symbol = MarkerSymbol.BoxMinusConnected;
            scintilla.Markers[Marker.FolderSub].Symbol = MarkerSymbol.VLine;
            scintilla.Markers[Marker.FolderTail].Symbol = MarkerSymbol.LCorner;

            // Enable automatic folding
            scintilla.AutomaticFold = (AutomaticFold.Show | AutomaticFold.Click | AutomaticFold.Change);
        }
    }

To display the line number, one can set txtScript.Margins[0].Width=30

Saturday, December 13, 2014

Winforms: Read and display Arabic characters from a text file

Recently I was working on a program which i need to read in and display a text file containing arabic characters. The problem gave me quite a bit of a challenge initially, therefore i decide to share the lesson that i learned while figuring out how to do that.

Read the text file containing Arabic characters

The essence lies on how you sent the encoding in your StreamReader object which reads the text file content. Firstly let me list out what will not work:

1. Default encoding like "StreamReader reader = new StreamReader(filepath)" will not work, you will get messed up text displayed when it comes to arabic characters.
2. Unicode encoding like "StreamReader reader = new StreamReader(filepath, System.Text.Encoding.Unicode)" will not work, your program will hang possibly.
3. UTF Encoding like "StreamReader reader = new StreamReader(filepath, System.Text.Encoding.UTF8)" will not work, you will get messed up arabic characters. Sames goes for UTF32, UTF7

Now below is what will work:

StreamReader reader = new StreamReader(filepath, System.Text.Encoding.GetEncoding("Arabic")

Display the text file containing arabic characters in a Winform control

Ok at this point, you may get it to work perfectly. but if you still cannot display text correctly, one solution is to apply a "Arial Unicode MS" font to your Winform controls. Below is the instruction on how to do this:

1. Download a copy of the "Arial Unicode MS" (google it), and embed into your program's resource file (copy and paste it directly in the "Resources" tab after your open your project's property page). Let's say the name of the embeded resource is "Arial_Unicode_MS".
2. Create a singleton class FontManager, which will be used to apply the "Arial_Unicode_MS" to the Winform. the codes of the FontManager is shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Text;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace Lab001
{
    public class FontManager
    {
        private static FontManager mInstance = null;
        private static object mSyncObj = new object();

        public static FontManager Instance
        {
            get
            {
                if (mInstance == null)
                {
                    lock (mSyncObj)
                    {
                        mInstance = new FontManager();
                    }
                }
                return mInstance;
            }
        }

        [System.Runtime.InteropServices.DllImport("gdi32.dll")]

        private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont,
           IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts);

        private PrivateFontCollection MYpfc = new PrivateFontCollection();

        private FontManager()
        {

            try
            {
                unsafe
                {
                    fixed (byte* pFontData = Properties.Resources.Arial_Unicode_MS)
                    {
                        uint dummy = 0;
                        MYpfc.AddMemoryFont((IntPtr)pFontData, Properties.Resources.Arial_Unicode_MS.Length);
                        AddFontMemResourceEx((IntPtr)pFontData, (uint)Properties.Resources.Arial_Unicode_MS.Length, IntPtr.Zero, ref dummy);
                    }
                }
            }
            catch
            {

            }
        }

        public FontFamily UnicodeFontFamily
        {
            get
            {
                return MYpfc.Families[0];
            }
        }

        public FontFamily DefaultFontFamily
        {
            get
            {
                return UnicodeFontFamily;
            }
        }


        public void ApplyDefaultFont(Control control)
        {
            control.Font = new Font(DefaultFontFamily, control.Font.Size, control.Font.Style);
        }

        public void ApplyDefaultFont(Form frm)
        {
            foreach (Control c in frm.Controls)
            {
                ApplyDefaultFont(c);
            }
        }
    }
}

3. Now in your Winform's contructor, add in the following line immidiately after the "InitializeComponent();" line:

FontManager.Instance.ApplyDefaultFont(this);

4. In your project property page, click the "Build" tab and check the "Allow unsafe code" option.

Now build and run your application, you should be able to read and display the arabic characters in your text files.

Monday, August 5, 2013

Load local html file into the winform browser

string url = @"C:\temp.html";
url = url.Replace(@"\", @"/");
url = url.Replace(@" ", @"%20");
url = "file:///" + url;

webBrowser1.Navigate(url);

Thursday, July 18, 2013

Timely GUI update of progress for background worker process in .NET

Sometime when you are performing a very expensive process using a background working in .NET, for example processing records from the database one by one, you want the GUI to display update on the progress of the progress, typical code will look like to following:

BackgroundWorker worker=new BackgroundWorker();
worker.WorkerReportsProgress=true;

bool is_running=true;

int total_record_count=EmployeeDb.GetDbRecordCount(criteria)
worker.DoWork+=(s1, e1)=>
{
    EmployeeDb.DoAnalysis(criteria, (rec_index)=>
      {
           worker.ReportProgress(rec_index * 100 / total_record_count);
           return is_running;
      });
};
worker.ProgressChanged+=(s1, e1)=>
{
    progressBar1.Value=e1.ProgressPercentage;
};
worker.RunWorkerCompleted+=(s1, e1)=>
{
   MessageBox.Show("Done!");
};

worker.RunWorkerAsync();

The problem with the above method is that we may not know how frequently the worker.ReportProgress() is called, and within what time interval two consecutive worker.ReportProgress() are called. This can be bad for two reason: firstly, if the time interval between two consecutive calls to worker.ReportProgress() is very short, the GUI may not get updated since it a low priority task; secondly, two many calls to worker.ReportProgress() wasting CPU cycles while present no real difference to the user.

My solution at the moment is to timely call worker.ReportProgress() instead, e.g. by every 1 seconds. This is very easily done. the following shows the timely call procedure (the change is in the bold highlight):

BackgroundWorker worker=new BackgroundWorker();
worker.WorkerReportsProgress=true;

bool is_running=true;

DateTime current_time=DateTime.Now;
DateTime report_time=DateTime.Now;
TimeSpan ts;

int total_record_count=EmployeeDb.GetDbRecordCount(criteria)
worker.DoWork+=(s1, e1)=>
{
    EmployeeDb.DoAnalysis(criteria, (rec_index)=>
      {
           current_time=DateTime.Now;
           ts=current_time - report_time;
           if(ts.TotalMilliSeconds > 1000)
           {
                  report_time=current_time;
                  worker.ReportProgress(rec_index * 100 / total_record_count);
           }
           return is_running;
      });
};
worker.ProgressChanged+=(s1, e1)=>
{
    progressBar1.Value=e1.ProgressPercentage;
};
worker.RunWorkerCompleted+=(s1, e1)=>
{
   MessageBox.Show("Done!");
};

worker.RunWorkerAsync();



Wednesday, July 17, 2013

Hide .NET Winform application in tray when minimized

First drop a NotifyIcon onto the winform and name it "notifyIcon", add a mouse double click event handler for the notifyIcon to the winform as shown below:

private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
 ShowApp();
}

private void ShowApp()
{
 this.WindowState = FormWindowState.Maximized;
 this.ShowInTaskbar = true;
 this.Show();
}
This will ensure that when the notifyIcon in the system tray is clicked, the application will be shown. Next add a resize event handler to the winform as shown below:

private void FrmCrawler_Resize(object sender, EventArgs e)
{
 if (FormWindowState.Minimized == this.WindowState)
 {
  this.ShowInTaskbar = false;
  this.Hide();
 }
}
This is triggered when user click the minimize icon on the winform app, which in turns hide the app.

Tuesday, July 16, 2013

Add auto complete function for a textbox in your winform

auto complete is useful in a winform to, for example, help user to save time for type things such as username, to add auto listing to a textbox in a winform is very easy, below is an example code added to the Load delegate method in a winform:


            List<string> usernames = AccountManager.Instance.Usernames;
            if (usernames.Count > 0)
            {
                var source = new AutoCompleteStringCollection();
                foreach (string username in usernames)
                {
                    source.Add(username);
                }

                txtUsername.AutoCompleteCustomSource = source;
                txtUsername.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                txtUsername.AutoCompleteSource = AutoCompleteSource.CustomSource;
            }

Increase 32 bit .NET program memory limit beyond 2 GB

Normally a 32 bit .NET program can only use memory up to 2GB even when you have much more memory on your computer. There are several ways to solve this problem:

1. Cloud: effective and best solution except when porting your application to cloud will prove too much effort

2. Increase program memory limit: for a win32 C# program, it is possible to increase the memory limit to 3GB using guide line from (http://blogs.msdn.com/b/calvin_hsia/archive/2010/09/27/10068359.aspx),

3. Change the 32bit program to 64bit program and follow guideline from
http://blogs.msdn.com/b/calvin_hsia/archive/2010/09/27/10068359.aspx
which shows how you extend the memory limit to 64bit

For a program that handles very large data, option 1 seems to be the only reasonable option.

Surface Map in C# winforms using ChartDirector

The following code shows how to plot a surface map (similar to the one in MATLab) in C# winform using ChartDirector (The data to be displayed is stored in a matrix):

private void UpdatePrimitiveFitnessSurfaceMapByData(WinChartViewer viewer, List<double[]> matrix)
        {
            int dim1 = matrix.Count;
            if (dim1 == 0) return;
            int dim2 = matrix[0].Length;

            // The x and y coordinates of the grid
            double[] dataX = new double[dim1];
            double[] dataY = new double[dim2];

            for (int i = 0; i < dim1; ++i)
            {
                dataX[i] = i;
            }
            for (int i = 0; i < dim2; ++i)
            {
                dataY[i] = i;
            }

            double[] dataZ = new double[(dataX.Length) * (dataY.Length)];
            for (int i = 0; i < dim1; ++i)
            {
                for (int j = 0; j < dim2; ++j)
                {
                    dataZ[i * dim2 + j] = matrix[i][j];
                }
            }

            // Create a SurfaceChart object of size 720 x 600 pixels
            SurfaceChart c = new SurfaceChart(720, 600);

            // Add a title to the chart using 20 points Times New Roman Italic font
            c.addTitle("Variable Fitness Distribution", "Times New Roman Italic", 20);

            // Set the center of the plot region at (350, 280), and set width x depth
            // x height to 360 x 360 x 270 pixels
            c.setPlotRegion(350, 280, 360, 360, 270);

            // Set the data to use to plot the chart
            c.setData(dataX, dataY, dataZ);

            // Spline interpolate data to a 80 x 80 grid for a smooth surface
            c.setInterpolation(80, 80);

            // Add a color axis (the legend) in which the left center is anchored at
            // (645, 270). Set the length to 200 pixels and the labels on the right
            // side.
            c.setColorAxis(645, 270, Chart.Left, 200, Chart.Right);

            // Set the x, y and z axis titles using 10 points Arial Bold font
            c.xAxis().setTitle("Generation", "Arial Bold", 10);
            c.yAxis().setTitle("Terminal Variable Index", "Arial Bold", 10);
            c.zAxis().setTitle("Variable Fitness Distribution",
                "Arial Bold", 10);

            // Output the chart
            viewer.Chart = c;
        }

Wednesday, July 10, 2013

Create a uninstall link for a .Net application in the Start program folder in Windows platform

Normally when an application is installed in the windows platform, in its Start program folder, user always expects a uninstall link that user can click to uninstall the application. By default, though, the .Net Setup project in VS2010 does not create such a link automatically for the user when it packages the .Net application. However, this can be done easily. 

Step 1: Create and configure Setup project for the .Net Application
Create a setup project for the .Net application. This is straightforward.

After the Setup project is created and properly configured for the .Net application, right-click the setup project in the VS2010 IDE, and selects View->File System from the popup context menu. When the file system of the setup project is opened, double click "Application Folder" on the right panel. This will show the list of files to be in the program folder when the application is installed on the user's computer. 

Now look for a file named "Primary output from XXX (Active)" (where XXX refers to the name of the .Net application project), right-click and select "Create Shortcut to Primary output from XXX (Active)", this will creates a shortcut to the .net application software. renamed this shortcut to "Uninstall". 

Now right-click the "Uninstall" shortcut and selects "Properties Window", in the "Properties Window", enter "/u=[ProductCode]" for the "Arguments" property of the "Uninstall" shortcut. 

Next in the "User's Programs Menu", create a folder with the name of the .Net application project, let's say "XXX". Now cut and paste the "Uninstall" shortcut from the "Application Folder" to "User's Programs Menu/XXX" folder. With this step the configuration for the setup project is completed. But we need to also tells the .Net application that if it receives the "/u" arguments then it should perform uninstallation. This is done by adding codes to the .Net application project's Program.cs file.

Step 2: Modify Program.cs in .Net Application for unstallation
Open the Program.cs in the .Net application project, change the codes in the Main() to the following

        static void Main()
        {
            bool uninstalling = false;
            //uninstaller part of the code
            string[] arguments= Environment.GetCommandLineArgs();
            foreach(string argument in arguments)
            {
                 if(argument.Split('=')[0].ToLower() == "/u")
                 {
                     uninstalling = true;
                    string guid = argument.Split('=')[1];
                    string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
                    System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo(path + "\\msiexec.exe", "/i " + guid);
                    System.Diagnostics.Process.Start(si);
                    Application.Exit();
                 }
            }

            if (uninstalling == false)
            {
                //if it is not unstalling, then run the normal code for starting the .Net application, for example, the following
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new MainForm());
            }
        }

This completes the necessary details for creating the unistall link

Using Microsoft Agent in Windows 7

By default, Microsoft no longer supports Microsoft Agent in Windows 7. However, i managed to find the following open source alternative

http://doubleagent.sourceforge.net/

C# developer can ask the user to install this software to have the microsoft agents running on Window 7 and to have their winforms application invoke them. As this alternative is also based on ActiveX control, it is important to check the availability of the control on the user's computer within the coding to ensure that the application won't crash on the user's computer. To use this, declare the following variable in the winform:

private DoubleAgent.Control.Control msDoubleAgent = null;

In the winform's Load event, try to perform the initialization:

  try
            {
                msDoubleAgent=new DoubleAgent.Control.Control();
                msDoubleAgent.Characters.Load("Genie", Path.Combine(Application.StartupPath, "Genie.acs")));
}
            catch (Exception ex)
            {
                log.Error(ex.ToString());
            }


Now can define methods such as a the following that invokes the agent to speak or perform animation:

  public void ShowExplanation(string message)
        {
                try
                {
                    if (msDoubleAgent != null && msDoubleAgent.Characters["genie"] != null)
                    {
                        DoubleAgent.Control.Character agent = msDoubleAgent.Characters["genie"];
                        agent.Speak(message);
                    }
                    else
                    {
                        MessageBox.Show(message);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex.ToString());
                }
        }

 private void PlayAgentAnimation(string animation)
        {
                try
                {
                    if (msDoubleAgent != null && msDoubleAgent.Characters["genie"] != null)
                    {
                        DoubleAgent.Control.Character agent = msDoubleAgent.Characters["genie"];
                        agent.StopAll();
                        agent.Play(animation);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex.ToString());
                }
        }

Note that the above code will always be degradable (that is, if the microsoft agent or double agent does not install on the user's computer, the application software will still function correctly).

Friday, July 5, 2013

Create 3D Pie Chart in Winforms

This post shows how to create 3D Pie Chart in Winforms using ChartDirector (http://www.advsofteng.com/),

        private void CreatePieChart(WinChartViewer viewer, string title, double[] data, string[] data_labels)
        {
            int width = viewer.Width;
            int height = viewer.Height;

            PieChart c = new PieChart(width, height);


            c.setPieSize(width / 2, height / 2, System.Math.Max(System.Math.Min(width / 2 - 40, height / 2 - 40), 100));


            c.addTitle(title);

            c.set3D();

            c.setSectorStyle(Chart.RoundedEdgeShading, 0xffffff, 1);


            // Set the pie data and the pie labels

            c.setData(data, data_labels);
            // Output the chart
            viewer.Chart = c;
            viewer.ImageMap = c.getHTMLImageMap("clickable", "",
                "title='{label}: {value} ({percent}%)'");
        }

Create 3D Scatter Chart for Winform

There are some tutorial on CodeProject that shows how to create 3D scatter chart (e.g. the one frequently seen in MATLAB), but they are quite primitive. ChartDirector (http://www.advsofteng.com/) seems to offer an excellent solution for this. Below is the piece of code that adds a 3D scatter chart to a ChartDirector win chart viewer after it is added to a Winform:

public void Create3DScatterChart(WinChartViewer viewer, string title, List<Point> plot, int width, int height)
{
try
{
ThreeDScatterChart c = new ThreeDScatterChart(width, height);

c.addTitle(title, "Times New Roman Italic", 10);

c.setPlotRegion(width / 2 - 10, height / 2 - 15, width / 2, width / 2, height / 2 - 10);

c.setViewAngle(15, 30);

c.addLegend(width - 60, height - 180);

double[] xData=new double[plots.Count];
double[] yData=new double[plots.Count];
double[] zData=new double[plots.Count];
for(int i=0; i < plot.Count; ++i)
{
xData[i] = plot[i].X;
yData[i] = plot[i].Y;
zData[i] = plot[i].Z;
}

ThreeDScatterGroup g = c.addScatterGroup(xData, yData, zData, 
"Legend1",
ChartDirector.Chart.GlassSphere2Shape, 13, 
0xFF0000);
g.setLegendIcon(15, 15, 0xFF0000);

// Set the x, y and z axis titles using 10 points Arial Bold font
c.xAxis().setTitle("X", "Arial Bold", 10);
c.yAxis().setTitle("Y", "Arial Bold", 10);
c.zAxis().setTitle("Z", "Arial Bold", 10);

// Output the chart
viewer.Chart = c;


//include tool tip for the chart
viewer.ImageMap = c.getHTMLImageMap("clickable", "", "title='(X={x|p}, Y={y|p}, Z={z|p})'");
}
catch
{

}
}

To instead save the scatter 3d plot to a file, use the following code:

public void Create3DScatterChart(string filename, string title, List<Point> plot, int width, int height)
{
try
{
ThreeDScatterChart c = new ThreeDScatterChart(width, height);

c.addTitle(title, "Times New Roman Italic", 10);

c.setPlotRegion(width / 2 - 10, height / 2 - 15, width / 2, width / 2, height / 2 - 10);

c.setViewAngle(15, 30);

c.addLegend(width - 60, height - 180);

double[] xData=new double[plots.Count];
double[] yData=new double[plots.Count];
double[] zData=new double[plots.Count];
for(int i=0; i < plot.Count; ++i)
{
xData[i] = plot[i].X;
yData[i] = plot[i].Y;
zData[i] = plot[i].Z;
}

ThreeDScatterGroup g = c.addScatterGroup(xData, yData, zData, 
"Legend1",
ChartDirector.Chart.GlassSphere2Shape, 13, 
0xFF0000);
g.setLegendIcon(15, 15, 0xFF0000);

// Set the x, y and z axis titles using 10 points Arial Bold font
c.xAxis().setTitle("X", "Arial Bold", 10);
c.yAxis().setTitle("Y", "Arial Bold", 10);
c.zAxis().setTitle("Z", "Arial Bold", 10);

// Output the chart
using(Image img=c.makeImage())
  {
      img.Save(filename);
   }


}
catch
{

}
}

Monday, February 14, 2011

The designer could not be shown for this file because none of the classes within it can be designed

I encountered this bug in vs2008 winform C# programs after messing around with installing vs6, vs2005, vs2008 and vs2010 installation. the bug caused the winform not able to render itself during the design time and throws the following error message:


The designer could not be shown for this file because none of the classes within it can be designed




After doing much google search and found not working solution, it happens to me that maybe the .Net 3.5 version in my PC is corrupted. I therefore download the .net cleaning utility from
http://blogs.msdn.com/b/astebner/archive/2008/08/28/8904493.aspx
and after running the tool to clean .Net 3.5 from my computer and reinstalling the vs2008. everything works!