示例#1
0
 /// <summary>
 /// Attempts to create a capture handle if it does not already exist.  Returns false if the capture handle could not be created.
 /// </summary>
 private bool CreateCaptureHandleIfNecessary()
 {
     if (deviceContext == null)
     {
         deviceContext = AutoDisposeHandle.Create(NativeMethods.GetDC(IntPtr.Zero), h => NativeMethods.ReleaseDC(IntPtr.Zero, h));
     }
     return(deviceContext != null);
 }
示例#2
0
 private void ClearCaptureHandle()
 {
     if (deviceContext != null)
     {
         deviceContext.Dispose();
     }
     deviceContext = null;
 }
示例#3
0
 /// <summary>
 /// If the current thread's desktop is not the desktop that receives input, then change it. Returns true if the desktop was changed.
 /// </summary>
 public static bool AssociateCurrentThreadWithDefaultDesktop()
 {
     using (AutoDisposeHandle inputDesktop = GetInputDesktop())
     {
         string inputDesktopName         = GetDesktopName(inputDesktop);
         string currentThreadDesktopName = GetDesktopName(GetThreadDesktop());
         if (currentThreadDesktopName != inputDesktopName)
         {
             if (NativeMethods.SetThreadDesktop(inputDesktop))
             {
                 return(true);
             }
             Win32Helper.ThrowLastWin32Error("Unable to set thread desktop");
         }
     }
     return(false);
 }
示例#4
0
        /// <summary>
        /// Attempts to capture a screenshot of the current desktop.
        /// </summary>
        /// <returns></returns>
        private Screenshot CaptureScreenshot(int x, int y, int width, int height)
        {
            BasicEventTimer bet = new BasicEventTimer("0.000");

            bet.Start("Setup");
            if (!CreateCaptureHandleIfNecessary())
            {
                return(null);
            }

            NativeMethods.BITMAPINFO bmpInfo = new NativeMethods.BITMAPINFO();
            using (AutoDisposeHandle bmp = AutoDisposeHandle.Create(NativeMethods.CreateCompatibleBitmap(deviceContext, 1, 1), h => NativeMethods.DeleteObject(h)))
            {
                bmpInfo.bmiHeader.biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFOHEADER));
                if (0 == NativeMethods.GetDIBits(deviceContext, bmp, 0, 1, null, ref bmpInfo, NativeMethods.DIB_Color_Mode.DIB_RGB_COLORS))
                {
                    Win32Helper.ThrowLastWin32Error();
                }
                bmpInfo.bmiHeader.biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFO));
                if (0 == NativeMethods.GetDIBits(deviceContext, bmp, 0, 1, null, ref bmpInfo, NativeMethods.DIB_Color_Mode.DIB_RGB_COLORS))
                {
                    Win32Helper.ThrowLastWin32Error();
                }
            }
            bmpInfo.bmiHeader.biWidth     = width;
            bmpInfo.bmiHeader.biHeight    = -height;
            bmpInfo.bmiHeader.biSizeImage = 0;

            // Create memory device context.  When done, delete it.
            using (AutoDisposeHandle dc = AutoDisposeHandle.Create(NativeMethods.CreateCompatibleDC(IntPtr.Zero), h => NativeMethods.DeleteDC(h)))
            {
                if (dc == null)
                {
                    Win32Helper.ThrowLastWin32Error("Failed to create memory device context");
                }

                // Create "DIB Section" (a Bitmap, more or less).  When done, delete it.
                IntPtr ppvBits = new IntPtr();
                using (AutoDisposeHandle newDib = AutoDisposeHandle.Create(NativeMethods.CreateDIBSection(dc, ref bmpInfo, 0U, out ppvBits, IntPtr.Zero, 0U), h => NativeMethods.DeleteObject(h)))
                //using (AutoDisposeHandle newDib = AutoDisposeHandle.Create(NativeMethods.CreateCompatibleBitmap(deviceContext, width, height), h => NativeMethods.DeleteObject(h)))
                {
                    if (newDib == null)
                    {
                        Win32Helper.ThrowLastWin32Error("Failed to create DIB Section");
                    }

                    // Assign new DIB Section to our memory device context.  When done, put back the old DIB Section.
                    using (AutoDisposeHandle oldDib = AutoDisposeHandle.Create(NativeMethods.SelectObject(dc, newDib), h => NativeMethods.SelectObject(dc, h)))
                    {
                        if (oldDib == null)
                        {
                            Win32Helper.ThrowLastWin32Error("Failed to assign new DIB Section to memory device context");
                        }
                        bet.Start("BitBlt");

                        // Copy data from the screen to our memory device context
                        if (!NativeMethods.BitBlt(dc, 0, 0, width, height, deviceContext, x, y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt))
                        {
                            Logger.Debug("BitBlt failed with error code: " + Win32Helper.GetLastWin32Error());
                            ClearCaptureHandle();
                            DesktopManager.ShouldReassociate = true;
                        }
                        else
                        {
                            bet.Start("new Screenshot/Copy bits");
                            Screenshot screenshot = new Screenshot(width, height, bmpInfo.bmiHeader.biBitCount);
                            Marshal.Copy(ppvBits, screenshot.Buffer, 0, screenshot.Buffer.Length);
                            bet.Stop();
                            //Logger.Info(bet.ToString(Environment.NewLine));
                            return(screenshot);
                        }
                    }
                }
            }
            return(null);
        }
示例#5
0
 /// <summary>
 /// Gets a handle to the desktop that receives user input.
 /// </summary>
 /// <returns></returns>
 private static AutoDisposeHandle GetInputDesktop()
 {
     return(AutoDisposeHandle.Create(NativeMethods.OpenInputDesktop(0, false, (uint)NativeMethods.ACCESS_MASK.DESKTOP_ALL_ACCESS), h => NativeMethods.CloseDesktop(h)));
 }
示例#6
0
 /// <summary>
 /// Retrieves a handle to the desktop assigned to the current thread.  This handle does not need to be closed.
 /// </summary>
 /// <returns></returns>
 private static AutoDisposeHandle GetThreadDesktop()
 {
     // The value returned by GetThreadDesktop does not need to be closed, so we pass null for the onRelease method.
     return(AutoDisposeHandle.Create(NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId()), null));
 }