ข้ามไปที่เนื้อหา

คอนโทรล

คอนโทรลช่วยให้เกิดการโต้ตอบบางอย่างที่เกี่ยวข้องกับ cBot อินดิเคเตอร์ และปลั๊กอิน โดยใช้คู่มือด้านล่าง คุณสามารถสร้างคอนโทรล UI พื้นฐานและขั้นสูงบนกราฟได้อย่างง่ายดาย

มีคลาสในตัวหลายตัวที่แสดงถึงคอนโทรลยอดนิยม เช่น ปุ่ม บล็อกข้อความ กล่องข้อความ และรูปร่าง อย่างไรก็ตาม คุณยังสามารถสร้างคอนโทรลที่กำหนดเองได้

พิจารณาตัวอย่างต่อไปนี้:

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

หากคุณสร้างอินดิเคเตอร์ข้างต้นและสร้างอินสแตนซ์ คุณควรเห็นปุ่มสีเทา คลิกฉัน ตรงกลางกราฟ

ความแตกต่างระหว่างคอนโทรลและออบเจ็กต์กราฟ

ในส่วนก่อนหน้านี้ เราได้กล่าวถึงออบเจ็กต์กราฟไปแล้ว คอนโทรลช่วยให้ผู้ใช้สามารถโต้ตอบกับ cBot และอินดิเคเตอร์ได้ ในทางกลับกัน ออบเจ็กต์กราฟให้โอกาสในการวาดบางสิ่งบนกราฟการเทรดหรือในหน้าต่างแสดงผลอินดิเคเตอร์แยก

คอนโทรลกราฟสืบทอดมาจากคลาส ControlBase ในขณะที่ออบเจ็กต์กราฟสืบทอดมาจากคลาส ChartObject

คอนโทรลกราฟถูกวางตำแหน่งแบบคงที่โดยใช้ตัวเลือกการจัดตำแหน่งที่แตกต่างกัน ในขณะที่ออบเจ็กต์กราฟสามารถวางตำแหน่งได้ในลักษณะเดียวกัน ตำแหน่งของพวกมันยังสามารถเปลี่ยนแปลงแบบไดนามิกขึ้นอยู่กับพิกัด X และ 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)
        {
        }
    }
}

หลังจากสร้างอินสแตนซ์ของอินดิเคเตอร์ คุณควรเห็นปุ่ม คลิกฉัน ในหน้าต่างแสดงผลอินดิเคเตอร์

ColorPicker

คอนโทรล ColorPicker ช่วยให้นักเทรดสามารถเลือกสีที่ต้องการสำหรับองค์ประกอบหรือออบเจ็กต์หลักใน cTrader ตัวอย่างเช่น นักพัฒนาอาจรวมคอนโทรล ColorPicker เข้ากับ cBot ที่วาดเส้นแนวโน้มเพื่อให้ผู้ใช้สามารถเลือกสีที่ต้องการสำหรับเส้นแนวโน้มแต่ละเส้น การตั้งค่านี้ช่วยให้นักเทรดแยกแยะระหว่างประเภทเส้นแนวโน้มต่างๆ ได้ง่ายขึ้น

ปลั๊กอินที่เพิ่มอินดิเคเตอร์ลงในกราฟก็สามารถใช้คอนโทรล ColorPicker ได้เช่นกัน เนื่องจากฟีเจอร์นี้ช่วยให้ผู้ใช้สามารถเลือกสีสำหรับเส้นอินดิเคเตอร์ต่างๆ ได้

เมื่อผู้ใช้คลิกที่สี่เหลี่ยมสี ตัวเลือกสีจะปรากฏขึ้น จากนั้นผู้ใช้สามารถเลือกระหว่างสีมาตรฐานและสีที่กำหนดเองได้

ตัวอย่างโค้ด:

 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

คอนโทรล DropZone ช่วยให้นักเทรดสามารถดำเนินการลากและวางที่เกี่ยวข้องกับ cBot อินดิเคเตอร์ หรือปลั๊กอินได้ ในการใช้คอนโทรลนี้ในอัลกอริทึมของคุณ ให้ใช้คลาส DropZone คอนโทรล DropZone สามารถจัดการได้เหมือนกับคอนโทรลอื่นๆ

เมื่อผู้ใช้วางไฟล์หรือโฟลเดอร์ที่เข้ากันได้ลงในกล่อง อีเวนต์ Dropped จะถูกสร้างขึ้น เมื่อผู้ใช้วางโฟลเดอร์หรือหลายโฟลเดอร์ลงในกล่อง เฉพาะไฟล์ที่เข้ากันได้ซึ่งมีนามสกุลที่ระบุใน FilterExtensions เท่านั้นที่จะถูกประมวลผลและคัดลอก

หมายเหตุ

ไฟล์ที่วางมักจะถูกคัดลอกและบันทึกไว้ในตำแหน่งนี้: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\

ตำแหน่งสำหรับอินสแตนซ์ของ cBot แตกต่างจากข้างต้น: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\

โค้ดปลั๊กอินนี้แสดงวิธีการเพิ่มคอนโทรล DropZone ไปยัง 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

คอนโทรล ProgressBar แสดงความคืบหน้าของการดำเนินการที่กำลังดำเนินอยู่ แถบความคืบหน้าทำให้อัลกอริทึมใช้งานง่ายขึ้นและช่วยจัดการความคาดหวังของนักเทรดเกี่ยวกับเวลารอสำหรับการดำเนินการบางอย่าง

cTrader Algo API อนุญาตให้นักพัฒนาเพิ่มคอนโทรล ProgressBar สองประเภท: คอนโทรลไม่มีที่สิ้นสุดและคอนโทรลที่กำหนดได้

ขอบเขตการควบคุมไม่จำกัด

คุณอาจต้องการใช้การควบคุมแบบไม่จำกัดในสถานการณ์ต่อไปนี้:

  • คุณไม่สามารถกำหนดเวลารอสำหรับการดำเนินการได้
  • คุณไม่สามารถตรวจจับความคืบหน้าของการดำเนินการได้
  • คุณไม่ต้องการระบุว่าการดำเนินการจะใช้เวลานานเท่าใด

Image title

การควบคุมแบบกำหนดได้

คุณอาจต้องการใช้การควบคุมนี้เมื่อคุณสามารถกำหนดเวลารอสำหรับการดำเนินการได้และต้องการให้ผู้ใช้เห็นตัวบ่งชี้ตามเวลานั้น

ในการแสดงความคืบหน้าของการดำเนินการ ให้ใช้คุณสมบัติ Value เพื่อกำหนดตัวเลข ในการกำหนดเปอร์เซ็นต์ของแถบความคืบหน้า ให้ใช้คุณสมบัติ Minimum และ Maximum

Image title

โค้ดปลั๊กอินด้านล่างแสดงวิธีการสร้างแถบความคืบหน้าโดยใช้การควบคุมทั้งแบบไม่จำกัดและแบบกำหนดได้ (สีเขียว):

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

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

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

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

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

            panel.AddChild(_infiniteProgressBar);

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

            panel.AddChild(_determinateProgressBar);

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

            autoProgressButton.Click += AutoProgressButton_Click;

            panel.AddChild(autoProgressButton);

            aspBlock.Child = panel;

        }

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

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

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

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

กล่องโต้ตอบ

OpenFileDialog และ OpenFolderDialog

cTrader Algo API มี interface OpenFileDialog เพื่อให้ผู้ใช้สามารถเลือกไฟล์สำหรับอัลกอริทึม เมื่อผู้ใช้เลือกไฟล์ในหน้าต่างที่ปรากฏขึ้น ไฟล์จะถูกคัดลอกไปยังโฟลเดอร์ Selected files ของอัลกอริทึม อัลกอริทึมสามารถทำงานกับไฟล์ภายในโฟลเดอร์ Selected files ได้โดยไม่มีข้อจำกัด

เคล็ดลับ

ใช้ฟังก์ชัน OpenFileDialog เมื่อคุณต้องการโหลดไฟล์ข้อมูลสำคัญ ไฟล์สำรองข้อมูลหรือไฟล์การกำหนดค่า ตัวบ่งชี้ที่กำหนดเองหรือสคริปต์

โค้ดด้านล่างแสดงวิธีการใช้กล่องโต้ตอบ OpenFileDialog ในตัวบ่งชี้:

 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 มี interface OpenFolderDialog เพื่อให้ผู้ใช้สามารถระบุโฟลเดอร์สำหรับอัลกอริทึม เมื่อผู้ใช้เลือกโฟลเดอร์ในหน้าต่างที่ปรากฏขึ้น ไฟล์และโฟลเดอร์ทั้งหมดที่มีไฟล์อยู่ภายในโฟลเดอร์ที่เลือกจะถูกคัดลอกไปยังโฟลเดอร์ Selected files ของอัลกอริทึม

เคล็ดลับ

ใช้ฟังก์ชัน OpenFolderDialog เมื่อคุณต้องการโหลดโฟลเดอร์ที่มีไฟล์ข้อมูลสำคัญ ไฟล์สำรองข้อมูลหรือไฟล์การกำหนดค่า ตัวบ่งชี้ที่กำหนดเองหรือสคริปต์

ไฟล์และโฟลเดอร์ที่เลือกมักจะถูกคัดลอกไปยังโฟลเดอร์ Selected files เนื่องจากอัลกอริทึมสามารถทำงานกับรายการภายในโฟลเดอร์นั้นได้แม้ว่า AccessRights จะถูกตั้งค่าเป็น None

หมายเหตุ

โฟลเดอร์ Selected files ของอัลกอริทึมมักจะอยู่ตามเส้นทางนี้: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\

โฟลเดอร์ Selected files สำหรับอินสแตนซ์ของ cBot จะแตกต่างจากข้างต้น: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\

โค้ดด้านล่างแสดงวิธีการใช้กล่องโต้ตอบ OpenFolderDialog ในตัวบ่งชี้:

 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

cTrader Algo API มี interface SaveFileDialog เพื่อให้ผู้ใช้สามารถบันทึกไฟล์ (ในเครื่อง) ลงในคอมพิวเตอร์ของตนเองได้ เมื่อหน้าต่างที่เกี่ยวข้องปรากฏขึ้น ผู้ใช้จะเลือกโฟลเดอร์ที่ต้องการบันทึกไฟล์และป้อนชื่อสำหรับไฟล์ จากนั้นไฟล์จะถูกบันทึกในตำแหน่งที่ระบุ

เคล็ดลับ

ใช้ฟังก์ชัน SaveFileDialog เมื่อคุณต้องการทำสิ่งใดสิ่งหนึ่งต่อไปนี้:

  • บันทึกรายงานประสิทธิภาพ ผลลัพธ์การ backtesting ไฟล์การกำหนดค่า หรือข้อมูลการปรับให้เหมาะสม
  • ส่งออกบันทึกการเทรด บันทึกการดำเนินการ หรือข้อมูลกิจกรรมทั่วไปของผู้ใช้
  • จัดเก็บตัวบ่งชี้ที่กำหนดเอง ข้อมูลสำหรับแผนภูมิและการแสดงผล หรือพารามิเตอร์สำหรับกลยุทธ์

โค้ดด้านล่างแสดงวิธีการใช้กล่องโต้ตอบ SaveFileDialog ในตัวบ่งชี้:

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

การควบคุมแบบลาก

การควบคุมแบบลากในพื้นที่แผนภูมิ

Interface ChartDraggable และ ChartDraggables มีประเภทที่ช่วยให้คุณสามารถเพิ่มการควบคุมแบบลากที่สามารถรองรับการควบคุมอื่น ๆ และองค์ประกอบต่าง ๆ ลงในแผนภูมิได้ การควบคุมแบบลากเหล่านี้ช่วยให้ผู้ใช้สามารถโต้ตอบกับองค์ประกอบต่าง ๆ ของแผนภูมิได้ง่ายขึ้น

หมายเหตุ

การควบคุมแบบลากสามารถเคลื่อนย้ายหรือจัดตำแหน่งใหม่ได้เฉพาะภายในแผนภูมิที่ถูกเพิ่มเข้าไปเท่านั้น

โค้ดนี้แสดงวิธีการสร้างตัวบ่งชี้ที่เพิ่มการควบคุมสองอย่างที่สามารถเคลื่อนย้ายได้ภายในแผนภูมิ:

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

การควบคุมแบบลากในหน้าต่างแอปพลิเคชัน

Interface ApplicationDraggable และ ApplicationDraggables มีประเภทที่ใช้เพิ่มการควบคุมแบบลอยที่สามารถเคลื่อนย้ายแต่ละอันได้ทั่วทั้งหน้าต่างแอปพลิเคชัน cTrader การควบคุมดังกล่าวช่วยให้คุณสามารถสร้างส่วนติดต่อผู้ใช้แบบโต้ตอบและแบบไดนามิกได้

หมายเหตุ

ในบรรดาประเภทอัลกอริทึมทั้งสามประเภท มีเพียงปลั๊กอินเท่านั้นที่ได้รับอนุญาตให้ใช้การควบคุมแบบลากทั่วทั้งแอปพลิเคชัน

โค้ดนี้แสดงวิธีการสร้างปลั๊กอินที่เพิ่มคอมโพเนนต์ WebView และบล็อกข้อความในหน้าต่างแยกกันสองหน้าต่าง ซึ่งสามารถเคลื่อนย้ายได้ทั่วทั้ง UI ของ 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;
        }
    }
}

การควบคุมแท็บ

คลาส TabControl มีประเภทที่ช่วยให้คุณสามารถสร้างแท็บหลายแท็บสำหรับอัลกอริทึมได้ แท็บเหล่านี้สามารถใช้เพื่อรวมองค์ประกอบที่เกี่ยวข้องไว้ด้วยกันหรือนำเสนอมุมมองแยกสำหรับฟังก์ชันการทำงานต่าง ๆ

โค้ดนี้แสดงวิธีการใช้แท็บในปลั๊กอินที่เพิ่มเข้าไปในแผงสัญลักษณ์ที่ใช้งานอยู่:

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

การควบคุมที่กำหนดเอง

การควบคุมที่กำหนดเองคือการควบคุมที่โดยพื้นฐานแล้วประกอบด้วยการควบคุมที่กำหนดไว้ล่วงหน้าหลายอย่าง กล่าวอีกนัยหนึ่ง เป็นการควบคุมที่มีการควบคุมอื่น ๆ เป็นเนื้อหาของมัน

การควบคุมที่กำหนดเองทำหน้าที่เป็นคลาสที่นำกลับมาใช้ใหม่ได้เช่นเดียวกับการควบคุมที่มีอยู่แล้ว

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

อินสแตนซ์ของตัวบ่งชี้นี้ควรแสดงกล่องข้อความสี่กล่องโดยตรงที่ตรงกลางของแผนภูมิหลัก

จัดระเบียบการควบคุมด้วยแผง

เพื่อให้การทำงานกับการควบคุมสะดวกยิ่งขึ้น คุณอาจต้องการวางการควบคุมหลายอย่างไว้ในกลุ่มที่แยกต่างหากซึ่งมีตำแหน่งของตัวเองใน UI ในการทำเช่นนี้ คุณสามารถใช้คลาส Panels และอนุพันธ์ของมัน

คิดว่าแผงเป็นการควบคุมที่มีการควบคุมอื่น ๆ เป็นเนื้อหาของมัน cTrader รองรับห้าคลาสที่แตกต่างกันซึ่งสืบทอดมาจากคลาส Panels พื้นฐาน (ซึ่งสืบทอดมาจากคลาส Control):

  • Canvas
  • DockPanel
  • Grid
  • StackPanel
  • WrapPanel

แต่ละคลาสข้างต้นใช้เค้าโครงแผงและกลยุทธ์การจัดตำแหน่ง

แคนวาส

แคนวาสเป็นแผงที่อนุญาตให้จัดตำแหน่งของตัวควบคุมตามพิกัด X และ Y ที่กำหนด

โดยเฉพาะอย่างยิ่ง แกน X และ Y นั้นแตกต่างจากที่ใช้กับวัตถุหรือการวาดบนกราฟ พิกัด X และ Y ที่ใช้โดยคลาส Canvas แสดงค่าตัวเลขเริ่มต้นจาก (0, 0) จากมุมซ้ายบนของกราฟ

พิจารณาตัวอย่างต่อไปนี้:

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

เมื่อสร้างอินสแตนซ์ของอินดิเคเตอร์ข้างต้น คุณควรเห็นปุ่ม Click me ที่มุมซ้ายบนของกราฟ

คุณสมบัติ Top ของตัวควบคุมกำหนดตำแหน่งของมันบนแกน Y ในทางกลับกัน คุณสมบัติ Left กำหนดตำแหน่งของมันบนแกน X

โค้ดข้างต้นยังใช้คุณสมบัติ Padding และ Margin ด้วย Padding หมายถึงระยะห่างระหว่างเนื้อหาของตัวควบคุมและขอบนอกของมัน Margin คือระยะห่างระหว่างตัวควบคุมและขอบของตัวควบคุมหลักของมัน คุณสมบัติ Padding และ Margin สามารถใช้ได้กับทุกแผง ไม่เฉพาะแค่คลาสแคนวาส พวกมันมีประโยชน์สำหรับการจัดการระยะห่างระหว่างตัวควบคุมของคุณ

ในกรณีส่วนใหญ่ คลาส Canvas ถูกใช้เพื่อจัดกลุ่มตัวควบคุมจำนวนน้อยเท่านั้น

สร้างแผงใหม่

คลาส DockPanel ใช้เพื่อยึด (วาง) ตัวควบคุมในตำแหน่งคงที่บนกราฟ มีตำแหน่งยึดที่เป็นไปได้สี่ตำแหน่ง:

  • บน
  • ล่าง
  • ซ้าย
  • ขวา

แต่ละตัวควบคุมมีคุณสมบัติ Dock เมื่อใช้คลาส DockPanel คุณสามารถใช้คุณสมบัตินี้เพื่อกำหนดตำแหน่งของตัวควบคุมภายใน DockPanel ซึ่งแสดงในตัวอย่างต่อไปนี้:

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

เมื่อสร้างอินสแตนซ์ของอินดิเคเตอร์นี้ คุณควรเห็นแผงยึดที่กึ่งกลางของกราฟซึ่งมีช่องข้อความและปุ่มที่คลิกได้

โปรดทราบว่าแผงยึดสามารถจัดเรียงได้ทั้งแนวนอนหรือแนวตั้ง คุณไม่สามารถใช้การจัดเรียงทั้งสองแบบพร้อมกันได้ การวางแนวของแผงยึดถูกตั้งค่าโดยอัตโนมัติเมื่อตั้งค่าตัวควบคุมแรกใน DockPanel หากคุณสมบัติ Dock ของตัวควบคุมแรกถูกตั้งค่าเป็น Top หรือ Bottom ทั้ง DockPanel จะถูกวางแนวในแนวตั้ง และในทางกลับกัน

สแต็กพาเนล

แผงซ้อนเป็นหนึ่งในตัวควบคุมที่ใช้บ่อยที่สุดเนื่องจากความเรียบง่ายและความสะดวกในการใช้งาน แผงซ้อนจัดเรียงตัวควบคุมย่อยทั้งในแนวนอนหรือแนวตั้งทีละตัว ดังที่แสดงด้านล่าง คุณเพียงแค่ต้องตั้งค่าการวางแนวของมันและคลาสจะจัดการส่วนที่เหลือให้:

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

หลังจากสร้างอินสแตนซ์ของอินดิเคเตอร์ คุณควรเห็นแผงซ้อนแนวนอนที่มีช่องข้อความสองช่องและปุ่ม 'Submit' ที่มุมขวาล่างของกราฟหลัก

สร้างแผงใหม่

แผงห่อเหมือนกับแผงซ้อนเกือบทั้งหมด อย่างไรก็ตาม เมื่อไม่มีพื้นที่เพียงพอที่จะใส่องค์ประกอบทั้งหมดของแผงห่อ มันจะห่อตัวควบคุมที่เหลือไปยังบรรทัดถัดไปบนแกน Y โดยอัตโนมัติ

กริด

คิดว่าตารางเป็นเหมือนสเปรดชีตที่มีจำนวนคอลัมน์และแถวที่กำหนด เมื่อใช้ตาราง คุณสามารถเพิ่มตัวควบคุมลงในแต่ละเซลล์แยกกันได้

ดังที่แสดงด้านล่าง เมื่อคุณสร้างอินสแตนซ์ของคลาส Grid คุณส่งจำนวนแถวและคอลัมน์ของมันเป็นอาร์กิวเมนต์ integer เมื่อเพิ่มตัวควบคุมหรือลูกใหม่ คุณต้องระบุจำนวนแถวและคอลัมน์ของลูกเช่นกัน

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

เมื่อสร้างอินสแตนซ์ของอินดิเคเตอร์ข้างต้น คุณควรเห็นตาราง 10x2 ตรงกลางของกราฟ

ควบคุมตำแหน่งภายในพิกัดราคาและเวลา

นอกเหนือจากการควบคุมแผง cTrader ยังอนุญาตให้ระบุพิกัดราคาและเวลาสำหรับการควบคุมโดยตรงในพื้นที่แผนภูมิ เมธอด AddControl() และ MoveControl() มอบฟังก์ชันการทำงานนี้ให้กับนักพัฒนาอัลกอริทึม

ใช้โอเวอร์โหลดเมธอดต่อไปนี้เพื่อจัดการพิกัดของการควบคุมแผนภูมิของคุณตามความต้องการ

เพื่อเพิ่มการควบคุมแผนภูมิลงในพื้นที่แผนภูมิหรืออินดิเคเตอร์บนดัชนีแท่งเทียนสัมบูรณ์และพิกัดราคา (x, y)

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

เพื่อย้ายการควบคุมแผนภูมิไปยังพื้นที่แผนภูมิหรืออินดิเคเตอร์บนดัชนีแท่งเทียนสัมบูรณ์และพิกัดราคา (x, y)

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

เพื่อเพิ่มการควบคุมแผนภูมิลงในพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดเวลาและราคาสัมบูรณ์ (x, y)

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

เพื่อย้ายการควบคุมแผนภูมิไปยังพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดเวลาและราคาสัมบูรณ์ (x, y)

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

เพื่อเพิ่มการควบคุมแผนภูมิลงในพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดเวลาสัมบูรณ์ (x)

1
void AddControl(ControlBase control, DateTime time)

เพื่อย้ายการควบคุมแผนภูมิไปยังพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดเวลาสัมบูรณ์ (x)

1
void MoveControl(ControlBase control, DateTime time)

เพื่อเพิ่มการควบคุมแผนภูมิลงในพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดดัชนีแท่งเทียนสัมบูรณ์ (x)

1
void AddControl(ControlBase control, int barIndex)

เพื่อย้ายการควบคุมแผนภูมิไปยังพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดดัชนีแท่งเทียนสัมบูรณ์ (x)

1
void MoveControl(ControlBase control, int barIndex)

เพื่อเพิ่มการควบคุมแผนภูมิลงในพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดราคาสัมบูรณ์ (y)

1
void AddControl(ControlBase control, double y)

เพื่อย้ายการควบคุมแผนภูมิไปยังพื้นที่แผนภูมิหรืออินดิเคเตอร์บนพิกัดราคาสัมบูรณ์ (y)

1
void MoveControl(ControlBase control, double y)

พารามิเตอร์คลาส ControlBase สามารถรวมคลาสย่อยอื่น ๆ (Control, Button ฯลฯ) เพื่อให้เมธอดถูกเรียกตามลายเซ็นข้างต้น

ตัวอย่าง cBot ต่อไปนี้เพิ่มปุ่ม Click me! เหนือแท่งเทียนสุดท้ายบนแผนภูมิ ปุ่มจะถูกย้ายไปข้างหน้าพร้อมกับแท่งเทียนใหม่ทุกแท่งที่เพิ่มเข้ามา หลังจากคลิกที่ปุ่ม กล่องข้อความจะปรากฏบนหน้าจอ

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

คำเตือน

จำนวนการควบคุมรากที่จะเพิ่มลงในแผนภูมิจำกัดไว้ที่ 100 เนื่องจากปัญหาประสิทธิภาพที่อาจเกิดขึ้น ข้อจำกัดนี้ใช้กับอินสแตนซ์อัลกอริทึมเดียวและการควบคุมที่แนบกับราคาและแท่งเทียนเท่านั้น

คุณสมบัติ padding และ margin

คุณสมบัติ Margin กำหนดพื้นที่ระหว่างขอบของวัตถุ Control และพาเรนต์ของมัน (แผนภูมิ, แผง, ขอบ ฯลฯ)

ในทางกลับกัน คุณสมบัติ Padding กำหนดพื้นที่ระหว่างเนื้อหาของการควบคุมและขอบของมัน คุณสามารถเปลี่ยนแปลงค่าคุณสมบัติเพื่อให้แตกต่างกันสำหรับด้านต่าง ๆ

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

อินสแตนซ์ของอินดิเคเตอร์นี้จะสร้างปุ่ม Click me สีเทาที่มุมบนซ้ายของแผนภูมิ แก้ไขพารามิเตอร์ในหน้าต่าง Add instance หรือ Modify parameters เพื่อดูว่าค่า margin และ padding ที่แตกต่างกันเปลี่ยนแปลงการแสดงผลการควบคุมอย่างไร

สไตล์

เมื่อใช้สไตล์ คุณสามารถให้ลักษณะที่คล้ายกันกับการควบคุมหลายประเภทที่แตกต่างกันได้ สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อต้องจัดการกับการควบคุมจำนวนมาก (ห้าหรือมากกว่า)

คลาส Style อนุญาตให้กำหนดค่าสำหรับคุณสมบัติต่าง ๆ ของการควบคุม เช่น Margin หรือ BackgroundColor หลังจากนั้น คุณสามารถนำค่าเหล่านี้มาใช้ซ้ำเป็นเทมเพลตสำหรับการควบคุมอื่น ๆ หลายรายการ

เราสามารถสร้างลักษณะที่สอดคล้องกันสำหรับการควบคุมหลายรายการโดยไม่ต้องใช้คลาส 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)
        {
        }
    }
}

นี่คือวิธีที่การใช้คลาส 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
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)
        {
        }
    }
}

ทั้งสองส่วนของโค้ดข้างต้นควรแสดงการควบคุมเดียวกันหากคุณเปิดใช้งานอินสแตนซ์อินดิเคเตอร์ที่เกี่ยวข้อง

คุณยังสามารถใช้คลาส 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
using cAlgo.API;

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

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

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

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

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

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

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

            Chart.AddControl(panel);
        }

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

รูปภาพ

การควบคุม Image สามารถใช้เพื่อแสดงรูปภาพที่จัดเก็บในเครื่อง การควบคุม Image ใช้คลาส Bitmap ของ .NET ซึ่งหมายความว่ารองรับรูปแบบรูปภาพยอดนิยมส่วนใหญ่ เช่นต่อไปนี้:

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

ปรึกษาเอกสารคลาส Bitmap ของ .NET เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับมัน

เพื่อใช้การควบคุม Image ให้ตั้งค่าคุณสมบัติ Source เป็นข้อมูลไฟล์รูปภาพในอาร์เรย์ไบต์ (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)
        {
        }
    }
}

หลังจากเปิดใช้งานอินสแตนซ์ของอินดิเคเตอร์ข้างต้น คุณไม่ควรเห็นสิ่งใหม่บนแผนภูมิหลัก อย่างไรก็ตาม ให้ป้อนพาธไฟล์ที่ถูกต้องเป็นค่าของพารามิเตอร์ (Image File Path) และคุณควรเห็นรูปภาพที่เลือกแสดงที่กึ่งกลางของหน้าจอ

คุณยังสามารถใช้ทรัพยากรโครงการของคุณเพื่อจัดเก็บรูปภาพและแสดงผ่านการควบคุม Image ได้ เพื่อทำเช่นนั้น ให้เปิดทรัพยากรโครงการใน Visual Studio และสลับไปที่แท็บ Resources ในนั้น ให้สร้างทรัพยากรใหม่และเพิ่มรูปภาพที่มีอยู่ หลังจากนั้น คุณจะสามารถใช้รูปภาพนี้เป็นแหล่งที่มาในการควบคุม Image ใด ๆ ผ่านคุณสมบัติ Project_Name_Space.Properties.Resources._Image_Name

ตัวอย่างเช่น คัดลอกรูปภาพด้านล่างและบันทึกเป็น "image.png" บนระบบของคุณ:

Image title

สร้างอินดิเคเตอร์ใหม่ใน cTrader ตั้งชื่อเป็น "Image Sample" และเปิดผ่าน Visual Studio หลังจากนั้น ให้เพิ่มโครงการอินดิเคเตอร์โลโก้เป็นทรัพยากร เพื่อทำเช่นนั้น ให้คลิกขวาที่โครงการของคุณ เลือก Properties และคลิก Resources จากนั้นคลิก Create and manage assembly resources คัดลอกไฟล์ logo.png ลงในแท็บที่เพิ่งเปิดใหม่

คัดลอกโค้ดด้านล่างไปยังไฟล์โค้ดต้นฉบับหลักของอินดิเคเตอร์ของคุณ:

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

หลังจากสร้างอินสแตนซ์ของอินดิเคเตอร์นี้ คุณควรเห็นผลลัพธ์ต่อไปนี้

Image title

หมายเหตุ

ขนาดสูงสุดสำหรับรูปภาพคือ 10 MB