【问题标题】:Saving image (screenshot) of control in WPF - MVVM Pattern在 WPF 中保存控件的图像(屏幕截图) - MVVM 模式
【发布时间】:2021-01-07 11:40:39
【问题描述】:

我正在尝试在 WPF 应用程序中截取用户控件(视口)的屏幕截图。我的问题是我不知道如何在保持与 MVVM 模式一致的情况下获取窗口或视口的位置。

这是方法,但它占用了所有屏幕而不是我的视口,因为我不知道如何将窗口/视口属性绑定到它。

    private void saveScreenshot()
        {
            double screenLeft = SystemParameters.VirtualScreenLeft;
            double screenTop = SystemParameters.VirtualScreenTop;
            double screenWidth = SystemParameters.VirtualScreenWidth;
            double screenHeight = SystemParameters.VirtualScreenHeight;


            using (Bitmap bmp = new Bitmap((int)screenWidth, (int)screenHeight))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    string fileName = "ScreenCapture -" + DateTime.Now.ToString("ddMMyyyy-hhmmss") + ".png";    
                    
                    g.CopyFromScreen((int)screenLeft, (int)screenTop, 0, 0, bmp.Size);

                    SaveFileDialog saveFile = new SaveFileDialog();                    ;
                    saveFile.Filter = "JPEG|*.jpeg|Bitmap|*.bmp|Gif|*.gif|Png|*.png";                    

                    if (saveFile.ShowDialog() == true)
                    {
                        bmp.Save(saveFile.FileName);
                    }                   
                    
                }
            }

        }

我试图将一些窗口属性绑定到 ViewModel,以访问屏幕上的窗口位置,但没有成功。

XAML:

<Window
    x:Class="SimpleDemo.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:hx="http://helix-toolkit.org/wpf/SharpDX"
    xmlns:hw="http://helix-toolkit.org/wpf" 
    xmlns:local="clr-namespace:SimpleDemo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    Title="Point cloud visualization"
    Width="1280"
    Height="720"    
    Left="{Binding LeftScreenPosition, Mode=TwoWay}"
    Top="{Binding TopScreenPosition, Mode=TwoWay}"
    mc:Ignorable="d" Background="#FF465065" Foreground="#FFFFFEFE">

这里是ViewModel(SetValue包含PropertyChanged事件的东西)

 private double leftScreenPosition;
        private double topScreenPosition;

        public double LeftScreenPosition
        {
            get { return leftScreenPosition; }
            set { SetValue(ref leftScreenPosition, value); }
        }

        public double TopScreenPosition
        {
            get { return leftScreenPosition; }
            set { SetValue(ref leftScreenPosition, value); }
        }

如果有人能向我解释错误在哪里,或者告诉我另一种处理方法,我将非常感激(请考虑到我是一个完全的初学者,谢谢)。

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    CommandParameter 技巧可以让您将一些 FrameworkElement 传递给放置在 ViewModel 中的命令。我的例子

    xaml(如果您只需要在 CommandParameter 中进行控制,则可以细化)

    <Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTestApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        d:DataContext="{d:DesignInstance Type=local:YourViewModel, IsDesignTimeCreatable=True}">
    <Grid>
        <Button Content="Make screenShot" Command="{Binding MakeScreenShotCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
    </Grid>
    

    视图模型

    public class YourViewModel
    {
        private ICommand _makeScreenShotCommand;
        public ICommand MakeScreenShotCommand => _makeScreenShotCommand ?? (_makeScreenShotCommand = new ActionCommand(TakeScreenShot));
    
        private void TakeScreenShot(object control)
        {
            FrameworkElement element = control as FrameworkElement;
            if (element == null)
                throw new Exception("Invalid parameter");
    
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((int)element.ActualWidth, (int)element.ActualHeight, 96, 96, PixelFormats.Pbgra32);
            renderTargetBitmap.Render(element);
            PngBitmapEncoder pngImage = new PngBitmapEncoder();
            pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
            using (Stream fileStream = File.Create("filePath"))
            {
                pngImage.Save(fileStream);
            }
        }
    }
    

    【讨论】:

    • 更好用var element = control as FrameworkElement; if (element == null) ...
    猜你喜欢
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2021-11-14
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多