《WPF程序设计指南》读书笔记——第7章 Canvas

1.Canvas面板

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Shapes;

namespace LY.PaintTheButton
{
    public class PaintTheButton:Window
    {
        [STAThread]
        public static void Main()
        {
            new Application().Run(new PaintTheButton());
        }
        public PaintTheButton()
        {
            Title = "Paint The Button";
            Button btn = new Button();
            btn.HorizontalAlignment = HorizontalAlignment.Center;
            btn.VerticalAlignment = VerticalAlignment.Center;
            Content = btn;

            Canvas canv = new Canvas();
            canv.Width = 144;
            canv.Height = 144;
            btn.Content = canv;
            
            Rectangle rect = new Rectangle();
            rect.Width = canv.Width;
            rect.Height = canv.Height;
            //使矩形的角变圆
            rect.RadiusX = 24;
            rect.RadiusY = 24;
            rect.Fill = Brushes.Blue;
            canv.Children.Add(rect);
            //根据坐标位置放置控件
            Canvas.SetLeft(rect, 0);
            Canvas.SetTop(rect, 0);

            Polygon poly = new Polygon();
            poly.Fill = Brushes.Yellow;
            //颜色填充规则
            poly.FillRule = FillRule.Nonzero;
            //poly.Points=new PointCollection();
            for (int i = 0; i < 5; i++)
            {
                double angle = i * 4 * Math.PI / 5;
                Point pt = new Point(48 * Math.Sin(angle), -48 * Math.Cos(angle));
                poly.Points.Add(pt);
            }
            canv.Children.Add(poly);
            Canvas.SetLeft(poly, canv.Width / 2);
            Canvas.SetTop(poly, canv.Height / 2);
        }
    }
}

  Canvas面板是根据坐标放置控件。

2.UniformGrid面板

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace LY.Puzzle
{
    public class PlayPuzzle : Window
    {
        int xEmpty, yEmpty, iCounter;
        UniformGrid unigrid;
        Random rand;
        [STAThread]
        public static void Main()
        {
            new Application().Run(new PlayPuzzle());
        }
        public PlayPuzzle()
        {
            Title = "LY的小游戏";
            SizeToContent = SizeToContent.WidthAndHeight;
            ResizeMode = ResizeMode.CanMinimize;
            Background = SystemColors.ControlBrush;

            //加入一个Stack面板
            StackPanel stack = new StackPanel();
            Content = stack;

            //加入按钮
            Button btn = new Button();
            btn.Content = "打乱(_S)";
            btn.HorizontalAlignment = HorizontalAlignment.Center;
            btn.Margin = new Thickness(10);
            btn.Click += btn_Click;
            stack.Children.Add(btn);

            //加入边框
            Border bord = new Border();
            bord.BorderThickness = new Thickness(1);
            bord.BorderBrush = SystemColors.ControlDarkDarkBrush;
            stack.Children.Add(bord);

            //加入UniformGrid面板
            unigrid = new UniformGrid();
            unigrid.Rows = 4;
            unigrid.Columns = 4;
            bord.Child = unigrid;

            for (int i = 0; i < 15; i++)
            {
                Tile tile = new Tile();
                tile.Text = (i + 1).ToString();
                tile.MouseDown += tile_MouseDown;
                unigrid.Children.Add(tile);
            }
            unigrid.Children.Add(new Empty());
            xEmpty = 3;
            yEmpty = 3;
        }

        private void btn_Click(object sender, RoutedEventArgs e)
        {
            rand = new Random();
            iCounter = 16 * 4 * 4;
            DispatcherTimer tim = new DispatcherTimer();
            tim.Interval = TimeSpan.FromMilliseconds(10);
            tim.Tick += tim_Tick;
            tim.Start();
        }

        void tim_Tick(object sender, EventArgs e)
        {
            for (int i = 0; i < 5; i++)
            {
                MoveTile(xEmpty, yEmpty + rand.Next(3) - 1);
                MoveTile(xEmpty + rand.Next(3) - 1, yEmpty);
            }
            iCounter--;
            if (iCounter == 0)
                (sender as DispatcherTimer).Stop();

        }

        private void tile_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Tile tile = sender as Tile;
            int yTile = unigrid.Children.IndexOf(tile) / 4;
            int xTile = unigrid.Children.IndexOf(tile) % 4;
            //可以一次移动多个tile,所以用while循环
            if (xTile == xEmpty)
                while (yTile != yEmpty)
                    MoveTile(xTile, yEmpty + (yTile - yEmpty) / Math.Abs(yTile - yEmpty));
            if (yTile == yEmpty)
                while (xTile != xEmpty)
                    MoveTile(xEmpty + (xTile - xEmpty) / Math.Abs(xTile - xEmpty), yTile);
        }

        private void MoveTile(int xTile, int yTile)
        {
            //为tim_Tick事件剔除无用值
            if ((xTile == xEmpty && yTile == yEmpty) || xTile < 0 ||
                xTile > 3 || yTile < 0 || yTile > 3) return;
            int iTile = yTile * 4 + xTile;
            int iEmpty = yEmpty * 4 + xEmpty;

            UIElement elTile = unigrid.Children[iTile];
            UIElement elEmpty = unigrid.Children[iEmpty];
            unigrid.Children.Remove(elTile);
            unigrid.Children.Insert(iEmpty, elTile);
            unigrid.Children.Remove(elEmpty);
            unigrid.Children.Insert(iTile, elEmpty);
            xEmpty = xTile;
            yEmpty = yTile;
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            switch (e.Key)
            {
                case Key.Right: MoveTile(xEmpty - 1, yEmpty); break;
                case Key.Left: MoveTile(xEmpty + 1, yEmpty); break;
                case Key.Down: MoveTile(xEmpty, yEmpty - 1); break;
                case Key.Up: MoveTile(xEmpty, yEmpty + 1); break;
            }
        }

    }
}

  

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace LY.Puzzle
{
    public class Tile : Canvas
    {
        const int Bord = 6;
        const int Size = 64;
        TextBlock txtblk;

        public Tile()
        {
            Width = Size;
            Height = Size;

            //左上多边形
            Polygon poly = new Polygon();
            poly.Points = new PointCollection(new Point[]{
                new Point(0,0),new Point(Size,0),new Point(Size-Bord,Bord),
                new Point(Bord,Bord),new Point(Bord,Size-Bord),
                new Point(0,Size)});
            poly.Fill = SystemColors.ControlLightLightBrush;
            Children.Add(poly);
            //poly本身带着坐标信息,因此不用再设定在面板中的位置
            //Canvas.SetLeft(poly, 0);
            //Canvas.SetTop(poly, 0);

            //右下多边形
            poly = new Polygon();
            poly.Points = new PointCollection(new Point[]{
                new Point(Size,Size),new Point(0,Size),new Point(Bord,Size-Bord),
                new Point(Size-Bord,Size-Bord),new Point(Size-Bord,Bord),
                new Point(Size,0)});
            poly.Fill = SystemColors.ControlDarkBrush;
            Children.Add(poly);
            //很多图形对象本身带着坐标信息
            //Canvas.SetRight(poly, 0);
            //Canvas.SetBottom(poly, 0);

            //在元素周围绘制边框或背景
            Border border = new Border();
            border.Width = Size - 2 * Bord;
            border.Height = Size - 2 * Bord;
            //border.BorderThickness = new Thickness(6);
            border.Background = SystemColors.ControlBrush;
            Children.Add(border);
            //这里以下两种方式都可以
            SetLeft(border, Bord);
            Canvas.SetTop(border, Bord);

            //中间放上TextBlock控件
            txtblk = new TextBlock();
            txtblk.FontSize = 32d;
            txtblk.Foreground = SystemColors.ControlTextBrush;
            txtblk.HorizontalAlignment = HorizontalAlignment.Center;
            txtblk.VerticalAlignment = VerticalAlignment.Center;
            border.Child = txtblk;
        }
        public string Text
        {
            get { return txtblk.Text; }
            set { txtblk.Text = value; }
        }
    }

    //空白格子类
    class Empty : FrameworkElement
    { 
    }
}

  UniformGrid面板类似于Grid面板,但它是固定行列大小的,用Rows、Columns直接指定行数和列数即可。

posted @ 2013-08-26 19:24  小p  阅读(408)  评论(0编辑  收藏  举报