-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMainFormLayout.cs
More file actions
371 lines (327 loc) · 14.7 KB
/
MainFormLayout.cs
File metadata and controls
371 lines (327 loc) · 14.7 KB
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
namespace MidiForwarder
{
public class MainFormLayout
{
private readonly Form form;
private static readonly System.Resources.ResourceManager ResourceManager = new("MidiForwarder.Resources", typeof(MainFormLayout).Assembly);
public ComboBox InputComboBox { get; private set; } = null!;
public ComboBox OutputComboBox { get; private set; } = null!;
public Button ConnectButton { get; private set; } = null!;
public Button RefreshButton { get; private set; } = null!;
public Button FilterBluetoothButton { get; private set; } = null!;
public Button OutputFilterBluetoothButton { get; private set; } = null!;
public CheckBox AutoConnectCheckBox { get; private set; } = null!;
public Label StatusLabel { get; private set; } = null!;
public TextBox LogTextBox { get; private set; } = null!;
// GroupBoxes for localization updates
private GroupBox inputGroupBox = null!;
private GroupBox outputGroupBox = null!;
private GroupBox logGroupBox = null!;
private Label inputLabel = null!;
private Label outputLabel = null!;
// ToolTip instances for filter buttons
private ToolTip filterButtonToolTip = null!;
private ToolTip outputFilterButtonToolTip = null!;
public event EventHandler? ConnectButtonClicked;
public event EventHandler? RefreshButtonClicked;
public event EventHandler? FilterBluetoothButtonClicked;
public event EventHandler? OutputFilterBluetoothButtonClicked;
public event EventHandler? AutoConnectChanged;
public event EventHandler? InputSelectionChanged;
public event EventHandler? OutputSelectionChanged;
public event EventHandler? DeviceSelectionChangedWhileConnected;
// 用于区分是用户手动选择还是程序刷新
public bool IsRefreshingDevices { get; set; } = false;
public MainFormLayout(Form form)
{
this.form = form;
InitializeLayout();
LocalizationManager.LanguageChanged += (s, e) => UpdateLocalizedText();
}
private void InitializeLayout()
{
form.Text = LocalizationManager.GetString("AppTitle");
form.Size = new Size(600, 500);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = true;
// 初始化 ToolTip 实例
filterButtonToolTip = new ToolTip();
outputFilterButtonToolTip = new ToolTip();
// 输入设备区域
inputGroupBox = new GroupBox
{
Text = LocalizationManager.GetString("InputDeviceGroup"),
Location = new Point(10, 10),
Size = new Size(270, 120)
};
inputLabel = new Label
{
Text = LocalizationManager.GetString("SelectInputDevice"),
Location = new Point(10, 25),
AutoSize = true
};
// 蓝牙设备过滤按钮
FilterBluetoothButton = new Button
{
Name = "filterBluetoothButton",
Text = "",
Image = LoadEmbeddedImage("plus_sign20.png"),
Location = new Point(235, 23),
Size = new Size(25, 23),
FlatStyle = FlatStyle.Flat,
FlatAppearance = { BorderSize = 0 },
Cursor = Cursors.Hand
};
// 工具提示在 UpdateFilterButtonState 中动态设置
InputComboBox = new ComboBox
{
Name = "inputComboBox",
Location = new Point(10, 50),
Size = new Size(250, 23),
DropDownStyle = ComboBoxStyle.DropDownList
};
// 输出设备区域
outputGroupBox = new GroupBox
{
Text = LocalizationManager.GetString("OutputDeviceGroup"),
Location = new Point(300, 10),
Size = new Size(270, 120)
};
outputLabel = new Label
{
Text = LocalizationManager.GetString("SelectOutputDevice"),
Location = new Point(10, 25),
AutoSize = true
};
// 输出设备蓝牙过滤按钮
OutputFilterBluetoothButton = new Button
{
Name = "outputFilterBluetoothButton",
Text = "",
Image = LoadEmbeddedImage("plus_sign20.png"),
Location = new Point(235, 23),
Size = new Size(25, 23),
FlatStyle = FlatStyle.Flat,
FlatAppearance = { BorderSize = 0 },
Cursor = Cursors.Hand
};
// 工具提示在 UpdateOutputFilterButtonState 中动态设置
OutputComboBox = new ComboBox
{
Name = "outputComboBox",
Location = new Point(10, 50),
Size = new Size(250, 23),
DropDownStyle = ComboBoxStyle.DropDownList
};
// 日志区域
logGroupBox = new GroupBox
{
Text = LocalizationManager.GetString("LogGroup"),
Location = new Point(10, 140),
Size = new Size(560, 270)
};
LogTextBox = new TextBox
{
Name = "logTextBox",
Multiline = true,
ReadOnly = true,
ScrollBars = ScrollBars.Both,
Location = new Point(10, 25),
Size = new Size(540, 230),
Font = new Font("Consolas", 9)
};
// 自动连接复选框
AutoConnectCheckBox = new CheckBox
{
Name = "autoConnectCheckBox",
Text = LocalizationManager.GetString("AutoConnectOnStartup"),
Location = new Point(15, 423),
AutoSize = true
};
// 状态标签
StatusLabel = new Label
{
Name = "statusLabel",
Text = LocalizationManager.GetString("StatusDisconnected"),
Location = new Point(150, 424),
AutoSize = true,
ForeColor = Color.Red
};
// 控制按钮
ConnectButton = new Button
{
Name = "connectButton",
Text = LocalizationManager.GetString("ConnectButton"),
Location = new Point(320, 417),
Size = new Size(120, 30),
Enabled = false,
TextAlign = ContentAlignment.MiddleCenter,
Padding = new Padding(0, 1, 0, 0)
};
RefreshButton = new Button
{
Name = "refreshButton",
Text = LocalizationManager.GetString("RefreshDevicesButton"),
Location = new Point(450, 417),
Size = new Size(120, 30),
TextAlign = ContentAlignment.MiddleCenter,
Padding = new Padding(0, 2, 0, 0)
};
// 组装控件
inputGroupBox.Controls.Add(inputLabel);
inputGroupBox.Controls.Add(FilterBluetoothButton);
inputGroupBox.Controls.Add(InputComboBox);
outputGroupBox.Controls.Add(outputLabel);
outputGroupBox.Controls.Add(OutputFilterBluetoothButton);
outputGroupBox.Controls.Add(OutputComboBox);
logGroupBox.Controls.Add(LogTextBox);
form.Controls.Add(inputGroupBox);
form.Controls.Add(outputGroupBox);
form.Controls.Add(ConnectButton);
form.Controls.Add(RefreshButton);
form.Controls.Add(AutoConnectCheckBox);
form.Controls.Add(StatusLabel);
form.Controls.Add(logGroupBox);
// 绑定事件
ConnectButton.Click += (s, e) => ConnectButtonClicked?.Invoke(this, e);
RefreshButton.Click += (s, e) => RefreshButtonClicked?.Invoke(this, e);
FilterBluetoothButton.Click += (s, e) => FilterBluetoothButtonClicked?.Invoke(this, e);
OutputFilterBluetoothButton.Click += (s, e) => OutputFilterBluetoothButtonClicked?.Invoke(this, e);
AutoConnectCheckBox.CheckedChanged += (s, e) => AutoConnectChanged?.Invoke(this, e);
InputComboBox.SelectedIndexChanged += (s, e) =>
{
// 如果是程序刷新设备列表,不触发断开连接
if (IsRefreshingDevices)
{
InputSelectionChanged?.Invoke(this, e);
return;
}
// 如果已连接,先断开连接
if (IsConnected)
{
DeviceSelectionChangedWhileConnected?.Invoke(this, e);
}
InputSelectionChanged?.Invoke(this, e);
};
OutputComboBox.SelectedIndexChanged += (s, e) =>
{
// 如果是程序刷新设备列表,不触发断开连接
if (IsRefreshingDevices)
{
OutputSelectionChanged?.Invoke(this, e);
return;
}
// 如果已连接,先断开连接
if (IsConnected)
{
DeviceSelectionChangedWhileConnected?.Invoke(this, e);
}
OutputSelectionChanged?.Invoke(this, e);
};
}
private void UpdateLocalizedText()
{
form.Text = LocalizationManager.GetString("AppTitle");
inputGroupBox.Text = LocalizationManager.GetString("InputDeviceGroup");
inputLabel.Text = LocalizationManager.GetString("SelectInputDevice");
outputGroupBox.Text = LocalizationManager.GetString("OutputDeviceGroup");
outputLabel.Text = LocalizationManager.GetString("SelectOutputDevice");
logGroupBox.Text = LocalizationManager.GetString("LogGroup");
AutoConnectCheckBox.Text = LocalizationManager.GetString("AutoConnectOnStartup");
RefreshButton.Text = LocalizationManager.GetString("RefreshDevicesButton");
// 更新蓝牙过滤按钮的工具提示
UpdateFilterButtonToolTip();
UpdateOutputFilterButtonToolTip();
// 根据当前状态更新状态标签和连接按钮
bool isConnected = ConnectButton.Text == LocalizationManager.GetString("DisconnectButton") ||
(ConnectButton.Text != LocalizationManager.GetString("ConnectButton") && StatusLabel.ForeColor == Color.Green);
SetConnectedState(isConnected);
}
public void UpdateConnectButtonState(bool enabled)
{
ConnectButton.Enabled = enabled;
}
/// <summary>
/// 更新输入设备蓝牙过滤按钮状态(+ 或 -)
/// </summary>
/// <param name="isInExclusionList">设备是否在排除名单中</param>
public void UpdateFilterButtonState(bool isInExclusionList)
{
string imageName = isInExclusionList ? "minus_sign20.png" : "plus_sign20.png";
FilterBluetoothButton.Image = LoadEmbeddedImage(imageName);
UpdateFilterButtonToolTip(isInExclusionList);
}
/// <summary>
/// 更新输入设备蓝牙过滤按钮工具提示
/// </summary>
private void UpdateFilterButtonToolTip(bool? isInExclusionList = null)
{
isInExclusionList ??= FilterBluetoothButton.Image?.ToString()?.Contains("minus") ?? false;
string tooltipText = isInExclusionList.Value
? LocalizationManager.GetString("RemoveFromExclusionList")
: LocalizationManager.GetString("AddToExclusionList");
filterButtonToolTip.SetToolTip(FilterBluetoothButton, tooltipText);
}
/// <summary>
/// 更新输出设备蓝牙过滤按钮状态(+ 或 -)
/// </summary>
/// <param name="isInExclusionList">设备是否在排除名单中</param>
public void UpdateOutputFilterButtonState(bool isInExclusionList)
{
string imageName = isInExclusionList ? "minus_sign20.png" : "plus_sign20.png";
OutputFilterBluetoothButton.Image = LoadEmbeddedImage(imageName);
UpdateOutputFilterButtonToolTip(isInExclusionList);
}
/// <summary>
/// 更新输出设备蓝牙过滤按钮工具提示
/// </summary>
private void UpdateOutputFilterButtonToolTip(bool? isInExclusionList = null)
{
isInExclusionList ??= OutputFilterBluetoothButton.Image?.ToString()?.Contains("minus") ?? false;
string tooltipText = isInExclusionList.Value
? LocalizationManager.GetString("RemoveFromExclusionList")
: LocalizationManager.GetString("AddToExclusionList");
outputFilterButtonToolTip.SetToolTip(OutputFilterBluetoothButton, tooltipText);
}
public bool IsConnected => ConnectButton.Text == LocalizationManager.GetString("DisconnectButton");
public void SetConnectedState(bool connected)
{
ConnectButton.Text = connected ? LocalizationManager.GetString("DisconnectButton") : LocalizationManager.GetString("ConnectButton");
StatusLabel.Text = connected ? LocalizationManager.GetString("StatusConnected") : LocalizationManager.GetString("StatusDisconnected");
StatusLabel.ForeColor = connected ? Color.Green : Color.Red;
}
public void LogMessage(string message)
{
if (LogTextBox.InvokeRequired)
{
LogTextBox.Invoke(new Action<string>(LogMessage), message);
}
else
{
LogTextBox.AppendText($"{message}\r\n");
LogTextBox.ScrollToCaret();
}
}
public void ClearLog()
{
if (LogTextBox.InvokeRequired)
{
LogTextBox.Invoke(new Action(ClearLog));
}
else
{
LogTextBox.Clear();
}
}
private static Image LoadEmbeddedImage(string resourceName)
{
var assembly = typeof(MainFormLayout).Assembly;
string fullResourceName = $"MidiForwarder.Resources.{resourceName}";
using var stream = assembly.GetManifestResourceStream(fullResourceName)
?? throw new InvalidOperationException($"Resource not found: {fullResourceName}");
return Image.FromStream(stream);
}
}
}