Zum Inhalt

Steuerelemente

Steuerelemente ermöglichen bestimmte Interaktionen mit cBots, Indikatoren und Plugins. Mithilfe der nachfolgenden Anleitung können Sie einfache und erweiterte UI-Steuerelemente direkt in einem Chart erstellen.

Es gibt mehrere integrierte Klassen, die gängige Steuerelemente wie Buttons, Textblöcke, Textfelder und Formen darstellen. Sie können jedoch auch benutzerdefinierte Steuerelemente erstellen.

Betrachten Sie das folgende Beispiel:

 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)
        {
        }
    }
}

Wenn Sie den obigen Indikator erstellen und eine Instanz anlegen, sollten Sie einen grauen Button Klick mich genau in der Mitte des Charts sehen.

Unterschied zwischen Steuerelementen und Chartobjekten

In einem früheren Abschnitt haben wir bereits Chartobjekte behandelt. Steuerelemente ermöglichen es Benutzern, mit cBots und Indikatoren zu interagieren. Umgekehrt bieten Chartobjekte die Möglichkeit, etwas auf dem Handelschart oder in einem separaten Indikatorausgabefenster zu zeichnen.

Chartsteuerelemente leiten sich von der Klasse ControlBase ab, während Chartobjekte von der Klasse ChartObject abgeleitet sind.

Chartsteuerelemente werden statisch positioniert, indem verschiedene Ausrichtungsoptionen verwendet werden. Während Chartobjekte auf genau die gleiche Weise positioniert werden können, kann sich ihre Position auch dynamisch in Abhängigkeit von bestimmten X- und Y-Koordinaten ändern.

Ähnlich wie Chartobjekte können Chartsteuerelemente sowohl zum Hauptchart als auch zu beliebigen Indikatorausgabefenstern (falls vorhanden) hinzugefügt werden. Ein Beispiel für eine solche Positionierung wird nachfolgend gegeben:

 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)
        {
        }
    }
}

Nach dem Erstellen einer Indikatorinstanz sollten Sie einen Button Klick mich im Indikatorausgabefenster sehen.

ColorPicker

Das Steuerelement ColorPicker ermöglicht es Händlern, ihre bevorzugte Farbe für wichtige Elemente oder Objekte in cTrader auszuwählen. Beispielsweise kann ein Entwickler das Steuerelement ColorPicker in einen cBot integrieren, der Trendlinien zeichnet, sodass Benutzer ihre bevorzugte Farbe für jede Trendlinie auswählen können. Diese Einrichtung erleichtert es Händlern, zwischen verschiedenen Trendlinientypen zu unterscheiden.

Ein Plugin, das Indikatoren zu Charts hinzufügt, kann ebenfalls das Steuerelement ColorPicker implementieren, da diese Funktion es Benutzern ermöglicht, eine Farbe für verschiedene Indikatorlinien auszuwählen.

Wenn Benutzer auf das Farbquadrat klicken, erscheint die Farbauswahl. Benutzer können dann zwischen Standardfarben und benutzerdefinierten Farben wählen.

Codebeispiel:

 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

Das Steuerelement DropZone ermöglicht es Händlern, Drag-and-Drop-Aktionen mit cBots, Indikatoren oder Plugins durchzuführen. Um dieses Steuerelement in Ihrem Algorithmus zu implementieren, verwenden Sie die Klasse DropZone. Das Steuerelement DropZone kann wie jedes andere Steuerelement manipuliert werden.

Wenn ein Benutzer eine kompatible Datei oder einen Ordner in das Feld zieht, wird das Ereignis Dropped generiert. Wenn ein Benutzer einen Ordner oder mehrere Ordner in das Feld zieht, werden nur kompatible Dateien mit den in FilterExtensions angegebenen Erweiterungen verarbeitet und kopiert.

Hinweis

Die abgelegten Dateien werden normalerweise an diesem Speicherort kopiert und gespeichert: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\

Der Speicherort für cBot-Instanzen unterscheidet sich vom obigen: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\

Dieser Plugin-Code zeigt Ihnen, wie Sie ein Steuerelement DropZone zu Trade Watch hinzufügen:

 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

Das Steuerelement ProgressBar zeigt den Fortschritt einer laufenden Operation an. Fortschrittsbalken machen Algorithmen benutzerfreundlicher und helfen, die Erwartungen der Händler hinsichtlich der Wartezeit für bestimmte Operationen zu steuern.

Die cTrader Algo API ermöglicht es Entwicklern, zwei Arten von Steuerelementen ProgressBar hinzuzufügen: unendliches Steuerelement und bestimmtes Steuerelement.

Unendliches Steuerelement

Sie möchten möglicherweise ein unendliches Steuerelement in den folgenden Situationen verwenden:

  • Sie können die Wartezeit für eine Operation nicht bestimmen.
  • Sie können den Fortschritt einer Operation nicht erkennen.
  • Sie möchten nicht angeben, wie lange eine Operation dauern wird.

Image title

Bestimmtes Steuerelement

Sie möchten dieses Steuerelement möglicherweise verwenden, wenn Sie die Wartezeit für eine Operation bestimmen können und möchten, dass Benutzer einen Indikator basierend auf dieser Zeit sehen.

Um den Fortschritt der Operation anzuzeigen, verwenden Sie die Eigenschaft Value, um eine Zahl festzulegen. Um den Prozentsatz des Fortschrittsbalkens festzulegen, verwenden Sie die Eigenschaften Minimum und Maximum.

Image title

Der nachfolgende Plugin-Code zeigt Ihnen, wie Sie einen Fortschrittsbalken mit sowohl unendlichen als auch bestimmten (grünen) Steuerelementen erstellen:

 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
        }
    }        
}

Dialogfenster

OpenFileDialog und OpenFolderDialog

Die cTrader Algo API stellt die Schnittstelle OpenFileDialog bereit, um Benutzern die Auswahl einer Datei für einen Algorithmus zu ermöglichen. Wenn ein Benutzer eine Datei im resultierenden Fenster auswählt, wird die Datei in den Ordner Selected files des Algorithmus kopiert. Ein Algorithmus kann ohne Einschränkungen mit Dateien in seinem Ordner Selected files arbeiten.

Tipp

Verwenden Sie die Funktionalität OpenFileDialog, wenn Sie wichtige Datendateien, Sicherungs- oder Konfigurationsdateien, benutzerdefinierte Indikatoren oder Skripte laden müssen.

Der nachfolgende Code zeigt Ihnen, wie Sie das Dialogfenster OpenFileDialog in einem Indikator verwenden:

 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

Die cTrader Algo API stellt die Schnittstelle OpenFolderDialog bereit, um Benutzern die Angabe eines Ordners für einen Algorithmus zu ermöglichen. Wenn ein Benutzer einen Ordner im resultierenden Fenster auswählt, werden alle Dateien und Ordner mit Dateien innerhalb des ausgewählten Ordners in den Ordner Selected files des Algorithmus kopiert.

Tipp

Verwenden Sie die Funktionalität OpenFolderDialog, wenn Sie einen Ordner laden müssen, der kritische Datendateien, Sicherungs- oder Konfigurationsdateien, benutzerdefinierte Indikatoren oder Skripte enthält.

Ausgewählte Dateien und Ordner werden normalerweise in den Ordner Selected files kopiert, da ein Algorithmus mit Elementen in diesem Ordner arbeiten kann, selbst wenn seine AccessRights auf None gesetzt sind.

Hinweis

Der Ordner Selected files eines Algorithmus befindet sich normalerweise unter folgendem Pfad: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\ ((4)) ((4)) Der Ordner Selected files für eine cBot-Instanz unterscheidet sich vom obigen Pfad: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\

Der nachstehende Code zeigt Ihnen, wie Sie den Dialog OpenFolderDialog in einem Indikator verwenden:

 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

Die cTrader Algo API stellt die Schnittstelle SaveFileDialog bereit, um Nutzern das (lokale) Speichern von Dateien auf ihren Computern zu ermöglichen. Wenn das entsprechende Fenster erscheint, wählt ein Nutzer den Ordner aus, in dem er die Datei speichern möchte, und gibt einen Namen für die Datei ein. Die Datei wird dann am angegebenen Speicherort gespeichert.

Tipp

Nutzen Sie die Funktionalität SaveFileDialog, wenn Sie eine der folgenden Aktionen durchführen müssen:

  • Speichern von Leistungsberichten, Backtesting-Ergebnissen, Konfigurationsdateien oder Optimierungsdaten.
  • Exportieren von Handelsprotokollen, Operationsjournalen oder allgemeinen Nutzeraktivitätsdaten.
  • Speichern von benutzerdefinierten Indikatoren, Daten für Charts und Visualisierungen oder Parametern für eine Strategie.

Der nachstehende Code zeigt Ihnen, wie Sie den Dialog SaveFileDialog in einem Indikator verwenden:

 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)
        {
        }
    }
}

Ziehbare Steuerelemente

Ziehbares Steuerelement im Chartbereich

Die Schnittstellen ChartDraggable und ChartDraggables stellen Typen bereit, mit denen Sie einem Chart ein ziehbares Steuerelement hinzufügen können, das andere Steuerelemente und verschiedene Elemente hosten kann. Diese ziehbaren Steuerelemente erleichtern Nutzern die Interaktion mit verschiedenen Chartelementen.

Hinweis

Ein ziehbares Steuerelement kann nur innerhalb des Charts verschoben oder neu positioniert werden, zu dem es hinzugefügt wurde.

Dieser Code zeigt Ihnen, wie Sie einen Indikator erstellen, der zwei Steuerelemente hinzufügt, die innerhalb eines Charts verschoben werden können:

 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})");
        }
    }
}

Ziehbares Steuerelement im Anwendungsfenster

Die Schnittstellen ApplicationDraggable und ApplicationDraggables stellen die Typen bereit, die zum Hinzufügen von unverankerten Steuerelementen verwendet werden, die einzeln über das gesamte cTrader-Anwendungsfenster verschoben werden können. Solche Steuerelemente ermöglichen es Ihnen, interaktive und dynamische Benutzeroberflächen zu erstellen.

Hinweis

Von den drei Algorithmustypen dürfen nur Plugins anwendungsweite ziehbare Steuerelemente implementieren.

Dieser Code zeigt Ihnen, wie Sie ein Plugin erstellen, das eine WebView-Komponente und einen Textblock in zwei separaten Fenstern hinzufügt, die über die gesamte cTrader-Benutzeroberfläche verschoben werden können:

 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;
        }
    }
}

Registerkarten-Steuerelement

Die Klasse TabControl stellt Typen bereit, mit denen Sie mehrere Registerkarten für einen Algorithmus erstellen können. Diese Registerkarten können verwendet werden, um zusammengehörige Elemente zusammenzuhalten oder separate Ansichten für Funktionalitäten darzustellen.

Dieser Code zeigt Ihnen, wie Sie Registerkarten in einem Plugin verwenden, das dem Bereich eines aktiven Symbols hinzugefügt wurde:

 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()
        {
        }
    }
}

Benutzerdefinierte Steuerelemente

Ein benutzerdefiniertes Steuerelement ist ein Steuerelement, das im Wesentlichen aus mehreren vordefinierten Steuerelementen aufgebaut ist. Mit anderen Worten: Es ist ein Steuerelement, für das andere Steuerelemente seinen Inhalt bilden.

Benutzerdefinierte Steuerelemente fungieren ähnlich wie integrierte Steuerelemente als wiederverwendbare Klassen.

 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);
        }
    }
}

Eine Instanz dieses Indikators sollte vier Textfelder direkt in der Mitte des Hauptcharts anzeigen.

Steuerelemente mit Panels organisieren

Um die Arbeit mit Steuerelementen komfortabler zu gestalten, möchten Sie möglicherweise mehrere Steuerelemente in einer eigenen Gruppe mit eigener Position in der Benutzeroberfläche platzieren. Hierzu können Sie die Klasse Panels und ihre Ableitungen verwenden.

Stellen Sie sich ein Panel als ein Steuerelement mit anderen Steuerelementen als Inhalt vor. cTrader unterstützt fünf verschiedene Klassen, die von der Basisklasse Panels erben (die selbst von der Klasse Control erbt):

  • Canvas
  • DockPanel
  • Grid
  • StackPanel
  • WrapPanel

Jede der oben genannten Klassen verwendet unterschiedliche Panel-Layouts und Positionierungsstrategien, wie nachstehend erläutert.

Canvas

Das Canvas ist ein Panel, das die Positionierung von Steuerelementen basierend auf bestimmten X- und Y-Koordinaten ermöglicht.

Bemerkenswert ist, dass sich die X- und Y-Achsen von denen unterscheiden, die von Chartobjekten oder Zeichnungen verwendet werden. Die von der Klasse Canvas verwendeten X- und Y-Koordinaten stellen numerische Werte dar, die von (0, 0) aus der oberen linken Ecke des Charts beginnen.

Betrachten Sie das folgende Beispiel:

 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)
        {
        }
    }
}

Beim Erstellen einer Instanz des oben genannten Indikators sollten Sie den Button Click me in der oberen linken Ecke des Charts sehen.

Die Eigenschaft Top eines Steuerelements bestimmt seine Positionierung auf der Y-Achse. Die Eigenschaft Left wiederum definiert seine Positionierung auf der X-Achse.

Der obige Code verwendet auch die Eigenschaften Padding und Margin. Padding bezieht sich auf den Abstand zwischen dem Inhalt des Steuerelements und seinen äußeren Rändern. Margin ist der Abstand zwischen dem Steuerelement und den Rändern seines übergeordneten Elements. Die Eigenschaften Padding und Margin sind auf alle Panels anwendbar, nicht nur auf die Canvas-Klasse. Sie sind nützlich für die Verwaltung von Abständen zwischen Ihren Steuerelementen.

In der Mehrzahl der Fälle wird die Klasse Canvas verwendet, um nur eine kleine Anzahl von Steuerelementen zu gruppieren.

Dock-Panel

Die Klasse DockPanel wird verwendet, um ein Steuerelement an einer statischen Position im Chart anzudocken (zu platzieren). Es gibt vier mögliche Dock-Positionen:

  • Oben
  • Unten
  • Links
  • Rechts

Jedes Steuerelement verfügt über eine Eigenschaft Dock. Bei Verwendung der Klasse DockPanel können Sie diese Eigenschaft verwenden, um ein Steuerelement innerhalb eines DockPanel zu positionieren. Dies wird im folgenden Beispiel veranschaulicht:

 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)
        {
        }
    }
}

Beim Erstellen einer Instanz dieses Indikators sollten Sie ein Dock-Panel in der Mitte des Charts sehen, das ein Textfeld und einen anklickbaren Button enthält.

Beachten Sie, dass Dock-Panels entweder horizontal oder vertikal befüllt werden können. Sie können nicht beide dieser Ausrichtungen gleichzeitig verwenden. Die Ausrichtung des Dock-Panels wird automatisch festgelegt, wenn das erste Steuerelement in einem DockPanel eingerichtet wird. Wenn die Eigenschaft Dock des ersten Steuerelements auf Top oder Bottom gesetzt ist, wird das gesamte DockPanel vertikal ausgerichtet, und umgekehrt.

Stack-Panel

Stack-Panels gehören aufgrund ihrer Einfachheit und Benutzerfreundlichkeit zu den am häufigsten verwendeten Steuerelementen. Stack-Panels richten untergeordnete Steuerelemente entweder horizontal oder vertikal nacheinander aus. Wie nachstehend gezeigt, müssen Sie nur seine Ausrichtung festlegen, und die Klasse verwaltet den Rest:

 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)
        {
        }
    }
}

Nach dem Erstellen einer Indikatorinstanz sollten Sie ein horizontales Stack-Panel mit zwei Textfeldern und einem Button Submit in der unteren rechten Ecke des Hauptcharts sehen.

Wrap-Panel

Wrap-Panels sind größtenteils identisch mit Stack-Panels. Wenn jedoch nicht genügend Platz vorhanden ist, um alle Elemente eines Wrap-Panels unterzubringen, werden die verbleibenden Steuerelemente automatisch in die nächste Zeile auf der Y-Achse umgebrochen.

Raster

Stellen Sie sich Raster als Tabellenkalkulationen mit einer festgelegten Anzahl von Spalten und Zeilen vor. Bei Verwendung von Rastern können Sie jeder einzelnen Zelle Steuerelemente hinzufügen.

Wie nachstehend demonstriert, übergeben Sie beim Erstellen einer Instanz der Klasse Grid die Anzahl ihrer Zeilen und Spalten als integer-Argumente. Beim Hinzufügen neuer untergeordneter Elemente oder Steuerelemente müssen Sie ebenfalls die Anzahl der untergeordneten Zeilen und Spalten angeben.

 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)
        {
        }
    }
}

Beim Erstellen einer Instanz des oben genannten Indikators sollten Sie ein 10x2-Raster direkt in der Mitte des Charts sehen.

Steuerelemente innerhalb von Kurs- und Zeitkoordinaten positionieren

Zusätzlich zu Panel-Steuerelementen ermöglicht cTrader die direkte Angabe von Kurs- und Zeitkoordinaten für Steuerelemente im Chartbereich. Die Methoden AddControl() und MoveControl() stellen Algo-Entwicklern diese Funktionalität zur Verfügung.

Verwenden Sie die folgenden Methodenüberladungen, um die Koordinaten Ihrer Chart-Steuerelemente je nach Ihren Präferenzen zu verwalten.

Um ein Chart-Steuerelement zum Chart- oder Indikatorbereich auf absoluten Balkenindex- und Kurs-(x, y)-Koordinaten hinzuzufügen.

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

Um ein Chartsteuerungselement in den Chart- oder Indikatorbereich auf absoluten Balkenindex- und Kurs-(x, y-)Koordinaten zu verschieben.

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

Um ein Chartsteuerungselement zum Chart- oder Indikatorbereich auf absoluten Zeit- und Kurs-(x, y-)Koordinaten hinzuzufügen.

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

Um ein Chartsteuerungselement in den Chart- oder Indikatorbereich auf absoluten Zeit- und Kurs-(x, y-)Koordinaten zu verschieben.

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

Um ein Chartsteuerungselement zum Chart- oder Indikatorbereich auf absoluter Zeit-(x-)Koordinate hinzuzufügen.

1
void AddControl(ControlBase control, DateTime time)

Um ein Chartsteuerungselement in den Chart- oder Indikatorbereich auf absoluter Zeit-(x-)Koordinate zu verschieben.

1
void MoveControl(ControlBase control, DateTime time)

Um ein Chartsteuerungselement zum Chart- oder Indikatorbereich auf absoluter Balkenindex-(x-)Koordinate hinzuzufügen.

1
void AddControl(ControlBase control, int barIndex)

Um ein Chartsteuerungselement in den Chart- oder Indikatorbereich auf absoluter Balkenindex-(x-)Koordinate zu verschieben.

1
void MoveControl(ControlBase control, int barIndex)

Um ein Chartsteuerungselement zum Chart- oder Indikatorbereich auf absoluter Kurs-(y-)Koordinate hinzuzufügen.

1
void AddControl(ControlBase control, double y)

Um ein Chartsteuerungselement in den Chart- oder Indikatorbereich auf absoluter Kurs-(y-)Koordinate zu verschieben.

1
void MoveControl(ControlBase control, double y)

Die Parameterklasse ControlBase kann jede andere untergeordnete Klasse (Control, Button usw.) enthalten, damit die Methode gemäß den obigen Signaturen aufgerufen wird.

Das folgende cBot-Beispiel fügt die Schaltfläche Klick mich! über dem letzten Balken im Chart hinzu. Die Schaltfläche wird mit jedem neu hinzugefügten Balken nach vorne verschoben. Nach dem Klicken auf die Schaltfläche erscheint ein Meldungsfeld auf dem Bildschirm.

 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");
        }
    }
}

Warnung

Die Anzahl der Stammsteuerungselemente, die einem Chart hinzugefügt werden können, ist aufgrund möglicher Leistungsprobleme auf 100 begrenzt. Diese Einschränkung gilt nur für eine Algorithmusinstanz und Steuerungselemente, die an Kurse und Balken angehängt sind.

Padding- und Margin-Eigenschaften

Die Eigenschaft Margin definiert den Abstand zwischen den Rändern eines Control-Objekts und seinem übergeordneten Element (einem Chart, einem Bereich, einem Rahmen usw.).

Die Eigenschaft Padding wiederum bestimmt den Abstand zwischen dem Inhalt des Steuerungselements und seinen Rändern. Sie können die Eigenschaftswerte so variieren, dass sie für verschiedene Seiten alle unterschiedlich sind.

 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)
        {
        }
    }
}

Eine Instanz dieses Indikators erstellt eine graue Schaltfläche Klick mich in der oberen linken Ecke des Charts. Ändern Sie die Parameter in den Fenstern Instanz hinzufügen oder Parameter ändern, um zu sehen, wie genau unterschiedliche Margin- und Padding-Werte die Darstellung des Steuerungselements verändern.

Stile

Bei Verwendung von Stilen können Sie mehreren verschiedenen Arten von Steuerungselementen ein ähnliches Aussehen verleihen. Dies ist besonders nützlich, wenn Sie mit einer großen (fünf oder mehr) Anzahl von Steuerungselementen arbeiten.

Die Klasse Style ermöglicht das Festlegen von Werten für verschiedene Eigenschaften von Steuerungselementen wie Margin oder BackgroundColor. Anschließend können Sie diese Werte als Vorlage für mehrere andere Steuerungselemente wiederverwenden.

Wir können auch ein einheitliches Aussehen für mehrere Steuerungselemente erstellen, ohne die Klasse Style überhaupt zu verwenden.

 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)
        {
        }
    }
}

So kann die Verwendung der Klasse Style die Arbeit mit mehreren Steuerungselementen vereinfachen.

 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)
        {
        }
    }
}

Beide obigen Codeausschnitte sollten dieselben Steuerungselemente anzeigen, wenn Sie ihre jeweiligen Indikatorinstanzen starten.

Sie können auch die Klasse Style verwenden, um das Aussehen eines Steuerungselements basierend auf seinem Zustand zu ändern.

 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)
        {
        }
    }
}

Bild

Das Steuerungselement Image kann verwendet werden, um ein lokal gespeichertes Bild anzuzeigen. Das Steuerungselement Image verwendet die .NET-Bitmap-Klasse, was bedeutet, dass es die Mehrheit der gängigen Bildformate wie die folgenden unterstützt:

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

Konsultieren Sie die Dokumentation der .NET-Bitmap-Klasse, um mehr darüber zu erfahren.

Um ein Steuerungselement Image zu verwenden, setzen Sie seine Eigenschaft Source auf Bilddateidaten in einem Byte-Array (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)
        {
        }
    }
}

Nach dem Starten einer Instanz des obigen Indikators sollten Sie nichts Neues im Hauptchart sehen. Geben Sie jedoch einen gültigen Dateipfad als Wert des Parameters (Bilddateipfad) ein, und Sie sollten das ausgewählte Bild in der Mitte des Bildschirms sehen.

Sie können auch Ihre Projektressourcen zum Speichern von Bildern und deren Anzeige über das Steuerungselement Image verwenden. Öffnen Sie dazu die Projektressourcen in Visual Studio und wechseln Sie zur Registerkarte Resources. Erstellen Sie darin eine neue Ressource und fügen Sie ein vorhandenes Bild hinzu. Anschließend können Sie dieses Bild als Quelle in jedem Steuerungselement Image über die Eigenschaft Project_Name_Space.Properties.Resources._Image_Name verwenden.

Kopieren Sie als Beispiel das untenstehende Bild und speichern Sie es als „image.png" auf Ihrem System:

Image title

Erstellen Sie einen neuen Indikator in cTrader, setzen Sie seinen Namen auf „Image Sample" und öffnen Sie ihn über Visual Studio. Fügen Sie anschließend das Logo-Indikatorprojekt als Ressource hinzu. Klicken Sie dazu mit der rechten Maustaste auf Ihr Projekt, wählen Sie Properties und klicken Sie auf Resources, dann klicken Sie auf Create and manage assembly resources. Kopieren Sie die Datei logo.png in die neu geöffnete Registerkarte.

Kopieren Sie den untenstehenden Code in Ihre Hauptquellcodedatei des Indikators:

 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)
        {
        }
    }
}

Nach dem Erstellen einer Instanz dieses Indikators sollten Sie die folgende Ausgabe sehen.

Image title

Hinweis

Die maximale Größe für Bilder beträgt 10 MB.