Implement lens magnification to magnify the Windows Taskbar

谁说我不能喝 提交于 2021-02-11 15:19:13

问题


I want to be able to perform lens magnificaiton on top of the windows taskbar. So far I've been unsuccessful in implementing this seeing as the taskbar will always open on top of my window. Windows built-in magnifier is able to do this so I'm hoping it is indeed possible.

I've attached two screenshots showing Windows built-in magnifier and how it is able to magnify the taskbar and how my application will render below the taskbar.

Windows built-in Magnifier:

Windows built-in Magnifier

My application:

My application

Is there any way to have my application render above the taskbar and thus magnify the taskbar?

<Window x:Class="WpfNativeTesting.MagnificationWindow"
        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:WpfNativeTesting"
        mc:Ignorable="d"
        Title="MagnificationWindow"
        
        Height="400"
        Width="400"
        
        WindowStyle="None"
        ResizeMode="NoResize"
        AllowsTransparency="true"
        ShowInTaskbar="False"
        Topmost="True">
    <Grid x:Name="ContainerGrid">
        <Grid x:Name="MagnificationGrid" />
    </Grid>
</Window>
public partial class MagnificationWindow : Window
    {
        private IntPtr HWnd;
        private IntPtr HWndMag;
        private bool MagnificationInitialized = false;
        private DispatcherTimer Timer = new DispatcherTimer();
        private RECT MagWindowRect = new RECT();
        private bool IsColorEffectSet = false;

        private float magnification = 1.0f;
        public float Magnification
        {
            get { return magnification; }
            set
            {
                if (value < 1.0f)
                {
                    value = 1.0f;
                }

                if (HWndMag != null)
                {
                    if (magnification != value)
                    {
                        magnification = value;

                        Transformation matrix = new Transformation(magnification);
                        NativeMethods.MagSetWindowTransform(HWndMag, ref matrix);
                    }
                }
            }
        }

        public MagnificationWindow()
        {
            InitializeComponent();

            Loaded += MagnificationWindow_Loaded;

            Show();
        }

        private void MagnificationWindow_Loaded(object sender, RoutedEventArgs e)
        {
            HWnd = new WindowInteropHelper(this).Handle;

            var exStyle = NativeMethods.GetWindowLong(HWnd, NativeMethods.GWL_EXSTYLE);
            exStyle |= (int)ExtendedWindowStyles.WS_EX_TOPMOST | (int)ExtendedWindowStyles.WS_EX_LAYERED | (int)ExtendedWindowStyles.WS_EX_TRANSPARENT;
            NativeMethods.SetWindowLong(HWnd, NativeMethods.GWL_EXSTYLE, exStyle);

            var style = NativeMethods.GetWindowLong(HWnd, NativeMethods.GWL_STYLE);
            style |= (int)WindowStyles.WS_CAPTION | (int)WindowStyles.WS_SYSMENU;
            NativeMethods.SetWindowLong(HWnd, NativeMethods.GWL_STYLE, exStyle);

            MagnificationInitialized = NativeMethods.MagInitialize();

            if (MagnificationInitialized)
            {
                SetupMagnifier();

                Timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM);
                Timer.Tick += Timer_Tick;
                Timer.Start();
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            RemoveMagnifier();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            UpdateMaginifier();
        }


        private void SetupMagnifier()
        {
            var hInst = NativeMethods.GetModuleHandle(null);

            NativeMethods.GetClientRect(HWnd, ref MagWindowRect);

            HWndMag = NativeMethods.CreateWindow((int)ExtendedWindowStyles.WS_EX_STATICEDGE, NativeMethods.WC_MAGNIFIER,
                    "MagnificationWindow", (int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR | (int)WindowStyles.WS_VISIBLE,
                    MagWindowRect.left, MagWindowRect.top, MagWindowRect.right, MagWindowRect.bottom, HWnd, IntPtr.Zero, hInst, IntPtr.Zero);

            NativeMethods.MagShowSystemCursor(false);

            if (HWndMag == IntPtr.Zero)
            {
                return;
            }

            var matrix = new Transformation(Magnification);
            NativeMethods.MagSetWindowTransform(HWndMag, ref matrix);
        }

        private void UpdateMaginifier()
        {
            if (!MagnificationInitialized || HWndMag == IntPtr.Zero)
            {
                return;
            }

            POINT mousePoint = new POINT();
            RECT sourceRect = new RECT();

            NativeMethods.GetCursorPos(ref mousePoint);

            int width = (int)((MagWindowRect.right - MagWindowRect.left) / Magnification);
            int height = (int)((MagWindowRect.bottom - MagWindowRect.top) / Magnification);

            sourceRect.left = mousePoint.x - width / 2;
            sourceRect.top = mousePoint.y - height / 2;

            NativeMethods.MagSetWindowSource(HWndMag, sourceRect);

            POINT mouse = new POINT();
            NativeMethods.GetCursorPos(ref mouse);

            NativeMethods.SetWindowPos(HWnd, NativeMethods.HWND_TOPMOST, mouse.x - (int)(magnification * width / 2), mouse.y - (int)(magnification * height / 2), width, height, 
                (int)SetWindowPosFlags.SWP_NOACTIVATE | 
                (int)SetWindowPosFlags.SWP_NOSIZE);

            NativeMethods.InvalidateRect(HWndMag, IntPtr.Zero, true);
        }

        public void RemoveMagnifier()
        {
            if (MagnificationInitialized)
            {
                NativeMethods.MagUninitialize();

                MagnificationInitialized = false;
            }
        }    
    
        // ...
   }

回答1:


I posted this question in the Microsoft Q/A forum and got a solution that got it working.

https://docs.microsoft.com/en-us/answers/questions/54196/magnifier-control-unable-to-magnify-the-taskbar-st.html


We need to make it a Accessibility app by setting uiAcess=true in the manifest, sign the executable, and placing it in a secure location (e.g. Program Files) as described below:

  1. Set uiAccess=true in the manifest Set this option in Visual Studio by setting Linker | Manifest File | UAC Bypass UI Protection to Yes

  2. Sign the executable See https://docs.microsoft.com/en-us/previous-versions/bb756995(v=msdn.10)

  3. Place it in a secure location See https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-account-control-only-elevate-uiaccess-applications-that-are-installed-in-secure-locations


I placed the application in a secure location before I signed it and used the following commands to create the certificate and sign the application.

makecert /n "CN=Company, O=Company, C=SE" /r /pe /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e 01/01/2021 /sv Company.pvk Company.cer

Pvk2Pfx /pvk Company.pvk /pi "password" /spc Company.cer /pfx Company.pfx /po "password" /pi "password"

and finally

signtool sign /f "Company.pfx" /p "password" "application".exe

And that's it!



来源:https://stackoverflow.com/questions/63111438/implement-lens-magnification-to-magnify-the-windows-taskbar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!