Bỏ qua

Điều khiển

Điều khiển cho phép một số tương tác liên quan đến cBot, chỉ báo và plugin. Sử dụng hướng dẫn dưới đây, bạn có thể dễ dàng tạo các điều khiển giao diện người dùng cơ bản và nâng cao trực tiếp trên biểu đồ.

Có một số lớp tích hợp sẵn đại diện cho các điều khiển phổ biến như nút, khối văn bản, hộp văn bản và hình dạng. Tuy nhiên, bạn cũng có thể tạo các điều khiển tùy chỉnh.

Xem xét ví dụ sau:

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

Nếu bạn xây dựng chỉ báo trên và tạo một thể hiện, bạn sẽ thấy một nút Click me màu xám ngay giữa biểu đồ.

Sự khác biệt giữa điều khiển và đối tượng biểu đồ

Trong phần trước, chúng tôi đã đề cập đến các đối tượng biểu đồ. Điều khiển cho phép người dùng tương tác với cBot và chỉ báo. Ngược lại, đối tượng biểu đồ cho phép vẽ một thứ gì đó trên biểu đồ giao dịch hoặc trong cửa sổ đầu ra chỉ báo tách rời.

Điều khiển biểu đồ được kế thừa từ lớp ControlBase trong khi đối tượng biểu đồ được kế thừa từ lớp ChartObject.

Điều khiển biểu đồ được định vị tĩnh bằng cách sử dụng các tùy chọn căn chỉnh khác nhau. Mặc dù đối tượng biểu đồ có thể được định vị theo cách hoàn toàn giống nhau, vị trí của chúng cũng có thể thay đổi động tùy thuộc vào các tọa độ X và Y nhất định.

Tương tự như đối tượng biểu đồ, điều khiển biểu đồ có thể được thêm vào cả biểu đồ chính và bất kỳ cửa sổ đầu ra chỉ báo nào (nếu có). Một ví dụ về việc định vị như vậy được đưa ra dưới đây:

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

Sau khi tạo một thể hiện chỉ báo, bạn sẽ thấy một nút Click me trong cửa sổ đầu ra chỉ báo.

ColorPicker

Điều khiển ColorPicker cho phép các nhà giao dịch chọn màu sắc ưa thích cho các yếu tố hoặc đối tượng chính trong cTrader. Ví dụ, nhà phát triển có thể tích hợp điều khiển ColorPicker vào cBot vẽ đường xu hướng để người dùng có thể chọn màu ưa thích cho mỗi đường xu hướng. Thiết lập này giúp các nhà giao dịch dễ dàng phân biệt giữa các loại đường xu hướng khác nhau.

Một plugin thêm chỉ báo vào biểu đồ cũng có thể triển khai điều khiển ColorPicker vì tính năng này cho phép người dùng chọn màu cho các đường chỉ báo khác nhau.

Khi người dùng nhấp vào ô màu, bộ chọn màu sẽ xuất hiện. Sau đó, người dùng có thể chọn giữa các màu tiêu chuẩn và tùy chỉnh.

Mẫu mã:

 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

Điều khiển DropZone cho phép các nhà giao dịch thực hiện các thao tác kéo và thả liên quan đến cBot, chỉ báo hoặc plugin. Để triển khai điều khiển này trong thuật toán của bạn, hãy sử dụng lớp DropZone. Điều khiển DropZone có thể được thao tác như bất kỳ điều khiển nào khác.

Khi người dùng thả một tệp hoặc thư mục tương thích vào hộp, sự kiện Dropped sẽ được tạo ra. Khi người dùng thả một thư mục hoặc nhiều thư mục vào hộp, chỉ các tệp tương thích có phần mở rộng được chỉ định trong FilterExtensions mới được xử lý và sao chép.

Ghi chú

Các tệp được thả thường được sao chép và lưu ở vị trí này: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\

Vị trí cho các thể hiện cBot khác với trên: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\

Mã plugin này cho bạn thấy cách thêm điều khiển DropZone vào 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

Điều khiển ProgressBar hiển thị tiến trình của một hoạt động đang diễn ra. Thanh tiến trình giúp các thuật toán thân thiện với người dùng hơn và giúp quản lý kỳ vọng của các nhà giao dịch về thời gian chờ đợi cho các hoạt động nhất định.

cTrader Algo API cho phép các nhà phát triển thêm hai loại điều khiển ProgressBar: điều khiển vô hạn và điều khiển xác định.

Điều khiển vô hạn

Bạn có thể muốn sử dụng điều khiển vô hạn trong các tình huống sau:

  • Bạn không thể xác định thời gian chờ đợi cho một hoạt động.
  • Bạn không thể phát hiện tiến trình của một hoạt động.
  • Bạn không muốn chỉ ra hoạt động sẽ mất bao lâu.

Image title

Điều khiển xác định

Bạn có thể muốn sử dụng điều khiển này khi bạn có thể xác định thời gian chờ đợi cho một hoạt động và muốn người dùng thấy một chỉ báo dựa trên thời gian đó.

Để hiển thị tiến trình của hoạt động, sử dụng thuộc tính Value để đặt một con số. Để đặt phần trăm thanh tiến trình, sử dụng các thuộc tính MinimumMaximum.

Image title

Mã plugin dưới đây cho bạn thấy cách tạo thanh tiến trình sử dụng cả điều khiển vô hạn và xác định (màu xanh lá):

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

Hộp thoại

OpenFileDialog và OpenFolderDialog

cTrader Algo API cung cấp giao diện OpenFileDialog để cho phép người dùng chọn một tệp cho thuật toán. Khi người dùng chọn một tệp trong cửa sổ kết quả, tệp đó được sao chép vào thư mục Selected files của thuật toán. Một thuật toán có thể làm việc với các tệp bên trong thư mục Selected files của nó mà không bị hạn chế.

Mẹo

Sử dụng chức năng OpenFileDialog khi bạn cần tải các tệp dữ liệu quan trọng, tệp sao lưu hoặc cấu hình, chỉ báo tùy chỉnh hoặc tập lệnh.

Mã dưới đây cho bạn thấy cách sử dụng hộp thoại OpenFileDialog trong một chỉ báo:

 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

cTrader Algo API cung cấp giao diện OpenFolderDialog để cho phép người dùng chỉ định một thư mục cho thuật toán. Khi người dùng chọn một thư mục trong cửa sổ kết quả, tất cả các tệp và thư mục có tệp bên trong thư mục được chọn sẽ được sao chép vào thư mục Selected files của thuật toán.

Mẹo

Sử dụng chức năng OpenFolderDialog khi bạn cần tải một thư mục chứa các tệp dữ liệu quan trọng, tệp sao lưu hoặc cấu hình, chỉ báo tùy chỉnh hoặc tập lệnh.

Các tệp và thư mục được chọn thường được sao chép vào thư mục Selected files vì một thuật toán có thể làm việc với các mục bên trong thư mục đó ngay cả khi AccessRights của nó được đặt thành None.

Ghi chú

Thư mục Selected files của một thuật toán thường nằm theo đường dẫn này: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\

Thư mục Selected files cho một thể hiện cBot khác với trên: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\

Mã dưới đây cho bạn thấy cách sử dụng hộp thoại OpenFolderDialog trong một chỉ báo:

 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

API cTrader Algo cung cấp giao diện SaveFileDialog để cho phép người dùng lưu các tệp (cục bộ) vào máy tính của họ. Khi cửa sổ liên quan xuất hiện, người dùng chọn thư mục mà họ muốn lưu tệp và nhập tên cho tệp. Sau đó, tệp sẽ được lưu vào vị trí đã chỉ định.

Mẹo

Sử dụng chức năng SaveFileDialog khi bạn cần thực hiện bất kỳ điều nào sau đây:

  • Lưu báo cáo hiệu suất, kết quả backtest, tệp cấu hình hoặc dữ liệu tối ưu hóa.
  • Xuất bản ghi giao dịch, nhật ký hoạt động hoặc dữ liệu hoạt động chung của người dùng.
  • Lưu trữ các chỉ báo tùy chỉnh, dữ liệu cho biểu đồ và trực quan hóa hoặc các tham số cho chiến lược.

Mã dưới đây cho bạn thấy cách sử dụng hộp thoại SaveFileDialog trong một chỉ báo:

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

Các điều khiển có thể kéo thả

Điều khiển có thể kéo thả trong khu vực biểu đồ

Các giao diện ChartDraggableChartDraggables cung cấp các loại cho phép bạn thêm một điều khiển có thể kéo thả có khả năng chứa các điều khiển khác và các phần tử khác nhau vào biểu đồ. Các điều khiển có thể kéo thả này giúp người dùng dễ dàng tương tác với các phần tử biểu đồ khác nhau hơn.

Ghi chú

Một điều khiển có thể kéo thả chỉ có thể được di chuyển hoặc định vị lại trong phạm vi biểu đồ nơi nó đã được thêm vào.

Đoạn mã này cho bạn thấy cách tạo một chỉ báo thêm hai điều khiển có thể di chuyển trong biểu đồ:

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

Điều khiển có thể kéo thả trong cửa sổ ứng dụng

Các giao diện ApplicationDraggableApplicationDraggables cung cấp các loại được sử dụng để thêm các điều khiển nổi có thể di chuyển riêng lẻ trên toàn bộ cửa sổ ứng dụng cTrader. Các điều khiển như vậy cho phép bạn tạo ra giao diện người dùng tương tác và năng động.

Ghi chú

Trong ba loại thuật toán, chỉ có plugin được phép triển khai các điều khiển có thể kéo thả trên toàn ứng dụng.

Đoạn mã này cho bạn thấy cách tạo một plugin thêm một thành phần WebView và khối văn bản trong hai cửa sổ riêng biệt, có thể di chuyển trên toàn bộ giao diện người dùng 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;
        }
    }
}

Điều khiển tab

Lớp TabControl cung cấp các loại cho phép bạn tạo nhiều tab cho một thuật toán. Các tab này có thể được sử dụng để giữ các phần tử liên quan với nhau hoặc trình bày các chế độ xem riêng biệt cho các chức năng.

Đoạn mã này cho bạn thấy cách sử dụng các tab trong một plugin được thêm vào Bảng ký hiệu đang hoạt động:

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

Các điều khiển tùy chỉnh

Một điều khiển tùy chỉnh về bản chất là một điều khiển được tạo thành từ một số điều khiển được xác định trước. Nói cách khác, đó là một điều khiển mà các điều khiển khác tạo nên nội dung của nó.

Các điều khiển tùy chỉnh hoạt động như các lớp có thể tái sử dụng tương tự như các điều khiển tích hợp sẵn.

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

Một phiên bản của chỉ báo này sẽ hiển thị bốn hộp văn bản trực tiếp ở trung tâm của biểu đồ chính.

Sắp xếp các điều khiển bằng panel

Để làm việc với các điều khiển thuận tiện hơn, bạn có thể muốn đặt một số điều khiển vào một nhóm riêng biệt với vị trí riêng trong giao diện người dùng. Để làm điều này, bạn có thể sử dụng lớp Panels và các lớp dẫn xuất của nó.

Hãy xem panel như một điều khiển có các điều khiển khác làm nội dung của nó. cTrader hỗ trợ năm lớp khác nhau kế thừa từ lớp cơ sở Panels (lớp này kế thừa từ lớp Control):

  • Canvas
  • DockPanel
  • Grid
  • StackPanel
  • WrapPanel

Mỗi lớp trong số các lớp trên sử dụng các bố cục panel và chiến lược định vị khác nhau như được thảo luận dưới đây.

Canvas

Canvas là một panel cho phép định vị các điều khiển dựa trên các tọa độ X và Y nhất định.

Đáng chú ý là trục X và Y khác với các trục được sử dụng bởi các đối tượng biểu đồ hoặc bản vẽ. Tọa độ X và Y được sử dụng bởi lớp Canvas đại diện cho các giá trị số bắt đầu từ (0, 0) từ góc trên bên trái của biểu đồ.

Xem xét ví dụ sau:

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

Khi tạo một phiên bản của chỉ báo trên, bạn sẽ thấy nút Click me ở góc trên bên trái của biểu đồ.

Thuộc tính Top của một điều khiển xác định vị trí của nó trên trục Y. Ngược lại, thuộc tính Left xác định vị trí của nó trên trục X.

Đoạn mã trên cũng sử dụng các thuộc tính PaddingMargin. Padding đề cập đến khoảng cách giữa nội dung điều khiển và đường viền ngoài của nó. Margin là khoảng cách giữa điều khiển và đường viền của phần tử cha của nó. Các thuộc tính PaddingMargin áp dụng cho tất cả các panel, không chỉ riêng lớp canvas. Chúng hữu ích để quản lý khoảng cách giữa các điều khiển của bạn.

Trong phần lớn các trường hợp, lớp Canvas được sử dụng để nhóm chỉ một số lượng nhỏ các điều khiển.

Gắn bảng điều khiển

Lớp DockPanel được sử dụng để gắn (đặt) một điều khiển vào một vị trí cố định trên biểu đồ. Có bốn vị trí gắn có thể:

  • Trên cùng
  • Dưới cùng
  • Trái
  • Phải

Mỗi điều khiển có một thuộc tính Dock. Khi sử dụng lớp DockPanel, bạn có thể sử dụng thuộc tính này để định vị một điều khiển bên trong DockPanel. Điều này được minh họa trong ví dụ sau:

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

Khi tạo một phiên bản của chỉ báo này, bạn sẽ thấy một dock panel ở trung tâm của biểu đồ chứa một trường văn bản và một nút có thể nhấp.

Lưu ý rằng các dock panel có thể được điền theo chiều ngang hoặc chiều dọc. Bạn không thể sử dụng cả hai hướng này cùng một lúc. Hướng của dock panel được thiết lập tự động khi thiết lập điều khiển đầu tiên trong DockPanel. Nếu thuộc tính Dock của điều khiển đầu tiên được đặt thành Top hoặc Bottom, toàn bộ DockPanel sẽ được định hướng theo chiều dọc, và ngược lại.

Bảng điều khiển xếp chồng

Stack panel là một trong những điều khiển được sử dụng thường xuyên nhất do tính đơn giản và khả năng sử dụng của chúng. Stack panel sắp xếp các điều khiển con theo chiều ngang hoặc chiều dọc lần lượt. Như được hiển thị dưới đây, bạn chỉ cần thiết lập hướng của nó và lớp sẽ quản lý phần còn lại:

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

Sau khi tạo một phiên bản chỉ báo, bạn sẽ thấy một stack panel nằm ngang với hai trường văn bản và một nút 'Submit' ở góc dưới bên phải của biểu đồ chính.

Bọc bảng điều khiển

Các panel bọc về cơ bản giống với các panel xếp chồng. Tuy nhiên, khi không có đủ không gian để chứa tất cả các phần tử của một panel bọc, nó sẽ tự động bọc các điều khiển còn lại sang dòng tiếp theo trên trục Y.

Lưới

Hãy nghĩ về lưới như các bảng tính với số cột và hàng cố định. Khi sử dụng lưới, bạn có thể thêm các điều khiển vào từng ô riêng biệt.

Như được minh họa bên dưới, khi bạn tạo một thể hiện của lớp Grid, bạn truyền vào số hàng và cột của nó dưới dạng các đối số integer. Khi thêm các phần tử con hoặc điều khiển mới, bạn cũng phải chỉ định số hàng và cột của phần tử con.

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

Khi tạo một thể hiện của chỉ báo trên, bạn sẽ thấy một lưới 10x2 ngay giữa biểu đồ.

Kiểm soát vị thế trong tọa độ giá và thời gian

Ngoài các điều khiển panel, cTrader cho phép chỉ định tọa độ giá và thời gian cho các điều khiển trực tiếp trong khu vực biểu đồ. Các phương thức AddControl()MoveControl() cung cấp cho các nhà phát triển thuật toán chức năng này.

Sử dụng các phương thức overload sau để quản lý tọa độ của các điều khiển biểu đồ của bạn tùy theo sở thích.

Để thêm một điều khiển biểu đồ vào khu vực biểu đồ hoặc chỉ báo trên tọa độ chỉ số thanh tuyệt đối và giá (x, y).

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

Để di chuyển một điều khiển biểu đồ đến khu vực biểu đồ hoặc chỉ báo trên tọa độ chỉ số thanh tuyệt đối và giá (x, y).

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

Để thêm một điều khiển biểu đồ vào khu vực biểu đồ hoặc chỉ báo trên tọa độ thời gian và giá tuyệt đối (x, y).

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

Để di chuyển một điều khiển biểu đồ đến khu vực biểu đồ hoặc chỉ báo trên tọa độ thời gian và giá tuyệt đối (x, y).

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

Để thêm một điều khiển biểu đồ vào khu vực biểu đồ hoặc chỉ báo trên tọa độ thời gian tuyệt đối (x).

1
void AddControl(ControlBase control, DateTime time)

Để di chuyển một điều khiển biểu đồ đến khu vực biểu đồ hoặc chỉ báo trên tọa độ thời gian tuyệt đối (x).

1
void MoveControl(ControlBase control, DateTime time)

Để thêm một điều khiển biểu đồ vào khu vực biểu đồ hoặc chỉ báo trên tọa độ chỉ số thanh tuyệt đối (x).

1
void AddControl(ControlBase control, int barIndex)

Để di chuyển một điều khiển biểu đồ đến khu vực biểu đồ hoặc chỉ báo trên tọa độ chỉ số thanh tuyệt đối (x).

1
void MoveControl(ControlBase control, int barIndex)

Để thêm một điều khiển biểu đồ vào khu vực biểu đồ hoặc chỉ báo trên tọa độ giá tuyệt đối (y).

1
void AddControl(ControlBase control, double y)

Để di chuyển một điều khiển biểu đồ đến khu vực biểu đồ hoặc chỉ báo trên tọa độ giá tuyệt đối (y).

1
void MoveControl(ControlBase control, double y)

Tham số lớp ControlBase có thể bao gồm bất kỳ lớp phụ nào khác (Control, Button, v.v.) để phương thức được gọi theo các chữ ký trên.

Ví dụ cBot sau thêm nút Click me! phía trên thanh cuối cùng trên biểu đồ. Nút này được di chuyển về phía trước cùng với mỗi thanh mới được thêm vào. Sau khi nhấp vào nút, một hộp thông báo sẽ xuất hiện trên màn hình.

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

Cảnh báo

Số lượng điều khiển gốc có thể được thêm vào biểu đồ bị giới hạn ở 100 do các vấn đề hiệu suất có thể xảy ra. Giới hạn này chỉ áp dụng cho một thể hiện thuật toán và các điều khiển gắn với giá và thanh.

Các thuộc tính padding và margin

Thuộc tính Margin xác định khoảng cách giữa các đường viền của đối tượng Control và phần tử cha của nó (biểu đồ, panel, đường viền, v.v.).

Ngược lại, thuộc tính Padding xác định khoảng cách giữa nội dung điều khiển và các đường viền của nó. Bạn có thể thay đổi giá trị thuộc tính để chúng khác nhau cho các cạnh khác nhau.

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

Một thể hiện của chỉ báo này sẽ tạo ra một nút màu xám Click me ở góc trên bên trái của biểu đồ. Sửa đổi các tham số trong cửa sổ Add instance hoặc Modify parameters để xem chính xác các giá trị margin và padding khác nhau thay đổi cách hiển thị điều khiển như thế nào.

Kiểu dáng

Khi sử dụng kiểu, bạn có thể tạo giao diện tương tự cho một số loại điều khiển khác nhau. Điều này đặc biệt hữu ích khi xử lý một số lượng lớn (năm trở lên) các điều khiển.

Lớp Style cho phép đặt giá trị cho các thuộc tính khác nhau của điều khiển như Margin hoặc BackgroundColor. Sau đó, bạn có thể tái sử dụng các giá trị này làm mẫu cho nhiều điều khiển khác.

Chúng ta cũng có thể tạo giao diện nhất quán cho nhiều điều khiển mà không cần sử dụng lớp 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)
        {
        }
    }
}

Đây là cách sử dụng lớp Style có thể đơn giản hóa việc làm việc với nhiều điều khiển.

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

Cả hai đoạn mã trên đều nên hiển thị các điều khiển giống nhau nếu bạn khởi chạy các thể hiện chỉ báo tương ứng của chúng.

Bạn cũng có thể sử dụng lớp Style để thay đổi giao diện của một điều khiển dựa trên trạng thái của nó.

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

Hình ảnh

Điều khiển Image có thể được sử dụng để hiển thị một hình ảnh được lưu trữ cục bộ. Điều khiển Image sử dụng lớp Bitmap của .NET, có nghĩa là nó hỗ trợ phần lớn các định dạng hình ảnh phổ biến như sau:

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

Tham khảo tài liệu của lớp Bitmap .NET để tìm hiểu thêm về nó.

Để sử dụng điều khiển Image, hãy đặt thuộc tính Source của nó thành dữ liệu tệp hình ảnh trong một mảng 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)
        {
        }
    }
}

Sau khi khởi chạy một thể hiện của chỉ báo trên, bạn sẽ không thấy gì mới trên biểu đồ chính. Tuy nhiên, nhập một đường dẫn tệp hợp lệ làm giá trị của tham số (Image File Path), và bạn sẽ thấy hình ảnh đã chọn được hiển thị ở giữa màn hình.

Bạn cũng có thể sử dụng tài nguyên dự án của mình để lưu trữ hình ảnh và hiển thị chúng thông qua điều khiển Image. Để làm điều này, hãy mở tài nguyên dự án trong Visual Studio và chuyển sang tab Resources. Trong đó, tạo một tài nguyên mới và thêm một hình ảnh hiện có. Sau đó, bạn sẽ có thể sử dụng hình ảnh này làm nguồn trong bất kỳ điều khiển Image nào thông qua thuộc tính Project_Name_Space.Properties.Resources._Image_Name.

Ví dụ, hãy sao chép hình ảnh bên dưới và lưu nó dưới dạng "image.png" trên hệ thống của bạn:

Image title

Tạo một chỉ báo mới trong cTrader, đặt tên là "Image Sample", và mở nó qua Visual Studio. Sau đó, thêm chỉ báo logo dự án làm tài nguyên. Để làm điều này, nhấp chuột phải vào dự án của bạn, chọn Properties và nhấp vào Resources, sau đó nhấp vào Create and manage assembly resources. Sao chép tệp logo.png vào tab mới mở.

Sao chép mã bên dưới vào tệp mã nguồn chính của chỉ báo của bạn:

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

Sau khi tạo một thể hiện của chỉ báo này, bạn sẽ thấy kết quả sau.

Image title

Ghi chú

Kích thước tối đa cho hình ảnh là 10 MB.