0

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;
    }
4

0 に答える 0