WebView dalam cTrader
WebView ialah kawalan yang boleh digunakan untuk memaparkan halaman web pada carta atau tetingkap output indikator.
WebView adalah berdasarkan Microsoft Edge WebView2. Hasilnya, ia serasi sepenuhnya dengan semua piawaian web moden.
Anda juga boleh melaksanakan kod JavaScript pada halaman dan mendapatkan hasilnya melalui WebView.
Nota
WebView hanya berfungsi pada indikator dan cBot .NET 6 atau lebih baharu.
Menggunakan WebView dalam cTrader
Sebagai contoh, kita akan memaparkan laman web cTrader.com di dalam tetingkap dan carta utama.
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 cAlgo.Robots
{
[Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
public class WebViewOnWindow : Indicator
{
private WebView _webView;
[Parameter("On Window?", DefaultValue = false)]
public bool OnWindow { get; set; }
protected override void Initialize()
{
_webView = new WebView
{
DefaultBackgroundColor = Color.Red
};
_webView.Loaded += OnWebViewLoaded;
if (OnWindow)
{
var window = new Window
{
Child = _webView
};
window.Show();
}
else
{
Chart.AddControl(_webView);
}
}
public override void Calculate(int index)
{
}
private void OnWebViewLoaded(WebViewLoadedEventArgs args)
{
_webView.NavigateAsync("https://ctrader.com/");
}
}
}
|
Selepas mencipta contoh indikator di bawah, anda akan dapat menavigasi antara pelbagai halaman web di cTrader.com. Tetingkap output pilihan anda akan berkelakuan serupa dengan pelayar web.
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 | using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.None)]
public class WebViewOnWindow : Robot
{
private WebView _webView;
private TextBox _addressTextBox;
private TextBox _scriptTextbox;
private Button _executeScriptButton;
protected override void OnStart()
{
var goBackButton = new Button
{
Text = "←",
Margin = 3
};
goBackButton.Click += OnGoBackButtonClick;
var goForwardButton = new Button
{
Text = "→",
Margin = 3
};
goForwardButton.Click += OnGoForwardButtonClick;
_addressTextBox = new TextBox
{
Text = "https://ctrader.com/",
Margin = 3,
Width = 150,
MinWidth = 150,
MaxWidth = 150
};
var goButton = new Button
{
Text = "→",
Margin = 3
};
goButton.Click += OnGoButtonClick;
var reloadButton = new Button
{
Text = "Reload",
Margin = 3
};
reloadButton.Click += OnReloadButtonClick;
var stopButton = new Button
{
Text = "x",
Margin = 3
};
stopButton.Click += OnStopButtonClick;
_scriptTextbox = new TextBox
{
Text = "alert('Hi');",
Margin = 3,
Width = 150,
MinWidth = 150,
MaxWidth = 150,
IsEnabled = false
};
_executeScriptButton = new Button
{
Text = "Execute Script",
Margin = 3,
IsEnabled = false
};
_executeScriptButton.Click += OnExecuteScriptButtonClick;
var addressBarPanel = new StackPanel
{
MaxHeight = 50,
VerticalAlignment = VerticalAlignment.Top,
BackgroundColor = Color.Black,
Orientation = Orientation.Horizontal
};
addressBarPanel.AddChild(goBackButton);
addressBarPanel.AddChild(goForwardButton);
addressBarPanel.AddChild(_addressTextBox);
addressBarPanel.AddChild(goButton);
addressBarPanel.AddChild(reloadButton);
addressBarPanel.AddChild(stopButton);
addressBarPanel.AddChild(_scriptTextbox);
addressBarPanel.AddChild(_executeScriptButton);
_webView = new WebView
{
DefaultBackgroundColor = Color.Red
};
_webView.NavigationCompleted += OnWebViewNavigationCompleted;
_webView.WebMessageReceived += OnWebViewWebMessageReceived;
_webView.Loaded += OnWebViewLoaded;
_webView.Unloaded += OnWebViewUnloaded;
var mainGrid = new Grid(2, 1);
mainGrid.Rows[0].SetHeightToAuto();
mainGrid.Rows[1].SetHeightInStars(1);
mainGrid.AddChild(addressBarPanel, 0, 0);
mainGrid.AddChild(_webView, 1, 0);
var window = new Window
{
Child = mainGrid
};
window.Show();
}
private void OnWebViewLoaded(WebViewLoadedEventArgs args)
{
Print($"Webview loaded, IsLoaded: {args.WebView.IsLoaded}");
_webView.NavigateAsync(_addressTextBox.Text);
}
private void OnWebViewUnloaded(WebViewUnloadedEventArgs args)
{
Print($"Webview unloaded, IsLoaded: {args.WebView.IsLoaded}");
}
private void OnStopButtonClick(ButtonClickEventArgs args)
{
_webView.StopAsync();
}
private void OnExecuteScriptButtonClick(ButtonClickEventArgs args)
{
var result = _webView.ExecuteScript(_scriptTextbox.Text);
Print($"IsSuccessful: {result.IsSuccessful} | Json: {result.Json}");
}
private void OnReloadButtonClick(ButtonClickEventArgs args)
{
_webView.ReloadAsync();
}
private void OnGoForwardButtonClick(ButtonClickEventArgs args)
{
_webView.GoForwardAsync();
}
private void OnGoBackButtonClick(ButtonClickEventArgs args)
{
_webView.GoBackAsync();
}
private void OnGoButtonClick(ButtonClickEventArgs args)
{
_webView.NavigateAsync(_addressTextBox.Text);
}
private void OnWebViewWebMessageReceived(WebViewWebMessageReceivedEventArgs args)
{
Print($"Source: {args.Source} | Message: {args.Message}");
}
private void OnWebViewNavigationCompleted(WebViewNavigationCompletedEventArgs args)
{
Print($"{args.HttpStatusCode} | {args.IsSuccessful} | {args.Url}");
_addressTextBox.Text = args.Url;
_scriptTextbox.IsEnabled = true;
_executeScriptButton.IsEnabled = true;
}
}
}
|
Menggunakan skrip dan mengendalikan peristiwa mesej
Kelas WebView mempunyai dua ahli yang berkuasa, iaitu kaedah ExecuteScript() dan peristiwa WebMessageReceived. Anda boleh menggunakannya untuk mencipta algo yang mengakses halaman web pilihan anda (contohnya, suapan berita Forex atau mana-mana halaman dengan HTML tersuai), melaksanakan JavaScript tersuai pada halaman ini, dan mengendalikan dengan betul sebarang mesej yang dihantar dari WebView kembali ke algo.
Laksanakan skrip
Untuk melaksanakan skrip tersuai dalam WebView anda, anda hanya perlu memanggil kaedah WebView.ExecuteScript(String javaScript) seperti yang ditunjukkan di bawah.
| private _webView = new WebView();
_webView.ExecuteScript("document.getElementById('nextButton').style.display = 'none';");
|
Skrip yang perlu dilaksanakan dalam WebView boleh dihantar sebagai rentetan kepada kaedah ExecuteString().
Perhatikan bahawa rentetan ini mesti mengandungi JavaScript yang tepat sepenuhnya. Contohnya, ia mesti memasukkan koma bertitik selepas setiap baris yang boleh dilaksanakan.
JavaScript Berbilang Baris
Anda boleh menghantar JavaScript berbilang baris kepada kaedah ExecuteScript() seperti yang ditunjukkan dalam contoh di bawah (perhatikan penggunaan literal rentetan).
| _webView.ExecuteScript(@"
const element = document.getElementById('nextButton');
element.style.display = 'none';
");
|
Kendalikan peristiwa mesej
Peristiwa WebMessageReceived dibangkitkan apabila kandungan yang dipaparkan dalam WebView menghantar mesej. Anda boleh bertindak balas terhadap peristiwa ini dengan melanggan mana-mana pengendali peristiwa yang sesuai.
| private _webView = new WebView();
_webView.WebMessageReceived += OnWebMessageReceived;
private void OnWebMessageReceived(WebViewWebMessageReceivedEventArgs args)
{
Print($"Source: {args.Source} | Message: {args.Message}");
}
|
Untuk menghantar mesej dari WebView, anda hanya perlu memanggil window.postMessage() dari kod JavaScript di dalam halaman HTML. Sebagai contoh, anda boleh menghantar skrip dalam contoh di bawah untuk mengira perbezaan persentil antara dua nombor (seperti harga kemasukan dan keluar yang mungkin untuk kedudukan).
| function percentChange(oldVal, newVal) {
let change = ((newVal - oldVal) / oldVal) * 100;
window.postMessage('Change: ${change}%');
}
percentChange(1.0784, 1.0975);
|
Pemboleh ubah dan interpolasi rentetan
Konteks tidak dikongsi antara C# dan JavaScript apabila anda memanggil kaedah ExecuteScript(). Jika anda ingin menghantar pemboleh ubah dari skop C# ke skop JavaScript, anda perlu menggunakan interpolasi rentetan.
| var a = 2 + 2;
_webView.ExecuteScript($"window.postMessage({a});");
|
Letakkan kawalan di dalam WebView
Adalah mungkin untuk menggabungkan ExecuteScript() dan OnWebMessageReceived untuk meletakkan kawalan di dalam halaman yang dibuka melalui WebView yang, apabila berinteraksi, menghantar mesej kembali kepada cBot. Dalam contoh di bawah, kami menggunakan fungsi ini untuk membolehkan dagangan secara langsung di dalam WebView. Perhatikan bahawa WebView membuka halaman HTML tersuai dan bukannya sumber sedia ada.
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 | 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;
using System.Text.Json;
namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.None)]
public class WebViewInteractionsExample : Robot
{
private WebView _webView;
protected override void OnStart()
{
var window = new Window();
_webView = new WebView();
_webView.Loaded += WebView_Loaded;
_webView.NavigationCompleted += WebView_NavigationCompleted;
_webView.WebMessageReceived += WebView_WebMessageReceived;
window.Child = _webView;
window.Width = 500;
window.Height = 500;
window.Show();
window.Closed += args => Stop(); // stop cBot when window is closed
}
private void WebView_WebMessageReceived(WebViewWebMessageReceivedEventArgs args)
{
Print("Message received from WebView: {0}", args.Message);
var tradeMessage = JsonSerializer.Deserialize<TradeMessage>(args.Message);;
var tradeType = tradeMessage.side == "buy" ? TradeType.Buy : TradeType.Sell;
ExecuteMarketOrder(tradeType, tradeMessage.symbolName, tradeMessage.volume);
}
private void WebView_Loaded(WebViewLoadedEventArgs args)
{
args.WebView.NavigateToStringAsync(@"
<script>
function setSymbols(symbols) // called from the cBot
{
const symbolSelector = document.getElementById('symbolHtml');
symbolSelector.innerHTML = '';
symbols.forEach((symbol) => {
symbolSelector.add(new Option(symbol));
});
}
function trade(operation)
{
const symbolSelector = document.getElementById('symbolHtml');
const selectedSymbolName = symbolSelector.options[symbolSelector.selectedIndex].text;
window.postMessage({
side: operation,
volume: Number(document.getElementById('volumeHtml').value),
symbolName: selectedSymbolName
}); //send message to cBot
}
</script>
<body bgcolor='white'>
<div style='display:flex;flex-direction:column;width:300px'>
<h1>This is HTML page</h1>
<div>Symbol:</div>
<select id='symbolHtml'></select>
<span style='margin-top: 10px'>Volume:</span>
<input id='volumeHtml' value='1000' />
<div style='margin-top:10px'>
<input type='button' value='Buy' onclick='trade(`buy`)' />
<input type='button' value='Sell' onclick='trade(`sell`)' />
</div>
</div>
</body>
");
}
private void WebView_NavigationCompleted(WebViewNavigationCompletedEventArgs obj)
{
SendSymbolsToHtml();
}
private void SendSymbolsToHtml()
{
var allSymbols = "";
foreach (var symbol in Symbols)
{
allSymbols = allSymbols + "'" + symbol + "',";
}
_webView.ExecuteScript("setSymbols([" + allSymbols + "]);"); // invokes the corresponding function inside HTML
}
}
class TradeMessage
{
public string side { get; set; }
public double volume { get; set; }
public string symbolName { get; set; }
}
}
|
Melalui WebView, cBot membuka halaman HTML tersuai yang mengandungi kawalan yang membolehkan kita meletakkan pesanan baharu. Menggunakan kaedah SendSymbolsToHtml(), cBot mengisi menu dropdown di dalam HTML dengan senarai semua simbol yang boleh didagangkan oleh akaun. Semasa cBot sedang berjalan, pengguna boleh memilih simbol, menentukan volum pesanan dan kemudian meletakkan pesanan baharu secara langsung di dalam halaman web tanpa perlu berinteraksi dengan kawalan di dalam cTrader.