Захват, зум и отображение части окна приложения

212
20 октября 2018, 15:50

Есть программа оверлей, в которой должно отображаться увеличенное изображение части окна другого приложения. В какую сторону смотреть, что бы реализовать это?

Answer 1

Можно сделать это с помощью DWM Thumbnail API. Следующий пример демонстрирует показ увеличенного изображения части окна на элементе управления в WPF и перемещение области при нажатии кнопок.

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Width="500" Height="300" Loaded="Window_Loaded_1" SizeChanged="Window_SizeChanged_1"
        >    
    <Grid>
        <Button Content=">" HorizontalAlignment="Left" Height="30" Margin="60,20,0,0" VerticalAlignment="Top" Width="30" 
                Click="Button_Click_Right"/>
        <Button Content="&lt;" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="30" 
                Click="Button_Click_Left" Margin="20,20,0,0"/>
        <Grid x:Name="mygrid" HorizontalAlignment="Stretch"  Margin="20,63,20,20" VerticalAlignment="Stretch" 
              Background="{DynamicResource {x:Static SystemColors.AppWorkspaceBrushKey}}"/>
    </Grid>
</Window>

C#:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;
using System.Windows.Interop;
using System.Runtime.InteropServices;
namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        IntPtr source = IntPtr.Zero; //дескриптор окна, предспросмотр которого будет отображаться
        IntPtr thumb = IntPtr.Zero; //дескриптор объекта DWM Thumbnail
        Point position = new Point(0, 0); //начальное положение области предпросмотра
        double zoom = 2.0; //фактор увеличения
        void UpdateView() //перерисовка окна
        {
            //освободим предыдущий Thumbnail
            if (thumb != IntPtr.Zero) { DwmUnregisterThumbnail(thumb); thumb = IntPtr.Zero; }
            //создадим новый Thumbnail
            thumb = CreatePreview(mygrid, source, position, zoom);
        }
        public MainWindow()
        {
            InitializeComponent();
            //получим дескриптор окна, которое нужно отобразить
            var pr = System.Diagnostics.Process.GetProcessesByName("Taskmgr")[0];
            source = pr.MainWindowHandle;            
        }
        private void Window_Loaded_1(object sender, RoutedEventArgs e)
        {
            UpdateView();
        }
        private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
        {
            UpdateView();
        }       
        private void Button_Click_Right(object sender, RoutedEventArgs e)
        {
            position.X += 10;
            UpdateView();  
        }
        private void Button_Click_Left(object sender, RoutedEventArgs e)
        {
            position.X -= 10;
            UpdateView();
        }
        /// <summary>
        /// Создает предпросмотр части окна source в указанном элементе с помощью DWM Thumbnail API
        /// </summary>
        /// <param name="target">Элемент, в котором нужно создать предпросмотр</param>
        /// <param name="source">Дескриптор окна, предпросмотр которого нужно создать</param>
        /// <param name="pos">Положение области в окне source, которую будет отображать предпросмотр</param>
        /// <param name="zoom">Фактор увеличения</param>
        /// <returns>Дескриптор объекта DWM Thumbnail</returns>
        public static IntPtr CreatePreview(FrameworkElement target, IntPtr source, Point pos, double zoom)
        {
            HwndSource hwndTarget = (HwndSource)HwndSource.FromVisual(target);
            Point p0 = target.TranslatePoint(new Point(0, 0), Window.GetWindow(target));
            Point p1 = target.TranslatePoint(new Point(target.ActualWidth, target.ActualHeight), Window.GetWindow(target));
            RECT rcDest = new RECT
            {
                Left = (int)p0.X,
                Top = (int)p0.Y,
                Right = (int)p1.X,
                Bottom = (int)p1.Y
            };
            RECT rcSource = new RECT
            {
                Left = (int)pos.X,
                Top = (int)pos.Y,
                Right = (int)(pos.X + target.ActualWidth / zoom),
                Bottom = (int)(pos.Y + target.ActualHeight / zoom)
            };

            IntPtr thumb = IntPtr.Zero;
            int res = DwmRegisterThumbnail(hwndTarget.Handle, source, out thumb);
            if (res != 0)
            {
                throw new System.ComponentModel.Win32Exception("DwmRegisterThumbnail failed with code 0x" + res.ToString("X"));
            }

            DWM_THUMBNAIL_PROPERTIES dskThumbProps = new DWM_THUMBNAIL_PROPERTIES();
            dskThumbProps.dwFlags =
                DWM_TNP_SOURCECLIENTAREAONLY | DWM_TNP_VISIBLE | DWM_TNP_OPACITY | DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE;
            dskThumbProps.fSourceClientAreaOnly = 0;
            dskThumbProps.fVisible = 1;
            dskThumbProps.opacity = (255 * 70) / 100;
            dskThumbProps.rcDestination = rcDest;
            dskThumbProps.rcSource = rcSource;
            res = DwmUpdateThumbnailProperties(thumb, ref dskThumbProps);
            if (res != 0)
            {
                throw new System.ComponentModel.Win32Exception("DwmUpdateThumbnailProperties failed with code 0x" + res.ToString("X"));
            }
            return thumb;
        }
        /***  DWM Api Functions  ***/
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("dwmapi.dll", SetLastError = true)]
        static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb);
        [DllImport("dwmapi.dll", PreserveSig = true)]
        public static extern int DwmUpdateThumbnailProperties(IntPtr hThumbnail, ref DWM_THUMBNAIL_PROPERTIES props);
        [DllImport("dwmapi.dll")]
        static extern int DwmUnregisterThumbnail(IntPtr thumb);
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left, Top, Right, Bottom;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct DWM_THUMBNAIL_PROPERTIES
        {
            public uint dwFlags;
            public RECT rcDestination;
            public RECT rcSource;
            public byte opacity;
            public int fVisible;
            public int fSourceClientAreaOnly;
        }
        const uint DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010;
        const uint DWM_TNP_VISIBLE = 0x00000008;
        const uint DWM_TNP_RECTDESTINATION = 0x00000001;
        const uint DWM_TNP_RECTSOURCE = 0x00000002;
        const uint DWM_TNP_OPACITY = 0x00000004;      

    }  
}
READ ALSO
C#. не получает cookies

C#. не получает cookies

Делаю авторизациюПосле ввода логина и пароля со страницы логина отправляются cookies и на странице user принимаются и проверяются

196
Привязка из контекстного меню

Привязка из контекстного меню

Есть DataGrid в которой в DataGridRowDetail нужно сделать binding context menu к главной view modelКак это сделать? Оно сейчас пишет что не может найти property непосредственно...

195
Смещение часового пояса ASP.NET MVC

Смещение часового пояса ASP.NET MVC

У меня есть сайт и серверХочу, чтобы клиентам из разных часовых поясов показывалось разное время

195
Парсинг значения json с помощью Newtonsoft на с#

Парсинг значения json с помощью Newtonsoft на с#

Задача: получить значение "lastPriceProtected"

215