none
WPF 放大镜 RRS feed

  • 问题

  • 我在使用Graphics的CopyFromScreen方法不断截取屏幕位图制作放大镜程序,当鼠标移动到哪里,放大镜的窗口就会显示一个放大的位图,但是当我把鼠标移动到放大镜的窗口上时,放大镜窗口呈现的图片会被不断地放大,最终变得很模糊,请问如何避免放大镜窗口上现实的位图不被多次放大,谢谢
    2012年3月1日 5:13

答案

全部回复

  • 相关代码:

    namespace Magnifier
    {
        /// <summary>
        /// 屏幕放大镜
        /// </summary>
        public class ScreenMagnifier 

        {
            /// <summary>
            /// 获得指定点,指定大小,指定倍数的位图
            /// </summary>
            /// <param name="mousePos">鼠标坐标</param>
            /// <param name="size">放大的大小</param>
            /// <param name="times">放大的倍数</param>
            /// <returns></returns>
            public System.Drawing.Bitmap GetPicture(System.Drawing.Point mousePos,System.Windows.Size size, double times)
            {
                int width = (int)(size.Width / times);
                int height = (int)(size.Height / times);
                TmpBitmap = new Bitmap(width, height);
                Graphics g = Graphics.FromImage(TmpBitmap);
                //从指定的区域中复制图形,并且已经放大好了
                g.CopyFromScreen((int)(mousePos.X - width / 2), (int)(mousePos.Y - height / 2), 0, 0, new System.Drawing.Size(280, 200));
                g.Dispose();
                return TmpBitmap;
            }

             /// <summary>
            /// 在传入的控件中显示放大后的图片
            /// </summary>
            /// <param name="shower"></param>
            public void ShowPicture(Border shower)
            {
                IntPtr ip = TmpBitmap.GetHbitmap();
                BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    ip, IntPtr.Zero, Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                DeleteObject(ip);
                //将bitmapSource赋值给shower的source
                shower.Background = new ImageBrush(bitmapSource);
            }

            /// <summary>
            /// 释放 IntPtr资源
            /// </summary>
            /// <param name="ptr"></param>
            /// <returns></returns>
            [DllImport("gdi32")]
            static extern int DeleteObject(IntPtr ptr);
        }
    }

    测试代码:

    ScreenMagnifier a = new ScreenMagnifier ();

    Timer mag_timer = new Timer();

    mag_timer.Tick += new EventHandler(mag_timer_Tick);

     void mag_timer_Tick(object sender, EventArgs e)
     {
                a.getPicture(System.Windows.Forms.Control.MousePosition, times);
                overall =a.magPicture(a.TmpBitmap);
                a.showPicture(borderShow);
                this.Focus();
     }

    其中borderShow是显示放大后位图的WPF的Border控件,谢谢指导

    2012年3月1日 5:32
  • Hi Ocean He,

      你可以通过MouseMove 事件e.x 和 e.y 去得到鼠标的坐标是否落在放大镜窗口,如果是的话就不允许放大,循环放大的最终结果的确会把位图文件变模糊,毕竟是位图文件图片,而不是矢量图片。当然,你也能参考下面的两个例子获得一些灵感,他们只是简单的在图片上弹出WPF Magnifier 控件。

     

      Using the WPF Magnifier

       http://www.codeproject.com/Articles/307239/Using-the-WPF-Magnifier 

      Magnifying Effect in WPF

    http://www.codeproject.com/KB/WPF/MagnifyingInWPF.aspx?q=WPF+and+magnifier+

     


    orichisonic http://blog.csdn.net/orichisonic If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    2012年3月1日 7:22
  • 如果你的放大镜应用是基于WPF的,那么你可以处理最外层元素的MouseEnter 和MouseLeave 事件,标记鼠标是否进入了放大镜区域。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月2日 7:49
    版主
  • 如何限制鼠标移到放大镜区域后就不能放大,那么鼠标移动放大镜时,放大的对象就不会被更新,跟微软的放大镜不同,不符合我们的设计需求

    2012年3月5日 4:39
  • 因为你是直接取屏幕的,即使你强制你的鼠标在放大镜上方置放大一次,你的屏幕已经被你重绘改变了,你再次放大肯定就不是原来的屏幕内容的。微软的本身他提供了放大镜所用的API,你可以直接使用它的API来做效果: http://msdn.microsoft.com/en-us/library/windows/desktop/ms692162(v=vs.85).aspx 


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月5日 5:24
    版主
  • Bob Bao不好意思,微软的API是本地C++,我是C#程序员一来是看不懂,二来不知道怎么使用,请指教,谢谢
    2012年3月6日 2:54
  • .Net 调用 Native 代码,无非 1. 通过添加引用到COM , 然后根据生成的Interop Assembly 来使用COM中的接口  2. 通过P/Invoke 来直接调用Native公开的方法。  这里的话,你就可以使用第二种方式,P/Inovke:http://msdn.microsoft.com/en-us/magazine/cc164123.aspx 你也可以在这个站点上 http://pinvoke.net/index.aspx 学习如何去写P/Invoke的签名等。然后参考 http://msdn.microsoft.com/en-us/library/windows/desktop/ms692162(v=vs.85).aspx 的例子和文档,就可以调用C++ 的函数了。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年3月6日 6:23
    版主