Description
This indicator is to solve the problem cTrader ver 4.4.12 removed to access and edit the icon's comments
For problem details, please see: https://ctrader.com/forum/ctrader-support/39021
Usage:
1. Select Icon, Alt + D to popup a ChartText with the icon's comment;
2. Edit ChartText as needed;
3. Alt + D to save revised comments, hit again to hide popup ChartText;
Interested in the currency strength meter in the chart?
Get the free download link at Telegram Group: cTrader FOREX Club
using System;
using System.IO;
using System.Linq;
using cAlgo.API;
//This indicator is to solve the problem cTrader ver 4.4.12 removed to access and edit the icon's comments
//Problem details see: https://ctrader.com/forum/ctrader-support/39021
//Usage:
//1. Select Icon, Alt + D to popup a ChartText with the icon's comment;
//2. Edit ChartText as needed;
//3. Alt + D to save revised comments, hit again to hide popup ChartText;
//4. Alt + C to make a copy of comments box;
//5. Alt + E to remove copied comments box;
//
//Ver 1.01 Optimise : Short cut key change to only Alt + D, save and hide ChartText;
// 1.02 Optimise : Short cut key change to only Alt + D, unhide, save and hide ChartText;
// : Temporarily fill with 'empty...' if Icon has no comment;
// 1.03 Add Function : Can edit Trendline and Rectangle's comments;
// 1.04 Optimise : MakeSure Textbox is interactive; TextBox can be seen(in the last trading day) if Trendline too old;
// Optimise : Framework .NET 6.0 ready;
// 1.05 Optimise : Use IsInteractive to hide CommentTextBox; Code Structure; CommentTextBox color is not transparent;
// 1.06 Add Function : Alt + X: quick (Un)Lock select trendlines, rectangles, icons, text box;
// 1.07 Optimise : Fixed bug of Alt + D to display textbox immediately;
// Optimise : Put Comments-Box in the mid of chart for TrendLine, Rectangle, HorizentalLine;
// Add Function : Alt + X: can (Un)Lock ChartArrowLines;
// Add Function : Can edit HorizentalLine's Comments;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class EditIconCmmt : Indicator
{
string s_objnme, s_objsve, s_objcmt;//Object Name, Save, Comment
double db_obj_Y; //Object Y-Value
int i_ObjIdx; //Object Bar-Index
Color cl_objCl; //Object Color
private ChartText tx_Cmmt, tx_Copy; //ChartTextBox to display,edit ObjectComment; Copy of ObjectComment;
private ChartStaticText sx_RorS; //Display control process
private ChartObjectType ty_Obj; //Record Select Object ChartObjectType
private readonly static string pfx_CmX = "Cmmt_Tx", pfx_Cms="RorS"; //Prifix : at Name of ObjectCommentTextBox, ControlMessage Text;
private readonly static string sfx_Cpy = "- CmtCpy"; //Sufix : at Name of Copy of ObjectComment;
private readonly static string cnt_Ept = "empty...", nEp=""; //Content: Temperary to fill ObjectCommentTextBox; SymbolEmpty;
private readonly static string act_Sve = " comment saved..."; //Action : ObjectComment saved
private readonly static string act_Hdn = " comment hidden..."; //Action : ObjectComment hidden
private readonly static string act_Cpy = " comment coppied..."; //Action : ObjectComment copy
private readonly static string act_Rmv = " comment removed..."; //Action : ObjectComment remove
private readonly static string act_unL = "Selected objects free now..."; //Action : Objects unlocked
private readonly static string act_Lck = "Selected objects locked..."; //Action : Objects locked
protected override void Initialize()
{ //System.Diagnostics.Debugger.Launch();
Chart.KeyDown += Chart_KeyDown; //HotKeys to SaveChange;
Chart.ObjectsSelectionChanged += Chart_ObjectsSelectionChanged; //Select Icons to popup comments in ChartText;
//Prepare ObjectCommentText and PopupMessageText
sx_RorS = Chart.DrawStaticText(pfx_Cms, string.Format(nEp), VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.Red); sx_RorS.IsHidden=false;
}
public override void Calculate(int index) {}
//Select effective object to prepare CommentTextBox, hidden yet
private void Chart_ObjectsSelectionChanged(ChartObjectsSelectionChangedEventArgs obj)
{
//Exempt object numbers selected (only work for 1 object) - Update Name of SelectObject
if ( Chart.SelectedObjects.Count()==0 ) //Clear Message when select no object
{ PPmsg(nEp,false); }
else if ( Chart.SelectedObjects.Count()==1 ) //Record SelectObject's Name,Type,Comments
{
if ( Chart.SelectedObjects[0].Name!=pfx_CmX ) //Don't do, if tx_Cmmt is selected
{
s_objnme = Chart.SelectedObjects[0].Name; //SelectObjectName
ty_Obj = Chart.SelectedObjects[0].ObjectType; //ChartObjectType
s_objsve = s_objnme; //NameToSave
s_objcmt = Chart.SelectedObjects[0].Comment; //Comment Content
int iStr = Chart.FirstVisibleBarIndex; //Get the first bar-index in Chart
int iEnd = Chart.LastVisibleBarIndex; //Get the last bar-index in Chart
int iMid = (iStr + iEnd) / 2; //Get the mid bar-index in Chart
switch (ty_Obj) //Record ObjectTime, Y-Value
{
case ChartObjectType.Icon : var Ics=Chart.FindAllObjects(ChartObjectType.Icon ).Where(x => x.Name==s_objnme); foreach (ChartIcon ic in Ics) { int iT=Bars.OpenTimes.GetIndexByTime(ic.Time ); i_ObjIdx = iT; db_obj_Y = ic.Y; cl_objCl = ic.Color; } break;
case ChartObjectType.TrendLine : var Trs=Chart.FindAllObjects(ChartObjectType.TrendLine ).Where(x => x.Name==s_objnme); foreach (ChartTrendLine tr in Trs) { int iT=Bars.OpenTimes.GetIndexByTime(tr.Time1); i_ObjIdx = iT<iStr ? iMid : iT; db_obj_Y = tr.Y1; cl_objCl = tr.Color; } break;
case ChartObjectType.Rectangle : var Rts=Chart.FindAllObjects(ChartObjectType.Rectangle ).Where(x => x.Name==s_objnme); foreach (ChartRectangle rt in Rts) { int iT=Bars.OpenTimes.GetIndexByTime(rt.Time1); i_ObjIdx = iT<iStr ? iMid : iT; db_obj_Y = rt.Y1; cl_objCl = rt.Color; } break;
case ChartObjectType.HorizontalLine : var Hls=Chart.FindAllObjects(ChartObjectType.HorizontalLine).Where(x => x.Name==s_objnme); foreach (ChartHorizontalLine hl in Hls) { i_ObjIdx = iMid ; db_obj_Y = hl.Y ; cl_objCl = hl.Color; } break;
default: return;
}
RemvCmTx(); //Remove comments box first to avoid mis-saving
}
}
else if ( Chart.SelectedObjects.Count()>=2 ) //Select multiple object to remove comment box
{ RemvCmTx(); }
}
//Alt+D,C,E: to Popup,Copy,Erase CommentTextBox
private void Chart_KeyDown(ChartKeyboardEventArgs obj)
{
if (obj.AltKey)
{
if (obj.Key.Equals(Key.D)) //Alt + D: to Edit,Save,Hide ObjectComment
{
var Txs= Chart.FindAllObjects(ChartObjectType.Text).Where(x => x.Name==pfx_CmX);
if ( Txs.Count() == 0 ) //First hit to write & display comment;
{
int iStr = Chart.FirstVisibleBarIndex; //Get the first bar-index in Chart
int iEnd = Chart.LastVisibleBarIndex; //Get the last bar-index in Chart
int iMid = (iStr + iEnd) / 2; //Get the mid bar-index in Chart
switch (ty_Obj) //Prepare ObjectCommentText according to ObjectType
{ // ↓↓ Visiable in chart ↓↓ Not transparent
case ChartObjectType.Icon : var Ics=Chart.FindAllObjects(ChartObjectType.Icon ).Where(x => x.Name==s_objnme); foreach (ChartIcon ic in Ics) { int iT=Bars.OpenTimes.GetIndexByTime(ic.Time ); ReadCmTx(ic.Comment, iT, ic.Y, Color.FromArgb(255,ic.Color)); } break;
case ChartObjectType.TrendLine : var Trs=Chart.FindAllObjects(ChartObjectType.TrendLine ).Where(x => x.Name==s_objnme); foreach (ChartTrendLine tr in Trs) { int iT=Bars.OpenTimes.GetIndexByTime(tr.Time1); ReadCmTx(tr.Comment, iT<iStr ? iMid : iT, tr.Y1, Color.FromArgb(255,tr.Color)); } break;
case ChartObjectType.Rectangle : var Rts=Chart.FindAllObjects(ChartObjectType.Rectangle ).Where(x => x.Name==s_objnme); foreach (ChartRectangle rt in Rts) { int iT=Bars.OpenTimes.GetIndexByTime(rt.Time1); ReadCmTx(rt.Comment, iT<iStr ? iMid : iT, rt.Y1, Color.FromArgb(255,rt.Color)); } break;
case ChartObjectType.HorizontalLine : var Hls=Chart.FindAllObjects(ChartObjectType.HorizontalLine).Where(x => x.Name==s_objnme); foreach (ChartHorizontalLine hl in Hls) { ReadCmTx(hl.Comment, iMid , hl.Y , Color.FromArgb(255,hl.Color)); } break;
default: return;
}
}
else //Hit again to save if comment changed;
{
if ( tx_Cmmt.Text != s_objcmt && tx_Cmmt.Text != cnt_Ept)
{
switch (ty_Obj) //Works only at the ObjectSelected
{ // Save comments to Object, Update Comments to compare
case ChartObjectType.Icon : var Ics=Chart.FindAllObjects(ChartObjectType.Icon ).Where(x => x.Name==s_objnme); foreach (ChartIcon ic in Ics) { ic.Comment=tx_Cmmt.Text; s_objcmt=tx_Cmmt.Text; } break;
case ChartObjectType.TrendLine : var Trs=Chart.FindAllObjects(ChartObjectType.TrendLine ).Where(x => x.Name==s_objnme); foreach (ChartTrendLine tr in Trs) { tr.Comment=tx_Cmmt.Text; s_objcmt=tx_Cmmt.Text; } break;
case ChartObjectType.Rectangle : var Rts=Chart.FindAllObjects(ChartObjectType.Rectangle ).Where(x => x.Name==s_objnme); foreach (ChartRectangle rt in Rts) { rt.Comment=tx_Cmmt.Text; s_objcmt=tx_Cmmt.Text; } break;
case ChartObjectType.HorizontalLine : var Hls=Chart.FindAllObjects(ChartObjectType.HorizontalLine).Where(x => x.Name==s_objnme); foreach (ChartHorizontalLine hl in Hls) { hl.Comment=tx_Cmmt.Text; s_objcmt=tx_Cmmt.Text; } break;
default: return;
}
PPmsg(s_objsve+act_Sve, false);
}
else { RemvCmTx(); PPmsg(s_objnme+act_Hdn, true); } //Hit again to Remove comment TextBox;
}
} //Alt + D: to Edit,Save,Hide ObjectComment
else if (obj.Key.Equals(Key.C)) //Alt + C: Leave a Copy Unhiden for ObjectComment
{
tx_Copy = Chart.DrawText(s_objnme+sfx_Cpy, s_objcmt == nEp ? cnt_Ept : s_objcmt, i_ObjIdx, db_obj_Y, Color.FromArgb(255,cl_objCl));
//Put CopyCommentBox at proper position by ObjectType
switch (ty_Obj)
{
case ChartObjectType.Icon : tx_Copy.HorizontalAlignment=HorizontalAlignment.Left; break; //Left beside Icon
case ChartObjectType.TrendLine: tx_Copy.HorizontalAlignment=HorizontalAlignment.Right; break; //LeftBottom Trendline
case ChartObjectType.Rectangle: tx_Copy.HorizontalAlignment=HorizontalAlignment.Right; break; //LeftBotton Rectangle
default: return;
}
tx_Copy.IsHidden=false; tx_Copy.IsInteractive=true; tx_Copy.IsLocked=true; //Display CommentBoxCopy
RemvCmTx(); //Hide CommentsTextBox
PPmsg(s_objsve+act_Cpy, false);
} //Alt + C: Leave a Copy Unhiden for ObjectComment
else if (obj.Key.Equals(Key.E)) //Alt + E: Remove Copied ObjectCommentTextBox, Hide CommentTextBox;
{
var Txs=Chart.FindAllObjects(ChartObjectType.Text).Where(x => x.Name.Contains(s_objnme)); foreach (ChartText Tx in Txs) { Chart.RemoveObject(Tx.Name); }
RemvCmTx(); //Hide CommentsTextBox
PPmsg(s_objsve+act_Rmv, true);
} //Alt + E: Remove Copied ObjectCommentTextBox, Hide CommentTextBox;
else if (obj.Key.Equals(Key.X)) //Alt + X: (Un)Lock select trendlines, rectangles, icons;
{
string s_nm = string.Empty;
//Check all SelectedObjects
for (int i = 0; i < Chart.SelectedObjects.Count; i++ )
{
s_nm = Chart.SelectedObjects[i].Name;
if (Chart.SelectedObjects[i].ObjectType == ChartObjectType.ArrowLine)
{ var ALs = Chart.FindAllObjects(ChartObjectType.ArrowLine).Where( x => x.Name==s_nm ); foreach (ChartArrow al in ALs) { al.IsLocked = !al.IsLocked; PPmsg(al.IsLocked ? act_Lck : act_unL, false);} }
if (Chart.SelectedObjects[i].ObjectType == ChartObjectType.TrendLine)
{ var Trs = Chart.FindAllObjects(ChartObjectType.TrendLine).Where( x => x.Name==s_nm ); foreach (ChartTrendLine tr in Trs) { tr.IsLocked = !tr.IsLocked; PPmsg(tr.IsLocked ? act_Lck : act_unL, false);} }
else if (Chart.SelectedObjects[i].ObjectType == ChartObjectType.Rectangle)
{ var Rts = Chart.FindAllObjects(ChartObjectType.Rectangle).Where( x => x.Name==s_nm ); foreach (ChartRectangle rt in Rts) { rt.IsLocked = !rt.IsLocked; PPmsg(rt.IsLocked ? act_Lck : act_unL, false);} }
else if (Chart.SelectedObjects[i].ObjectType == ChartObjectType.Icon)
{ var Ics = Chart.FindAllObjects(ChartObjectType.Icon) .Where( x => x.Name==s_nm ); foreach (ChartIcon ic in Ics) { ic.IsLocked = !ic.IsLocked; PPmsg(ic.IsLocked ? act_Lck : act_unL, false);} }
else if (Chart.SelectedObjects[i].ObjectType == ChartObjectType.Text)
{ var Txs = Chart.FindAllObjects(ChartObjectType.Text) .Where( x => x.Name==s_nm ); foreach (ChartText tx in Txs) { tx.IsLocked = !tx.IsLocked; PPmsg(tx.IsLocked ? act_Lck : act_unL, false);} }
}
} //Alt + X: (Un)Lock select trendlines, rectangles, icons;
}
}
//Read the SelectObject comment to display;
private void ReadCmTx(string s_CmTx, int i_CmTx, double Y_CmTx, Color cl_CmTx)
{
//Read(Display) Comments content
tx_Cmmt = Chart.DrawText(pfx_CmX, (s_CmTx == nEp) ? cnt_Ept : s_CmTx, i_CmTx, 0, cl_CmTx);
tx_Cmmt.Time = Bars[i_CmTx].OpenTime; tx_Cmmt.Y = Y_CmTx; tx_Cmmt.FontSize = 14;
tx_Cmmt.IsInteractive = true; tx_Cmmt.IsLocked = false;
tx_Cmmt.HorizontalAlignment=HorizontalAlignment.Right;
}
//Set CommentTextBox (Un)Hidden
private void RemvCmTx()
{ if ( Chart.FindAllObjects(ChartObjectType.Text).Where(x => x.Name==pfx_CmX).Count() > 0 ) { Chart.RemoveObject(tx_Cmmt.Name); } }
//Popup Control Message
private void PPmsg(string msg, bool ishidden)
{
if (ishidden) { sx_RorS.Text = nEp; sx_RorS.IsHidden = true ; }
else { sx_RorS.Text = msg; sx_RorS.IsHidden = false; }
}
}
}
Capt.Z-Fort.Builder
Joined on 03.06.2020
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: Edit Icon Comment.algo
- Rating: 5
- Installs: 883
- Modified: 19/07/2023 22:32
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
No comments found.