首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用从WinForms到WPF的放大API

使用从WinForms到WPF的放大API
EN

Stack Overflow用户
提问于 2012-08-10 20:17:47
回答 2查看 2.7K关注 0票数 3

我在网上找到了一个图书馆,它使用了WinForms中的放大镜API,它的工作非常棒。我试着让它与WPF一起工作,但是没有运气,没有异常或错误,一切看起来都很好。我开始认为这不是WPF的本意。

WinForms代码:

代码语言:javascript
复制
public class Magnifier : IDisposable
{
    private Form form;
    private IntPtr hwndMag;
    private float magnification;
    private bool initialized;
    private RECT magWindowRect = new RECT();
    private System.Windows.Forms.Timer timer;

    public Magnifier(Form form)
    {
        if (form == null)
            throw new ArgumentNullException("form");

        magnification = 2.0f;
        this.form = form;
        this.form.Resize += new EventHandler(form_Resize);
        this.form.FormClosing += new FormClosingEventHandler(form_FormClosing);

        timer = new Timer();
        timer.Tick += new EventHandler(timer_Tick);

        initialized = NativeMethods.MagInitialize();
        if (initialized)
        {
            SetupMagnifier();
            timer.Interval = NativeMethods.USER_TIMER_MINIMUM;
            timer.Enabled = true;
        }
    }

    void form_FormClosing(object sender, FormClosingEventArgs e)
    {
        timer.Enabled = false;
    }

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

    void form_Resize(object sender, EventArgs e)
    {
        ResizeMagnifier();
    }

    ~Magnifier()
    {
        Dispose(false);
    }

    protected virtual void ResizeMagnifier()
    {
        if ( initialized && (hwndMag != IntPtr.Zero))
        {
            NativeMethods.GetClientRect(form.Handle, ref magWindowRect);
            // Resize the control to fill the window.
            NativeMethods.SetWindowPos(hwndMag, IntPtr.Zero,
                magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, 0);
        }
    }

    public virtual void UpdateMaginifier()
    {
        if ((!initialized) || (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;


        // Don't scroll outside desktop area.
        if (sourceRect.left < 0)
        {
            sourceRect.left = 0;
        }
        if (sourceRect.left > NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width)
        {
            sourceRect.left = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width;
        }
        sourceRect.right = sourceRect.left + width;

        if (sourceRect.top < 0)
        {
            sourceRect.top = 0;
        }
        if (sourceRect.top > NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height)
        {
            sourceRect.top = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height;
        }
        sourceRect.bottom = sourceRect.top + height;

        if (this.form == null)
        {
            timer.Enabled = false;
            return;
        }

        if (this.form.IsDisposed)
        {
            timer.Enabled = false;
            return;
        }

        // Set the source rectangle for the magnifier control.
        NativeMethods.MagSetWindowSource(hwndMag, sourceRect);

        // Reclaim topmost status, to prevent unmagnified menus from remaining in view. 
        NativeMethods.SetWindowPos(form.Handle, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0,
            (int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE);

        // Force redraw.
        NativeMethods.InvalidateRect(hwndMag, IntPtr.Zero, true);
    }

    public float Magnification
    {
        get { return magnification; }
        set
        {
            if (magnification != value)
            {
                magnification = value;
                // Set the magnification factor.
                Transformation matrix = new Transformation(magnification);
                NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
            }
        }
    }

    protected void SetupMagnifier()
    {
        if (!initialized)
            return;

        IntPtr hInst;

        hInst = NativeMethods.GetModuleHandle(null);

        // Make the window opaque.
        form.AllowTransparency = true;
        form.TransparencyKey = Color.Empty;
        form.Opacity = 255;

        // Create a magnifier control that fills the client area.
        NativeMethods.GetClientRect(form.Handle, ref magWindowRect);
        hwndMag = NativeMethods.CreateWindow((int)ExtendedWindowStyles.WS_EX_CLIENTEDGE, NativeMethods.WC_MAGNIFIER,
            "MagnifierWindow", (int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR |
            (int)WindowStyles.WS_VISIBLE,
            magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, form.Handle, IntPtr.Zero, hInst, IntPtr.Zero);

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

        // Set the magnification factor.
        Transformation matrix = new Transformation(magnification);
        NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
    }

    protected void RemoveMagnifier()
    {
        if (initialized)
            NativeMethods.MagUninitialize();
    }

    protected virtual void Dispose(bool disposing)
    {
        timer.Enabled = false;
        if (disposing)
            timer.Dispose();
        timer = null;
        form.Resize -= form_Resize;
        RemoveMagnifier();
    }

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion
}

在WPF代码中,我刚刚修改了Magn显弗类:

代码语言:javascript
复制
public class Magnifier : IDisposable
{
    private Window window;
    private IntPtr hwnd;
    private IntPtr hwndMag;
    private float magnification;
    private bool initialized;
    private RECT magWindowRect = new RECT();
    private DispatcherTimer timer;

    public Magnifier(Window window)
    {
        if (window == null)
            throw new ArgumentNullException("form");

        hwnd = new WindowInteropHelper(window).Handle;
        magnification = 2.0f;
        this.window = window;
        this.window.SizeChanged += form_Resize;
        this.window.Closing += form_FormClosing;

        timer = new DispatcherTimer();
        timer.Tick += timer_Tick;

        initialized = NativeMethods.MagInitialize();
        if (initialized)
        {
            SetupMagnifier();
            timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM);
            timer.IsEnabled = true;
        }
    }

    void form_FormClosing(object sender, CancelEventArgs e)
    {
        timer.IsEnabled = false;
    }

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

    void form_Resize(object sender, RoutedEventArgs e)
    {
        ResizeMagnifier();
    }

    ~Magnifier()
    {
        Dispose(false);
    }

    protected virtual void ResizeMagnifier()
    {
        if (initialized && (hwndMag != IntPtr.Zero))
        {
            NativeMethods.GetClientRect(hwnd, ref magWindowRect);
            // Resize the control to fill the window.
            NativeMethods.SetWindowPos(hwndMag, IntPtr.Zero,
                magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, 0);
        }
    }

    public virtual void UpdateMaginifier()
    {
        if ((!initialized) || (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;


        // Don't scroll outside desktop area.
        if (sourceRect.left < 0)
        {
            sourceRect.left = 0;
        }
        if (sourceRect.left > NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width)
        {
            sourceRect.left = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) - width;
        }
        sourceRect.right = sourceRect.left + width;

        if (sourceRect.top < 0)
        {
            sourceRect.top = 0;
        }
        if (sourceRect.top > NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height)
        {
            sourceRect.top = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN) - height;
        }
        sourceRect.bottom = sourceRect.top + height;

        if (this.window == null)
        {
            timer.IsEnabled = false;
            return;
        }

        //if (this.window.IsDisposed)
        //{
        //    timer.IsEnabled = false;
        //    return;
        //}

        // Set the source rectangle for the magnifier control.
        NativeMethods.MagSetWindowSource(hwndMag, sourceRect);

        // Reclaim topmost status, to prevent unmagnified menus from remaining in view. 
        NativeMethods.SetWindowPos(hwnd, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0,
            (int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE);

        // Force redraw.
        NativeMethods.InvalidateRect(hwndMag, IntPtr.Zero, true);
    }

    public float Magnification
    {
        get { return magnification; }
        set
        {
            if (magnification != value)
            {
                magnification = value;
                // Set the magnification factor.
                Transformation matrix = new Transformation(magnification);
                NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
            }
        }
    }

    protected void SetupMagnifier()
    {
        if (!initialized)
            return;

        IntPtr hInst;

        hInst = NativeMethods.GetModuleHandle(null);

        // Make the window opaque.
        //form.AllowTransparency = true; (done in xaml)
        //window.Background = Brushes.Transparent; (done in xaml)
        //window.Opacity = 255;

        // Create a magnifier control that fills the client area.
        NativeMethods.GetClientRect(hwnd, ref magWindowRect);
        hwndMag = NativeMethods.CreateWindow((int)ExtendedWindowStyles.WS_EX_CLIENTEDGE, NativeMethods.WC_MAGNIFIER,
            "MagnifierWindow", (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);

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

        // Set the magnification factor.
        Transformation matrix = new Transformation(magnification);
        NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
    }

    protected void RemoveMagnifier()
    {
        if (initialized)
            NativeMethods.MagUninitialize();
    }

    protected virtual void Dispose(bool disposing)
    {
        timer.IsEnabled = false;
        //if (disposing)
        //    timer.Dispose();
        timer = null;
        window.SizeChanged -= form_Resize;
        RemoveMagnifier();
    }

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion
}

XAML:

代码语言:javascript
复制
<Window x:Class="WpfApplication11.MagnifierWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MagnifierWindow" Height="350" Width="525" AllowsTransparency="True" WindowStyle="None">

<Window.Background>
    <SolidColorBrush />
</Window.Background>

-To使用我刚刚在表单/窗口的构造函数中初始化的类。

-Changes I在WPF中制造:

  • 添加"hwnd“字段,在放大镜构造函数中初始化它。
  • 将System.Windows.Forms.Timer替换为System.Windows.Threading.DispatcherTimer。
  • form.Resize改为window.SizeChanged,form.FormClosing改为window.Closing。但这是无关紧要的,对吧?
  • 在UpdateMagnifier()中注释if (UpdateMagnifier),因为窗口中没有IsDisposed属性。
  • 在Dispose()中注释了一个处理检查。

由于字符限制,-I无法添加本机方法和结构。

非常感谢您的帮助,谢谢。

EN

回答 2

Stack Overflow用户

发布于 2014-04-02 02:24:08

您应该在加载窗口并检索窗口句柄的加载事件中初始化放大镜。否则,它永远是零。

代码语言:javascript
复制
public Magnifier(Window window)
{
    if (window == null)
        throw new ArgumentNullException("form");

    hwnd = new WindowInteropHelper(window).Handle;
    magnification = 2.0f;
    this.window = window;
    this.window.SizeChanged += form_Resize;
    this.window.Closing += form_FormClosing;

    timer = new DispatcherTimer();
    timer.Tick += timer_Tick;
    Loaded+=MainWindow_Loaded;
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    initialized = NativeMethods.MagInitialize();
    if (initialized)
    {
        handle = new WindowInteropHelper(this).Handle;
        SetupMagnifier();
        timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM);
        timer.Start();// = true;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2021-06-19 11:13:37

若要在窗口窗体中使用此放大镜类,请执行以下操作。

代码语言:javascript
复制
 public Home()
    {
    InitializeComponent();
    Magnifier mg = new Magnifier(this);
    }
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11908676

复制
相关文章

相似问题

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