public Bitmap GetClientWindowImage() { try { IntPtr hDC = WIN32_API.GetDC(windowHandle); IntPtr hMemDC = WIN32_API.CreateCompatibleDC(hDC); if (hDC == IntPtr.Zero || hMemDC == IntPtr.Zero) return null; WIN32_API.RECT windowSize = new WIN32_API.RECT(); WIN32_API.GetClientRect(windowHandle, ref windowSize); if ((int)windowSize.width <= 10 || (int)windowSize.height <= 10) return null; if (windowBitmapHandle == IntPtr.Zero || (int)windowSize.width != windowImage.Width || (int)windowSize.height != windowImage.Height) { System.Diagnostics.Debug.WriteLine("got a new bitmap handle"); scriptControl.log("New Window Resolution:" + (int)windowSize.width + " x " + (int)windowSize.height); if (LeagueUtils.Preferences.hideLeagueBorders) { //adjust the window position and show the UI WIN32_API.SetWindowLong(windowHandle, WIN32_API.GWL_STYLE, WIN32_API.GetWindowLong(windowHandle, WIN32_API.GWL_STYLE) & ~WIN32_API.WS_CAPTION); int XPadding = (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - windowSize.width) / 2; int YPadding = (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - windowSize.height) / 2; WIN32_API.SetWindowPos(windowHandle, 0, XPadding, YPadding, windowSize.width, windowSize.height, 0); this.Left = XPadding; this.Top = YPadding; this.Width = windowSize.width; this.Height = windowSize.height; mainCanvas.Width = this.Width; mainCanvas.Height = this.Height; } //init the UI rectangle locations and notify scripts LeagueUI.init(windowSize.width, windowSize.height); //windowBitmapHandle = WIN32_API.CreateCompatibleBitmap(hDC, (IntPtr)windowSize.width, (IntPtr)windowSize.height); WIN32_API.BITMAPINFO bmi = new WIN32_API.BITMAPINFO(); bmi.biSize = 40; // the size of the BITMAPHEADERINFO struct bmi.biWidth = windowSize.width; bmi.biHeight = windowSize.height; bmi.biPlanes = 1; // "planes" are confusing. We always use just 1. Read MSDN for more info. bmi.biBitCount = 24; // ie. 1bpp or 8bpp bmi.biCompression = WIN32_API.BI_RGB; // ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes bmi.biSizeImage = 0; bmi.biXPelsPerMeter = 1000000; // not really important bmi.biYPelsPerMeter = 1000000; // not really important bmi.biClrUsed = 0; bmi.biClrImportant = 0; rawWindowImage = new Bitmap(windowSize.width, windowSize.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); windowBitmapHandle = WIN32_API.CreateDIBSection(hDC, ref bmi, WIN32_API.DIB_RGB_COLORS, out rawWindowImageBits, IntPtr.Zero, 0); } if (windowBitmapHandle != IntPtr.Zero) { IntPtr hOld = (IntPtr)WIN32_API.SelectObject(hMemDC, windowBitmapHandle); if (!leagueInfo.outOfLoadScreen) WIN32_API.BitBlt(hMemDC, 0, 0, windowSize.width, windowSize.height, hDC, 0, 0, WIN32_API.SRCCOPY); else WIN32_API.BitBlt(hMemDC, 0, 0, windowSize.width, windowSize.height, hDC, 0, 0, WIN32_API.SRCCOPY); //WIN32_API.BitBlt(hMemDC, 0, 3 * windowSize.height / 4, windowSize.width / 4, windowSize.height / 4, hDC, 0, 3 * windowSize.height / 4, WIN32_API.SRCCOPY); WIN32_API.SelectObject(hMemDC, hOld); WIN32_API.DeleteDC(hMemDC); WIN32_API.ReleaseDC(windowHandle, hDC); var bInfo = rawWindowImage.LockBits(new System.Drawing.Rectangle(0, 0, rawWindowImage.Width, rawWindowImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); //copy the data from the windows bitmap to a c# bitmap...would be nice to not have to do this unsafe { int* s = (int*)bInfo.Scan0; int intWidth = bInfo.Stride / 4; int len = rawWindowImage.Height * intWidth; int* screenImg = (int*)rawWindowImageBits + len; int* t; int yCount = rawWindowImage.Height; int lineLen = intWidth; int bitSkip = 0; if (leagueInfo.outOfLoadScreen) { int startY = 3 * windowSize.height / 4; yCount = rawWindowImage.Height / 4; s += startY * intWidth; screenImg -= startY * intWidth; //lineLen /= (2/3); bitSkip = intWidth - lineLen; } for (int y = 0; y < yCount; y++) { screenImg -= intWidth; t = screenImg; for (int x = 0; x < lineLen; x++) { *(s++) = *(t++); } s += bitSkip; } } rawWindowImage.UnlockBits(bInfo); //Bitmap bm = System.Drawing.Image.FromHbitmap(windowBitmapHandle); return rawWindowImage; } WIN32_API.DeleteDC(hMemDC); WIN32_API.ReleaseDC(windowHandle, hDC); return null; } catch (Exception e) { new ScriptControl(null).log("[ERROR] (" + e.Source + "): " + e.Message + "\n" + e.StackTrace); throw; } finally { //rawWindowImage.Dispose(); } }
void processingTimer_Tick(object sender, EventArgs e) { try { if (LeagueInfo.heroName != "" && firstLoad) { processingTimer.Interval = TimeSpan.FromMilliseconds(LeagueUtils.Preferences.processingTimer); //scriptControl.log("Interval Timer updated."); firstLoad = false; } StringBuilder sb = new StringBuilder(256); IntPtr tempHandle = WIN32_API.GetForegroundWindow(); WIN32_API.GetWindowText(tempHandle, sb, (IntPtr)sb.MaxCapacity); if (windowHandle != IntPtr.Zero) { uint windowStyle = (uint)WIN32_API.GetWindowLong(windowHandle, WIN32_API.GWL_STYLE); if (windowStyle == 0) { scriptControl.log("Closing...League of legends window no longer detected"); System.Environment.Exit(1); return; } else if ((windowStyle & 0x80000) != 0x80000) { scriptControl.log("Error: League was in fullscreen mode when the overlay started"); this.Close(); return; } } if (sb.ToString().ToLower().Contains("league of legends (tm) client")) { this.Visibility = Visibility.Visible; DateTime start = DateTime.Now; //grab the current screen image from league of legends windowHandle = tempHandle; Bitmap temp = GetClientWindowImage(); if (temp != null) { //windowImage.Dispose(); windowImage = temp; } else { return; } if (windowImage.Width < 10 || windowImage.Height < 10) return; if (LeagueUtils.Preferences.hideLeagueBorders == false) { //adjust the window position and show the UI WIN32_API.RECT leagueLoc = new WIN32_API.RECT(); WIN32_API.RECT clientDim = new WIN32_API.RECT(); WIN32_API.GetWindowRect(windowHandle, ref leagueLoc); WIN32_API.GetClientRect(windowHandle, ref clientDim); //the numbers used may depend on what kind of window the person is using //probably gives wrong alignments on windows xp... //45 = 3d width //5 = border width //31 = titlebar height this.Left = leagueLoc.x + (int)WIN32_API.GetSystemMetrics((IntPtr)45) + (int)WIN32_API.GetSystemMetrics((IntPtr)5); this.Top = leagueLoc.y + (int)WIN32_API.GetSystemMetrics((IntPtr)45) + (int)WIN32_API.GetSystemMetrics((IntPtr)5) + (int)WIN32_API.GetSystemMetrics((IntPtr)31); this.Width = clientDim.width; this.Height = clientDim.height; mainCanvas.Width = this.Width; mainCanvas.Height = this.Height; } //TODO: Add image processing here leagueInfo.update(); scriptControl.raiseEvent("processingFinished", ""); this.procTimeLabel.Content = "Procesing Time:" + (int)(Math.Round((DateTime.Now - start).TotalMilliseconds)) + "ms"; //temp.Dispose(); //windowImage.Dispose(); } else { this.Visibility = Visibility.Hidden; } sb = null; } catch (Exception error) { new ScriptControl(null).log("[ERROR] (" + error.Source + "): " + error.Message + "\n" + error.StackTrace); throw; } }