View Full Version : MouseMove event
cls71
06-03-2008, 04:56 AM
Greetings,
I am doing an indicator for displaying the mouse coordinates in MouseMove event.
The indicator calls the method "chart_MouseMove" when the mouse is moved but the text isn't updated.
Is there any way for calling to Plot method ?
Now the indicator works fine only when clickmouse or Alt+Tab windows or key press.
( I know that this doubt is beyond the scope of what you provide support for but I would be very grateful if you could help me ).
Thanks very much.
protectedoverridevoid OnBarUpdate()
{
if ((ChartControl != null) && (!_initMouseEvents))
{
this.ChartControl.ChartPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_ MouseMove);
_initMouseEvents = true;
}
}
publicoverridevoid Plot(Graphics graphics, Rectangle bounds, double min, double max)
{
_boundsChart = bounds;
_minChartPrice = min;
_maxChartPrice = max;
graphics.DrawString( "Y: " + _mouseOffset, fontTexto, brushTexto, 10, 280 );
}
privatevoid chart_MouseMove(object sender, MouseEventArgs e)
{
if (ChartControl != null)
{
double price1 = ConvertYtoPrice ( e.Y );
_mouseOffset = price1 ;
}
}
privatedouble ConvertYtoPrice (int i)
{
int _tickLength=0;
if (TickSize < 1)
_tickLength = TickSize.ToString ().Length-2;
double chartscale = Math.Abs (_maxChartPrice - _minChartPrice);
double boundAreaScale = _boundsChart.Bottom - _boundsChart.Y ;
double ratio = (double)(chartscale)/ boundAreaScale ;
double chartPrice = Math.Round ( (_minChartPrice ) + ((_boundsChart.Bottom -i) * ratio), _tickLength);
return chartPrice;
}
NinjaTrader_Dierk
06-03-2008, 05:03 AM
Sorry, but as you already figured this clearly is beyond the scope what we provide support for, since coding at that level easily could screw up NT if you don't know exactly what you are doing.
As last resort you could contact a certified NinjaScript consultant: http://www.ninjatrader.com/webnew/partners_onlinetrading_NinjaScript.htm
traderT
12-28-2009, 04:03 AM
Hi cls71
Did you manage to make any progress with your code. I am also trying to capture the mouse/crosshair location and use this within an indicator.
Basically my indicator is a drawing tool that can be used to measure the ticks between 2 points. The idea is to alt-click once at one point on the chart, then alt-click again on the 2nd point. A line should then appear between the two points as well as the distance between the two points.
What I am missing is the X and Y coordinates of the two alt-mouse clicks.
I have attached my code for you to have a look at and any suggestions/help would be much appreciated.
The sample pic shows what I am trying to achieve. Currently my code has the X and Y coordinates fillled in, but I would like to use what you have done, if it works, and use chart clicked coordinates in my code.
bukkan
12-28-2009, 04:44 AM
Hi cls71
Did you manage to make any progress with your code. I am also trying to capture the mouse/crosshair location and use this within an indicator.
Basically my indicator is a drawing tool that can be used to measure the ticks between 2 points. The idea is to alt-click once at one point on the chart, then alt-click again on the 2nd point. A line should then appear between the two points as well as the distance between the two points.
What I am missing is the X and Y coordinates of the two alt-mouse clicks.
I have attached my code for you to have a look at and any suggestions/help would be much appreciated.
The sample pic shows what I am trying to achieve. Currently my code has the X and Y coordinates fillled in, but I would like to use what you have done, if it works, and use chart clicked coordinates in my code.
havent look at the code, but basically you got to figure out the bar counts (of the two points). mouse position will only get you the pixel point. you have to calculate the bar count from those pixel points. once you figure out the bar count then its piece of cake.
http://www.ninjatrader-support2.com/vb/local_links.php?action=jump&catid=3&id=245
traderT
12-28-2009, 06:07 AM
Hi bukkan,
Thanks for the info, I see that converting the xpos to barcount is fairly straight forward, however I am a little stumped on how to do the ypos - how can I determine the ypos and then convert it to price?
As this is not always from a high to a low, I need to calc and convert the ypos too.
bukkan
12-28-2009, 06:16 AM
the said indi does not calculates the price scale as it is redundant for its need.
anyway, the bars itself contains the price value. isnt it.
like Close[barcount] will give you the closing price of that bar. now you got to calculate a range and then some more calculation beween the pixel pts (where the mouse was clicked) and you will find what you need.
traderT
12-28-2009, 06:51 AM
Thx again bukkan, will try and figure out how to do the range vertically. Have only just started programming this year, so this will be a challenge.
I see that cls71 has some code that converts Y to price so will try and modify that to suit my needs, if I can figure it out.
piersh
12-28-2009, 11:13 AM
NinjaTrader is broken wrt/ asynchronous events like this - it does not leave the Bars collection in a valid state outside the OnBarUpdate method, so you cannot access the historical values of the indicator or its Input.
however, here's what I have for bar & price:
#region Using declarations
using System;
using System.Diagnostics;
using System.Drawing;
using NinjaTrader.Gui.Chart;
#endregion
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
public class XYIndicator : Indicator
{
protected override void Initialize ()
{
}
void ChartControl_MouseMove (object sender, System.Windows.Forms.MouseEventArgs e)
{
double right = _chartBounds.Right - this.ChartControl.BarMarginRight - this.ChartControl.BarWidth - this.ChartControl.BarSpace / 2;
double bottom = _chartBounds.Bottom;
double x = right - e.X;
double y = bottom - e.Y;
int iBar = this.LastVisibleBar + (int) Math.Round (x / this.ChartControl.BarSpace);
double price = y * (_max - _min) / _chartBounds.Height;
/*
if (iBar < 0 || iBar >= this.Count)
return;
double barPrice = this [iBar];
Debug.WriteLine (x + "," + y + ", " + barPrice);
*/
Debug.WriteLine (iBar + "," + price);
//((IndicatorBase) this).DrawDot ("foo" + iBar, iBar, price, Color.Red);
}
public override void Plot (Graphics graphics, Rectangle bounds, double min, double max)
{
base.Plot (graphics, bounds, min, max);
_chartBounds = bounds;
_min = min;
_max = max;
}
public override void Dispose ()
{
base.Dispose ();
if (_chartControl != null)
_chartControl.ChartPanel.MouseMove -= new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
}
ChartControl _chartControl;
Rectangle _chartBounds;
double _min, _max;
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate ()
{
if (this.ChartControl != _chartControl)
{
if (_chartControl != null)
_chartControl.ChartPanel.MouseMove -= new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
_chartControl = this.ChartControl;
if (_chartControl != null)
_chartControl.ChartPanel.MouseMove += new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
}
}
}
}
#region NinjaScript generated code. Neither change nor remove.
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
public partial class Indicator : IndicatorBase
{
private XYIndicator [] cacheXYIndicator = null;
private static XYIndicator checkXYIndicator = new XYIndicator ();
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public XYIndicator XYIndicator ()
{
return XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public XYIndicator XYIndicator (Data.IDataSeries input)
{
if (cacheXYIndicator != null)
for (int idx = 0; idx < cacheXYIndicator.Length; idx++)
if (cacheXYIndicator [idx].EqualsInput (input))
return cacheXYIndicator [idx];
XYIndicator indicator = new XYIndicator ();
indicator.BarsRequired = BarsRequired;
indicator.CalculateOnBarClose = CalculateOnBarClose;
indicator.Input = input;
indicator.SetUp ();
XYIndicator [] tmp = new XYIndicator [cacheXYIndicator == null ? 1 : cacheXYIndicator.Length + 1];
if (cacheXYIndicator != null)
cacheXYIndicator.CopyTo (tmp, 0);
tmp [tmp.Length - 1] = indicator;
cacheXYIndicator = tmp;
Indicators.Add (indicator);
return indicator;
}
}
}
// This namespace holds all market analyzer column definitions and is required. Do not change it.
namespace NinjaTrader.MarketAnalyzer
{
public partial class Column : ColumnBase
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition ("Indicator")]
public Indicator.XYIndicator XYIndicator ()
{
return _indicator.XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public Indicator.XYIndicator XYIndicator (Data.IDataSeries input)
{
return _indicator.XYIndicator (input);
}
}
}
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition ("Indicator")]
public Indicator.XYIndicator XYIndicator ()
{
return _indicator.XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public Indicator.XYIndicator XYIndicator (Data.IDataSeries input)
{
if (InInitialize && input == null)
throw new ArgumentException ("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
return _indicator.XYIndicator (input);
}
}
}
#endregion
traderT
12-28-2009, 01:38 PM
Hi Piersh, thanks for the info. One thing that I am concerned about is the fact that the "double price" is not correct when I print it to the Output window. Is this working a designed or is the maths wrong?
piersh
12-28-2009, 02:01 PM
Hi Piersh, thanks for the info. One thing that I am concerned about is the fact that the "double price" is not correct when I print it to the Output window. Is this working a designed or is the maths wrong?
sorry, that line should be
double price = _min + y * (_max - _min) / _chartBounds.Height;
traderT
12-28-2009, 02:09 PM
I just added price to _min and it come out right as well, but your way is better - thanks again.
traderT
12-28-2009, 02:53 PM
Is there a way to do the calculations only on a mouse up, rather than using mousemove? Or should I continue to use mousemove and just grab the x and y coordinates on a mouseup?
piersh
12-28-2009, 02:56 PM
Is there a way to do the calculations only on a mouse up, rather than using mousemove? Or should I continue to use mousemove and just grab the x and y coordinates on a mouseup?
sure, the math is the same. just listen on the MouseUp event instead...
Mindset
12-29-2009, 01:28 AM
I modified your great code Bukkan just so that it switches on and off effectively.
Unfortunately this code breaks in NT7 and I can't work out why - I have the same problem with another indicator- it works on a single chart but if you add another chart on the same panel the barclick returns the wrong number !!
Edit - the text still appears btw but it is shifted approx 2 bars to the left
If someone could help me with this I would be immensely grateful as it's unsupported.
bukkan
12-29-2009, 05:29 AM
I modified your great code Bukkan just so that it switches on and off effectively.
Unfortunately this code breaks in NT7 and I can't work out why - I have the same problem with another indicator- it works on a single chart but if you add another chart on the same panel the barclick returns the wrong number !!
Edit - the text still appears btw but it is shifted approx 2 bars to the left
If someone could help me with this I would be immensely grateful as it's unsupported.
thanks mindset.
traderT
12-30-2009, 05:58 AM
Piersh,
Code works well with MouseUp and the coordinates are displayed in the Output window successfully using the Print statement.
I have tried to add the code (highlighted in bold) to the use these coordinates to draw a line between the clicked on areas, but this does not work - I get a "Ninja has detected a problem ..." error when I click. I have also tried to replace X and Y with static values and this also generates the same error. Do I have my drawline in the right place, Am I doing something stupid? Any suggestions would be most appreciated.
void ChartControl_MouseMove (object sender, System.Windows.Forms.MouseEventArgs e)
{
eventCount ++;
double right = _chartBounds.Right - this.ChartControl.BarMarginRight - this.ChartControl.BarWidth - this.ChartControl.BarSpace / 2;
double bottom = _chartBounds.Bottom;
double x = right - e.X;
double y = bottom - e.Y;
int iBar = this.LastVisibleBar + (int) Math.Round (x / this.ChartControl.BarSpace);
double price = _min + y * (_max - _min) / _chartBounds.Height;
if(eventCount == 1)
{
x1 = iBar;
y1 = price; // y1-axis;
}
else if(eventCount == 2)
{
x2 = iBar;
y2 = price; // y2-axis;
eventCount = 0;
}
profitLine = Math.Max(y1, y2) - Math.Min(y1, y2);
midPoint = Math.Min(y1, y2) + profitLine /2;
string str = (profitLine * 10000).ToString("f0");
Print(y1 + "::" + x1 + " , " + y2 + "::" + x2);
if(Math.Min(y1,y2) > 0)
{
DrawLine("tag" + y1, 10, y1, 5, y2, Color.LimeGreen,DashStyle.Solid, 2);
// DrawLine("tag" + y1, 10, 1.5090, 5, 1.4456, Color.LimeGreen,DashStyle.Solid, 2);
// DrawText("tag2", str, 10, midPoint, Color.Black);
}
}
piersh
12-30-2009, 11:42 AM
I get a "Ninja has detected a problem ..." error when I click. I have also tried to replace X and Y with static values and this also generates the same error. Do I have my drawline in the right place, Am I doing something stupid?
no, i got the same error:
XYIndicator.DrawDot: bar out of valid range 0 through -1, was 75.
i think this is because NT leaves the Bars collection in an invalid state. i've poked around in the debugger, but everything throws exceptions during mouse events.
there's a workaround, however.
declare the following in your Indicator's class:
delegate void Action ();
Queue<Action> _rgPending = new Queue<Action> ();
then add pending operations to the queue in your ChartControl_MouseXXXX event handler. don't forget to refresh the control:
_rgPending.Enqueue (
delegate () {
this.DrawDot ("foo" + iBar, iBar, price, Color.Red);
}
);
this.ChartControl.Refresh ();
then, in Plot(), do the following:
foreach (Action pending in _rgPending)
pending ();
then you can waste a few minutes drawing silly lines on your charts ;-) like this:
traderT
12-30-2009, 12:26 PM
Found another way, not sure how good it will be, but it seems to work using a custom event (basically, wait for ALT to be pressed then do drawing thing)
if(((Control.ModifierKeys & Keys.Alt) == Keys.Alt))
{
TriggerCustomEvent(new CustomEvent(MyCustomHandler), e);
My only problem now is getting xx1 and xx2 to work properly, seems to convert from double to int32 and give a result of 0, no idea why yet.
Anyway, the indicator below draws a line between 2 alt clicked points on the vertical access and tells you the points/distance. Tradestation has this tool, but NT doesn't.
#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
using System.Windows.Forms;
#endregion
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
public class XYIndicator : Indicator
{
#region Variables
// Wizard generated variables
private int init1 = 1; // Default setting for Init1
private int init2 = 1; // Default setting for Init2
private bool _init = false;
private bool click = false;
private double _mouseOffset = 0;
private int eventCount = 0;
private double x1 = 0;
private double y1 = 0;
private double x2 = 0;
private double y2 = 0;
private int xx1 = 0;
private int xx2 = 0;
private double midPoint = 0;
private double profitLine = 0;
private string strProfitLine = "";
private string str = "";
private Font strFont;
// private double _mouseOffset = 0;
// private double _mouseOffset = 0;
// User defined variables (add any user defined variables below)
#endregion
protected override void Initialize ()
{
strFont = new Font("Arial", 20);
CalculateOnBarClose = false;
PaintPriceMarkers = false;
Overlay = true;
PriceTypeSupported = false;
PlotsConfigurable = false;
}
void ChartControl_MouseMove (object sender, System.Windows.Forms.MouseEventArgs e)
{
eventCount ++;
double right = _chartBounds.Right - this.ChartControl.BarMarginRight - this.ChartControl.BarWidth - this.ChartControl.BarSpace / 2;
double bottom = _chartBounds.Bottom;
double x = right - e.X;
double y = bottom - e.Y;
int iBar = this.LastVisibleBar + (int) Math.Round (x / this.ChartControl.BarSpace);
double price = _min + y * (_max - _min) / _chartBounds.Height;
if(eventCount == 1)
{
x1 = iBar;
y1 = price; // y1-axis;
}
else if(eventCount == 2)
{
x2 = iBar;
y2 = price; // y2-axis;
eventCount = 0;
}
profitLine = Math.Max(y1, y2) - Math.Min(y1, y2);
midPoint = Math.Min(y1, y2) + profitLine /2;
string str = (profitLine * 1000).ToString("f0");
strProfitLine = str;
int xx1 = Convert.ToInt32(x1);
int xx2 = Convert.ToInt32(x2);
//Print(y1 + "::" + x1 + " , " + y2 + "::" + x2);
if(Math.Min(y1,y2) > 0)
{
if(((Control.ModifierKeys & Keys.Alt) == Keys.Alt))
{
TriggerCustomEvent(new CustomEvent(MyCustomHandler), e);
}
}
}
private void MyCustomHandler(object state)
{
// Print(midPoint + " : " + strProfitLine + " : " + x1 + " : " + x2 );
DrawLine("tag1", xx2, y2, xx1, y1, Color.DarkGreen,DashStyle.Solid, 2);
DrawText("tag3", strProfitLine, 2, midPoint, Color.Black, new Font("ArialBold", 20), StringAlignment.Center, Color.Transparent, Color.Transparent, 10 );
}
public override void Plot (Graphics graphics, Rectangle bounds, double min, double max)
{
base.Plot (graphics, bounds, min, max);
_chartBounds = bounds;
_min = min;
_max = max;
}
public override void Dispose ()
{
base.Dispose ();
if (_chartControl != null)
_chartControl.ChartPanel.MouseUp -= new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
}
ChartControl _chartControl;
Rectangle _chartBounds;
double _min, _max;
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate ()
{
if (this.ChartControl != _chartControl)
{
if (_chartControl != null)
_chartControl.ChartPanel.MouseUp -= new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
_chartControl = this.ChartControl;
if (_chartControl != null)
_chartControl.ChartPanel.MouseUp += new System.Windows.Forms.MouseEventHandler (ChartControl_MouseMove);
}
}
}
}
#region NinjaScript generated code. Neither change nor remove.
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
public partial class Indicator : IndicatorBase
{
private XYIndicator [] cacheXYIndicator = null;
private static XYIndicator checkXYIndicator = new XYIndicator ();
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public XYIndicator XYIndicator ()
{
return XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public XYIndicator XYIndicator (Data.IDataSeries input)
{
if (cacheXYIndicator != null)
for (int idx = 0; idx < cacheXYIndicator.Length; idx++)
if (cacheXYIndicator [idx].EqualsInput (input))
return cacheXYIndicator [idx];
XYIndicator indicator = new XYIndicator ();
indicator.BarsRequired = BarsRequired;
indicator.CalculateOnBarClose = CalculateOnBarClose;
indicator.Input = input;
indicator.SetUp ();
XYIndicator [] tmp = new XYIndicator [cacheXYIndicator == null ? 1 : cacheXYIndicator.Length + 1];
if (cacheXYIndicator != null)
cacheXYIndicator.CopyTo (tmp, 0);
tmp [tmp.Length - 1] = indicator;
cacheXYIndicator = tmp;
Indicators.Add (indicator);
return indicator;
}
}
}
// This namespace holds all market analyzer column definitions and is required. Do not change it.
namespace NinjaTrader.MarketAnalyzer
{
public partial class Column : ColumnBase
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition ("Indicator")]
public Indicator.XYIndicator XYIndicator ()
{
return _indicator.XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public Indicator.XYIndicator XYIndicator (Data.IDataSeries input)
{
return _indicator.XYIndicator (input);
}
}
}
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition ("Indicator")]
public Indicator.XYIndicator XYIndicator ()
{
return _indicator.XYIndicator (Input);
}
/// <summary>
/// Enter the description of your new custom indicator here
/// </summary>
/// <returns></returns>
public Indicator.XYIndicator XYIndicator (Data.IDataSeries input)
{
if (InInitialize && input == null)
throw new ArgumentException ("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");
return _indicator.XYIndicator (input);
}
}
}
#endregion
piersh
12-30-2009, 12:44 PM
nice. yeah TriggerCustomEvent is the way to go...
piersh
12-30-2009, 11:34 PM
ok, here's what i have.
Alt+right-click-drag to draw lines:
traderT
12-31-2009, 02:19 AM
Now you're just showing off ;-)
Very good, will have a look at the code shortly and see if I can add an instrument modifier to convert the pips for different instruments as it does decimels for forex.
Thanks again for the help. Attached is my current implementation.
Mindset
01-11-2010, 04:19 AM
Piersh - any idea how to get your code to work correctly on NT7 with second chart on panel.
Ps works fine on a single lone chart
Mindset
01-16-2010, 11:49 AM
Well I have played with various things to sort this out but so far it has evaded me.
Looks simple using the new GetXByBarIdx(BarsArray[0],idx). But for the life of me I can't get m.X to convert to an idx.
I have spent so long looking at it now I am useless.
zweistein
01-16-2010, 01:58 PM
Hello MindSet,
the Y value of the mouse can be in Panel 1 or Panel 2, so there is the ChartPanel[] Panel Property of ChartControl to find out.
I havnt' t done yet and please tell me your approach.
the X coordinate is easy:
I do:
private void MouseClick(object state) {
System.Windows.Forms.MouseEventArgs e = ( System.Windows.Forms.MouseEventArgs) state;
MethodInfo mi=this.ChartControl.GetType().GetMethod("GetTimeByX",BindingFlags.Instance|BindingFlags.NonPublic|Bind ingFlags.Public);
DateTime t=(DateTime) mi.Invoke(this.ChartControl,new object[]{e.X});
Print("Mouse("+e.X.ToString()+","+e.Y.ToString()+")"+ t.ToShortTimeString());
}
regards
Andreas
www.zweisteintrading.eu (http://www.zweisteintrading.eu)
NinjaTinyMobileTrader : control your NinjaTrader via a cell phone
Mindset
01-17-2010, 01:25 AM
return (((((this.bounds.Y + this.bounds.Height) - y) * ChartControl.MaxMinusMin(this.max, this.min)) / ((double)this.bounds.Height)) + this.min);
This was my code before and it works on a single chart but not on multiple charts.
Your coding is way beyond my current learning but the mi line doesn't compile?
private void myCustomEvent(object state)
{
MouseEventArgs m = (MouseEventArgs)state;
int xpos = m.X;
int ypos = m.Y;
MethodInfo mi=this.ChartControl.GetType().GetMethod("GetTimeByX",BindingFlags.Instance|BindingFlags.NonPublic|Bind ingFlags.Public);
DateTime t=(DateTime) ;
mi.Invoke(this.ChartControl,newobject[]{e.X});// error at array start
Print("Mouse("+e.X.ToString()+","+e.Y.ToString()+")"+ t.ToShortTimeString());
zweistein
01-17-2010, 02:53 AM
using System.Windows.Forms;
using System.Reflection;
also:
"new object" instead of "newobject"
keep me updated on the multiple Panel solutions
regards
Andreas
www.zweisteintrading.eu (http://www.zweisteintrading.eu)
NinjaTinyMobileTrader : control your NinjaTrader via a cell phone
Mindset
01-18-2010, 02:38 AM
Thanks Zweistein.
It seems that multiple charts reside in 1 form - the Y co ord simply covers the whole no of charts - as far as I can tell.
I spent most of Sunday fiddling around with the mouse nos and realise that I just don't grasp the concepts of bounds and canvas, etc correctly.
On top of that do you use co ordinates or time/price values - so I have remained utterly confused. I am going back to the beginning to try and get what exactly bounds, etc is/does and how to use it to plot things.
What is so frustrating for me is that all my work still works perfectly on a single chart - the pragmatic trader in me says simply don't use multiple charts on one panel. The coder in me however says that would be surrendering and we don't do that!!
If I ever sort this out or find a solution I will post it here.
Mindset
01-18-2010, 06:13 AM
Below is a new indicator that simply plots a line dissecting the selected bar ( via mouse).
I seem to have sorted out the Y value ( remarkably easy actually).
However my X co ord again still only works on a single chart and misplots on multiple charts within 1 panel.
NB THIS IS FOR NT7 BETA ONLY
#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
using System.Reflection;
using System.Windows.Forms;
#endregion
namespace NinjaTrader.Indicator
{
/// <summary>
/// Reveals a line along the axis of the selected bar
/// Produces wrong bar on multiple charts in single panel
/// Mindset Jan 18 2010
/// </summary>
[Description("Plots price on Mouse Click(Up)")]
public class mouseline : Indicator
{
#region Variables
private bool click = false;
private bool IsOn = false;
int bCount = 0;
int barclick = 0;
Font textFont1 = new Font("Verdana", 7F);
public int TextOffset = 2;
int xpos = 0;
int myx = 0;
internal double max;
internal double min;
#endregion
protected override void Initialize()
{
CalculateOnBarClose = false;
Overlay = true;
PriceTypeSupported = false;
PlotsConfigurable = false;
PaintPriceMarkers = false;
}
private void myMouseEvents(object sender, MouseEventArgs e)
{
TriggerCustomEvent(new CustomEvent(myCustomEvent),e );
}
private void myCustomEvent(object state)
{
MouseEventArgs m = (MouseEventArgs)state;
//MethodInfo mi=this.ChartControl.GetType().GetMethod("GetTimeByX",BindingFlags.Instance|BindingFlags.NonPublic|Bind ingFlags.Public);
//DateTime t=(DateTime) mi.Invoke (this.ChartControl ,new object[] {m.X});
xpos = m.X;
int ypos = m.Y;
int totalbars = this.ChartControl.BarsPainted - 1; //make it zero based
bCount = Bars.Count - 1; //make it zero based
int lastbarpainted = this.ChartControl.LastBarPainted;
int firstbarpainted = this.ChartControl.FirstBarPainted;
int barspace = this.ChartControl.BarSpace;
barclick = (int)(xpos/barspace); //gets the bar, from the painted ones where the mouse is clicked
if(IsOn == false)
{
//get rid of the free space on the left side if there are insufficient bars to fill the chartpanel
if (totalbars > lastbarpainted)
{
barclick -= (totalbars - lastbarpainted);
}
//finally get the actual barclick
barclick += firstbarpainted -1;
//make sure bar clicks is not less than 0 or greater than the total bars
if (barclick > bCount)
{
barclick = bCount;
}
if (barclick < 0)
{
barclick = 0;
}
int mybarno = (bCount - barclick);
IsOn = true;
}
else
{
IsOn = false;
RemoveDrawObjects();
}
}
protected override void OnBarUpdate()
{
if (!click)
{
click = true;
this.ChartControl.ChartPanel.MouseUp += new MouseEventHandler(myMouseEvents);
}
}
public override void Dispose()
{
if (this.ChartControl != null)
{
this.ChartControl.ChartPanel.MouseUp -= myMouseEvents;
}
base.Dispose();
}
public override void Plot(Graphics graphics, Rectangle bounds, double min, double max)
{
if(ChartControl != null)
{this.min = min;
this.max = max;
bounds = ChartControl.Bounds;
Pen linePen = new Pen(Color.Red);
linePen.Width = 4;
int pointX = ChartControl.GetXByBarIdx(BarsArray[0], barclick);
int myhigh = ChartControl.GetYByValue(BarsArray[0],High[bCount - barclick] +TickSize * 2);
int mylow = ChartControl.GetYByValue(BarsArray[0],Low[bCount - barclick]- TickSize * 2);
double y1 = myhigh;
double y2 = mylow;
graphics.DrawLine(linePen,pointX,(float)y1,pointX, (float)y2);
linePen.Dispose();
}
}
}
}
Mindset
01-18-2010, 10:57 AM
These 2 new methods in v7 are usefully outlined in the regression channel indicator.
GetXpos and GetYPos.
Again same problem - fine on single chart does NOT work on multi chart panel correctly.
here is the relevant section of code.
It is not a bug so this is the end of the road for me - I just don't see what is causing this behaviour.
public override void Plot(Graphics graphics, Rectangle bounds, double min, double max)
{
if(ChartControl != null)
{
this.min = min;
this.max = max;
bounds = ChartControl.Bounds;
Pen linePen = new Pen(Color.Red);
linePen.Width = 4;
int pointX = GetXPos(barsback);
double y1 = GetYPos(High[barsback]+(TickSize ),bounds,min,max);
double y2 = GetYPos(Low[barsback]-TickSize,bounds,min,max);
SmoothingMode oldSmoothingMode = graphics.SmoothingMode;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawLine(linePen,pointX,(float)y1,pointX, (float)y2);
graphics.SmoothingMode = oldSmoothingMode;
linePen.Dispose();
}
}
private int GetXPos(int barsback)//from regression channel
{
int idx = (Bars.Count - 1) + Math.Max(0, Bars.Count - 1 - ChartControl.LastBarPainted) - barsback;
return ChartControl.GetXByBarIdx(BarsArray[0], idx) + 1 ;//- ChartControl.ChartStyle.GetBarPaintWidth(Bars.Bars Data.ChartStyle.BarWidthUI) / 2;
}
private int GetYPos(double price, Rectangle bounds, double min, double max)
{
return ChartControl.GetYByValue(this, price);
}
Mindset
01-22-2010, 05:28 AM
I notice that there is a new signature for the custom event in 7.
I am unsure if this would cause the behaviour I am seeing but I don't understand what barsinprogress refers to. (not BarsArray[0] or just plain int 0).
mrlogik
02-04-2010, 07:56 AM
Hey Guys,
Great work here.
I am trying to modify the use of this a bit to draw a few horizontal lines rather than a click and drag line. I notice that using the DrawLine function will only draw 1 line, regardless how how many times it is called. I am using a different tag for each draw object.
Anyone else have this problem? Any idea's why this is?
Thanks
NinjaTrader_Josh
02-04-2010, 08:07 AM
mrlogik,
NinjaScript DrawLine() is a new line per tag. If you are using the Plot override, that is a completely different story as that is using C# graphics.
mrlogik
02-04-2010, 08:13 AM
Yes, I am using the Plot override.
I understand that this is outside of the scope as to what you provide support for.
PrTester
02-04-2010, 07:47 PM
Hey Guys,
Great work here.
I am trying to modify the use of this a bit to draw a few horizontal lines rather than a click and drag line. I notice that using the DrawLine function will only draw 1 line, regardless how how many times it is called. I am using a different tag for each draw object.
Anyone else have this problem? Any idea's why this is?
Thanks
This is not my code i found it on other Forum, but maybe this help you or give you some hints
DeanV
11-24-2010, 06:44 AM
ok, here's what i have.
Alt+right-click-drag to draw lines:
Tweeked this to work on Panel 1 when multi-charted (NT 7.b22). Still won't X-scale correct on a Panel 2 (seems to be getting some info from the first panel).