From 3531b727935306c94639a0c5b592df568e418e63 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R" Date: Fri, 1 Nov 2019 00:01:42 +0100 Subject: [PATCH] Initial commit --- .gitignore | 4 + VAR.ScreenAutomation.sln | 25 +++ VAR.ScreenAutomation/App.config | 6 + VAR.ScreenAutomation/Bots/DummyBot.cs | 28 +++ VAR.ScreenAutomation/Code/Mouse.cs | 169 ++++++++++++++++ VAR.ScreenAutomation/Code/Screenshoter.cs | 40 ++++ VAR.ScreenAutomation/Code/WindowHandling.cs | 43 +++++ .../Controls/CtrImageViewer.cs | 115 +++++++++++ VAR.ScreenAutomation/Controls/CtrOutput.cs | 182 ++++++++++++++++++ .../FrmScreenAutomation.Designer.cs | 169 ++++++++++++++++ VAR.ScreenAutomation/FrmScreenAutomation.cs | 96 +++++++++ VAR.ScreenAutomation/FrmScreenAutomation.resx | 120 ++++++++++++ .../Interfaces/IAutomationBot.cs | 11 ++ .../Interfaces/IOutputHandler.cs | 8 + VAR.ScreenAutomation/Program.cs | 19 ++ .../Properties/AssemblyInfo.cs | 36 ++++ .../Properties/Resources.Designer.cs | 71 +++++++ .../Properties/Resources.resx | 117 +++++++++++ .../Properties/Settings.Designer.cs | 30 +++ .../Properties/Settings.settings | 7 + .../VAR.ScreenAutomation.csproj | 99 ++++++++++ VAR.ScreenAutomation/app.manifest | 76 ++++++++ 22 files changed, 1471 insertions(+) create mode 100644 .gitignore create mode 100644 VAR.ScreenAutomation.sln create mode 100644 VAR.ScreenAutomation/App.config create mode 100644 VAR.ScreenAutomation/Bots/DummyBot.cs create mode 100644 VAR.ScreenAutomation/Code/Mouse.cs create mode 100644 VAR.ScreenAutomation/Code/Screenshoter.cs create mode 100644 VAR.ScreenAutomation/Code/WindowHandling.cs create mode 100644 VAR.ScreenAutomation/Controls/CtrImageViewer.cs create mode 100644 VAR.ScreenAutomation/Controls/CtrOutput.cs create mode 100644 VAR.ScreenAutomation/FrmScreenAutomation.Designer.cs create mode 100644 VAR.ScreenAutomation/FrmScreenAutomation.cs create mode 100644 VAR.ScreenAutomation/FrmScreenAutomation.resx create mode 100644 VAR.ScreenAutomation/Interfaces/IAutomationBot.cs create mode 100644 VAR.ScreenAutomation/Interfaces/IOutputHandler.cs create mode 100644 VAR.ScreenAutomation/Program.cs create mode 100644 VAR.ScreenAutomation/Properties/AssemblyInfo.cs create mode 100644 VAR.ScreenAutomation/Properties/Resources.Designer.cs create mode 100644 VAR.ScreenAutomation/Properties/Resources.resx create mode 100644 VAR.ScreenAutomation/Properties/Settings.Designer.cs create mode 100644 VAR.ScreenAutomation/Properties/Settings.settings create mode 100644 VAR.ScreenAutomation/VAR.ScreenAutomation.csproj create mode 100644 VAR.ScreenAutomation/app.manifest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fe5011 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.vs/ +**/bin/** +**/obj/** +*.user diff --git a/VAR.ScreenAutomation.sln b/VAR.ScreenAutomation.sln new file mode 100644 index 0000000..8f78bf1 --- /dev/null +++ b/VAR.ScreenAutomation.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29418.71 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.ScreenAutomation", "VAR.ScreenAutomation\VAR.ScreenAutomation.csproj", "{E2BE8E2A-3422-42A6-82FA-5E0CCDC42032}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E2BE8E2A-3422-42A6-82FA-5E0CCDC42032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2BE8E2A-3422-42A6-82FA-5E0CCDC42032}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2BE8E2A-3422-42A6-82FA-5E0CCDC42032}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2BE8E2A-3422-42A6-82FA-5E0CCDC42032}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8DEFE02E-819D-4286-8378-BE842DBBBFC4} + EndGlobalSection +EndGlobal diff --git a/VAR.ScreenAutomation/App.config b/VAR.ScreenAutomation/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/VAR.ScreenAutomation/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/VAR.ScreenAutomation/Bots/DummyBot.cs b/VAR.ScreenAutomation/Bots/DummyBot.cs new file mode 100644 index 0000000..824474f --- /dev/null +++ b/VAR.ScreenAutomation/Bots/DummyBot.cs @@ -0,0 +1,28 @@ +using System.Drawing; +using VAR.ScreenAutomation.Interfaces; + +namespace VAR.ScreenAutomation.Bots +{ + public class DummyBot : IAutomationBot + { + private int frameCount = 0; + + public void Init(IOutputHandler output) + { + frameCount = 0; + output.Clean(); + } + + public Bitmap Process(Bitmap bmpInput, IOutputHandler output) + { + frameCount++; + output.AddLine(string.Format("Frame: {0}", frameCount)); + return bmpInput; + } + + public string ResponseKeys() + { + return "{UP}"; + } + } +} diff --git a/VAR.ScreenAutomation/Code/Mouse.cs b/VAR.ScreenAutomation/Code/Mouse.cs new file mode 100644 index 0000000..2c8cfcc --- /dev/null +++ b/VAR.ScreenAutomation/Code/Mouse.cs @@ -0,0 +1,169 @@ +using System; +using System.Runtime.InteropServices; + +namespace VAR.ScreenAutomation.Code +{ + public class Mouse + { + public enum MouseButtons + { + Left, + Middle, + Right + } + + public static void SetButton(MouseButtons button, bool down) + { + INPUT input = new INPUT + { + Type = INPUT_MOUSE + }; + input.Data.Mouse.X = 0; + input.Data.Mouse.Y = 0; + if (button == MouseButtons.Left) + { + input.Data.Mouse.Flags = down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; + } + if (button == MouseButtons.Middle) + { + input.Data.Mouse.Flags = down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; + } + if (button == MouseButtons.Right) + { + input.Data.Mouse.Flags = down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; + } + INPUT[] inputs = new INPUT[] { input }; + if (SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) + throw new Exception(); + } + + public static void Click(MouseButtons button) + { + SetButton(button, true); + System.Threading.Thread.Sleep(500); + SetButton(button, false); + } + + public static void GetPosition(out UInt32 x, out UInt32 y) + { + GetCursorPos(out POINT lpPoint); + x = lpPoint.X; + y = lpPoint.Y; + } + + public static void SetPosition(UInt32 x, UInt32 y) + { + SetCursorPos(x, y); + } + + [StructLayout(LayoutKind.Sequential)] + public struct INPUT + { + public uint Type; + public MOUSEKEYBDHARDWAREINPUT Data; + } + + public const int INPUT_MOUSE = 0; + public const int INPUT_KEYBOARD = 1; + public const int INPUT_HARDWARE = 2; + + /// + /// http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f0e82d6e-4999-4d22-b3d3-32b25f61fb2a + /// + [StructLayout(LayoutKind.Explicit)] + public struct MOUSEKEYBDHARDWAREINPUT + { + [FieldOffset(0)] + public HARDWAREINPUT Hardware; + + [FieldOffset(0)] + public KEYBDINPUT Keyboard; + + [FieldOffset(0)] + public MOUSEINPUT Mouse; + } + + /// + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx + /// + [StructLayout(LayoutKind.Sequential)] + public struct HARDWAREINPUT + { + public uint Msg; + public ushort ParamL; + public ushort ParamH; + } + + /// + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx + /// + [StructLayout(LayoutKind.Sequential)] + public struct KEYBDINPUT + { + public ushort Vk; + public ushort Scan; + public uint Flags; + public uint Time; + public IntPtr ExtraInfo; + } + + /// + /// http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/2abc6be8-c593-4686-93d2-89785232dacd + /// https://msdn.microsoft.com/es-es/library/windows/desktop/ms646273%28v=vs.85%29.aspx + /// + [StructLayout(LayoutKind.Sequential)] + public struct MOUSEINPUT + { + public int X; + public int Y; + public uint MouseData; + public uint Flags; + public uint Time; + public IntPtr ExtraInfo; + } + + public const int MOUSEEVENTD_XBUTTON1 = 0x0001; + public const int MOUSEEVENTD_XBUTTON2 = 0x0002; + + public const uint MOUSEEVENTF_ABSOLUTE = 0x8000; + public const uint MOUSEEVENTF_HWHEEL = 0x01000; + public const uint MOUSEEVENTF_MOVE = 0x0001; + public const uint MOUSEEVENTF_MOVE_NOCOALESCE = 0x2000; + public const uint MOUSEEVENTF_LEFTDOWN = 0x0002; + public const uint MOUSEEVENTF_LEFTUP = 0x0004; + public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; + public const uint MOUSEEVENTF_RIGHTUP = 0x0010; + public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020; + public const uint MOUSEEVENTF_MIDDLEUP = 0x0040; + public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000; + public const uint MOUSEEVENTF_WHEEL = 0x0800; + public const uint MOUSEEVENTF_XDOWN = 0x0080; + public const uint MOUSEEVENTF_XUP = 0x0100; + + [DllImport("User32.dll")] + public static extern int SendInput(int nInputs, INPUT[] pInputs, int cbSize); + + + + /// + /// Struct representing a point. + /// + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + public UInt32 X; + public UInt32 Y; + } + + /// + /// Retrieves the cursor's position, in screen coordinates. + /// + /// See MSDN documentation for further information. + [DllImport("user32.dll")] + public static extern bool GetCursorPos(out POINT lpPoint); + + [DllImport("User32.dll")] + public static extern Boolean SetCursorPos(UInt32 X, UInt32 Y); + + } +} \ No newline at end of file diff --git a/VAR.ScreenAutomation/Code/Screenshoter.cs b/VAR.ScreenAutomation/Code/Screenshoter.cs new file mode 100644 index 0000000..24b3b35 --- /dev/null +++ b/VAR.ScreenAutomation/Code/Screenshoter.cs @@ -0,0 +1,40 @@ +using System.Drawing; +using System.Windows.Forms; + +namespace VAR.ScreenAutomation.Code +{ + public class Screenshoter + { + public static Bitmap CaptureControl(Control ctrl, Bitmap bmp = null) + { + if (ctrl == null) { return bmp; } + Point picCapturerOrigin = ctrl.PointToScreen(new Point(0, 0)); + bmp = CaptureScreen(bmp, picCapturerOrigin.X, picCapturerOrigin.Y, ctrl.Width, ctrl.Height); + return bmp; + } + + public static Bitmap CaptureScreen(Bitmap bmp = null, int? left = null, int? top = null, int? width = null, int? height = null) + { + if (width <= 0 || height <= 0) { return bmp; } + + // Determine the size of the "virtual screen", which includes all monitors. + left = left ?? SystemInformation.VirtualScreen.Left; + top = top ?? SystemInformation.VirtualScreen.Top; + width = width ?? SystemInformation.VirtualScreen.Width; + height = height ?? SystemInformation.VirtualScreen.Height; + + // Create a bitmap of the appropriate size to receive the screenshot. + if (bmp == null || bmp?.Width != width || bmp?.Height != height) + { + bmp = new Bitmap(width ?? 0, height ?? 0); + } + + // Draw the screenshot into our bitmap. + using (Graphics g = Graphics.FromImage(bmp)) + { + g.CopyFromScreen(left ?? 0, top ?? 0, 0, 0, bmp.Size); + } + return bmp; + } + } +} diff --git a/VAR.ScreenAutomation/Code/WindowHandling.cs b/VAR.ScreenAutomation/Code/WindowHandling.cs new file mode 100644 index 0000000..33733e5 --- /dev/null +++ b/VAR.ScreenAutomation/Code/WindowHandling.cs @@ -0,0 +1,43 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace VAR.ScreenAutomation.Code +{ + public class WindowHandling + { + private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); + private const UInt32 SWP_NOSIZE = 0x0001; + private const UInt32 SWP_NOMOVE = 0x0002; + private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); + + public static void WindowSetTopLevel(Form form) + { + SetWindowPos(form.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); + } + + public static bool ApplicationIsActivated() + { + var activatedHandle = GetForegroundWindow(); + if (activatedHandle == IntPtr.Zero) + { + return false; + } + + var procId = Process.GetCurrentProcess().Id; + GetWindowThreadProcessId(activatedHandle, out int activeProcId); + return activeProcId == procId; + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); + } +} diff --git a/VAR.ScreenAutomation/Controls/CtrImageViewer.cs b/VAR.ScreenAutomation/Controls/CtrImageViewer.cs new file mode 100644 index 0000000..361a5eb --- /dev/null +++ b/VAR.ScreenAutomation/Controls/CtrImageViewer.cs @@ -0,0 +1,115 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace VAR.ScreenAutomation.Controls +{ + public class CtrImageViewer : PictureBox + { + #region Declarations + + private Image _imageShow = null; + + #endregion + + #region Properties + + public Image ImageShow + { + get { return _imageShow; } + set + { + lock (this) + { + _imageShow = value; + Invalidate(); + } + } + } + + #endregion + + #region Control life cycle + + public CtrImageViewer() + { + BackColor = Color.Black; + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + Redraw(pe.Graphics); + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + //Redraw(null); + this.Invalidate(); + } + + #endregion + + #region Private methods + + private void Redraw(Graphics graph) + { + if (_imageShow == null) + { + return; + } + lock (_imageShow) + { + if (graph == null) + { + graph = this.CreateGraphics(); + } + + // Calcular dimensiones a dibujar y centrar + int imgDrawWidth; + int imgDrawHeight; + float imgDrawX = 0; + float imgDrawY = 0; + float relation = (float)_imageShow.Width / (float)_imageShow.Height; + if (relation > 0) + { + // Imagen mas ancha que alta + imgDrawHeight = (int)(Width / relation); + if (imgDrawHeight > Height) + { + imgDrawHeight = Height; + imgDrawWidth = (int)(Height * relation); + imgDrawX = ((Width - imgDrawWidth) / 2.0f); + } + else + { + imgDrawWidth = Width; + imgDrawY = ((Height - imgDrawHeight) / 2.0f); + } + } + else + { + // Imagen mas alta que ancha + imgDrawWidth = (int)(Width * relation); + if (imgDrawWidth > Width) + { + imgDrawWidth = Width; + imgDrawHeight = (int)(Height / relation); + imgDrawY = ((Height - imgDrawHeight) / 2.0f); + } + else + { + imgDrawHeight = Height; + imgDrawX = ((Width - imgDrawWidth) / 2.0f); + } + } + + graph.DrawImage(_imageShow, imgDrawX, imgDrawY, imgDrawWidth, imgDrawHeight); + } + } + + #endregion + + } +} diff --git a/VAR.ScreenAutomation/Controls/CtrOutput.cs b/VAR.ScreenAutomation/Controls/CtrOutput.cs new file mode 100644 index 0000000..d64ce96 --- /dev/null +++ b/VAR.ScreenAutomation/Controls/CtrOutput.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using VAR.ScreenAutomation.Interfaces; + +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 System.Drawing.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 = false; + private readonly List _pendingOutput = new List(); + + 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; + } + } +} diff --git a/VAR.ScreenAutomation/FrmScreenAutomation.Designer.cs b/VAR.ScreenAutomation/FrmScreenAutomation.Designer.cs new file mode 100644 index 0000000..ad40994 --- /dev/null +++ b/VAR.ScreenAutomation/FrmScreenAutomation.Designer.cs @@ -0,0 +1,169 @@ +namespace VAR.ScreenAutomation +{ + partial class FrmScreenAutomation + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.picCapturer = new System.Windows.Forms.PictureBox(); + this.splitMain = new System.Windows.Forms.SplitContainer(); + this.splitOutput = new System.Windows.Forms.SplitContainer(); + this.picPreview = new VAR.ScreenAutomation.Controls.CtrImageViewer(); + this.btnStartEnd = new System.Windows.Forms.Button(); + this.ctrOutput = new VAR.ScreenAutomation.Controls.CtrOutput(); + ((System.ComponentModel.ISupportInitialize)(this.picCapturer)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); + this.splitMain.Panel1.SuspendLayout(); + this.splitMain.Panel2.SuspendLayout(); + this.splitMain.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitOutput)).BeginInit(); + this.splitOutput.Panel1.SuspendLayout(); + this.splitOutput.Panel2.SuspendLayout(); + this.splitOutput.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picPreview)).BeginInit(); + this.SuspendLayout(); + // + // picCapturer + // + this.picCapturer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.picCapturer.Location = new System.Drawing.Point(4, 4); + this.picCapturer.Margin = new System.Windows.Forms.Padding(4); + this.picCapturer.Name = "picCapturer"; + this.picCapturer.Padding = new System.Windows.Forms.Padding(10); + this.picCapturer.Size = new System.Drawing.Size(424, 799); + this.picCapturer.TabIndex = 0; + this.picCapturer.TabStop = false; + // + // splitMain + // + this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitMain.Location = new System.Drawing.Point(0, 0); + this.splitMain.Margin = new System.Windows.Forms.Padding(10); + this.splitMain.Name = "splitMain"; + // + // splitMain.Panel1 + // + this.splitMain.Panel1.Controls.Add(this.splitOutput); + // + // splitMain.Panel2 + // + this.splitMain.Panel2.Controls.Add(this.picCapturer); + this.splitMain.Size = new System.Drawing.Size(754, 816); + this.splitMain.SplitterDistance = 309; + this.splitMain.TabIndex = 3; + // + // splitOutput + // + this.splitOutput.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitOutput.Location = new System.Drawing.Point(0, 0); + this.splitOutput.Name = "splitOutput"; + this.splitOutput.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitOutput.Panel1 + // + this.splitOutput.Panel1.Controls.Add(this.picPreview); + // + // splitOutput.Panel2 + // + this.splitOutput.Panel2.Controls.Add(this.btnStartEnd); + this.splitOutput.Panel2.Controls.Add(this.ctrOutput); + this.splitOutput.Size = new System.Drawing.Size(309, 816); + this.splitOutput.SplitterDistance = 371; + this.splitOutput.TabIndex = 4; + // + // picPreview + // + this.picPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.picPreview.BackColor = System.Drawing.Color.Black; + this.picPreview.ImageShow = null; + this.picPreview.Location = new System.Drawing.Point(12, 12); + this.picPreview.Name = "picPreview"; + this.picPreview.Size = new System.Drawing.Size(294, 356); + this.picPreview.TabIndex = 1; + this.picPreview.TabStop = false; + // + // btnStartEnd + // + this.btnStartEnd.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btnStartEnd.Location = new System.Drawing.Point(12, 3); + this.btnStartEnd.Name = "btnStartEnd"; + this.btnStartEnd.Size = new System.Drawing.Size(294, 39); + this.btnStartEnd.TabIndex = 3; + this.btnStartEnd.Text = "Start"; + this.btnStartEnd.UseVisualStyleBackColor = true; + this.btnStartEnd.Click += new System.EventHandler(this.BtnStartEnd_Click); + // + // ctrOutput + // + this.ctrOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ctrOutput.Location = new System.Drawing.Point(12, 48); + this.ctrOutput.Name = "ctrOutput"; + this.ctrOutput.Size = new System.Drawing.Size(294, 380); + this.ctrOutput.TabIndex = 2; + this.ctrOutput.Text = "ctrOutput1"; + // + // FrmScreenAutomation + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(754, 816); + this.Controls.Add(this.splitMain); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "FrmScreenAutomation"; + this.Text = "ScreenAutomation"; + this.Load += new System.EventHandler(this.FrmScreenAutomation_Load); + ((System.ComponentModel.ISupportInitialize)(this.picCapturer)).EndInit(); + this.splitMain.Panel1.ResumeLayout(false); + this.splitMain.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); + this.splitMain.ResumeLayout(false); + this.splitOutput.Panel1.ResumeLayout(false); + this.splitOutput.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitOutput)).EndInit(); + this.splitOutput.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picPreview)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox picCapturer; + private Controls.CtrImageViewer picPreview; + private Controls.CtrOutput ctrOutput; + private System.Windows.Forms.SplitContainer splitMain; + private System.Windows.Forms.SplitContainer splitOutput; + private System.Windows.Forms.Button btnStartEnd; + } +} + diff --git a/VAR.ScreenAutomation/FrmScreenAutomation.cs b/VAR.ScreenAutomation/FrmScreenAutomation.cs new file mode 100644 index 0000000..96ef5d8 --- /dev/null +++ b/VAR.ScreenAutomation/FrmScreenAutomation.cs @@ -0,0 +1,96 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using VAR.ScreenAutomation.Bots; +using VAR.ScreenAutomation.Code; +using VAR.ScreenAutomation.Interfaces; + +namespace VAR.ScreenAutomation +{ + public partial class FrmScreenAutomation : Form + { + private bool _running = false; + private IAutomationBot _automationBot = new DummyBot(); + + private Timer timTicker; + private Bitmap bmpScreen = null; + + public FrmScreenAutomation() + { + AutoScaleMode = AutoScaleMode.None; + AutoScaleDimensions = new SizeF(1, 1); + InitializeComponent(); + } + + private void FrmScreenAutomation_Load(object sender, EventArgs e) + { + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + SetStyle(ControlStyles.SupportsTransparentBackColor, true); + TransparencyKey = Color.LimeGreen; + picCapturer.BackColor = Color.LimeGreen; + + if (components == null) { components = new Container(); } + timTicker = new Timer(components) + { + Interval = 16, + }; + timTicker.Tick += TimTicker_Tick; + timTicker.Enabled = true; + timTicker.Start(); + + WindowHandling.WindowSetTopLevel(this); + } + + private void TimTicker_Tick(object sender, EventArgs e) + { + timTicker.Stop(); + + bmpScreen = Screenshoter.CaptureControl(picCapturer, bmpScreen); + + if (_automationBot != null && _running) + { + bmpScreen = _automationBot.Process(bmpScreen, ctrOutput); + string responseKeys = _automationBot.ResponseKeys(); + if (string.IsNullOrEmpty(responseKeys) == false && WindowHandling.ApplicationIsActivated() == false) + { + SendKeys.Send(responseKeys); + } + } + picPreview.ImageShow = bmpScreen; + + timTicker.Start(); + } + + private void BtnStartEnd_Click(object sender, EventArgs e) + { + if (_running) + { + End(); + } + else + { + Start(); + } + } + + private void Start() + { + if (_running) { return; } + _running = true; + btnStartEnd.Text = "End"; + _automationBot?.Init(ctrOutput); + Point pointCapturerCenter = picCapturer.PointToScreen(new Point(picCapturer.Width / 2, picCapturer.Height / 2)); + Mouse.SetPosition((uint)pointCapturerCenter.X, (uint)pointCapturerCenter.Y); + Mouse.Click(Mouse.MouseButtons.Left); + } + + private void End() + { + if (_running == false) { return; } + _running = false; + btnStartEnd.Text = "Start"; + } + } +} diff --git a/VAR.ScreenAutomation/FrmScreenAutomation.resx b/VAR.ScreenAutomation/FrmScreenAutomation.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/VAR.ScreenAutomation/FrmScreenAutomation.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VAR.ScreenAutomation/Interfaces/IAutomationBot.cs b/VAR.ScreenAutomation/Interfaces/IAutomationBot.cs new file mode 100644 index 0000000..674788c --- /dev/null +++ b/VAR.ScreenAutomation/Interfaces/IAutomationBot.cs @@ -0,0 +1,11 @@ +using System.Drawing; + +namespace VAR.ScreenAutomation.Interfaces +{ + public interface IAutomationBot + { + void Init(IOutputHandler output); + Bitmap Process(Bitmap bmpInput, IOutputHandler output); + string ResponseKeys(); + } +} diff --git a/VAR.ScreenAutomation/Interfaces/IOutputHandler.cs b/VAR.ScreenAutomation/Interfaces/IOutputHandler.cs new file mode 100644 index 0000000..b86c242 --- /dev/null +++ b/VAR.ScreenAutomation/Interfaces/IOutputHandler.cs @@ -0,0 +1,8 @@ +namespace VAR.ScreenAutomation.Interfaces +{ + public interface IOutputHandler + { + void Clean(); + void AddLine(string line, object data = null); + } +} diff --git a/VAR.ScreenAutomation/Program.cs b/VAR.ScreenAutomation/Program.cs new file mode 100644 index 0000000..308f05b --- /dev/null +++ b/VAR.ScreenAutomation/Program.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; + +namespace VAR.ScreenAutomation +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new FrmScreenAutomation()); + } + } +} diff --git a/VAR.ScreenAutomation/Properties/AssemblyInfo.cs b/VAR.ScreenAutomation/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1f625a3 --- /dev/null +++ b/VAR.ScreenAutomation/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("VAR.ScreenAutomation")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("VAR.ScreenAutomation")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e2be8e2a-3422-42a6-82fa-5e0ccdc42032")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/VAR.ScreenAutomation/Properties/Resources.Designer.cs b/VAR.ScreenAutomation/Properties/Resources.Designer.cs new file mode 100644 index 0000000..106fa66 --- /dev/null +++ b/VAR.ScreenAutomation/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace VAR.ScreenAutomation.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VAR.ScreenAutomation.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/VAR.ScreenAutomation/Properties/Resources.resx b/VAR.ScreenAutomation/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/VAR.ScreenAutomation/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VAR.ScreenAutomation/Properties/Settings.Designer.cs b/VAR.ScreenAutomation/Properties/Settings.Designer.cs new file mode 100644 index 0000000..15e5d03 --- /dev/null +++ b/VAR.ScreenAutomation/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace VAR.ScreenAutomation.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/VAR.ScreenAutomation/Properties/Settings.settings b/VAR.ScreenAutomation/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/VAR.ScreenAutomation/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/VAR.ScreenAutomation/VAR.ScreenAutomation.csproj b/VAR.ScreenAutomation/VAR.ScreenAutomation.csproj new file mode 100644 index 0000000..2fb3d62 --- /dev/null +++ b/VAR.ScreenAutomation/VAR.ScreenAutomation.csproj @@ -0,0 +1,99 @@ + + + + + Debug + AnyCPU + {E2BE8E2A-3422-42A6-82FA-5E0CCDC42032} + WinExe + VAR.ScreenAutomation + VAR.ScreenAutomation + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + app.manifest + + + + + + + + + + + + + + + + + + + + + Component + + + Component + + + Form + + + FrmScreenAutomation.cs + + + + + + + FrmScreenAutomation.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/VAR.ScreenAutomation/app.manifest b/VAR.ScreenAutomation/app.manifest new file mode 100644 index 0000000..648dc43 --- /dev/null +++ b/VAR.ScreenAutomation/app.manifest @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + +