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

时间:2022-05-13 16:34:35

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直接指定行数和列数即可。