New our testing moves the mouse and clicks it.
This commit is contained in:
parent
eb5a5789c7
commit
75a4bf3c2e
7 changed files with 370 additions and 227 deletions
|
|
@ -559,12 +559,14 @@ namespace MatterHackers.MatterControl
|
|||
private void ButtonClickTest()
|
||||
{
|
||||
TestFramework test = new TestFramework("C:/TestImages");
|
||||
ImageIO.SaveImageData("test.png", test.GetCurrentScreen());
|
||||
test.Wait(2);
|
||||
test.ClickByName("SettingsAndControls");
|
||||
test.Wait(2);
|
||||
test.ClickImage("BackButton.png");
|
||||
}
|
||||
test.ClickImage("BackButton.png");
|
||||
|
||||
|
||||
//ImageIO.SaveImageData("test.png", test.GetCurrentScreen());
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4c2a2d0370a40ea4524d8df0ff32e8ff182ff1e5
|
||||
Subproject commit fd3e1f9259b528ab1f0d220c6007f53deb81c417
|
||||
145
TestRunner/NativeMethods.cs
Normal file
145
TestRunner/NativeMethods.cs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
Copyright (c) 2014, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MatterHackers.TestRunner
|
||||
{
|
||||
public static class NativeMethods
|
||||
{
|
||||
// P/Invoke declarations
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr DeleteDC(IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr DeleteObject(IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetDesktopWindow();
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetWindowDC(IntPtr ptr);
|
||||
|
||||
[DllImport("User32.Dll")]
|
||||
public static extern long SetCursorPos(int x, int y);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
|
||||
|
||||
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
|
||||
public const int MOUSEEVENTF_LEFTUP = 0x04;
|
||||
|
||||
public static int GetCurrentScreenHeight()
|
||||
{
|
||||
Size sz = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size;
|
||||
return sz.Height;
|
||||
}
|
||||
|
||||
public static ImageBuffer GetCurrentScreen()
|
||||
{
|
||||
ImageBuffer screenCapture = new ImageBuffer();
|
||||
|
||||
Size sz = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size;
|
||||
IntPtr hDesk = GetDesktopWindow();
|
||||
IntPtr hSrce = GetWindowDC(hDesk);
|
||||
IntPtr hDest = CreateCompatibleDC(hSrce);
|
||||
IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
|
||||
IntPtr hOldBmp = SelectObject(hDest, hBmp);
|
||||
bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
|
||||
Bitmap bmpScreenCapture = Bitmap.FromHbitmap(hBmp);
|
||||
SelectObject(hDest, hOldBmp);
|
||||
DeleteObject(hBmp);
|
||||
DeleteDC(hDest);
|
||||
ReleaseDC(hDesk, hSrce);
|
||||
|
||||
//bmpScreenCapture.Save("bitmapsave.png");
|
||||
|
||||
screenCapture = new ImageBuffer(bmpScreenCapture.Width, bmpScreenCapture.Height, 32, new BlenderBGRA());
|
||||
BitmapData bitmapData = bmpScreenCapture.LockBits(new Rectangle(0, 0, bmpScreenCapture.Width, bmpScreenCapture.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpScreenCapture.PixelFormat);
|
||||
|
||||
int offset;
|
||||
byte[] buffer = screenCapture.GetBuffer(out offset);
|
||||
int bitmapDataStride = bitmapData.Stride;
|
||||
int backBufferStrideInBytes = screenCapture.StrideInBytes();
|
||||
int backBufferHeight = screenCapture.Height;
|
||||
int backBufferHeightMinusOne = backBufferHeight - 1;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* bitmapDataScan0 = (byte*)bitmapData.Scan0;
|
||||
fixed (byte* pSourceFixed = &buffer[offset])
|
||||
{
|
||||
byte* pSource = bitmapDataScan0 + bitmapDataStride * backBufferHeightMinusOne;
|
||||
byte* pDestBuffer = pSourceFixed;
|
||||
for (int y = 0; y < screenCapture.Height; y++)
|
||||
{
|
||||
int* pSourceInt = (int*)pSource;
|
||||
pSourceInt -= (bitmapDataStride * y / 4);
|
||||
|
||||
int* pDestBufferInt = (int*)pDestBuffer;
|
||||
pDestBufferInt += (backBufferStrideInBytes * y / 4);
|
||||
|
||||
for (int x = 0; x < screenCapture.Width; x++)
|
||||
{
|
||||
pDestBufferInt[x] = pSourceInt[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bmpScreenCapture.UnlockBits(bitmapData);
|
||||
|
||||
bmpScreenCapture.Dispose();
|
||||
|
||||
return screenCapture;
|
||||
}
|
||||
}
|
||||
}
|
||||
212
TestRunner/TestFramework.cs
Normal file
212
TestRunner/TestFramework.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
Copyright (c) 2014, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace MatterHackers.TestRunner
|
||||
{
|
||||
public class TestFramework
|
||||
{
|
||||
private string imageDirectory;
|
||||
|
||||
public TestFramework(string imageDirectory)
|
||||
{
|
||||
this.imageDirectory = imageDirectory;
|
||||
}
|
||||
|
||||
public enum ClickOrigin { LowerLeft, Center };
|
||||
|
||||
public bool ClickByName(string widgetName, int xOffset = 0, int yOffset = 0, double upDelaySeconds = .2, ClickOrigin origin = ClickOrigin.Center)
|
||||
{
|
||||
foreach (SystemWindow window in SystemWindow.OpenWindows)
|
||||
{
|
||||
GuiWidget widgetToClick = window.FindNamedChildRecursive(widgetName);
|
||||
if (widgetToClick != null)
|
||||
{
|
||||
RectangleDouble childBounds = widgetToClick.TransformToParentSpace(window, widgetToClick.LocalBounds);
|
||||
|
||||
if (origin == ClickOrigin.Center)
|
||||
{
|
||||
xOffset += (int)childBounds.Width / 2;
|
||||
yOffset += (int)childBounds.Height / 2;
|
||||
}
|
||||
|
||||
Point2D screenPosition = new Point2D((int)childBounds.Left + xOffset, (int)window.Height - (int)(childBounds.Bottom + yOffset));
|
||||
|
||||
screenPosition.x += WidgetForWindowsFormsAbstract.MainWindowsFormsWindow.Location.X;
|
||||
screenPosition.y += WidgetForWindowsFormsAbstract.MainWindowsFormsWindow.Location.Y + WidgetForWindowsFormsAbstract.MainWindowsFormsWindow.TitleBarHeight;
|
||||
|
||||
SetCursorPos(screenPosition.x, screenPosition.y);
|
||||
NativeMethods.mouse_event(NativeMethods.MOUSEEVENTF_LEFTDOWN, screenPosition.x, screenPosition.y, 0, 0);
|
||||
|
||||
Wait(upDelaySeconds);
|
||||
|
||||
NativeMethods.mouse_event(NativeMethods.MOUSEEVENTF_LEFTUP, screenPosition.x, screenPosition.y, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Point2D CurrentMousPosition()
|
||||
{
|
||||
Point2D mousePos = new Point2D(System.Windows.Forms.Control.MousePosition.X, System.Windows.Forms.Control.MousePosition.Y);
|
||||
return mousePos;
|
||||
}
|
||||
|
||||
public enum InterpolationType { LINEAR, EASE_IN, EASE_OUT, EASE_IN_OUT };
|
||||
|
||||
public double GetInterpolatedValue(double compleatedRatio0To1, InterpolationType interpolationType)
|
||||
{
|
||||
switch (interpolationType)
|
||||
{
|
||||
case InterpolationType.LINEAR:
|
||||
return compleatedRatio0To1;
|
||||
|
||||
case InterpolationType.EASE_IN:
|
||||
return Math.Pow(compleatedRatio0To1, 3);
|
||||
|
||||
case InterpolationType.EASE_OUT:
|
||||
return (Math.Pow(compleatedRatio0To1 - 1, 3) + 1);
|
||||
|
||||
case InterpolationType.EASE_IN_OUT:
|
||||
if (compleatedRatio0To1 < .5)
|
||||
{
|
||||
return Math.Pow(compleatedRatio0To1 * 2, 3) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Math.Pow(compleatedRatio0To1 * 2 - 2, 3) + 2) / 2;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCursorPos(int x, int y)
|
||||
{
|
||||
Vector2 start = new Vector2(CurrentMousPosition().x, CurrentMousPosition().y);
|
||||
Vector2 end = new Vector2(x, y);
|
||||
Vector2 delta = end - start;
|
||||
int steps = 50;
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
double ratio = i / (double)steps;
|
||||
ratio = GetInterpolatedValue(ratio, InterpolationType.EASE_IN_OUT);
|
||||
Vector2 current = start + delta * ratio;
|
||||
NativeMethods.SetCursorPos((int)current.x, (int)current.y);
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
|
||||
NativeMethods.SetCursorPos((int)end.x, (int)end.y);
|
||||
}
|
||||
|
||||
public bool ClickImage(string imageName, int xOffset = 0, int yOffset = 0, double upDelaySeconds = .2, ClickOrigin origin = ClickOrigin.Center)
|
||||
{
|
||||
string pathToImage = Path.Combine(imageDirectory, imageName);
|
||||
|
||||
if (File.Exists(pathToImage))
|
||||
{
|
||||
ImageBuffer imageToLookFor = new ImageBuffer();
|
||||
|
||||
if (ImageIO.LoadImageData(pathToImage, imageToLookFor))
|
||||
{
|
||||
if (origin == ClickOrigin.Center)
|
||||
{
|
||||
xOffset += imageToLookFor.Width / 2;
|
||||
yOffset += imageToLookFor.Height / 2;
|
||||
}
|
||||
|
||||
ImageBuffer currentScreen = NativeMethods.GetCurrentScreen();
|
||||
|
||||
Vector2 matchPosition;
|
||||
double bestMatch;
|
||||
if (currentScreen.FindLeastSquaresMatch(imageToLookFor, out matchPosition, out bestMatch, 50))
|
||||
{
|
||||
// TODO: figure out which window the position is in
|
||||
Point2D screenPosition = new Point2D((int)matchPosition.x + xOffset, currentScreen.Height - (int)(matchPosition.y + yOffset));
|
||||
SetCursorPos(screenPosition.x, screenPosition.y);
|
||||
NativeMethods.mouse_event(NativeMethods.MOUSEEVENTF_LEFTDOWN, screenPosition.x, screenPosition.y, 0, 0);
|
||||
Wait(upDelaySeconds);
|
||||
NativeMethods.mouse_event(NativeMethods.MOUSEEVENTF_LEFTUP, screenPosition.x, screenPosition.y, 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImageBuffer GetCurrentScreen()
|
||||
{
|
||||
return NativeMethods.GetCurrentScreen();
|
||||
}
|
||||
|
||||
public bool ImageExists(ImageBuffer image)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ImageExists(string imageFileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool NameExists(string widgetName)
|
||||
{
|
||||
foreach (SystemWindow window in SystemWindow.OpenWindows)
|
||||
{
|
||||
GuiWidget widgetToClick = window.FindNamedChildRecursive(widgetName);
|
||||
if (widgetToClick != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Wait(double timeInSeconds)
|
||||
{
|
||||
Thread.Sleep((int)(timeInSeconds * 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2014, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MatterHackers.TestRunner
|
||||
{
|
||||
public class TestFramework
|
||||
{
|
||||
// P/Invoke declarations
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
|
||||
wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr DeleteDC(IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr DeleteObject(IntPtr hDc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
|
||||
[DllImport("gdi32.dll")]
|
||||
static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetDesktopWindow();
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetWindowDC(IntPtr ptr);
|
||||
|
||||
string imageDirectory;
|
||||
|
||||
public TestFramework(string imageDirectory)
|
||||
{
|
||||
this.imageDirectory = imageDirectory;
|
||||
}
|
||||
|
||||
public bool ClickByName(string widgetName, int xOffset = 0, int yOffset = 0, double upDelaySeconds = .2)
|
||||
{
|
||||
foreach (SystemWindow window in SystemWindow.OpenWindows)
|
||||
{
|
||||
GuiWidget widgetToClick = window.FindNamedChildRecursive(widgetName);
|
||||
if (widgetToClick != null)
|
||||
{
|
||||
RectangleDouble childBounds = widgetToClick.TransformToParentSpace(window, widgetToClick.LocalBounds);
|
||||
UiThread.RunOnIdle(() =>
|
||||
window.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1,
|
||||
childBounds.Left + xOffset, childBounds.Bottom + yOffset,
|
||||
0)));
|
||||
Wait(upDelaySeconds);
|
||||
UiThread.RunOnIdle(() =>
|
||||
window.OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0,
|
||||
childBounds.Left + xOffset, childBounds.Bottom + yOffset,
|
||||
0)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ClickImage(string imageName, int xOffset = 0, int yOffset = 0, double upDelaySeconds = .2)
|
||||
{
|
||||
string pathToImage = Path.Combine(imageDirectory, imageName);
|
||||
|
||||
ImageBuffer imageToLookFor = new ImageBuffer();
|
||||
if (ImageIO.LoadImageData(pathToImage, imageToLookFor))
|
||||
{
|
||||
ImageBuffer currentScreen = GetCurrentScreen();
|
||||
|
||||
Vector2 matchPosition;
|
||||
double bestMatch;
|
||||
if (currentScreen.FindLeastSquaresMatch(imageToLookFor, out matchPosition, out bestMatch))
|
||||
{
|
||||
// TODO: figure out which window the position is in
|
||||
SystemWindow window = SystemWindow.OpenWindows[0];
|
||||
|
||||
UiThread.RunOnIdle(() =>
|
||||
window.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1,
|
||||
matchPosition.x + xOffset, matchPosition.y + yOffset,
|
||||
0)));
|
||||
Wait(upDelaySeconds);
|
||||
UiThread.RunOnIdle(() =>
|
||||
window.OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0,
|
||||
matchPosition.x + xOffset, matchPosition.y + yOffset,
|
||||
0)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool NameExists(string widgetName)
|
||||
{
|
||||
foreach (SystemWindow window in SystemWindow.OpenWindows)
|
||||
{
|
||||
GuiWidget widgetToClick = window.FindNamedChildRecursive(widgetName);
|
||||
if (widgetToClick != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImageBuffer GetCurrentScreen()
|
||||
{
|
||||
ImageBuffer screenCapture = new ImageBuffer();
|
||||
|
||||
Size sz = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size;
|
||||
IntPtr hDesk = GetDesktopWindow();
|
||||
IntPtr hSrce = GetWindowDC(hDesk);
|
||||
IntPtr hDest = CreateCompatibleDC(hSrce);
|
||||
IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
|
||||
IntPtr hOldBmp = SelectObject(hDest, hBmp);
|
||||
bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
|
||||
Bitmap bmpScreenCapture = Bitmap.FromHbitmap(hBmp);
|
||||
SelectObject(hDest, hOldBmp);
|
||||
DeleteObject(hBmp);
|
||||
DeleteDC(hDest);
|
||||
ReleaseDC(hDesk, hSrce);
|
||||
|
||||
//bmpScreenCapture.Save("bitmapsave.png");
|
||||
|
||||
screenCapture = new ImageBuffer(bmpScreenCapture.Width, bmpScreenCapture.Height, 32, new BlenderBGRA());
|
||||
BitmapData bitmapData = bmpScreenCapture.LockBits(new Rectangle(0, 0, bmpScreenCapture.Width, bmpScreenCapture.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpScreenCapture.PixelFormat);
|
||||
|
||||
int offset;
|
||||
byte[] buffer = screenCapture.GetBuffer(out offset);
|
||||
int bitmapDataStride = bitmapData.Stride;
|
||||
int backBufferStrideInBytes = screenCapture.StrideInBytes();
|
||||
int backBufferHeight = screenCapture.Height;
|
||||
int backBufferHeightMinusOne = backBufferHeight - 1;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* bitmapDataScan0 = (byte*)bitmapData.Scan0;
|
||||
fixed (byte* pSourceFixed = &buffer[offset])
|
||||
{
|
||||
byte* pSource = bitmapDataScan0 + bitmapDataStride * backBufferHeightMinusOne;
|
||||
byte* pDestBuffer = pSourceFixed;
|
||||
for (int y = 0; y < screenCapture.Height; y++)
|
||||
{
|
||||
int* pSourceInt = (int*)pSource;
|
||||
pSourceInt -= (bitmapDataStride * y / 4);
|
||||
|
||||
int* pDestBufferInt = (int*)pDestBuffer;
|
||||
pDestBufferInt += (backBufferStrideInBytes * y / 4);
|
||||
|
||||
for (int x = 0; x < screenCapture.Width; x++)
|
||||
{
|
||||
pDestBufferInt[x] = pSourceInt[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bmpScreenCapture.UnlockBits(bitmapData);
|
||||
|
||||
bmpScreenCapture.Dispose();
|
||||
|
||||
return screenCapture;
|
||||
}
|
||||
|
||||
public bool ImageExists(ImageBuffer image)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ImageExists(string imageFileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Wait(double timeInSeconds)
|
||||
{
|
||||
Thread.Sleep((int)(timeInSeconds * 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -132,7 +132,8 @@
|
|||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="TestRunner.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="TestFramework.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Submodules\agg-sharp\agg\Agg.csproj">
|
||||
|
|
@ -162,6 +163,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
|||
4
TestRunner/packages.config
Normal file
4
TestRunner/packages.config
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="InputSimulator" version="1.0.4.0" targetFramework="net45" />
|
||||
</packages>
|
||||
Loading…
Add table
Add a link
Reference in a new issue