private static void ScreenshotBitBlt(IntPtr hWnd, ref DirectBitmap capture) { try { // get the hDC of the target window IntPtr hdcSrc = User32.GetDC(hWnd); // get the size Rectangle windowRect = new Rectangle(); User32.GetWindowRect(hWnd, ref windowRect); int width = windowRect.Right - windowRect.Left; int height = windowRect.Bottom - windowRect.Top; // create a device context we can copy to IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc); // create a bitmap we can copy it to, // using GetDeviceCaps to get the width/height IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height); // select the bitmap object IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap); // bitblt over Gdi32.BitBlt(hdcDest, 1, 31, width - 10, height, hdcSrc, 0, 0, (uint)Gdi32.TernaryRasterOperations.SRCCOPY | (uint)Gdi32.TernaryRasterOperations.CAPTUREBLT); // restore selection Gdi32.SelectObject(hdcDest, hOld); if (capture != null) { capture.Dispose(); } capture = new DirectBitmap(hdcSrc, hBitmap); // clean up Gdi32.DeleteDC(hdcDest); User32.ReleaseDC(hWnd, hdcSrc); // free up the Bitmap object Gdi32.DeleteObject(hBitmap); } catch (ExternalException) { // Failed to capture window, usually because it was closed. #if DEBUG CustomGameDebug.WriteLine("Failed to capture window. Is it closed?"); #endif } }
private void ScreenshotBitBlt() { try { // get the hDC of the target window IntPtr hdcSrc = User32.GetDC(OverwatchHandle); // get the size int width = Rectangles.ENTIRE_SCREEN.Width + Points.BITBLT_WINDOW_LOCATION.X; int height = Rectangles.ENTIRE_SCREEN.Height + Points.BITBLT_WINDOW_LOCATION.Y; // create a device context we can copy to IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc); // create a bitmap we can copy it to, // using GetDeviceCaps to get the width/height IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height); // select the bitmap object IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap); // bitblt over Gdi32.BitBlt(hdcDest, Points.BITBLT_WINDOW_LOCATION.X, Points.BITBLT_WINDOW_LOCATION.Y, width, height, hdcSrc, 0, 0, (uint)Gdi32.TernaryRasterOperations.SRCCOPY | (uint)Gdi32.TernaryRasterOperations.CAPTUREBLT); // restore selection Gdi32.SelectObject(hdcDest, hOld); if (Capture != null) { Capture.Dispose(); } Capture = new DirectBitmap(hdcSrc, hBitmap); // clean up Gdi32.DeleteDC(hdcDest); User32.ReleaseDC(OverwatchHandle, hdcSrc); // free up the Bitmap object Gdi32.DeleteObject(hBitmap); } catch (ExternalException) { // Failed to capture window, usually because it was closed. #if DEBUG CustomGameDebug.WriteLine("Failed to capture window. Is it closed?"); #endif } }
/// <summary> /// Gets the current Overwatch event. /// </summary> /// <returns>The current Overwatch event as the Event enum.</returns> public static OWEvent GetCurrentEvent() { // Search for the "Event Has Ended" box. const string searchFor = "<span class=\"btn m-lg u-center-block margin-18 is-disabled\">EVENT HAS ENDED</span>"; var eventPages = new Tuple <OWEvent, string>[] { new Tuple <OWEvent, string>(OWEvent.SummerGames, "https://playoverwatch.com/en-us/events/summer-games/"), new Tuple <OWEvent, string>(OWEvent.HalloweenTerror, "https://playoverwatch.com/en-us/events/halloween-terror/"), new Tuple <OWEvent, string>(OWEvent.WinterWonderland, "https://playoverwatch.com/en-us/events/winter-wonderland/"), new Tuple <OWEvent, string>(OWEvent.LunarNewYear, "https://playoverwatch.com/en-us/events/lunar-new-year/"), new Tuple <OWEvent, string>(OWEvent.Archives, "https://playoverwatch.com/en-us/events/archives/"), new Tuple <OWEvent, string>(OWEvent.Aniversary, "https://playoverwatch.com/en-us/events/anniversary/"), }; using (var client = new System.Net.WebClient()) { try { for (int i = 0; i < eventPages.Length; i++) { #if DEBUG CustomGameDebug.WriteLine($"Downloading data for {eventPages[i].Item1}"); #endif // If the page does not contain the box, then the event is active. if (!client.DownloadString(eventPages[i].Item2).Contains(searchFor)) { return(eventPages[i].Item1); } } } catch (System.Net.WebException) { throw new System.Net.WebException("Could not download event info from playoverwatch.com."); } } return(OWEvent.None); }
/// <summary> /// Creates an Overwatch process using the currently logged in battle.net account. /// </summary> /// <param name="processInfo">Parameters for creating the process.</param> /// <returns>The created Overwatch process.</returns> public static Process StartOverwatch(OverwatchInfoAuto processInfo = null) { if (processInfo == null) { processInfo = new OverwatchInfoAuto(); } if (!File.Exists(processInfo.BattlenetExecutableFilePath)) { throw new FileNotFoundException(string.Format("Battle.net.exe's executable at {0} was not found. " + "Change battlenetExeLocation to the location of the battle.net.exe executable.", processInfo.BattlenetExecutableFilePath)); } Stopwatch startTime = new Stopwatch(); // If battle.net is not started, start it. if (Process.GetProcessesByName("battle.net").Length == 0) { #if DEBUG CustomGameDebug.WriteLine("No battle.net process found, starting battle.net."); #endif Process battlenet = new Process(); battlenet.StartInfo.FileName = processInfo.BattlenetExecutableFilePath; battlenet.Start(); startTime.Start(); // The battle.net app is fully started when there are 3 battle.net processes. Loop while there are less than 3. while (Process.GetProcessesByName("battle.net").Length < 3) { if (startTime.ElapsedMilliseconds >= processInfo.MaxBattlenetStartTime || processInfo.MaxBattlenetStartTime == -1) { #if DEBUG CustomGameDebug.WriteLine("Error: Battle.net took too long to start."); #endif throw new OverwatchStartFailedException("Battle.net took too long to start."); } Thread.Sleep(200); } #if DEBUG CustomGameDebug.WriteLine("Finished starting Battle.net."); #endif } #if DEBUG else { CustomGameDebug.WriteLine("Battle.net process found."); } CustomGameDebug.WriteLine("Starting the Overwatch process."); #endif Process[] processList = Process.GetProcessesByName("Overwatch"); // Set the video settings. var initialSettings = ChangeVideoSettings(processInfo.OverwatchSettingsFilePath, VideoSettings.Item1, VideoSettings.Item2); Process battlenetOW = new Process(); // The arguments to start the game directly before August 2018: // battlenet.StartInfo.FileName = "battlenet://Pro"; // The arguments after: battlenetOW.StartInfo.FileName = processInfo.BattlenetExecutableFilePath; battlenetOW.StartInfo.Arguments = "--exec=\"launch Pro\""; battlenetOW.Start(); startTime.Restart(); while (startTime.ElapsedMilliseconds < processInfo.MaxOverwatchStartTime || processInfo.MaxOverwatchStartTime == -1) { Process[] newProcessList = Process.GetProcessesByName("Overwatch"); for (int i = 0; i < newProcessList.Length; i++) { if (processList.Contains(newProcessList[i]) == false) { Process owProcess = newProcessList[i]; WaitForVisibleProcessWindow(owProcess); RestoreVideoSettings(processInfo.OverwatchSettingsFilePath, initialSettings); if (processInfo.AutomaticallyCreateCustomGame) { DirectBitmap bmp = null; if (WaitForMainMenu(processInfo.ScreenshotMethod, owProcess.MainWindowHandle, bmp, processInfo.MaxWaitForMenuTime)) { #if DEBUG CustomGameDebug.WriteLine("Finished starting Overwatch."); #endif CreateCustomGame(owProcess.MainWindowHandle); if (bmp != null) { bmp.Dispose(); } } else { #if DEBUG CustomGameDebug.WriteLine("Could not start Overwatch, main menu did not load."); #endif if (bmp != null) { bmp.Dispose(); } if (processInfo.CloseOverwatchProcessOnFailure) { owProcess.CloseMainWindow(); owProcess.Close(); } throw new OverwatchStartFailedException("Could not start Overwatch, main menu did not load."); } } #if DEBUG else { CustomGameDebug.WriteLine("Finished starting Overwatch."); } #endif return(newProcessList[i]); } } Thread.Sleep(200); } #if DEBUG CustomGameDebug.WriteLine("Error: Overwatch took too long to start."); #endif RestoreVideoSettings(processInfo.OverwatchSettingsFilePath, initialSettings); throw new OverwatchStartFailedException("Overwatch took too long to start."); }
/// <summary> /// Creates an Overwatch process using the currently logged in battle.net account. /// </summary> /// <param name="processInfo">Parameters for creating the process.</param> /// <returns>The created Overwatch process.</returns> public static Process StartOverwatch(OverwatchInfoAuto processInfo = null) { // Return any Overwatch process that might already be running. Process foundProcess = GetOverwatchProcess(); if (foundProcess != null) { return(foundProcess); } #region Argument check if (processInfo == null) { processInfo = new OverwatchInfoAuto(); } // Check if the files in processInfo exist. if (!File.Exists(processInfo.BattlenetExecutableFilePath)) { throw new FileNotFoundException($"Battle.net.exe's executable at {processInfo.BattlenetExecutableFilePath} was not found. " + "Change OverwatchInfoAuto.BattlenetExecutableFilePath to the location of the battle.net.exe executable."); } if (!File.Exists(processInfo.OverwatchSettingsFilePath)) { throw new FileNotFoundException($"Overwatch's settings file at {processInfo.OverwatchSettingsFilePath} was not found. " + "Change OverwatchInfoAuto.OverwatchSettingsFilePath to the location of Overwatch's settings file."); } #endregion #region Start battle.net // If battle.net is not started, start it. if (Process.GetProcessesByName("battle.net").Length == 0) { CustomGameDebug.WriteLine("No battle.net process found, starting battle.net."); Process battlenet = new Process(); battlenet.StartInfo.FileName = processInfo.BattlenetExecutableFilePath; battlenet.Start(); // The battle.net app is fully started when there are 3 battle.net processes. Loop while there are less than 3. if (!SpinWait.SpinUntil(() => { return(Process.GetProcessesByName("battle.net").Length >= 3); }, processInfo.MaxBattlenetStartTime)) { // This code block will run if battle.net isn't finished setting up before the specified maximum time. CustomGameDebug.WriteLine("Error: Battle.net took too long to start."); throw new OverwatchStartFailedException("Battle.net took too long to start."); } CustomGameDebug.WriteLine("Finished starting Battle.net."); } else { CustomGameDebug.WriteLine("Battle.net process found."); } #endregion CustomGameDebug.WriteLine("Starting the Overwatch process."); // Set the video settings. var initialSettings = ChangeVideoSettings(processInfo.OverwatchSettingsFilePath, VideoSettings.Item1, VideoSettings.Item2); try { try { Process battlenetOW = new Process(); // The arguments to start the game directly before August 2018: // battlenet.StartInfo.FileName = "battlenet://Pro"; // The arguments after: battlenetOW.StartInfo.FileName = processInfo.BattlenetExecutableFilePath; battlenetOW.StartInfo.Arguments = "--exec=\"launch Pro\""; battlenetOW.Start(); Process owProcess = null; TimeSpan overwatchStartTimeSpan = new TimeSpan(0, 0, 0, 0, processInfo.MaxOverwatchStartTime); if (!SpinWait.SpinUntil(() => { owProcess = GetOverwatchProcess(); return(owProcess != null); }, overwatchStartTimeSpan)) { CustomGameDebug.WriteLine("Error: Overwatch took too long to start."); throw new OverwatchStartFailedException("Overwatch took too long to start."); } // Wait for the window to be visible. if (!SpinWait.SpinUntil(() => { owProcess.Refresh(); return(!string.IsNullOrEmpty(owProcess.MainWindowTitle)); }, overwatchStartTimeSpan)) { CustomGameDebug.WriteLine("Error: Overwatch took too long to start."); throw new OverwatchStartFailedException("Overwatch took too long to start."); } RestoreVideoSettings(processInfo.OverwatchSettingsFilePath, initialSettings); initialSettings = null; if (processInfo.AutomaticallyCreateCustomGame) { CustomGame cg = new CustomGame(new CustomGameBuilder() { OpenChatIsDefault = false, ScreenshotMethod = processInfo.ScreenshotMethod, OverwatchProcess = owProcess }); if (WaitForMainMenu(cg, processInfo.MaxWaitForMenuTime)) { cg.CreateCustomGame(); } else { CustomGameDebug.WriteLine("Could not start Overwatch, main menu did not load."); if (processInfo.CloseOverwatchProcessOnFailure) { owProcess.CloseMainWindow(); } throw new OverwatchStartFailedException("Could not start Overwatch, main menu did not load."); } } CustomGameDebug.WriteLine("Finished starting Overwatch."); return(owProcess); } finally { CustomGameDebug.WriteLine("Restoring video settings."); if (initialSettings != null) { RestoreVideoSettings(processInfo.OverwatchSettingsFilePath, initialSettings); } } } catch (OverwatchClosedException) { CustomGameDebug.WriteLine("Could not start Overwatch, was closed during initialization."); throw new OverwatchStartFailedException("Could not start Overwatch, was closed during initialization."); } }