Vai al contenuto

Controlli

I controlli consentono determinate interazioni che coinvolgono cBot, indicatori e plugin. Utilizzando la guida qui sotto, puoi creare facilmente controlli UI di base e avanzati direttamente su un grafico.

Esistono diverse classi integrate che rappresentano controlli popolari come pulsanti, blocchi di testo, caselle di testo e forme. Tuttavia, puoi anche creare controlli personalizzati.

Considera il seguente esempio:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = HorizontalAlignment.Center)]
        public HorizontalAlignment HorizontalAlignment { get; set; }

        [Parameter(DefaultValue = VerticalAlignment.Center)]
        public VerticalAlignment VerticalAlignment { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                HorizontalAlignment = HorizontalAlignment,
                VerticalAlignment = VerticalAlignment
            };

            button.Click += Button_Click;

            Chart.AddControl(button);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

Se compili l'indicatore sopra e crei un'istanza, dovresti vedere un pulsante grigio Click me proprio al centro del grafico.

Differenza tra controlli e oggetti del grafico

In una sezione precedente, abbiamo già trattato gli oggetti del grafico. I controlli consentono agli utenti di interagire con cBot e indicatori. Al contrario, gli oggetti del grafico offrono l'opportunità di disegnare qualcosa sul grafico di trading o in una finestra di output dell'indicatore separata.

I controlli del grafico derivano dalla classe ControlBase mentre gli oggetti del grafico derivano dalla classe ChartObject.

I controlli del grafico sono posizionati staticamente utilizzando diverse opzioni di allineamento. Mentre gli oggetti del grafico possono essere posizionati esattamente nello stesso modo, la loro posizione può anche cambiare dinamicamente a seconda di determinate coordinate X e Y.

Analogamente agli oggetti del grafico, i controlli del grafico possono essere aggiunti sia al grafico principale che a qualsiasi finestra di output dell'indicatore (se esistono). Un esempio di tale posizionamento è riportato di seguito:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = HorizontalAlignment.Center)]
        public HorizontalAlignment HorizontalAlignment { get; set; }

        [Parameter(DefaultValue = VerticalAlignment.Center)]
        public VerticalAlignment VerticalAlignment { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                HorizontalAlignment = HorizontalAlignment,
                VerticalAlignment = VerticalAlignment
            };

            button.Click += Button_Click;

            IndicatorArea.AddControl(button);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

Dopo aver creato un'istanza dell'indicatore, dovresti vedere un pulsante Click me nella finestra di output dell'indicatore.

ColorPicker

Il controllo ColorPicker consente ai trader di selezionare il colore preferito per elementi o oggetti chiave in cTrader. Ad esempio, uno sviluppatore può integrare il controllo ColorPicker in un cBot che disegna trendline in modo che gli utenti possano selezionare il colore preferito per ciascuna trendline. Questa configurazione rende più facile per i trader distinguere tra vari tipi di trendline.

Un plugin che aggiunge indicatori ai grafici può anche implementare il controllo ColorPicker poiché questa funzionalità consente agli utenti di scegliere un colore per diverse linee dell'indicatore.

Quando gli utenti fanno clic sul quadrato del colore, viene visualizzato il selettore dei colori. Gli utenti possono quindi scegliere tra colori standard e personalizzati.

Esempio di codice:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ColorPickerTest : Plugin
    {
        protected override void OnStart()
        {
            var aspBlock = Asp.SymbolTab.AddBlock("Color Picker");

            var colorPicker = new ColorPicker {IsStretched = true, SelectedColor = Color.Red, Height = 20, Width = 20, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center};

            aspBlock.Child = colorPicker;

            colorPicker.SelectedColorChanged += colorPicker_SelectedColorChanged;

        }

        private void colorPicker_SelectedColorChanged(ColorPickerSelectedColorChangedEventArgs obj)
        {
            Print($"colorPicker_SelectedColorChanged, NewSelectedColor: {obj.NewSelectedColor} | PreviousSelectedColor: {obj.PreviousSelectedColor}");
        }

        protected override void OnStop()
        {
            // Handle Plugin stop here
        }
    }        
}

Image title

DropZone

Il controllo DropZone consente ai trader di eseguire azioni drag-and-drop che coinvolgono cBot, indicatori o plugin. Per implementare questo controllo nel tuo algoritmo, utilizza la classe DropZone. Il controllo DropZone può essere manipolato come qualsiasi altro controllo.

Quando un utente rilascia un file o una cartella compatibile nella casella, viene generato l'evento Dropped. Quando un utente rilascia una cartella o più cartelle nella casella, vengono elaborati e copiati solo i file compatibili con le estensioni specificate in FilterExtensions.

Nota

I file rilasciati vengono solitamente copiati e salvati in questa posizione: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\

La posizione per le istanze di cBot differisce da quanto sopra: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\

Questo codice del plugin ti mostra come aggiungere un controllo DropZone a Trade Watch:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System;
using System.Drawing;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class TradeWatchTabSample : Plugin
    {
        protected override void OnStart()
        {
            var tab = TradeWatch.AddTab("DropZone");

            var _border = new Border
            {
                BorderThickness = 3,
                BorderColor = Color.DarkGray,
                Opacity = 0.7,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Height = 200,
                Width = 350,
                BackgroundColor = Color.LightGray
            };

            var _textBlock = new TextBlock
            {
                Text = "Drag your files here",
                Opacity = 1,
                ForegroundColor = Color.DarkGray,
                FontSize = 16,
                VerticalAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Center
            };

            var _dropzone = new DropZone
            {
                FilterExtensions = new string[] { "txt", "algo", "csv" },
                IsDirectoryDropAllowed = true,
                IsVisible = true,
                IsEnabled = true
            };
            _border.Child = _textBlock;
            _dropzone.Child = _border;
            //   _dropzone.Child = _textBlock;
            tab.Child = _dropzone;

            _dropzone.Dropped += Dropped_file;
        }

        private void Dropped_file(DroppedEventArgs obj)
        {
            Print("File has been added!");
        }
    }
}

Image title

ProgressBar

Il controllo ProgressBar visualizza la progressione di un'operazione in corso. Le barre di avanzamento rendono gli algoritmi più intuitivi e aiutano a gestire le aspettative dei trader riguardo al tempo di attesa per determinate operazioni.

L'API cTrader Algo consente agli sviluppatori di aggiungere due tipi di controlli ProgressBar: controllo infinito e controllo determinato.

Controllo infinito

Potresti voler utilizzare il controllo infinito nelle seguenti situazioni:

  • Non puoi determinare il tempo di attesa per un'operazione.
  • Non puoi rilevare la progressione di un'operazione.
  • Non vuoi indicare quanto tempo richiederà un'operazione.

Image title

Controllo determinato

Potresti voler utilizzare questo controllo quando puoi determinare il tempo di attesa per un'operazione e vuoi che gli utenti vedano un indicatore basato su quel tempo.

Per visualizzare l'avanzamento dell'operazione, utilizza la proprietà Value per impostare una cifra. Per impostare la percentuale della barra di avanzamento, utilizza le proprietà Minimum e Maximum.

Image title

Il codice del plugin qui sotto ti mostra come creare una barra di avanzamento utilizzando sia controlli infiniti che determinati (verdi):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ProgressBarTest : Plugin
    {
        private ProgressBar _infiniteProgressBar;
        private ProgressBar _determinateProgressBar;

        protected override void OnStart()
        {
            var aspBlock = Asp.SymbolTab.AddBlock("Progress bar");

            var panel = new StackPanel() {Height = 200, Width = 200, Orientation = Orientation.Vertical};

            _infiniteProgressBar = new ProgressBar {IsIndeterminate = true, Height = 20};

            panel.AddChild(_infiniteProgressBar);

            _determinateProgressBar = new ProgressBar {IsIndeterminate = false, Height = 20};

            panel.AddChild(_determinateProgressBar);

            var autoProgressButton = new Button {Text = "Start"};

            autoProgressButton.Click += AutoProgressButton_Click;

            panel.AddChild(autoProgressButton);

            aspBlock.Child = panel;

        }

        private void AutoProgressButton_Click(ButtonClickEventArgs obj)
        {
            Timer.Start(1);
        }

        protected override void OnTimer()
        {
            _determinateProgressBar.Value++;

            Print($"Value: {_determinateProgressBar.Value}");
        }

        protected override void OnStop()
        {
            // Handle Plugin stop here
        }
    }        
}

OpenFileDialog e OpenFolderDialog

L'API cTrader Algo fornisce l'interfaccia OpenFileDialog per consentire agli utenti di selezionare un file per un algoritmo. Quando un utente seleziona un file nella finestra risultante, il file viene copiato nella cartella Selected files dell'algoritmo. Un algoritmo può lavorare con i file all'interno della sua cartella Selected files senza restrizioni.

Suggerimento

Utilizza la funzionalità OpenFileDialog quando devi caricare file di dati importanti, file di backup o di configurazione, indicatori personalizzati o script.

Il codice qui sotto ti mostra come utilizzare la finestra di dialogo OpenFileDialog in un indicatore:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System;
using cAlgo.API;
using System.Text;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class OpenFileDialogExample : Indicator
    {
        private OpenFileDialog _openFileDialog;

        protected override void Initialize()
        {
            _openFileDialog = new OpenFileDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect = true,
                Title = "My Open File Dialog Title"
            };

            var showOpenFileDialog = new Button { Text = "Show Open File Dialog" };
            showOpenFileDialog.Click += showOpenFileDialog_Click;

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            panel.AddChild(showOpenFileDialog);
            Chart.AddControl(panel);
        }

        private void showOpenFileDialog_Click(ButtonClickEventArgs obj)
        {
            var result = _openFileDialog.ShowDialog();
            Print($"Result: {result} | FileName: {_openFileDialog.FileName} | FileNames: {string.Join(',', _openFileDialog.FileNames)}");
        }

        public override void Calculate(int index)
        {
        }
    }
}

Image title

L'API cTrader Algo fornisce l'interfaccia OpenFolderDialog per consentire agli utenti di specificare una cartella per un algoritmo. Quando un utente seleziona una cartella nella finestra risultante, tutti i file e le cartelle con file all'interno della cartella selezionata vengono copiati nella cartella Selected files dell'algoritmo.

Suggerimento

Utilizza la funzionalità OpenFolderDialog quando devi caricare una cartella contenente file di dati critici, file di backup o di configurazione, indicatori personalizzati o script.

I file e le cartelle selezionati vengono solitamente copiati nella cartella Selected files perché un algoritmo può lavorare con gli elementi all'interno di quella cartella anche quando il suo AccessRights è impostato su None.

Nota

La cartella Selected files di un algoritmo si trova solitamente lungo questo percorso: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\

La cartella Selected files per un'istanza di cBot differisce da quanto sopra: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\

Il codice qui sotto ti mostra come utilizzare la finestra di dialogo OpenFolderDialog in un indicatore:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using cAlgo.API;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class OpenFolderDialogExample : Indicator
    {
        private OpenFolderDialog _openFolderDialog;

        protected override void Initialize()
        {
            _openFolderDialog = new OpenFolderDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Title = "My Open Folder Dialog Title"
            };

            var showOpenFolderDialog = new Button { Text = "Show Open Folder Dialog" };
            showOpenFolderDialog.Click += showOpenFolderDialog_Click;

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            panel.AddChild(showOpenFolderDialog);
            Chart.AddControl(panel);
        }

        private void showOpenFolderDialog_Click(ButtonClickEventArgs obj)
        {
            var result = _openFolderDialog.ShowDialog();
            Print($"Result: {result} | FolderName: {_openFolderDialog.FolderName}");
        }

        public override void Calculate(int index)
        {
        }
    }
}

Image title

SaveFileDialog

L'API cTrader Algo fornisce l'interfaccia SaveFileDialog per consentire agli utenti di salvare file (localmente) sui propri computer. Quando viene visualizzata la finestra pertinente, un utente seleziona la cartella in cui desidera salvare il file e inserisce un nome per il file. Il file viene quindi salvato nella posizione specificata.

Suggerimento

Utilizza la funzionalità SaveFileDialog quando devi eseguire una delle seguenti operazioni:

  • Salvare report sulle prestazioni, risultati di backtesting, file di configurazione o dati di ottimizzazione.
  • Esportare registri di trading, giornali delle operazioni o dati generali sull'attività dell'utente.
  • Archivia indicatori personalizzati, dati per grafici e visualizzazioni o parametri per una strategia.

Il codice qui sotto ti mostra come usare la finestra di dialogo SaveFileDialog in un indicatore:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using cAlgo.API;
using System.Text;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class SaveFileDialogExample : Indicator
    {
        private SaveFileDialog _saveFileDialog;

        protected override void Initialize()
        {
            _saveFileDialog = new SaveFileDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Title = "My Save File Dialog Title"
            };

            var showSaveFileDialogText = new Button { Text = "Show Save File Dialog (Set Content as text)" };
            var showSaveFileDialogBytes = new Button { Text = "Show Save File Dialog (Set Content as bytes)" };

            showSaveFileDialogText.Click += showSaveFileDialogText_Click;
            showSaveFileDialogBytes.Click += showSaveFileDialogBytes_Click;

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };
            panel.AddChild(showSaveFileDialogText);
            panel.AddChild(showSaveFileDialogBytes);
            Chart.AddControl(panel);
        }

        private void showSaveFileDialogText_Click(ButtonClickEventArgs obj)
        {
            var result = _saveFileDialog.ShowDialog();
            Print($"Result: {result}");
            if (result != FileDialogResult.Cancel)
            {
                _saveFileDialog.WriteToFile("Test in text");
            }
        }

        private void showSaveFileDialogBytes_Click(ButtonClickEventArgs obj)
        {
            var result = _saveFileDialog.ShowDialog();
            Print($"Result: {result}");
            if (result != FileDialogResult.Cancel)
            {
                _saveFileDialog.WriteToFile(Encoding.UTF8.GetBytes("Test in bytes"));
            }
        }

        public override void Calculate(int index)
        {
        }
    }
}

Controlli trascinabili

Controllo trascinabile dell'area del grafico

Le interfacce ChartDraggable e ChartDraggables forniscono tipi che ti permettono di aggiungere un controllo trascinabile in grado di ospitare altri controlli ed elementi diversi a un grafico. Questi controlli trascinabili facilitano l'interazione degli utenti con vari elementi del grafico.

Nota

Un controllo trascinabile può essere spostato o riposizionato solo all'interno del grafico in cui è stato aggiunto.

Questo codice ti mostra come creare un indicatore che aggiunge due controlli che possono essere spostati all'interno di un grafico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None)]
    public class DragControl : Indicator
    {
        protected override void Initialize()
        {
            var draggable = Chart.Draggables.Add();
            var draggable2 = IndicatorArea.Draggables.Add();

            draggable.Child = GetDraggableChildWebView();
            draggable2.Child = GetDraggableChildText();

            draggable.LocationChanged += draggable_LocationChanged;
            draggable2.LocationChanged += draggable2_LocationChanged;
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = 
        }

        private StackPanel GetDraggableChildWebView()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var webView = new WebView() {Height = 500, Width = 300};

            webView.Loaded += webView_Loaded;

            stackPanel.AddChild(webView);

            return stackPanel;
        }

        private StackPanel GetDraggableChildText()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };
            var text_block = new TextBlock
                 {
                     Text = "Testing draggable controls",
                     Margin = 5,
                     ForegroundColor = Color.Black,
                     FontWeight = FontWeight.ExtraBold
                 };

            stackPanel.AddChild(text_block);

            return stackPanel;
        }


        private void webView_Loaded(WebViewLoadedEventArgs obj)
        {
            obj.WebView.NavigateAsync("https://www.youtube.com/");
        }

        private void draggable_LocationChanged(ChartDraggableLocationChangedEventArgs obj)
        {
            Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");
        }

        private void draggable2_LocationChanged(ChartDraggableLocationChangedEventArgs obj)
        {
            Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");
        }
    }
}

Controllo trascinabile della finestra dell'applicazione

Le interfacce ApplicationDraggable e ApplicationDraggables forniscono i tipi usati per aggiungere controlli mobili che possono essere spostati individualmente nell'intera finestra dell'applicazione cTrader. Tali controlli ti permettono di creare interfacce utente interattive e dinamiche.

Nota

Dei tre tipi di algoritmi, solo i plugin possono implementare controlli trascinabili a livello di applicazione.

Questo codice ti mostra come creare un plugin che aggiunge un componente WebView e un blocco di testo in due finestre separate, che possono essere spostate nell'intera interfaccia di cTrader:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ApplicationLevelDraggables : Plugin
    {
        private ApplicationDraggable _webDraggable;
        private ApplicationDraggable _textDraggable;

        protected override void OnStart()
        {
            _webDraggable = Application.Draggables.Add();
            _webDraggable.Child = GetDraggableChildWebView();
            _webDraggable.LocationChanged += OnDraggableLocationChanged;

            _textDraggable = Application.Draggables.Add();
            _textDraggable.Child = GetDraggableChildText();
            _textDraggable.LocationChanged += OnDraggableLocationChanged;
        }

        private void OnDraggableLocationChanged(ApplicationDraggableLocationChangedEventArgs args)
        {
            Print($"Draggable '{args.Draggable.Id}' location changed to: ({args.Draggable.X}, {args.Draggable.Y})");
        }

        private StackPanel GetDraggableChildWebView()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var webView = new WebView { Width = 300, Height = 200 };
            webView.Loaded += (args) => args.WebView.NavigateAsync("https://www.youtube.com/");

            stackPanel.AddChild(webView);

            return stackPanel;
        }

        private StackPanel GetDraggableChildText()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var textBlock = new TextBlock
            {
                Text = "Testing Application-level draggable",
                Margin = 5,
                ForegroundColor = Color.Black,
                FontWeight = FontWeight.ExtraBold
            };

            stackPanel.AddChild(textBlock);

            return stackPanel;
        }
    }
}

Controllo schede

La classe TabControl fornisce tipi che ti permettono di creare più schede per un algoritmo. Queste schede possono essere usate per tenere insieme elementi correlati o presentare viste separate per le funzionalità.

Questo codice ti mostra come usare le schede in un plugin aggiunto al Pannello del simbolo attivo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.FullAccess)]
    public class TabControlSimple : Plugin
    {
        private TabControl _tabControl;

        protected override void OnStart()
        {
            _tabControl = new TabControl
            {
                Height = 200,
                TabStripPlacement = Dock.Left 
            };

            var firstTab = new TabItem
            {
                Header = new TextBlock { Text = "First Tab" },
                Content = new TextBlock { Text = "First Tab Content", BackgroundColor = Color.Red }
            };

            var secondTab = new TabItem
            {
                Header = new TextBlock { Text = "Second Tab" },
                Content = new TextBlock { Text = "Second Tab Content" }
            };

            _tabControl.AddTab(firstTab);
            _tabControl.AddTab(secondTab);

            _tabControl.SelectedTabChanged += TabControl_SelectedTabChanged;

            _tabControl.SelectedTab = secondTab;

            var panel = new StackPanel { Orientation = Orientation.Vertical };
            panel.AddChild(_tabControl);

            var asp = Asp.SymbolTab.AddBlock("Simple Tab Control");
            asp.Child = panel;
            asp.Height = 300;
        }

        private void TabControl_SelectedTabChanged(TabControlSelectedTabChangedEventArgs obj)
        {
            Print($"Selected tab changed to: {obj.SelectedTab?.UniqueId}");
        }

        protected override void OnStop()
        {
        }
    }
}

Controlli personalizzati

Un controllo personalizzato è un controllo che, in sostanza, è costruito da diversi controlli predefiniti. In altre parole, è un controllo per il quale altri controlli costituiscono il suo contenuto.

I controlli personalizzati agiscono come classi riutilizzabili in modo simile ai controlli integrati.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter("# Of Text Areas", DefaultValue = 4)]
        public int NumberOfTextAreas { get; set; }

        protected override void Initialize()
        {
            var panel = new WrapPanel
            {
                Orientation = Orientation.Horizontal,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            for (int i = 0; i < NumberOfTextAreas; i++)
            {
                var textArea = new TextArea
                {
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Stretch,
                    Margin = 5,
                };

                panel.AddChild(textArea);
            }

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }

    public class TextArea : CustomControl
    {
        private readonly TextBox _textBox;

        public TextArea()
        {
            _textBox = new TextBox
            {
                TextAlignment = TextAlignment.Left,
                TextWrapping = TextWrapping.Wrap,
                AcceptsReturn = true,
                AcceptsTab = true,
                Width = 300,
                Height = 200,
            };

            AddChild(_textBox);
        }
    }
}

Un'istanza di questo indicatore dovrebbe visualizzare quattro caselle di testo direttamente al centro del grafico principale.

Organizza i controlli con i pannelli

Per rendere più comodo il lavoro con i controlli, potresti voler inserire diversi controlli in un gruppo distinto con la propria posizione nell'interfaccia. Per farlo, puoi usare la classe Panels e i suoi derivati.

Pensa a un pannello come a un controllo con altri controlli come suoi contenuti. cTrader supporta cinque diverse classi che ereditano dalla classe base Panels (che a sua volta eredita dalla classe Control):

  • Canvas
  • DockPanel
  • Grid
  • StackPanel
  • WrapPanel

Ciascuna delle classi sopra usa diversi layout di pannello e strategie di posizionamento come discusso di seguito.

Canvas

Il canvas è un pannello che permette di posizionare i controlli in base a determinate coordinate X e Y.

In particolare, gli assi X e Y sono diversi da quelli usati dagli oggetti del grafico o dai disegni. Le coordinate X e Y usate dalla classe Canvas rappresentano valori numerici a partire da (0, 0) dall'angolo in alto a sinistra del grafico.

Considera il seguente esempio:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Left { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Top { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Margin { get; set; }

        [Parameter(DefaultValue = 10)]
        public double Padding { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                Left = Left,
                Top = Top,
                Margin = Margin,
                Padding = Padding
            };

            button.Click += Button_Click;

            var canvas = new Canvas();

            /* We add our button control to the canvas
            panel. */
            canvas.AddChild(button);

            // We add our canvas panel to the chart.
            Chart.AddControl(canvas);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

Dopo aver creato un'istanza dell'indicatore sopra, dovresti vedere il pulsante Click me nell'angolo in alto a sinistra del grafico.

La proprietà Top di un controllo determina il suo posizionamento sull'asse Y. A sua volta, la proprietà Left definisce il suo posizionamento sull'asse X.

Il codice sopra usa anche le proprietà Padding e Margin. Padding si riferisce alla distanza tra i contenuti del controllo e i suoi bordi esterni. Margin è la distanza tra il controllo e i bordi del suo genitore. Le proprietà Padding e Margin sono applicabili a tutti i pannelli, non solo alla classe canvas. Sono utili per gestire la spaziatura tra i tuoi controlli.

Nella maggior parte dei casi, la classe Canvas viene usata per raggruppare solo un piccolo numero di controlli.

Pannello dock

La classe DockPanel viene usata per ancorare (posizionare) un controllo in una posizione statica sul grafico. Ci sono quattro possibili posizioni di ancoraggio:

  • In alto
  • In basso
  • Sinistra
  • Destra

Ogni controllo ha una proprietà Dock. Quando usi la classe DockPanel, puoi usare questa proprietà per posizionare un controllo all'interno di un DockPanel. Questo è illustrato nell'esempio seguente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = Dock.Top)]
        public Dock TextBoxDock { get; set; }

        [Parameter(DefaultValue = Dock.Bottom)]
        public Dock ButtonDock { get; set; }

        private TextBox _textBox;

        protected override void Initialize()
        {
            _textBox = new TextBox
            {
                Margin = 5,
                Text = "Write here...",
                ForegroundColor = Color.Yellow,
                Dock = TextBoxDock,
                Width = 200
            };

            var button = new Button
            {
                Text = "Tell what I wrote?",
                Dock = ButtonDock,
                Width = 200
            };

            button.Click += Button_Click;

            var dockPanel = new DockPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            dockPanel.AddChild(_textBox);
            dockPanel.AddChild(button);

            Chart.AddControl(dockPanel);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = $"You wrote: {_textBox.Text}";
        }

        public override void Calculate(int index)
        {
        }
    }
}

Quando crei un'istanza di questo indicatore, dovresti vedere un pannello dock al centro del grafico contenente un campo di testo e un pulsante cliccabile.

Nota che i pannelli dock possono essere popolati orizzontalmente o verticalmente. Non puoi usare entrambi questi allineamenti contemporaneamente. L'orientamento del pannello dock viene impostato automaticamente quando si configura il primo controllo in un DockPanel. Se la proprietà Dock del primo controllo è impostata su Top o Bottom, l'intero DockPanel sarà orientato verticalmente, e viceversa.

Pannello stack

I pannelli stack sono uno dei controlli più usati grazie alla loro semplicità e usabilità. I pannelli stack allineano i controlli figlio orizzontalmente o verticalmente uno per uno. Come mostrato di seguito, devi solo impostare il suo orientamento e la classe gestirà il resto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = Orientation.Vertical)]
        public Orientation Orientation { get; set; }

        protected override void Initialize()
        {
            var firstNameTextBox = new TextBox
            {
                Margin = 5,
                Text = "First Name...",
                Width = 200
            };

            var lastNameTextBox = new TextBox
            {
                Margin = 5,
                Text = "Last Name...",
                Width = 200
            };

            var isMarriedCheckBox = new CheckBox
            {
                Text = "Is Married?",
                Margin = 5,
            };

            var submitButton = new Button
            {
                Text = "Submit",
                Margin = 5
            };

            var stackPanel = new StackPanel
            {
                Orientation = Orientation,
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Bottom,
                BackgroundColor = Color.FromArgb(80, Color.Gold),
                Margin = 20
            };

            stackPanel.AddChild(firstNameTextBox);
            stackPanel.AddChild(lastNameTextBox);
            stackPanel.AddChild(isMarriedCheckBox);
            stackPanel.AddChild(submitButton);

            Chart.AddControl(stackPanel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Dopo aver creato un'istanza dell'indicatore, dovresti vedere un pannello stack orizzontale con due campi di testo e un pulsante Submit nell'angolo in basso a destra del grafico principale.

Pannello wrap

I pannelli wrap sono per lo più identici ai pannelli stack. Tuttavia, quando non c'è abbastanza spazio per contenere tutti gli elementi di un pannello wrap, questo avvolgerà automaticamente i controlli rimanenti alla riga successiva sull'asse Y.

Griglia

Pensa alle griglie come a fogli di calcolo con un numero prestabilito di colonne e righe. Quando usi le griglie, puoi aggiungere controlli a ogni cella separata.

Come dimostrato di seguito, quando crei un'istanza della classe Grid, passi il numero delle sue righe e colonne come argomenti integer. Quando aggiungi nuovi figli o controlli, devi specificare in modo simile il numero di righe e colonne figlio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter("Grid Rows #", DefaultValue = 10)]
        public int GridRowsNumber { get; set; }

        [Parameter("Grid Columns #", DefaultValue = 2)]
        public int GridColumnsNumber { get; set; }

        protected override void Initialize()
        {
            var grid = new Grid(GridRowsNumber, GridColumnsNumber)
            {
                BackgroundColor = Color.Gold,
                Opacity = 0.6,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                ShowGridLines = true
            };

            for (int iRow = 0; iRow < GridRowsNumber; iRow++)
            {
                for (int iColumn = 0; iColumn < GridColumnsNumber; iColumn++)
                {
                    grid.AddChild(new TextBlock
                    {
                        Text = string.Format("Row {0} and Column {1}", iRow, iColumn),
                        Margin = 5,
                        ForegroundColor = Color.Black,
                        FontWeight = FontWeight.ExtraBold
                    }, iRow, iColumn);
                }
            }

            Chart.AddControl(grid);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Quando crei un'istanza dell'indicatore sopra, dovresti vedere una griglia 10x2 proprio al centro del grafico.

Posiziona i controlli all'interno delle coordinate di prezzo e tempo

Oltre ai controlli pannello, cTrader permette di specificare le coordinate di prezzo e tempo per i controlli direttamente nell'area del grafico. I metodi AddControl() e MoveControl() forniscono agli sviluppatori di algoritmi questa funzionalità.

Usa i seguenti overload di metodo per gestire le coordinate dei tuoi controlli del grafico in base alle tue preferenze.

Per aggiungere un controllo del grafico al grafico o all'area dell'indicatore su coordinate assolute di indice della barra e prezzo (x, y).

1
void AddControl(ControlBase control, int barIndex, double y)

Per spostare un controllo del grafico al grafico o all'area dell'indicatore su coordinate assolute di indice della barra e prezzo (x, y).

1
void MoveControl(ControlBase control, int barIndex, double y)

Per aggiungere un controllo del grafico al grafico o all'area dell'indicatore su coordinate assolute di tempo e prezzo (x, y).

1
void AddControl(ControlBase control, DateTime time, double y)

Per spostare un controllo del grafico al grafico o all'area dell'indicatore su coordinate assolute di tempo e prezzo (x, y).

1
void MoveControl(ControlBase control, DateTime time, double y)

Per aggiungere un controllo del grafico al grafico o all'area dell'indicatore su coordinata assoluta di tempo (x).

1
void AddControl(ControlBase control, DateTime time)

Per spostare un controllo del grafico al grafico o all'area dell'indicatore su coordinata assoluta di tempo (x).

1
void MoveControl(ControlBase control, DateTime time)

Per aggiungere un controllo del grafico al grafico o all'area dell'indicatore su coordinata assoluta di indice della barra (x).

1
void AddControl(ControlBase control, int barIndex)

Per spostare un controllo del grafico al grafico o all'area dell'indicatore su coordinata assoluta di indice della barra (x).

1
void MoveControl(ControlBase control, int barIndex)

Per aggiungere un controllo del grafico al grafico o all'area dell'indicatore sulla coordinata del prezzo assoluto (y).

1
void AddControl(ControlBase control, double y)

Per spostare un controllo del grafico al grafico o all'area dell'indicatore sulla coordinata del prezzo assoluto (y).

1
void MoveControl(ControlBase control, double y)

La classe del parametro ControlBase può includere qualsiasi altra classe subordinata (Control, Button, ecc.) affinché il metodo venga chiamato in conformità con le firme di cui sopra.

Il seguente esempio di cBot aggiunge il pulsante Cliccami! sopra l'ultima barra sul grafico. Il pulsante viene spostato in avanti insieme a ogni nuova barra aggiunta. Dopo aver cliccato sul pulsante, sullo schermo compare una finestra di messaggio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class ButtonTest : Robot
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        Button button;

        protected override void OnStart() 
        {
            button = new Button
            {
                Text = "Click me!"
            };

            button.Click += Button_Click;

            Chart.AddControl(button, Bars.Count - 1);
        }

        protected override void OnBar() 
        {
            Chart.MoveControl(button, Bars.Count - 1);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            MessageBox.Show(Message, "Title/Caption");
        }
    }
}

Avvertenza

Il numero di controlli radice da aggiungere su un grafico è limitato a 100 a causa di possibili problemi di prestazioni. Questa limitazione si applica solo a un'istanza di algoritmo e ai controlli collegati al prezzo e alle barre.

Proprietà padding e margin

La proprietà Margin definisce lo spazio tra i bordi di un oggetto Control e il suo elemento padre (un grafico, un pannello, un bordo, ecc.).

A sua volta, la proprietà Padding determina lo spazio tra il contenuto del controllo e i suoi bordi. Puoi variare i valori delle proprietà in modo che siano tutti diversi per i diversi lati.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Left { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Top { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double LeftMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double TopMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double RightMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double BottomMargin { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double LeftPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double TopPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double RightPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double BottomPadding { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                Left = Left,
                Top = Top,
                Margin = new Thickness(LeftMargin, TopMargin, RightMargin, BottomMargin),
                Padding = new Thickness(LeftPadding, TopPadding, RightPadding, BottomPadding)
            };

            button.Click += Button_Click;

            var canvas = new Canvas();

            canvas.AddChild(button);

            Chart.AddControl(canvas);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

Un'istanza di questo indicatore creerà un pulsante grigio Cliccami nell'angolo in alto a sinistra del grafico. Modifica i parametri nelle finestre Aggiungi istanza o Modifica parametri per vedere esattamente come i diversi valori di margin e padding cambiano la modalità di visualizzazione del controllo.

Stili

Quando usi gli stili puoi dare un aspetto simile a diversi tipi di controlli. Questo è particolarmente utile quando si ha a che fare con un numero elevato (cinque o più) di controlli.

La classe Style consente di impostare valori per diverse proprietà dei controlli come Margin o BackgroundColor. Successivamente, puoi riutilizzare questi valori come modello per più altri controlli.

Possiamo anche creare un aspetto coerente per più controlli senza utilizzare affatto la classe Style.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var firstTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

            var secondTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

            var thirdTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Ecco come l'utilizzo della classe Style può semplificare il lavoro con più controlli.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var textBoxStyle = new Style();

            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Red);
            textBoxStyle.Set(ControlProperty.Margin, 5);
            textBoxStyle.Set(ControlProperty.FontFamily, "Cambria");
            textBoxStyle.Set(ControlProperty.FontSize, 12);
            textBoxStyle.Set(ControlProperty.Width, 150);

            var firstTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var secondTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var thirdTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Entrambi i frammenti di codice sopra dovrebbero visualizzare gli stessi controlli se avvii le rispettive istanze di indicatore.

Puoi anche utilizzare la classe Style per modificare l'aspetto di un controllo in base al suo stato.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using cAlgo.API;

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var textBoxStyle = new Style();

            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Red);
            textBoxStyle.Set(ControlProperty.Margin, 5);
            textBoxStyle.Set(ControlProperty.FontFamily, "Cambria");
            textBoxStyle.Set(ControlProperty.FontSize, 12);
            textBoxStyle.Set(ControlProperty.Width, 150);
            // Here we change the foreground color to Yellow if mouse hover over the textbox
            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Yellow, ControlState.Hover);

            var firstTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var secondTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var thirdTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Image

Il controllo Image può essere utilizzato per visualizzare un'immagine archiviata localmente. Il controllo Image utilizza la classe .NET Bitmap, il che significa che supporta la maggior parte dei formati di immagine più diffusi come i seguenti:

  • .PNG
  • .JPG
  • .BMP
  • .GIF
  • .TIFF

Consulta la documentazione della classe .NET Bitmap per saperne di più.

Per utilizzare un controllo Image, imposta la sua proprietà Source sui dati del file immagine in un array di byte (byte[]).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using cAlgo.API;
using System.IO;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class ImageSample : Indicator
    {
        [Parameter("Image File Path")]
        public string ImageFilePath { get; set; }

        protected override void Initialize()
        {
            if (File.Exists(ImageFilePath) is false)
            {
                Print($"Image not found: {ImageFilePath}");

                return;
            }

            var imageBytes = File.ReadAllBytes(ImageFilePath);

            var image = new Image
            {
                Source = imageBytes,
                Width = 200,
                Height = 200,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            Chart.AddControl(image);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Dopo aver avviato un'istanza dell'indicatore di cui sopra, non dovresti vedere nulla di nuovo sul grafico principale. Tuttavia, inserisci un percorso file valido come valore del parametro (Image File Path) e dovresti vedere l'immagine scelta visualizzata al centro dello schermo.

Puoi anche utilizzare le risorse del tuo progetto per archiviare le immagini e visualizzarle tramite il controllo Image. Per farlo, apri le risorse del progetto in Visual Studio e passa alla scheda Resources. In essa, crea una nuova risorsa e aggiungi un'immagine esistente. Successivamente, potrai utilizzare questa immagine come sorgente in qualsiasi controllo Image tramite la proprietà Project_Name_Space.Properties.Resources._Image_Name.

Come esempio, copia l'immagine qui sotto e salvala come "image.png" sul tuo sistema:

Image title

Crea un nuovo indicatore in cTrader, imposta il suo nome su "Image Sample" e aprilo tramite Visual Studio. Successivamente, aggiungi il progetto dell'indicatore del logo come risorsa. Per farlo, fai clic con il pulsante destro del mouse sul tuo progetto, seleziona Properties e fai clic su Resources, quindi fai clic su Create and manage assembly resources. Copia il file logo.png nella scheda appena aperta.

Copia il codice qui sotto nel file del codice sorgente principale del tuo indicatore:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ImageSample : Indicator
    {
        protected override void Initialize()
        {
            var image = new Image
            {
                Source = Image_Sample.Properties.Resources.logo,
                Width = 200,
                Height = 200,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            Chart.AddControl(image);
        }

        public override void Calculate(int index)
        {
        }
    }
}

Dopo aver creato un'istanza di questo indicatore, dovresti vedere il seguente output.

Image title

Nota

La dimensione massima per le immagini è 10 MB.