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 includeWrite()
andWriteLine()
: 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 includeReadLine()
, 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 theOnMouseEvent()
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
andStreamWriter
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.
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.