首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >显示UserControl的一部分,如CroppedBitmap

显示UserControl的一部分,如CroppedBitmap
EN

Stack Overflow用户
提问于 2014-12-16 08:08:31
回答 1查看 145关注 0票数 1

我的英语还不太好。即使你不能清楚地理解我,也请理解我。

我在UserControl.xaml中有一个巨大的数据表,但是缩小了这个UserControl对象在MainWindow中显示的范围。

我希望在UserControl中显示部分MainWindow的相同大小的数据表。

像这样的图像显示方式:

代码语言:javascript
运行
复制
<Image>
    <Image.Source>
        <CroppedBitmap Source="<path to source image>" SourceRect="20,20,50,50"/>
    </Image.Source>
</Image>

在MainWindow中像SourceRect一样显示SourceRect。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-27 11:51:04

如果我没听错,你有几个选择。第一种方法,我认为最简单的方法是使用ViewBox控件。

1. ViewBox

Viewbox继承而来的Decorator控件用于扩展或缩放子元素,但它是按比例缩放的(即不能将him大小设置为300x100 )。

Example

代码语言:javascript
运行
复制
<Viewbox Width="300"
         Height="300">

    <DataGrid>
    ...
    </DataGrid>
</ViewBox>

第二种方法是使用您想要显示的控件的屏幕截图,然后如果您想使用CroppedBitmap

2. Capturing screen

我在这里找到了Pete Brown关于这个主题的一篇很棒的文章:

Capturing Screen Images in WPF using GDI, Win32 and a little WPF Interop Help

在本文中是一个示例,如下所示:

ScreenCapture

代码语言:javascript
运行
复制
class ScreenCapture
{
    public static BitmapSource CaptureFullScreen(bool addToClipboard)
    {
        return CaptureRegion(
            User32.GetDesktopWindow(),
            (int)SystemParameters.VirtualScreenLeft,
            (int)SystemParameters.VirtualScreenTop,
            (int)SystemParameters.VirtualScreenWidth,
            (int)SystemParameters.VirtualScreenHeight,
            addToClipboard);
    }

    // capture a window. This doesn't do the alt-prtscrn version that loses the window shadow.
    // this version captures the shadow and optionally inserts a blank (usually white) area behind
    // it to keep the screen shot clean
    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

        User32.SetForegroundWindow(hWnd);

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

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

        return captured;
    }

    // capture a region of the full screen
    public static BitmapSource CaptureRegion(int x, int y, int width, int height, bool addToClipboard)
    {
        return CaptureRegion(User32.GetDesktopWindow(), x, y, width, height, addToClipboard);
    }

    // capture a region of a the screen, defined by the hWnd
    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
        {
            // gets the main desktop and all open windows
            sourceDC = User32.GetDC(User32.GetDesktopWindow());
            //sourceDC = User32.GetDC(hWnd);
            targetDC = Gdi32.CreateCompatibleDC(sourceDC);

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

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

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

            // Here's the WPF glue to make it all work. It converts from an 
            // hBitmap to a BitmapSource. Love the WPF interop functions
            bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                compatibleBitmapHandle, IntPtr.Zero, Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            if (addToClipboard)
            {
                //Clipboard.SetImage(bitmap); // high memory usage for large images
                IDataObject data = new DataObject();
                data.SetData(DataFormats.Dib, bitmap, false);
                Clipboard.SetDataObject(data, false);
            }

        }
        catch (Exception ex)
        {
            throw new ScreenCaptureException(string.Format("Error capturing region {0},{1},{2},{3}", x, y, width, height), ex);
        }
        finally
        {
            Gdi32.DeleteObject(compatibleBitmapHandle);

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

        return bitmap;
    }

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

使用示例:

代码语言:javascript
运行
复制
private void CaptureRegionButton_Click(object sender, RoutedEventArgs e)
{
    CapturedImage.Source = ScreenCapture.CaptureRegion(100, 100, 500, 500, true);
}

private void CaptureScreenButton_Click(object sender, RoutedEventArgs e)
{
    CapturedImage.Source = ScreenCapture.CaptureFullScreen(true);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27500148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档