Files
VAR.Toolbox/VAR.ScreenAutomation/Controls/CtrOutput.cs

190 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using VAR.ScreenAutomation.Interfaces;
// ReSharper disable InconsistentNaming
namespace VAR.ScreenAutomation.Controls
{
public class CtrOutput : Control, IOutputHandler
{
private ListBox _listBox;
private Timer _timer;
private class OutputItem
{
public string Text { get; set; }
public object Data { get; set; }
public override string ToString()
{
return Text;
}
}
public new event EventHandler DoubleClick;
public CtrOutput()
{
InitializeControls();
}
private void InitializeControls()
{
_listBox = new ListBox
{
Dock = DockStyle.Fill,
FormattingEnabled = true,
Font = new Font("Consolas", 9),
BackColor = Color.Black,
ForeColor = Color.Gray,
SelectionMode = SelectionMode.MultiExtended,
};
_listBox.MouseDoubleClick += ListBox_MouseDoubleClick;
_listBox.KeyDown += ListBox_KeyDown;
Controls.Add(_listBox);
_timer = new Timer
{
Interval = 100,
Enabled = true
};
_timer.Tick += Timer_Tick;
Disposed += CtrOutput_Disposed;
}
private void CtrOutput_Disposed(object sender, EventArgs e)
{
_timer.Stop();
_timer.Enabled = false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((keyData & Keys.Control) == Keys.Control && (keyData & Keys.C) == Keys.C)
{
CopyToClipboard();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void ListBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.C)
{
CopyToClipboard();
}
}
private void CopyToClipboard()
{
StringBuilder sbText = new StringBuilder();
foreach (OutputItem item in _listBox.SelectedItems)
{
sbText.AppendLine(item.Text);
}
if (sbText.Length > 0)
{
Clipboard.SetText(sbText.ToString());
}
}
private void ListBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
DoubleClick?.Invoke(sender, e);
}
private void Timer_Tick(object sender, EventArgs e)
{
if (_updated)
{
UpdatePosition();
}
}
private bool _updated;
private readonly List<OutputItem> _pendingOutput = new List<OutputItem>();
private void UpdatePosition()
{
lock (_pendingOutput)
{
EnableRepaint(new HandleRef(_listBox, _listBox.Handle), false);
_listBox.SuspendLayout();
foreach (OutputItem item in _pendingOutput)
{
_listBox.Items.Add(item);
}
_pendingOutput.Clear();
_listBox.ResumeLayout();
int visibleItems = _listBox.ClientSize.Height / _listBox.ItemHeight;
_listBox.TopIndex = Math.Max(_listBox.Items.Count - visibleItems + 1, 0);
_updated = false;
EnableRepaint(new HandleRef(_listBox, _listBox.Handle), true);
_listBox.Invalidate();
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam);
private static void EnableRepaint(HandleRef handle, bool enable)
{
const int WM_SETREDRAW = 0x000B;
SendMessage(handle, WM_SETREDRAW, new IntPtr(enable ? 1 : 0), IntPtr.Zero);
}
public void Clean()
{
if (_listBox.InvokeRequired)
{
_listBox.Invoke((MethodInvoker)(() =>
{
_listBox.Items.Clear();
_updated = true;
}));
}
else
{
_listBox.Items.Clear();
_updated = true;
}
}
public void AddLine(string line, object data = null)
{
lock (_pendingOutput)
{
_pendingOutput.Add(new OutputItem { Text = line, Data = data, });
_updated = true;
}
}
public string GetCurrentText()
{
if (_listBox.SelectedItems.Count == 0) { return null; }
OutputItem item = (OutputItem)_listBox.SelectedItems[0];
return item?.Text;
}
public object GetCurrentData()
{
if (_listBox.SelectedItems.Count == 0) { return null; }
OutputItem item = (OutputItem)_listBox.SelectedItems[0];
return item?.Data;
}
}
}