Skip to content

Commit c5e461d

Browse files
committed
Initial version of application
1 parent edfbd58 commit c5e461d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3129
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# http://stackoverflow.com/questions/2143956/gitignore-for-visual-studio-projects-and-solutions
2+
3+
Dist/
4+
Src/*.suo
5+
Src/**/[Bb]in/
6+
Src/**/[Oo]bj/
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
namespace ScreenGrid.Models.AppsInterop
2+
{
3+
using System;
4+
using System.Drawing;
5+
using System.Text;
6+
using System.Collections.Generic;
7+
8+
/// <summary>
9+
/// Native window wrapper
10+
/// </summary>
11+
public class NativeWindow
12+
{
13+
protected readonly IntPtr hWnd;
14+
15+
public NativeWindow(IntPtr hWnd)
16+
{
17+
this.hWnd = hWnd;
18+
}
19+
20+
public IntPtr Handle
21+
{
22+
get
23+
{
24+
return this.hWnd;
25+
}
26+
}
27+
28+
public bool IsMinimized
29+
{
30+
get
31+
{
32+
return WinApiInterop.NativeMethods.IsMinimized(this.hWnd);
33+
}
34+
}
35+
36+
public bool IsVisible
37+
{
38+
get
39+
{
40+
return WinApiInterop.NativeMethods.IsVisible(this.hWnd);
41+
}
42+
}
43+
44+
public string ClassName
45+
{
46+
get
47+
{
48+
var lpClassName = new StringBuilder(1000);
49+
WinApiInterop.NativeMethods.GetClassName(hWnd, lpClassName, 1000);
50+
51+
return lpClassName.ToString();
52+
}
53+
}
54+
55+
public Point Location
56+
{
57+
get
58+
{
59+
var rect = new WinApiInterop.RECT();
60+
var b = WinApiInterop.NativeMethods.GetWindowRect(hWnd, ref rect);
61+
if (!b)
62+
{
63+
;
64+
}
65+
66+
return new Point(rect.Left, rect.Top);
67+
}
68+
}
69+
70+
public Rectangle Rect
71+
{
72+
get
73+
{
74+
var rect = new WinApiInterop.RECT();
75+
var b = WinApiInterop.NativeMethods.GetWindowRect(hWnd, ref rect);
76+
if (!b)
77+
{
78+
;
79+
}
80+
81+
return new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
82+
}
83+
}
84+
85+
public Bitmap GetShot()
86+
{
87+
var rect = new WinApiInterop.RECT();
88+
var b = WinApiInterop.NativeMethods.GetWindowRect(this.hWnd, ref rect);
89+
return WinApiInterop.NativeMethods.GetWindowImage(this.hWnd, 0, 0, (rect.Right - rect.Left) + 1, (rect.Bottom - rect.Top) + 1); // TODO: +1 ?
90+
}
91+
92+
public static NativeWindow GetTopMostWindow(IEnumerable<string> classNames)
93+
{
94+
// Is there are win32 function to get a list off all top level windows
95+
// with a given class name?
96+
// Right now I am using EnumWindows (getting all windows) and then using
97+
// GetClassName on each window to see if it is a window that I care
98+
// about.
99+
100+
// https://code.msdn.microsoft.com/windowsapps/Enumerate-top-level-9aa9d7c1
101+
102+
var results = new List<IntPtr>();
103+
//WinApiInterop.WinApiUtils.EnumWindows(new WinApiInterop.WinApiUtils.EnumWindowsProc(EnumTheWindows), IntPtr.Zero);
104+
105+
// http://stackoverflow.com/a/296014
106+
107+
WinApiInterop.NativeMethods.EnumWindows((hWnd, lParam) =>
108+
{
109+
var win = new NativeWindow(hWnd);
110+
111+
foreach (var className in classNames)
112+
{
113+
if ((String.Compare(win.ClassName, className, StringComparison.OrdinalIgnoreCase) == 0) &&
114+
(!win.IsMinimized) &&
115+
(win.IsVisible))
116+
{
117+
results.Add(hWnd);
118+
}
119+
}
120+
121+
return true;
122+
}, IntPtr.Zero);
123+
124+
if (results.Count > 0)
125+
{
126+
return new NativeWindow(results[0]);
127+
}
128+
else
129+
{
130+
return null;
131+
}
132+
}
133+
}
134+
}
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
namespace ScreenGrid.Models.AppsInterop
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Drawing;
6+
using System.Linq;
7+
8+
/// <summary>
9+
/// Native window wrapper of Octane Render
10+
/// </summary>
11+
public class OctaneRenderWindow : NativeWindow
12+
{
13+
public OctaneRenderWindow(IntPtr hWnd)
14+
: base(hWnd)
15+
{
16+
17+
}
18+
19+
private const string ProcessName = "octane";
20+
21+
public static OctaneRenderWindow GetFromFirstProcess()
22+
{
23+
var proc = System.Diagnostics.Process.GetProcesses().Where(p => String.Compare(p.ProcessName, ProcessName, StringComparison.OrdinalIgnoreCase) == 0).FirstOrDefault();
24+
25+
if (proc != null)
26+
{
27+
return new OctaneRenderWindow(proc.MainWindowHandle);
28+
}
29+
else
30+
{
31+
return null;
32+
}
33+
}
34+
35+
public static IList<OctaneRenderWindow> GetFromAllProcesses()
36+
{
37+
var processes = System.Diagnostics.Process.GetProcesses().Where(p => String.Compare(p.ProcessName, ProcessName, StringComparison.OrdinalIgnoreCase) == 0).ToList();
38+
39+
return (processes.Select(w => new OctaneRenderWindow(w.MainWindowHandle)).ToList());
40+
}
41+
42+
private static Bitmap UpperLeftCorner
43+
{
44+
get
45+
{
46+
var imageData = ReadResourceFile("ScreenGrid.Models.Resources.UpperLeftCorner.png");
47+
using (var ms = new System.IO.MemoryStream(imageData))
48+
{
49+
return new Bitmap(ms);
50+
}
51+
}
52+
}
53+
54+
private static Bitmap LowerRightCorner
55+
{
56+
get
57+
{
58+
var imageData = ReadResourceFile("ScreenGrid.Models.Resources.LowerRightCorner.png");
59+
using (var ms = new System.IO.MemoryStream(imageData))
60+
{
61+
return new Bitmap(ms);
62+
}
63+
}
64+
}
65+
66+
private static Point TopLeftCorner(FlatImage image)
67+
{
68+
var topLeftCornerFragment = new FlatImage(OctaneRenderWindow.UpperLeftCorner);
69+
70+
var topLeftCornerX = 0;
71+
var topLeftCornerY = 0;
72+
for (var x = 0; x < image.Width - topLeftCornerFragment.Width; x++)
73+
{
74+
for (var y = 0; y < image.Height - topLeftCornerFragment.Height; y++)
75+
{
76+
if (image.CompareWithFragmentWithTolerance(topLeftCornerFragment, x, y))
77+
{
78+
topLeftCornerX = x + topLeftCornerFragment.Width - 1;
79+
topLeftCornerY = y + topLeftCornerFragment.Height - 1;
80+
return new Point(topLeftCornerX, topLeftCornerY);
81+
}
82+
}
83+
}
84+
85+
return new Point(0, 0);
86+
}
87+
88+
private static Point BottomRightCorner(FlatImage image)
89+
{
90+
var bottomRightCornerFragment = new FlatImage(OctaneRenderWindow.LowerRightCorner);
91+
92+
var bottomRightCornerX = 0;
93+
var bottomRightCornerY = 0;
94+
for (var x = 0; x < image.Width - bottomRightCornerFragment.Width; x++)
95+
{
96+
for (var y = 0; y < image.Height - bottomRightCornerFragment.Height; y++)
97+
{
98+
if (image.CompareWithFragmentWithTolerance(bottomRightCornerFragment, x, y))
99+
{
100+
bottomRightCornerX = x;
101+
bottomRightCornerY = y;
102+
return new Point(bottomRightCornerX, bottomRightCornerY);
103+
}
104+
}
105+
}
106+
107+
return new Point(0, 0);
108+
}
109+
110+
/// <summary>
111+
/// Search image top left point
112+
/// </summary>
113+
/// <param name="image"></param>
114+
/// <param name="topLeftCorner"></param>
115+
/// <param name="bottomRightCorner"></param>
116+
/// <returns></returns>
117+
private static Point TopLeftImage(FlatImage image, Point topLeftCorner, Point bottomRightCorner)
118+
{
119+
var topLeftCornerFragment = new FlatImage(OctaneRenderWindow.UpperLeftCorner);
120+
121+
var topLeftImageX = 0;
122+
var topLeftImageY = 0;
123+
124+
var canvasColor = image.pixels[(int)topLeftCorner.X, (int)topLeftCorner.Y];
125+
126+
for (var y = (int)topLeftCorner.Y; y < (int)bottomRightCorner.Y; y++)
127+
{
128+
for (var x = (int)topLeftCorner.X; x < (int)bottomRightCorner.X; x++)
129+
{
130+
//if (PointUtils.MidDiff(image.pixels[x, y], areaColor1) > 2)
131+
if (image.pixels[x, y] != canvasColor)
132+
{
133+
if (y > (int)topLeftCorner.Y)
134+
{
135+
topLeftImageX = x;
136+
topLeftImageY = y;
137+
return new Point(topLeftImageX, topLeftImageY);
138+
}
139+
140+
break;
141+
}
142+
}
143+
}
144+
145+
return new Point(0, 0);
146+
}
147+
148+
/// <summary>
149+
/// Search image bottom right point
150+
/// </summary>
151+
/// <param name="image"></param>
152+
/// <param name="topLeftCorner"></param>
153+
/// <param name="bottomRightCorner"></param>
154+
/// <returns></returns>
155+
private static Point BottomRightImage(FlatImage image, Point topLeftCorner, Point bottomRightCorner)
156+
{
157+
var bottomRightCornerFragment = new FlatImage(OctaneRenderWindow.LowerRightCorner);
158+
159+
var areaColor2 = image.pixels[(int)bottomRightCorner.X, (int)bottomRightCorner.Y];
160+
161+
for (var y = (int)bottomRightCorner.Y - 1; y > (int)topLeftCorner.Y; y--)
162+
{
163+
for (var x = (int)bottomRightCorner.X - 1; x > (int)topLeftCorner.X; x--)
164+
{
165+
if (image.pixels[x, y] != areaColor2)
166+
{
167+
if (y < bottomRightCorner.Y)
168+
{
169+
return new Point(x, y);
170+
}
171+
172+
break;
173+
}
174+
}
175+
}
176+
177+
return new Point(0, 0);
178+
}
179+
180+
public static Geometry.Rectangle FindRenderedImageBorders(FlatImage flatImage)
181+
{
182+
var topLeftCorner = OctaneRenderWindow.TopLeftCorner(flatImage);
183+
var bottomRightCorner = OctaneRenderWindow.BottomRightCorner(flatImage);
184+
var topLeftImage = OctaneRenderWindow.TopLeftImage(flatImage, topLeftCorner, bottomRightCorner);
185+
var bottomRightImage = OctaneRenderWindow.BottomRightImage(flatImage, topLeftCorner, bottomRightCorner);
186+
187+
// TODO: && topLeftImageFound && bottomRightImageFound)
188+
if ((topLeftCorner.X > 0) && (topLeftCorner.Y > 0) && (bottomRightCorner.X > 0) && (bottomRightCorner.Y > 0) && (topLeftImage.X > 0))
189+
{
190+
return new Geometry.Rectangle
191+
{
192+
X = topLeftImage.X,
193+
Y = topLeftImage.Y,
194+
Width = bottomRightImage.X - topLeftImage.X + 1,
195+
Height = bottomRightImage.Y - topLeftImage.Y + 1,
196+
};
197+
}
198+
else
199+
{
200+
return Geometry.Rectangle.Empty;
201+
}
202+
}
203+
204+
private static byte[] ReadResourceFile(string id)
205+
{
206+
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
207+
208+
byte[] data = null;
209+
using (var stream = assembly.GetManifestResourceStream(id))
210+
{
211+
data = new byte[stream.Length];
212+
stream.Read(data, 0, (int)stream.Length);
213+
}
214+
215+
return data;
216+
}
217+
}
218+
}

0 commit comments

Comments
 (0)