使用进程名称或ID捕获应用程序窗口

时间:2013-10-08 13:47:29

标签: c# wpf window

我正在使用WPF的屏幕捕获应用程序。我需要捕获应用程序窗口。我有一个捕获窗口的代码,但也有背景。我不希望捕获背景,只是窗口,如果它被调整大小,仍然只有窗口应该在运行时捕获。我对WPF有点新意。请帮我解决一下这个。 这是我的代码:

private void ShowExistingWindow(string processName)
{
    var processes = Process.GetProcessesByName(processName);
    foreach (var process in processes)
    {
        // the single-instance already open should have a MainWindowHandle
        if (process.MainWindowHandle != IntPtr.Zero)
        {
            // restores the window in case it was minimized
            ShowWindow(process.MainWindowHandle, SW_SHOWNORMAL);

            // brings the window to the foreground
            SetForegroundWindow(process.MainWindowHandle);
        }
    }
}

此代码的问题在于,它会使窗口恢复并将其与背景一起捕获。

这是我用于捕获窗口的代码,

public static BitmapSource CaptureWindow(IntPtr hWnd,bool recolorBackground,Color substituteBackgroundColor,bool addToClipboard)

    {
        Int32Rect rect = GetWindowActualRect(hWnd);

        Window blankingWindow = null;

        if (recolorBackground)
        {
            blankingWindow = new Window();

            blankingWindow.WindowStyle = WindowStyle.None;
            blankingWindow.Title = string.Empty;
            blankingWindow.ShowInTaskbar = false;
            blankingWindow.AllowsTransparency = true;
            blankingWindow.Background = new SolidColorBrush(substituteBackgroundColor);
            blankingWindow.Show();

            int fudge = 20;

            blankingWindow.Left = rect.X - fudge / 2;
            blankingWindow.Top = rect.Y - fudge / 2;
            blankingWindow.Width = rect.Width + fudge;
            blankingWindow.Height = rect.Height + fudge;

        }

        // bring the to-be-captured window to capture to the foreground
        // there's a race condition here where the blanking window
        // sometimes comes to the top. Hate those. There is surely
        // a non-WPF native solution to the blanking window which likely
        // involves drawing directly on the desktop or the target window

        SetForegroundWindow(hWnd);

        BitmapSource captured = CaptureRegion(
            hWnd,
            rect.X,
            rect.Y,
            rect.Width,
            rect.Height,
            true);

        if (blankingWindow != null)
            blankingWindow.Close();

        return captured;
    }
    // this accounts for the border and shadow. Serious fudgery here.

    private static Int32Rect GetWindowActualRect(IntPtr hWnd)
    {
            Win32Rect windowRect = new Win32Rect();
            Win32Rect clientRect = new Win32Rect();

            User32.GetWindowRect(hWnd, out windowRect);
            User32.GetClientRect(hWnd, out clientRect);

            int sideBorder = (windowRect.Width - clientRect.Width)/2 + 1;

            // sooo, yeah.
            const int hackToAccountForShadow = 4;

            Win32Point topLeftPoint = new Win32Point(windowRect.Left - sideBorder, windowRect.Top - sideBorder);

            User32.ClientToScreen(hWnd, ref topLeftPoint);

            Int32Rect actualRect = new Int32Rect(
                topLeftPoint.X,
                topLeftPoint.Y,
                windowRect.Width + sideBorder * 2 + hackToAccountForShadow,
                windowRect.Height + sideBorder * 2 + hackToAccountForShadow);

            return actualRect;
     }

public static BitmapSource CaptureRegion(IntPtr hWnd,int x,int y,int width,int height,bool addToClipboard)         {

        IntPtr sourceDC = IntPtr.Zero;
        IntPtr targetDC = IntPtr.Zero;
        IntPtr compatibleBitmapHandle = IntPtr.Zero;
        BitmapSource bitmap = null;

        try
        {
            width = User32.GetSystemMetrics(User32.SCREEN_X);
            height = User32.GetSystemMetrics(User32.SCREEN_Y);

            // gets the main desktop and all open windows
            sourceDC = GetDC(GetDesktopWindow());
            //sourceDC = User32.GetDC(hWnd);
            targetDC = CreateCompatibleDC(sourceDC);

            // create a bitmap compatible with our target DC
            compatibleBitmapHandle = CreateCompatibleBitmap(sourceDC, width, height);

            // gets the bitmap into the target device context
            SelectObject(targetDC, compatibleBitmapHandle);


            // copy from source to destination
            BitBlt(targetDC, 0, 0, width, height, sourceDC, x, y, SRCCOPY);

            // Here's the WPF glue to make it all work. It converts from an
            // hBitmap to a BitmapSource.
            bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            compatibleBitmapHandle, IntPtr.Zero, Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());
        }
        catch (Exception ex)
        {
            throw new Exception(string.Format("Error capturing region {0},{1},{2},{3}", x, y, width, height), ex);
        }
        finally
        {
            DeleteObject(compatibleBitmapHandle);

            ReleaseDC(IntPtr.Zero, sourceDC);
            ReleaseDC(IntPtr.Zero, targetDC);

        }

        return bitmap;
    }

0 个答案:

没有答案