Situation
You want to know how to only calculate code with mouse clicks (and bypass the CalcBar() override method), or want to know how to read and write text files in MultiCharts .NET.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using System.Windows.Forms;             // Added
using System.IO;                        // Added

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), MouseEvents(true)]
    public class Example_MouseClicksMethods : IndicatorObject
    {
        string fileName = @"C:\Temp\MCnetMouseClickData.txt";

        public Example_MouseClicksMethods(object _ctx) : base(_ctx) { }

        protected override void CalcBar() { }

        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            if (arg.buttons == MouseButtons.Left)
                OnlyCalcWithMouseClick(arg.keys);
        }

        private void OnlyCalcWithMouseClick(Keys keyboardKey)
        {
            if (keyboardKey == Keys.Control)
            {
                using (StreamWriter writer = new StreamWriter(fileName, true))
                {
                    writer.WriteLine("{0} - Writing a message to the file.",
                        DateTime.Now.ToString("HH:mm:ss.fff"));
                }
            }
            else if (keyboardKey == Keys.Shift)
            {
                Output.Clear();

                Output.WriteLine("Contents of the '{0}' file:", fileName);

                using (StreamReader reader = new StreamReader(fileName))
                {
                    while (!reader.EndOfStream)
                    {
                        Output.WriteLine(reader.ReadLine());
                    }
                }
            }
        }
    }
}

Output of the programming example

The text file contains the following lines after a few mouse clicks with the Control key:

09:56:03.428 - Writing a message to the file.
09:56:06.913 - Writing a message to the file.
09:56:07.968 - Writing a message to the file.
09:56:11.789 - Writing a message to the file.
09:56:12.744 - Writing a message to the file.
09:56:13.607 - Writing a message to the file.

A left mouse click with Shift generates the following output in the Output Window:

Contents of the 'C:\Temp\MCnetMouseClickData.txt' file:
09:56:03.428 - Writing a message to the file.
09:56:06.913 - Writing a message to the file.
09:56:07.968 - Writing a message to the file.
09:56:11.789 - Writing a message to the file.
09:56:12.744 - Writing a message to the file.
09:56:13.607 - Writing a message to the file.

Processing mouse clicks in MultiCharts .NET

Mouse clicks allow for different ways to control MultiCharts .NET, such as turning a script on or off, only calculating a script due to mouse clicks, or submitting market orders with mouse clicks.

Working with mouse clicks requires the following:

  • The MouseEvents attribute needs to be set to true;
  • The OnMouseEvent() method, that programmatically process mouse clicks (see PowerLanguage .NET Help, n.d.), needs to be implemented.

See working with mouse events and combining mouse clicks with keyboard keys to learn more.

The OnMouseEvent() method can call other methods, causing these methods to be only executed with mouse clicks on the price chart. This enables efficient indicator and trading strategy calculations, since some programming code does not need to be executed with every price update. An example of this is writing and reading text files.

Conveniently reading and writing text files in C#

Reading from and writing to a file is done with a stream in the .NET framework (Stellman & Greene, 2010). Two classes, both from the System.IO namespace, take care of the details to make reading and writing text files in C# convenient (Dorman, 2010; Stellman & Greene, 2010):

  • The StreamWriter class creates and manages a stream for writing bytes to a file. It methods include Write() and WriteLine(): both write a string to a file, but the latter does so with a line break.
  • The StreamReader class reads from a text file. It methods include ReadLine(), a method that reads a line of characters as a string followed by a line feed (\n), carriage return (\r), or carriage return-line feed (\r\n).

Both are used in the example: writing to a text file is triggered by a left mouse click and the Control key, while a left click with Shift reads the text file and displays it in the Output Window.

MultiCharts .NET programming example

The example begins with adding two namespaces:

using System.Windows.Forms;             // Added
using System.IO;                        // Added

Adding these namespaces makes referencing their components easier later on. The System.Windows.Forms namespace contains the Keys and MouseButtons enumerations, while the System.IO namespace contains the StreamWriter and StreamReader classes.

Setting MultiCharts .NET attributes and variables

Then two MultiCharts .NET attributes are set:

[SameAsSymbol(true), MouseEvents(true)]

Setting SameAsSymbol to true plots the indicator on the main price chart, and MouseEvents set to true enables the processing of mouse clicks.

Next a string variable is declared and initialised:

string fileName = @"C:\Temp\MCnetMouseClickData.txt";

The fileName variable contains the text file location to read from and write to. With the preceding @ character C# treats it as a literal string, without escape characters normally triggered by \ (Stellman & Greene, 2010).

Processing mouse clicks in MultiCharts .NET

The OnMouseEvent() method is the next part of the example:

protected override void CalcBar() { }

protected override void OnMouseEvent(MouseClickArgs arg)
{
    if (arg.buttons == MouseButtons.Left)
        OnlyCalcWithMouseClick(arg.keys);
}

The arg variable, which contains the MouseClickArgs struct data with mouse click information (see PowerLanguage .NET Help, n.d.), is used here in an if statement to evaluate whether the mouse click on the chart was a left click (MouseButtons.Left).

When that evaluates to true, the OnlyCalcWithMouseClick() method is called with the arg.keys enumerator as an argument.

By the way, even though the CalcBar() override method is empty here (line 17), it is still implemented because this method is marked abstract in the CStudyAbstract base class, which requires overriding this method in a concrete (non-abstract) derived class (Dorman, 2010).

Only calculate a MultiCharts .NET method with mouse clicks

This OnlyCalcWithMouseClick() method is implemented as follows:

private void OnlyCalcWithMouseClick(Keys keyboardKey)
{
    if (keyboardKey == Keys.Control)
    {
        using (StreamWriter writer = new StreamWriter(fileName, true))
        {
            writer.WriteLine("{0} - Writing a message to the file.",
                DateTime.Now.ToString("HH:mm:ss.fff"));
        }
    }
    else if (keyboardKey == Keys.Shift)
    {
        Output.Clear();

        Output.WriteLine("Contents of the '{0}' file:", fileName);

        using (StreamReader reader = new StreamReader(fileName))
        {
            while (!reader.EndOfStream)
            {
                Output.WriteLine(reader.ReadLine());
            }
        }
    }
}

The keyboardKey variable, which holds an enumerator from the Keys enumeration, is evaluated here to determine which of the two actions should be performed: writing to the text file (lines 27-34) or reading from the text file (lines 35-48).

Writing data to a text file in MultiCharts .NET

The if statement evaluates whether keyboardKey equals Keys.Control:

if (keyboardKey == Keys.Control)
{
    using (StreamWriter writer = new StreamWriter(fileName, true))
    {
        writer.WriteLine("{0} - Writing a message to the file.",
            DateTime.Now.ToString("HH:mm:ss.fff"));
    }
}

The body of this if statement consists out of a using statement (lines 29-33) that automatically closes the stream when the statements inside its braces ({ and }) are executed (Stellman & Greene, 2010). This is a different type of using statement from those used with namespaces (lines 1-6).

Streams created in a using statement are automatically closed when this code block ends. This is because using automatically calls the stream’s Dispose() method as soon as the code block is completed (Stellman & Greene, 2010). This prevents the common error of not closing the stream properly.

A using statement is always followed by an object declaration (Stellman & Greene, 2010). Here a StreamWriter object is declared (line 29): the first argument of the constructor sets the filename, which will be created if it does not exist yet (Microsoft Developer Network [MSDN] a, n.d.), while the second (a Boolean variable) turns appending to a file on (true).

In the using code block (lines 31-32) the WriteLine() method writes to the text file. In the method a string argument is passed, formatted with a string substitution parameter of the current computer DateTime to a string.

Reading the contents of a text file in MultiCharts .NET

The second part of the OnlyCalcWithMouseClick() method is the else-if statement:

else if (keyboardKey == Keys.Shift)
{
    Output.Clear();

    Output.WriteLine("Contents of the '{0}' file:", fileName);

    using (StreamReader reader = new StreamReader(fileName))
    {
        while (!reader.EndOfStream)
        {
            Output.WriteLine(reader.ReadLine());
        }
    }
}

First the PowerLanguage .NET Editor Output Window is cleared by calling the Output.Clear() method, followed by printing a general statement (including the fileName variable) with the Output.WriteLine() method (line 39).

The using statement reads a text file with a StreamReader object, with its constructor set to the fileName variable. The while loop uses the logical not operator (!) to iterate as long as the EndOfStream property is false, which it is as long as the current stream position is not the end of the stream (see MSDN b, n.d.).

In the while loop the string returned by the ReadLine() method is outputted to the Output Window, one line at a time, until the whole text file is outputted.

Key points

  • Working with mouse events requires adding the MouseEvents attribute and implementing the OnMouseEvent() method;
  • Methods of a script can be calculated independently from price updates by calling these in the OnMouseEvent() method;
  • Reading and writing text files can be done with the StreamReader and StreamWriter classes, respectively;
  • Streams created in a using statement are automatically disposed of when the code block has run, which ensures that the stream is always closed.
References

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN (USA): Sams/Pearson Education.

Microsoft Developer Network [MSDN] a (n.d.). StreamWriter Constructor (String, Boolean). Retrieved on August 24, 2014, from http://msdn.microsoft.com/en-us/library/36b035cb%28v=vs.110%29.aspx

MSDN b (n.d.). StreamReader.EndOfStream property. Retrieved on August 24, 2014, from http://msdn.microsoft.com/en-us/library/system.io.streamreader.endofstream%28v=vs.110%29.aspx

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm

Stellman, A. & Greene, J. (2010). Head First C#: A Brain-Friendly Guide (2nd edition). Sebastopol, CA: O’Reilly Media.

Visit programming tutorials for more helpful coding articles.