public Screenshot(IntPtr targetWindow, ScreenshotMethod method, bool withSolidGlass) { this.TargetHandle = targetWindow == IntPtr.Zero ? Windowing.GetForegroundWindow() : targetWindow; this.WindowClass = Windowing.GetWindowClass(TargetHandle); Trace.WriteLine(string.Format("Requested method is '{0}'", method), string.Format("Screenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); this.Method = method == ScreenshotMethod.Auto ? ScreenshotMethod.DWM : method; this.Method = FMUtils.WinApi.Helper.VisualStyle != Helper.VisualStyles.Aero ? ScreenshotMethod.GDI : this.Method; //I cannot recall why I uncommented the above and used this instead, undoing until I remember //this.Method = method; Trace.WriteLine(string.Format("Actual method is '{0}'", this.Method), string.Format("Screenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //this.TargetRect = isMaximized ? Screen.FromHandle(TargetHandle).WorkingArea : Helper.GetWindowRectangle(TargetHandle); this.TargetRect = Helper.GetWindowRectangleDPI(TargetHandle); this.isMaximized = Helper.IsWindowMazimized(TargetHandle); this.TargetScreen = Screen.FromHandle(TargetHandle); this.BaseScreenshotImage = this.Method == ScreenshotMethod.DWM ? ScreenshotWindowDWM(TargetHandle, withSolidGlass) : ScreenshotWindowGDI(TargetHandle, withSolidGlass); this.isRounded = !Helper.IsSquareWindowEdge(TargetHandle); this.WindowTitle = WinApi.Helper.GetWindowText(TargetHandle, true); this.Date = DateTime.Now; }
/// <summary> /// Creates new CustomGame object using an Overwatch process. /// </summary> /// <param name="overwatchHandle">Overwatch process handle to use. Leave at default to use the first Overwatch process found.</param> /// <param name="screenshotMethod">Method to take screenshots with.</param> /// <param name="openChatIsDefault">Determines if the chat should be opened at all times. Command scanning is more reliable if true.</param> public CustomGame(IntPtr overwatchHandle = new IntPtr(), ScreenshotMethod screenshotMethod = ScreenshotMethod.BitBlt, bool openChatIsDefault = true) { if (overwatchHandle == IntPtr.Zero) { // Get the overwatch process Process[] overwatchProcesses = Process.GetProcessesByName("Overwatch"); if (overwatchProcesses.Length > 0) { OverwatchHandle = overwatchProcesses[0].MainWindowHandle; } } else { OverwatchHandle = overwatchHandle; } if (OverwatchHandle == IntPtr.Zero) { throw new MissingOverwatchProcessException("Could not find any Overwatch processes running."); } SetupWindow(OverwatchHandle, ScreenshotMethod); Thread.Sleep(500); // Set up debug window if debugmode is set to true. if (debugmode) { new Task(() => { debug = new Form(); debug.Width = 1500; debug.Height = 1000; debug.Show(); g = debug.CreateGraphics(); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; Application.Run(debug); }).Start(); } Command = new Commands(this); AI = new CG_AI(this); Maps = new CG_Maps(this); Chat = new CG_Chat(this); Pause = new CG_Pause(this); PlayerInfo = new CG_PlayerInfo(this); Interact = new CG_Interact(this); GameSettings = new CG_Settings(this); // Create bitmap of overwatch client screen capture. ScreenshotMethod = screenshotMethod; // Set the screenshot method OpenChatIsDefault = openChatIsDefault; if (OpenChatIsDefault) { Chat.OpenChat(); } SetupGameOverCheck(); }
static void SetupWindow(IntPtr hWnd, ScreenshotMethod method) { if (method == ScreenshotMethod.ScreenCopy) { User32.SetForegroundWindow(hWnd); } else { User32.ShowWindow(hWnd, User32.nCmdShow.SW_SHOWNOACTIVATE); } User32.MoveWindow(hWnd, -7, 0, Rectangles.ENTIRE_SCREEN.Width, Rectangles.ENTIRE_SCREEN.Height, false); }
private static void Screenshot(ScreenshotMethod method, IntPtr hWnd, ref DirectBitmap capture) { Validate(hWnd); if (method == ScreenshotMethod.BitBlt) { ScreenshotBitBlt(hWnd, ref capture); } else if (method == ScreenshotMethod.ScreenCopy) { ScreenshotScreenCopy(hWnd, ref capture); } }
static void Screenshot(ScreenshotMethod method, IntPtr hWnd, ref Bitmap bmp) { // Show the window behind all other opened windows. Screenshot does not work if Overwatch is minimized. SetupWindow(hWnd, method); if (method == ScreenshotMethod.BitBlt) { ScreenshotBitBlt(hWnd, ref bmp); } else if (method == ScreenshotMethod.ScreenCopy) { ScreenshotScreenCopy(hWnd, ref bmp); } }
public Screenshot(Rectangle r) { this.Method = ScreenshotMethod.GDI; this.TargetRect = r; this.isMaximized = false; this.TargetScreen = Screen.FromRectangle(r); this.BaseScreenshotImage = Core.ScreenshotArea(r); this.isRounded = false; this.WindowTitle = "Screenshot (" + r.ToString() + ")"; this.Date = DateTime.Now; }
private static bool WaitForMainMenu(ScreenshotMethod screenshotMethod, IntPtr hwnd, DirectBitmap bmp, int maxTime) { Stopwatch elapsed = new Stopwatch(); elapsed.Start(); while (elapsed.ElapsedMilliseconds < maxTime || maxTime == -1) { Screenshot(screenshotMethod, hwnd, ref bmp); if (bmp.CompareColor(Points.MAIN_MENU_OVERWATCH_WATERMARK, Colors.WHITE, 10)) { Thread.Sleep(2000); return(true); } Thread.Sleep(500); } return(false); }
public ExtendedScreenshot(ScreenshotMethod method = ScreenshotMethod.DWM, bool withSolidGlass = true) : base(method, withSolidGlass) { }
public ComposedScreenshot(IntPtr targetWindow, ScreenshotMethod method = ScreenshotMethod.DWM, bool withSolidGlass = true) : base(targetWindow, method, withSolidGlass) { Trace.WriteLine("Creating composed screenshot...", string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); CursorLocation = Cursor.Position; CursorImage = Core.GetCursor(); //#32768 is the Windows Menu Class // || wc.StartsWith("WindowsForms10.Window.20808"); var ContextMenus = Windowing.GetChildWindows(Windowing.GetDesktopWindow()).Where(h => Windowing.GetWindowClass(h) == "#32768").ToList(); if (ContextMenus.Any(h => CaptureRect.IntersectsWith(Helper.GetWindowRectangle(h)))) { Trace.WriteLine(string.Format("Found Win32 {0} menus...", ContextMenus.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); CompositionStack.AddRange(ContextMenus.Select(h => Screenshot.FromBitmapRect(Core.ScreenshotWindow(h), Helper.GetWindowRectangle((h))))); } else { //If there are no Win32 popup context menus found, but the mouse is over something who's root is the target rect, walk that tree for composition items //Check if the thing the mouse is over is different (eg, an overhanging menu) IntPtr MouseTargetHandle = Windowing.WindowFromPoint(Cursor.Position); //We don't want to do this when we're trying to get popup context menus since they are children of the desktop window, //not the target window. However that situation is handled separately above. //What we're doing here is looking for overlapping windows, like GTK context menus if (Windowing.GetAncestor(MouseTargetHandle, Windowing.GA_ROOTOWNER) == this.TargetHandle) // && !this.TargetRect.Contains(Cursor.Position)) { Trace.WriteLine(string.Format("Mouse over something else, handle {0}...", MouseTargetHandle), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); while (MouseTargetHandle != TargetHandle && MouseTargetHandle != IntPtr.Zero) { //var MouseTargetWindowRect = Helper.GetWindowRectangle(MouseTargetHandle); //var MouseTargetScreenshot = Core.ScreenshotArea(MouseTargetHandle, MouseTargetWindowRect); //GTK menus seem to have virtually identical parents of themselves, so I initially tried to circumvent this //with a check to prevent any two same rects from being added //though, it's obsolete with the more robust removal below //if (!CompositionStack.Any(ss => ss.TargetRect == MouseTargetWindowRect)) //var layer = Screenshot.FromBitmapRect(MouseTargetScreenshot, MouseTargetWindowRect); var layer = new Screenshot(MouseTargetHandle, ScreenshotMethod.GDI, false); CompositionStack.Add(layer); Trace.WriteLine("Added " + layer.TargetHandle.ToString() + "; Class: " + layer.WindowClass, "ComposedScreenshot.ctor"); MouseTargetHandle = Windowing.GetParent(MouseTargetHandle); } Trace.WriteLine(string.Format("Added {0} items...", CompositionStack.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //Remove any rect which is completely inside of another. This is mainly an effort to avoid extra layers, //such as those generated by GTK menus, where some elements appear to be duplicated. var toRemove = CompositionStack.Where(cs => CompositionStack.Any(a => cs != a && a.TargetRect.Contains(cs.TargetRect))).ToList(); Trace.WriteLine(string.Format("Removing {0} items...", toRemove.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //In a case where there's one menu and two identical rects, don't remove both of them, or we'll have nothing to compose if (toRemove.Count == CompositionStack.Count && toRemove.Count > 0) { toRemove.RemoveAt(toRemove.Count - 1); } CompositionStack.RemoveAll(r => toRemove.Contains(r)); //If they're all fully inside the window bounds, remove them- probably just regular window elements if (CompositionStack.All(cs => this.TargetRect.Contains(cs.TargetRect))) { Trace.WriteLine(string.Format("Clearing {0} items...", toRemove.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //CompositionStack.RemoveAll(cs => !cs.WindowClass.StartsWith("WindowsForms10.Window.20808")); CompositionStack.Clear(); } } } //Since we compose where first is bottom and last is top, we'll need to reverse what we have so far since we enumerate the other direction CompositionStack.Reverse(); //Base window is always the bottom layer of the composition stack CompositionStack.Insert(0, this); Trace.WriteLine("Done.", string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); }
public ExtendedScreenshot(IntPtr targetWindow, ScreenshotMethod method = ScreenshotMethod.DWM, bool withSolidGlass = true) : base(targetWindow, method, withSolidGlass) { }
public ComposedScreenshot(IntPtr targetWindow, ScreenshotMethod method = ScreenshotMethod.DWM, bool withSolidGlass = true) : base(targetWindow, method, withSolidGlass) { Trace.WriteLine("Creating composed screenshot...", string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); CursorLocation = Cursor.Position; CursorImage = Core.GetCursor(); //#32768 is the Windows Menu Class // || wc.StartsWith("WindowsForms10.Window.20808"); var ContextMenus = Windowing.GetChildWindows(Windowing.GetDesktopWindow()).Where(h => Windowing.GetWindowClass(h) == "#32768").ToList(); if (ContextMenus.Any(h => CaptureRect.IntersectsWith(Helper.GetWindowRectangle(h)))) { Trace.WriteLine(string.Format("Found Win32 {0} menus...", ContextMenus.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); CompositionStack.AddRange(ContextMenus.Select(h => Screenshot.FromBitmapRect(Core.ScreenshotWindow(h), Helper.GetWindowRectangle((h))))); } else { //If there are no Win32 popup context menus found, but the mouse is over something who's root is the target rect, walk that tree for composition items //Check if the thing the mouse is over is different (eg, an overhanging menu) IntPtr MouseTargetHandle = Windowing.WindowFromPoint(Cursor.Position); //We don't want to do this when we're trying to get popup context menus since they are children of the desktop window, //not the target window. However that situation is handled separately above. //What we're doing here is looking for overlapping windows, like GTK context menus if (Windowing.GetAncestor(MouseTargetHandle, Windowing.GA_ROOTOWNER) == this.TargetHandle) // && !this.TargetRect.Contains(Cursor.Position)) { Trace.WriteLine(string.Format("Mouse over something else, handle {0}...", MouseTargetHandle), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); while (MouseTargetHandle != TargetHandle && MouseTargetHandle != IntPtr.Zero) { //var MouseTargetWindowRect = Helper.GetWindowRectangle(MouseTargetHandle); //var MouseTargetScreenshot = Core.ScreenshotArea(MouseTargetHandle, MouseTargetWindowRect); //GTK menus seem to have virtually identical parents of themselves, so I initially tried to circumvent this //with a check to prevent any two same rects from being added //though, it's obsolete with the more robust removal below //if (!CompositionStack.Any(ss => ss.TargetRect == MouseTargetWindowRect)) //var layer = Screenshot.FromBitmapRect(MouseTargetScreenshot, MouseTargetWindowRect); var layer = new Screenshot(MouseTargetHandle, ScreenshotMethod.GDI, false); CompositionStack.Add(layer); Trace.WriteLine("Added " + layer.TargetHandle.ToString() + "; Class: " + layer.WindowClass, "ComposedScreenshot.ctor"); MouseTargetHandle = Windowing.GetParent(MouseTargetHandle); } Trace.WriteLine(string.Format("Added {0} items...", CompositionStack.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //Remove any rect which is completely inside of another. This is mainly an effort to avoid extra layers, //such as those generated by GTK menus, where some elements appear to be duplicated. var toRemove = CompositionStack.Where(cs => CompositionStack.Any(a => cs != a && a.TargetRect.Contains(cs.TargetRect))).ToList(); Trace.WriteLine(string.Format("Removing {0} items...", toRemove.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //In a case where there's one menu and two identical rects, don't remove both of them, or we'll have nothing to compose if (toRemove.Count == CompositionStack.Count && toRemove.Count > 0) toRemove.RemoveAt(toRemove.Count - 1); CompositionStack.RemoveAll(r => toRemove.Contains(r)); //If they're all fully inside the window bounds, remove them- probably just regular window elements if (CompositionStack.All(cs => this.TargetRect.Contains(cs.TargetRect))) { Trace.WriteLine(string.Format("Clearing {0} items...", toRemove.Count), string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); //CompositionStack.RemoveAll(cs => !cs.WindowClass.StartsWith("WindowsForms10.Window.20808")); CompositionStack.Clear(); } } } //Since we compose where first is bottom and last is top, we'll need to reverse what we have so far since we enumerate the other direction CompositionStack.Reverse(); //Base window is always the bottom layer of the composition stack CompositionStack.Insert(0, this); Trace.WriteLine("Done.", string.Format("ComposedScreenshot.ctor [{0}]", System.Threading.Thread.CurrentThread.Name)); }
public ComposedScreenshot(ScreenshotMethod method = ScreenshotMethod.DWM, bool withSolidGlass = true) : this(IntPtr.Zero, method, withSolidGlass) { }