C # wpf implementa una lupa de escritorio


Prefacio

Al realizar la función de captura de pantalla del escritorio, necesita una lupa para mostrar la imagen ampliada de la posición del mouse. Puede usar la propiedad ViewBox de Bursh en WPF para lograr la ampliación de la imagen. Necesita tomar una captura de pantalla de la pantalla del escritorio. En términos generales, es relativamente fácil de implementar.


1. ¿Cómo lograrlo?

1. Crea una ventana sin bordes

Se recomienda utilizar WindowChrome

<Window Background="{x:Null}" ResizeMode="NoResize"  WindowStyle="None">

WindowChrome se coloca en la etiqueta Ventana

<WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"   CaptionHeight="0"   />
</WindowChrome.WindowChrome>

2. Ampliación del cuadro de visualización

Defina un control Elipse como una lupa. El cuadro de visualización tiene como valor predeterminado unidades relativas, es decir, el rango es 0 a 1. Cuanto menor sea el valor, mayor será la relación de ampliación.

<Ellipse Stroke="LightBlue">
   <Ellipse.Fill>
       <ImageBrush x:Name="ib" Viewbox="0,0,0.5,0.5" />
   </Ellipse.Fill>
</Ellipse>

3. Visualización de captura de pantalla

(1), captura de pantalla

Consulte la captura de pantalla simple en "C# wpf usa GDI+ para tomar capturas de pantalla" y listo. El tipo de datos obtenido es Bitmap.

(2), transferir a BitmapSource

Consulte "Método de conversión de mapa de bits WPF de C# a mapa de bits Writeable (BitmapSource)" para convertir el mapa de bits en un objeto WPF.

(3), pantalla

Simplemente obtenga BitmapSource y asigne un valor al control.

//显示到界面
ib.ImageSource = wb;

4. Capturas de pantalla programadas

La visualización del escritorio debe requerir imágenes en tiempo real, por lo que se requieren capturas de pantalla periódicas.

//启动定时器,截屏
var dispatcherTimer = new DispatcherTimer() {
    
     Interval = TimeSpan.FromMilliseconds(33), };
dispatcherTimer.Tick += (s, e) =>
{
    
    
   //截屏并显示
};
dispatcherTimer.Start();

2. Código completo

El código completo se basa en System.Drawing. Para agregar un método de referencia, consulte "C# wpf usa GDI+ para implementar capturas de pantalla" .

Ventana principal.xaml

<Window x:Class="WpfMagnifier.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:WpfMagnifier"
        mc:Ignorable="d"
        Background="{x:Null}"
        ResizeMode="NoResize"
        WindowStyle="None"
        ShowInTaskbar="False"
        Topmost="True"
        Title="MainWindow" Height="200" Width="200" 
        MouseLeftButtonDown="Window_MouseDown">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"   CaptionHeight="0"   />
    </WindowChrome.WindowChrome>
    <Ellipse Stroke="LightBlue">
        <Ellipse.Fill>
            <ImageBrush x:Name="ib" Viewbox="0,0,0.5,0.5" />
        </Ellipse.Fill>
    </Ellipse>
</Window>

Ventana principal.xaml.cs

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace WpfMagnifier
{
    
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
    
    
        public MainWindow()
        {
    
    
            InitializeComponent();
            //启动定时器,截屏
            var dispatcherTimer = new DispatcherTimer() {
    
     Interval = TimeSpan.FromMilliseconds(33), };
            dispatcherTimer.Tick += (s, e) =>
            {
    
    
                //gdi+截屏,截取窗口左边的区域(可根据具体使用场景调整截屏位置),使用PointToScreen消除dpi影响
                var leftTop = PointToScreen(new Point(-Width, 0));
                var rightBottom = PointToScreen(new Point(0, Height));
                var bm = Snapshot((int)leftTop.X, (int)leftTop.Y, (int)(rightBottom.X - leftTop.X), (int)(rightBottom.Y - leftTop.Y));
                var wb = BitmapToWriteableBitmap(bm);
                //显示到界面
                ib.ImageSource = wb;
            };
            dispatcherTimer.Start();
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
    
    
            DragMove();
        }
        /// <summary>
        /// 截取一帧图片
        /// </summary>
        /// <param name="x">x坐标</param>
        /// <param name="y">y坐标</param>
        /// <param name="width">宽</param>
        /// <param name="height">高</param>
        /// <returns>截屏后的位图对象,需要调用Dispose手动释放资源。</returns>
        public static System.Drawing.Bitmap Snapshot(int x, int y, int width, int height)
        {
    
    
            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
            {
    
    
                graphics.CopyFromScreen(x, y, 0, 0, new System.Drawing.Size(width, height), System.Drawing.CopyPixelOperation.SourceCopy);
            }
            return bitmap;
        }
        //将Bitmap 转换成WriteableBitmap 
        public static WriteableBitmap BitmapToWriteableBitmap(System.Drawing.Bitmap src)
        {
    
    
            var wb = CreateCompatibleWriteableBitmap(src);
            System.Drawing.Imaging.PixelFormat format = src.PixelFormat;
            if (wb == null)
            {
    
    
                wb = new WriteableBitmap(src.Width, src.Height, 0, 0, System.Windows.Media.PixelFormats.Bgra32, null);
                format = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
            }
            BitmapCopyToWriteableBitmap(src, wb, new System.Drawing.Rectangle(0, 0, src.Width, src.Height), 0, 0, format);
            return wb;
        }
        //创建尺寸和格式与Bitmap兼容的WriteableBitmap
        public static WriteableBitmap CreateCompatibleWriteableBitmap(System.Drawing.Bitmap src)
        {
    
    
            System.Windows.Media.PixelFormat format;
            switch (src.PixelFormat)
            {
    
    
                case System.Drawing.Imaging.PixelFormat.Format16bppRgb555:
                    format = System.Windows.Media.PixelFormats.Bgr555;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format16bppRgb565:
                    format = System.Windows.Media.PixelFormats.Bgr565;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
                    format = System.Windows.Media.PixelFormats.Bgr24;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format32bppRgb:
                    format = System.Windows.Media.PixelFormats.Bgr32;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format32bppPArgb:
                    format = System.Windows.Media.PixelFormats.Pbgra32;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
                    format = System.Windows.Media.PixelFormats.Bgra32;
                    break;
                default:
                    return null;
            }
            return new WriteableBitmap(src.Width, src.Height, 0, 0, format, null);
        }
        //将Bitmap数据写入WriteableBitmap中
        public static void BitmapCopyToWriteableBitmap(System.Drawing.Bitmap src, WriteableBitmap dst, System.Drawing.Rectangle srcRect, int destinationX, int destinationY, System.Drawing.Imaging.PixelFormat srcPixelFormat)
        {
    
    
            var data = src.LockBits(new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), src.Size), System.Drawing.Imaging.ImageLockMode.ReadOnly, srcPixelFormat);
            dst.WritePixels(new Int32Rect(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height), data.Scan0, data.Height * data.Stride, data.Stride, destinationX, destinationY);
            src.UnlockBits(data);
        }
    }
}

3. Vista previa del efecto

Lo que se muestra es la imagen en el lado izquierdo de la ventana (lupa)
Insertar descripción de la imagen aquí


Resumir

Lo anterior es de lo que hablaré hoy. Este artículo solo presenta brevemente el método para implementar una lupa de escritorio. La clave es usar Viewbox. La función de captura de pantalla es relativamente simple porque está lista. Por supuesto, el método en este artículo Es simple de implementar, pero aún se puede optimizar, especialmente los objetos de mapa de bits se pueden reutilizar en capturas de pantalla. En general, es relativamente fácil implementar una lupa de escritorio en WPF y el efecto es muy bueno.

Supongo que te gusta

Origin blog.csdn.net/u013113678/article/details/132743195
Recomendado
Clasificación