[Silverlight]要如何把Deep Zoom產生的檔案內嵌到已完成的Silverlight網頁中?

[Silverlight]要如何把Deep Zoom產生的檔案內嵌到已完成的Silverlight網頁中?

我們知道可以透過Deep Zoom Composer輕易地作出可以Zoom In & Zoom Out的圖片瀏覽功能:

 

1. Import 圖片進Deep Zoom Composer:

image

 

2. Compose圖片,這邊就輕鬆擺一下:

image

 

3. 設定名稱、匯出專案樣板類型(這邊我們選擇Deep Zoom Classic + Source),然後按下匯出:

image

 

 

4. 然後我們可以看到專案被放在下列目錄:

image

 

 

 

打開Exported Data目錄,接下來再打開deepzoomtest目錄(這個名稱就是我們在匯出那步驟所命名的名稱).

image

 

接下來,我們處理要放到Silverlight專案的部分:

 

5. 開啟一個新的Silverlight專案(這裡我們把這個專案取名為DeepZoomMigrate),然後將GeneratedImages目錄整個複製到DeepZoomMigrate.Web

   專案的ClientBin目錄下。

 

6. 在DeepZoomMigrate專案中加入DeepZoomProject目錄下的MouseWheelHelper.cs類別檔案。

    這個類別顧名思義是用來處理滑鼠滾輪的事件及方法:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace DeepZoomProject
{
        // Courtesy of Pete Blois
        public class MouseWheelEventArgs : EventArgs
        {
            private double delta;
            private bool handled = false;

            public MouseWheelEventArgs(double delta)
            {
                this.delta = delta;
            }

            public double Delta
            {
                get { return this.delta; }
            }

            // Use handled to prevent the default browser behavior!
            public bool Handled
            {
                get { return this.handled; }
                set { this.handled = value; }
            }
        }

        public class MouseWheelHelper
        {

            public event EventHandler<MouseWheelEventArgs> Moved;
            private static Worker worker;
            private bool isMouseOver = false;

            public MouseWheelHelper(FrameworkElement element)
            {

                if (MouseWheelHelper.worker == null)
                    MouseWheelHelper.worker = new Worker();

                MouseWheelHelper.worker.Moved += this.HandleMouseWheel;

                element.MouseEnter += this.HandleMouseEnter;
                element.MouseLeave += this.HandleMouseLeave;
                element.MouseMove += this.HandleMouseMove;
            }

            private void HandleMouseWheel(object sender, MouseWheelEventArgs args)
            {
                if (this.isMouseOver)
                    this.Moved(this, args);
            }

            private void HandleMouseEnter(object sender, EventArgs e)
            {
                this.isMouseOver = true;
            }

            private void HandleMouseLeave(object sender, EventArgs e)
            {
                this.isMouseOver = false;
            }

            private void HandleMouseMove(object sender, EventArgs e)
            {
                this.isMouseOver = true;
            }

            private class Worker
            {

                public event EventHandler<MouseWheelEventArgs> Moved;

                public Worker()
                {

                    if (HtmlPage.IsEnabled)
                    {
                        HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel);
                        HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel);
                        HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel);
                    }

                }

                private void HandleMouseWheel(object sender, HtmlEventArgs args)
                {
                    double delta = 0;

                    ScriptObject eventObj = args.EventObject;

                    if (eventObj.GetProperty("wheelDelta") != null)
                    {
                        delta = ((double)eventObj.GetProperty("wheelDelta")) / 120;


                        if (HtmlPage.Window.GetProperty("opera") != null)
                            delta = -delta;
                    }
                    else if (eventObj.GetProperty("detail") != null)
                    {
                        delta = -((double)eventObj.GetProperty("detail")) / 3;

                        if (HtmlPage.BrowserInformation.UserAgent.IndexOf("Macintosh") != -1)
                            delta = delta * 3;
                    }

                    if (delta != 0 && this.Moved != null)
                    {
                        MouseWheelEventArgs wheelArgs = new MouseWheelEventArgs(delta);
                        this.Moved(this, wheelArgs);

                        if (wheelArgs.Handled)
                            args.PreventDefault();
                    }
                }
            }
        }
}

 

7. 然後我們在剛剛新增的Silverlight專案的MainPage.xaml,新增一個MultiScaleImage物件如下:

<UserControl x:Class="DeepZoomMigrate.MainPage"
    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" 
    mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="768">
    <StackPanel HorizontalAlignment="Left" >
        <MultiScaleImage x:Name="uxMS" Width="800" Height="600" ></MultiScaleImage>
    </StackPanel>
</UserControl>

 

 

8. 複製剛剛DeepZoomProject目錄下的Page.xaml.cs程式碼,並作一些調整如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DeepZoomProject;

namespace DeepZoomMigrate
{
    public partial class MainPage : UserControl
    {

        //
        // Based on prior work done by Lutz Gerhard, Peter Blois, and Scott Hanselman
        //

        double zoom = 1;
        bool duringDrag = false;
        bool mouseDown = false;
        Point lastMouseDownPos = new Point();
        Point lastMousePos = new Point();
        Point lastMouseViewPort = new Point();


        public double ZoomFactor
        {
            get { return zoom; }
            set { zoom = value; }
        }

        public MainPage()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

            //
            // Firing an event when the MultiScaleImage is Loaded
            //
            this.uxMS.Loaded += new RoutedEventHandler(uxMS_Loaded);

            //
            // Firing an event when all of the images have been Loaded
            //
            this.uxMS.ImageOpenSucceeded += new RoutedEventHandler(uxMS_ImageOpenSucceeded);

            //
            // Handling all of the mouse and keyboard functionality
            //
            this.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                lastMousePos = e.GetPosition(uxMS);

                if (duringDrag)
                {
                    Point newPoint = lastMouseViewPort;
                    newPoint.X += (lastMouseDownPos.X - lastMousePos.X) / uxMS.ActualWidth * uxMS.ViewportWidth;
                    newPoint.Y += (lastMouseDownPos.Y - lastMousePos.Y) / uxMS.ActualWidth * uxMS.ViewportWidth;
                    uxMS.ViewportOrigin = newPoint;
                }
            };

            this.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
            {
                lastMouseDownPos = e.GetPosition(uxMS);
                lastMouseViewPort = uxMS.ViewportOrigin;

                mouseDown = true;

                uxMS.CaptureMouse();
            };

            this.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                if (!duringDrag)
                {
                    bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
                    double newzoom = zoom;

                    if (shiftDown)
                    {
                        newzoom /= 2;
                    }
                    else
                    {
                        newzoom *= 2;
                    }

                    Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
                }
                duringDrag = false;
                mouseDown = false;

                uxMS.ReleaseMouseCapture();
            };

            this.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                lastMousePos = e.GetPosition(uxMS);
                if (mouseDown && !duringDrag)
                {
                    duringDrag = true;
                    double w = uxMS.ViewportWidth;
                    Point o = new Point(uxMS.ViewportOrigin.X, uxMS.ViewportOrigin.Y);
                    uxMS.UseSprings = false;
                    uxMS.ViewportOrigin = new Point(o.X, o.Y);
                    uxMS.ViewportWidth = w;
                    zoom = 1 / w;
                    uxMS.UseSprings = true;
                }

                if (duringDrag)
                {
                    Point newPoint = lastMouseViewPort;
                    newPoint.X += (lastMouseDownPos.X - lastMousePos.X) / uxMS.ActualWidth * uxMS.ViewportWidth;
                    newPoint.Y += (lastMouseDownPos.Y - lastMousePos.Y) / uxMS.ActualWidth * uxMS.ViewportWidth;
                    uxMS.ViewportOrigin = newPoint;
                }
            };

            new MouseWheelHelper(this).Moved += delegate(object sender, DeepZoomProject.MouseWheelEventArgs e)
            {
                e.Handled = true;

                double newzoom = zoom;

                if (e.Delta < 0)
                    newzoom /= 1.3;
                else
                    newzoom *= 1.3;

                Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
                uxMS.CaptureMouse();
            };
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            //這裡先註解
            //string path = App.Current.Resources["path"].ToString();
            //string zoomIn = App.Current.Resources["zoomIn"].ToString();

            this.uxMS.Source = new DeepZoomImageTileSource(new Uri("/GeneratedImages/dzc_output.xml", UriKind.Relative));
            //zoom = Int32.Parse(zoomIn);
        }

        void uxMS_ImageOpenSucceeded(object sender, RoutedEventArgs e)
        {
            //If collection, this gets you a list of all of the MultiScaleSubImages
            //
            //foreach (MultiScaleSubImage subImage in uxMS.SubImages)
            //{
            //    // Do something
            //}

            uxMS.ViewportWidth = 1;
        }

        void uxMS_Loaded(object sender, RoutedEventArgs e)
        {

        }

        private void Zoom(double newzoom, Point p)
        {
            if (newzoom < 0.5)
            {
                newzoom = 0.5;
            }

            uxMS.ZoomAboutLogicalPoint(newzoom / zoom, p.X, p.Y);
            zoom = newzoom;
        }

        //private void ZoomInClick(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    Zoom(zoom * 1.3, uxMS.ElementToLogicalPoint(new Point(.5 * uxMS.ActualWidth, .5 * uxMS.ActualHeight)));
        //}

        //private void ZoomOutClick(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    Zoom(zoom / 1.3, uxMS.ElementToLogicalPoint(new Point(.5 * uxMS.ActualWidth, .5 * uxMS.ActualHeight)));
        //}

        //private void GoHomeClick(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    this.uxMS.ViewportWidth = 1;
        //    this.uxMS.ViewportOrigin = new Point(0, 0);
        //    ZoomFactor = 1;
        //}

        //private void GoFullScreenClick(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    if (!Application.Current.Host.Content.IsFullScreen)
        //    {
        //        Application.Current.Host.Content.IsFullScreen = true;
        //    }
        //    else
        //    {
        //        Application.Current.Host.Content.IsFullScreen = false;
        //    }
        //}

        //// Handling the VSM states
        //private void LeaveMovie(object sender, System.Windows.Input.MouseEventArgs e)
        //{
        //    VisualStateManager.GoToState(this, "FadeOut", true);
        //}

        //private void EnterMovie(object sender, System.Windows.Input.MouseEventArgs e)
        //{
        //    VisualStateManager.GoToState(this, "FadeIn", true);
        //}


        //// unused functions that show the inner math of Deep Zoom
        //public Rect getImageRect()
        //{
        //    return new Rect(-uxMS.ViewportOrigin.X / uxMS.ViewportWidth, -uxMS.ViewportOrigin.Y / uxMS.ViewportWidth, 1 / uxMS.ViewportWidth, 1 / uxMS.ViewportWidth * uxMS.AspectRatio);
        //}

        //public Rect ZoomAboutPoint(Rect img, double zAmount, Point pt)
        //{
        //    return new Rect(pt.X + (img.X - pt.X) / zAmount, pt.Y + (img.Y - pt.Y) / zAmount, img.Width / zAmount, img.Height / zAmount);
        //}

        //public void LayoutDZI(Rect rect)
        //{
        //    double ar = uxMS.AspectRatio;
        //    uxMS.ViewportWidth = 1 / rect.Width;
        //    uxMS.ViewportOrigin = new Point(-rect.Left / rect.Width, -rect.Top / rect.Width);
        //}
    }
}

 

 

注解掉的地方是原本Deep Zoom Composer產生的按鈕的方法。

 

這裡要注意兩個地方:

1.

void Page_Loaded(object sender, RoutedEventArgs e)
       {
           //這裡先註解
           //string path = App.Current.Resources["path"].ToString();
           //string zoomIn = App.Current.Resources["zoomIn"].ToString(); 

           this.uxMS.Source = new DeepZoomImageTileSource(new Uri("/GeneratedImages/dzc_output.xml", UriKind.Relative));
           //zoom = Int32.Parse(zoomIn);
       }

 

這裡把原先程式碼中去讀resouce的圖片的部分改成讀ClientBin目錄下的圖片檔案

 

2.

new MouseWheelHelper(this).Moved += delegate(object sender, DeepZoomProject.MouseWheelEventArgs e)
            {
                e.Handled = true;

                double newzoom = zoom;

                if (e.Delta < 0)
                    newzoom /= 1.3;
                else
                    newzoom *= 1.3;

                Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
                uxMS.CaptureMouse();
            };

 

MouseWheekEventArgs是要引用DeepZoomProject的NameSpace。

 

 

 

結果:

image

 

檔案下載

線上Demo

 

 

 

參考連結:

MultiScaleImage 類別 - http://msdn.microsoft.com/zh-tw/library/system.windows.controls.multiscaleimage%28VS.95%29.aspx

 

 

如果您有微軟技術開發的問題,可以到MSDN Forum發問。

如果您有微軟IT管理的問題,可以到TechNet Forum發問喔。