开发者

how to get the visible area of canvas in wpf

开发者 https://www.devze.com 2023-02-14 20:22 出处:网络
I am creating an application just like a paint in WPF, and I want to add zoom functionality to it. I am taking canvas as a parent and writable bitmap on it as child on which I draw. When the size of t

I am creating an application just like a paint in WPF, and I want to add zoom functionality to it. I am taking canvas as a parent and writable bitmap on it as child on which I draw. When the size of the canvas is small, I am drawing on writable bitmap smoothly, but when the size of the canvas is large, and zoom it, canvas size will be large, problem occur to draw on this large area. So I want to find the visible region of the canvas so that I can draw on it smoothly. Please give me a source code to find the visible region of the canvas.

开发者_Python百科

I have create this application:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Interop;


namespace MapDesigner.Controls
{
class MapCanvas : Canvas
{
    #region Routed Events
    public static readonly RoutedEvent SelectedColorChangeEvent = EventManager.RegisterRoutedEvent(
        "SelectedColorChange", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ucToolBox));
    public event RoutedEventHandler SelectedColorChange
    {
        add { AddHandler(SelectedColorChangeEvent, value); }
        remove { RemoveHandler(SelectedColorChangeEvent, value); }
    }
    #endregion

    #region Enums
    public enum Tool
    {

        Pencil,
        FloodFill,
        Eraser,
        RectSelect,
        Brush,
        Part
    }
    #endregion

    WriteableBitmap _wBMP;

    Image _dispImg = new Image();
    ScaleTransform st = new ScaleTransform();
    int canvasHeight, canvasWidth;
    double zoomLevel = 1;
    Border brdGrid = new Border();
    Color cellColor = Colors.Black;
    Tool currentTool = Tool.Pencil;
    int[,] array;
    bool drawing = false;
    bool showGrids = true;
    public TextBlock tbPos;

    public Tool CurrentTool
    {
        get
        {
            return currentTool;
        }
        set
        {
            currentTool = value;
        }
    }
    public Color CellColor
    {
        get
        {
            return cellColor;
        }
        set
        {
            cellColor = value;
        }
    }
    public bool GridsVisible
    {
        get
        {
            return showGrids;
        }
        set
        {
            showGrids = value;
        }
    }
    public MapCanvas()
    {

        this.Children.Clear();
        this.Children.Add(_dispImg);
        //st.ScaleX = 1;
        //st.ScaleY = 1;
        // this.LayoutTransform = st;
    }

    void Refresh()
    {
        //canvas = new MapCanvas();
        this.Children.Clear();
        this.Children.Add(_dispImg);
        st.ScaleX = 1;
        st.ScaleY = 1;
        this.Height = 0;
        this.Width = 0;
        zoomLevel = 1;
        drawing = false;
    }

    public void LoadBMP(Uri bmpUri)
    {
        Refresh();
        BitmapImage bmi = new BitmapImage(bmpUri);
        _wBMP = new WriteableBitmap(bmi);
        _dispImg.Source = _wBMP;
        this.Height = bmi.Height;
        this.Width = bmi.Width;
        ShowGrids();
    }

    public void CreateBMP(int width, int height)
    {
        Refresh();
        _wBMP = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr32, BitmapPalettes.WebPalette);
        _wBMP.setPixel(Colors.White);
        _dispImg.Source = _wBMP;
        this.Height = height;
        this.Width = width;
        ShowGrids();
    }

    public void CreateNewDesign(Size mapSize)
    {

        Refresh();            
        _wBMP = new WriteableBitmap((int)mapSize.Width, (int)mapSize.Width, 96, 96, PixelFormats.Bgr32, BitmapPalettes.WebPalette);
        _wBMP.setPixel(Colors.White);
        _dispImg.Source = _wBMP;
        array = new int[(_wBMP.PixelHeight + 1), (_wBMP.PixelWidth + 1)];
        canvasWidth = (int)mapSize.Width;
        canvasHeight = (int)mapSize.Height;
        this.Height = mapSize.Height;
        this.Width = mapSize.Width;
        ShowGrids();
    }

    void ShowGrids()
    {

        return;
        double width = 1;// _tileWidth + _tileMargin;
        double height = 1;// _tileHeight + _tileMargin;
        double numTileToAccumulate = 16;
        Polyline gridCell = new Polyline();
        gridCell.Margin = new Thickness(.5);
        gridCell.Stroke = Brushes.LightBlue;
        gridCell.StrokeThickness = 0.1;
        gridCell.Points = new PointCollection(new Point[] { new Point(0, height-0.1),
                    new Point(width-0.1, height-0.1), new Point(width-0.1, 0) });
        VisualBrush gridLines = new VisualBrush(gridCell);
        gridLines.TileMode = TileMode.Tile;
        gridLines.Viewport = new Rect(0, 0, 1.0 / numTileToAccumulate, 1.0 / numTileToAccumulate);
        gridLines.AlignmentX = AlignmentX.Center;
        gridLines.AlignmentY = AlignmentY.Center;

        VisualBrush outerVB = new VisualBrush();
        Rectangle outerRect = new Rectangle();
        outerRect.Width = 10.0;  //can be any size
        outerRect.Height = 10.0;
        outerRect.Fill = gridLines;
        outerVB.Visual = outerRect;
        outerVB.Viewport = new Rect(0, 0,
                width * numTileToAccumulate, height * numTileToAccumulate);
        outerVB.ViewportUnits = BrushMappingMode.Absolute;
        outerVB.TileMode = TileMode.Tile;
        this.Children.Remove(brdGrid);
        brdGrid = new Border();
        brdGrid.Height = this.Height;
        brdGrid.Width = this.Width;
        brdGrid.Background = outerVB;
        this.Children.Add(brdGrid);
    }

    protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
    {
        base.OnMouseMove(e);
        tbPos.Text = (_wBMP.PixelWidth / zoomLevel).ToString() + "," + (_wBMP.PixelHeight / zoomLevel).ToString() + " | " + Math.Ceiling((((Point)e.GetPosition(this)).X) / zoomLevel).ToString() + "," + Math.Ceiling((((Point)e.GetPosition(this)).Y / zoomLevel)).ToString();

        if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
        {
            Point pos = e.GetPosition(this);

            int xPos = (int)Math.Ceiling((pos.X) / zoomLevel);
            int yPos = (int)Math.Ceiling((pos.Y) / zoomLevel);

            int xDraw = (int)Math.Ceiling(pos.X);
            int yDraw = (int)Math.Ceiling(pos.Y);
            array[xPos, yPos] = 1;
            drawing = true;

            SetPixelsFromArray((int)zoomLevel);
            //for (int i = 0; i < zoomLevel; i++)
            //{
            //    for (int j = 0; j < zoomLevel; j++)
            //    {
            //        _wBMP.setPixel(xDraw, yDraw, cellColor);
            //        _dispImg.Source = _wBMP;

            //    }
            //}
            //_wBMP.setPixel(xPos, yPos, cellColor);
            //_wBMP.setPixel((int)pos.X, (int)pos.Y, cellColor);
            //_dispImg.Source = _wBMP;


        }
    }

    private void SetPixelsFromArray(int ZoomLevel)
    {

        for (int i = 1; i < _wBMP.PixelWidth / ZoomLevel; i++)
        {
            for (int j = 1; j < _wBMP.PixelHeight / ZoomLevel; j++)
            {
                if (array[i, j] == 1)
                {
                    for (int k = 0; k < ZoomLevel; k++)
                    {
                        for (int l = 0; l < ZoomLevel; l++)
                        {
                            _wBMP.setPixel((int)(i * ZoomLevel + k), (int)(j * ZoomLevel + l), cellColor);
                            _dispImg.Source = _wBMP;
                        }
                    }
                }
            }
        }
    }

    protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
    {

        //double d= this.ActualHeight;

        //Double t =(double) this.GetValue(Canvas.TopProperty);
        //double i = Convert.ToDouble(top);

        getScreenRect();
        if (e.ChangedButton == System.Windows.Input.MouseButton.Right)
        {
            if (cellColor == Colors.Black)
            {
                cellColor = Colors.Red;
            }
            else
            {
                cellColor = Colors.Black;
            }
        }
        else if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
        {
            Point pos = e.GetPosition(this);
            int xPos = (int)Math.Ceiling((pos.X) / zoomLevel);
            int yPos = (int)Math.Ceiling((pos.Y) / zoomLevel);
            array[xPos, yPos] = 1;
            drawing = true;
            SetPixelsFromArray((int)zoomLevel);
            //_wBMP.setPixel((int)pos.X, (int)pos.Y, cellColor);
            //_dispImg.Source = _wBMP;


        }
    }

  private void getScreenRect()
  {
         Visual _rootVisual = HwndSource.FromVisual(this).RootVisual;


        GeneralTransform transformToRoot = this.TransformToAncestor(_rootVisual);

        Rect screenRect = new Rect(transformToRoot.Transform(new Point(0, 0)), transformToRoot.Transform(new Point(this.ActualWidth, this.ActualHeight)));

        DependencyObject parent = VisualTreeHelper.GetParent(this);

        while (parent != null)
        {

            Visual visual = parent as Visual;

            System.Windows.Controls.Control control = parent as System.Windows.Controls.Control;

            if (visual != null && control != null)
            {

                transformToRoot = visual.TransformToAncestor(_rootVisual);

                Point pointAncestorTopLeft = transformToRoot.Transform(new Point(0, 0));

                Point pointAncestorBottomRight = transformToRoot.Transform(new Point(control.ActualWidth, control.ActualHeight));

                Rect ancestorRect = new Rect(pointAncestorTopLeft, pointAncestorBottomRight);

                screenRect.Intersect(ancestorRect);

            }

            parent = VisualTreeHelper.GetParent(parent);

       //}

       // at this point screenRect is the bounding rectangle for the visible portion of "this" element
   }
   // return screenRect;


}
    protected override void OnMouseWheel(System.Windows.Input.MouseWheelEventArgs e)
    {

        base.OnMouseWheel(e);
        if (e.Delta > 0)
        {
            zoomLevel *= 2;
        }
        else
        {
            zoomLevel /= 2;
        }
        if (zoomLevel > 8)
        {
            zoomLevel = 8;
        }
        if (zoomLevel <= 1)
        {
            zoomLevel = 1;
            // brdGrid.Visibility = Visibility.Collapsed;
        }
        else
        {
            //brdGrid.Visibility = Visibility.Visible;
        }
        _wBMP = new WriteableBitmap((int)zoomLevel * canvasWidth, (int)zoomLevel * canvasHeight, 96, 96, PixelFormats.Bgr32, BitmapPalettes.WebPalette);
        _wBMP.setPixel(Colors.White);
        this.Width = zoomLevel * canvasWidth;
        this.Height = zoomLevel * canvasHeight;
        if (drawing == true)
        {
            SetPixelsFromArray((int)zoomLevel);
        }

        //this.InvalidateVisual();
    }

    internal bool SaveAsBMP(string fileName)
    {
        return true;
    }

}






    public static class bitmapextensions
    {
        public static void setPixel(this WriteableBitmap wbm, Color c)
        {

            if (!wbm.Format.Equals(PixelFormats.Bgr32))
                return;

            wbm.Lock();

            IntPtr buff = wbm.BackBuffer;
            int Stride = wbm.BackBufferStride;
            int x = 0;
            int y = 0;
            for (x = 0; x < wbm.PixelWidth; x++)
            {
                for (y = 0; y < wbm.PixelHeight; y++)
                {
                    unsafe
                    {

                        byte* pbuff = (byte*)buff.ToPointer();
                        int loc = y * Stride + x * 4;
                        pbuff[loc] = c.B;
                        pbuff[loc + 1] = c.G;
                        pbuff[loc + 2] = c.R;
                        //pbuff[loc + 3] = c.A;

                    }
                }
            }
            wbm.AddDirtyRect(new Int32Rect(0, 0, x, y));
            wbm.Unlock();
        }

        public static void setPixel(this WriteableBitmap wbm, int x, int y, Color c)
        {

            if (y > wbm.PixelHeight - 1 || x > wbm.PixelWidth - 1)
                return;

            if (y < 0 || x < 0)
                return;

            if (!wbm.Format.Equals(PixelFormats.Bgr32))
                return;

            wbm.Lock();

            IntPtr buff = wbm.BackBuffer;
            int Stride = wbm.BackBufferStride;

            unsafe
            {

                byte* pbuff = (byte*)buff.ToPointer();
                int loc = y * Stride + x * 4;
                pbuff[loc] = c.B;
                pbuff[loc + 1] = c.G;
                pbuff[loc + 2] = c.R;
                //pbuff[loc + 3] = c.A;

            }

            wbm.AddDirtyRect(new Int32Rect(x, y, 1, 1));
            wbm.Unlock();
        }

        public static Color getPixel(this WriteableBitmap wbm, int x, int y)
        {
            if (y > wbm.PixelHeight - 1 || x > wbm.PixelWidth - 1)
                return Color.FromArgb(0, 0, 0, 0);

            if (y < 0 || x < 0)
                return Color.FromArgb(0, 0, 0, 0);

            if (!wbm.Format.Equals(PixelFormats.Bgr32))
                return Color.FromArgb(0, 0, 0, 0);

            IntPtr buff = wbm.BackBuffer;
            int Stride = wbm.BackBufferStride;
            Color c;
            unsafe
            {
                byte* pbuff = (byte*)buff.ToPointer();
                int loc = y * Stride + x * 4;
                c = Color.FromArgb(pbuff[loc + 3], pbuff[loc + 2], pbuff[loc + 1], pbuff[loc]);
            }
            return c;
        }
    }
}


You should implement IScrollInfo on your canvas (or actually, create a custom Panel that inherits from Canvas and implements IScrollInfo).

That interface holds all that is relevant to your situation:

http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.iscrollinfo.aspx http://blogs.msdn.com/b/jgoldb/archive/2008/03/08/performant-virtualized-wpf-canvas.aspx

0

精彩评论

暂无评论...
验证码 换一张
取 消