Volunteer .NET Evangelist

A well oiled machine can’t run efficiently, if you grease it with water.
  首页  :: 联系 :: 订阅 订阅  :: 管理

AvalonPaint, My First WPF Application

Posted on 2006-01-27 21:31  Sheva  阅读(2307)  评论(2编辑  收藏  举报
    After playing for a while with the January CTP release of Windows Presentation Foundation, formerly known as Avalon, I write a simple application with which you can draw the lines continuously using mouse, the  XAML code and corresponding C# code dealing with the interactive logic is listed as follows:
DrawingWindow.xaml:
<Window x:Class="AvalonPaint.DrawingWindow"
    xmlns
="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns:x
="http://schemas.microsoft.com/winfx/xaml/2005"
    Title
="AvalonPaint"
    Loaded
="DrawingWindow_Loaded" Height="400" Width="600">
  
<Window.Resources>
    
<DrawingBrush x:Key="backgroundResource"
                              Viewport
="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      
<DrawingBrush.Drawing>
        
<DrawingGroup>
          
<DrawingGroup.Children>
            
<GeometryDrawing Brush="White">
              
<GeometryDrawing.Geometry>
                
<RectangleGeometry Rect="0,0,1,1" />
              
</GeometryDrawing.Geometry>
            
</GeometryDrawing>
            
<GeometryDrawing Brush="#AAE6E8F6"
              Geometry
="M 0,0 L 0,1 0.1,1 0.1,0.1 1,0.1 1,0 Z" />
          
</DrawingGroup.Children>
        
</DrawingGroup>
      
</DrawingBrush.Drawing>
    
</DrawingBrush>
  
</Window.Resources>
    
<Grid>
      
<Grid.ColumnDefinitions>
        
<ColumnDefinition />
      
</Grid.ColumnDefinitions>
      
<Grid.RowDefinitions>
        
<RowDefinition />
      
</Grid.RowDefinitions>
      
<Canvas Name="drawingBoard" Grid.Column="0" Grid.Row="0" Background="{StaticResource backgroundResource}"/>
      
<StackPanel Name="capturePanel" Background="Transparent"/>
    
</Grid>
</Window>

DrawingWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;


namespace AvalonPaint
{
    
/// <summary>
    
/// Interaction logic for DrawingWindow.xaml
    
/// </summary>

    
public partial class DrawingWindow : Window
    {
        
private Boolean isDrawing = false;
        
private Point startPoint;
        
public DrawingWindow()
        {
            InitializeComponent();
        }

        
private void DrawingWindow_Loaded(Object sender, RoutedEventArgs e)
        {
            capturePanel.MouseDown 
+= capturePanel_MouseDown;
            capturePanel.MouseMove 
+= capturePanel_MouseMove;
            capturePanel.MouseUp 
+= capturePanel_MouseUp;
        }

        
private void capturePanel_MouseDown(Object sender, MouseEventArgs e)
        {
            isDrawing 
= true;
            startPoint 
= e.GetPosition(this);
        }

        
private void capturePanel_MouseMove(Object sender, MouseEventArgs e)
        {
            
if (isDrawing && e.LeftButton == MouseButtonState.Pressed)
            {
                Point endPoint 
= e.GetPosition(this);
                DrawLine(startPoint, endPoint, drawingBoard);
                startPoint 
= endPoint;
            }
        }

        
private void capturePanel_MouseUp(Object sender, MouseEventArgs e)
        {
            startPoint 
= e.GetPosition(this);

            
//Disable mouse capture for the current Window element.
            Mouse.Capture(this, CaptureMode.None);
            isDrawing 
= false;
        }

        
// Private helper method responsible for drawing lines in the surface of Canvas element.
        private void DrawLine(Point from, Point to, Canvas targetCanvas)
        {
            Line line 
= new Line();
            line.StrokeEndLineCap 
= PenLineCap.Round;
            line.StrokeStartLineCap 
= PenLineCap.Round;
            line.Stroke 
= Brushes.Red;
            line.StrokeThickness 
= 3.0;
            line.X1 
= from.X;
            line.Y1 
= from.Y;
            line.X2 
= to.X;
            line.Y2 
= to.Y;
            Canvas.SetLeft(targetCanvas,
from.X);
            Canvas.SetTop(targetCanvas,
from.Y);
            targetCanvas.Children.Add(line);
        }
    }
}

    One caveat here is that it seems the Canvas element cannot capture any mouse event, for instance MouseDown, MouseUp and MouseMove events, after digging into this problem for a while, I find a workaround by overlapping a transparent StackPanel element named capturePanel on top of the Canvas  element, and hook up mouse event handlers with this capturePanel's corresponding mouse events, I can actually capture the mouse events for the Canvas element, and then draw the line in it.
    It's simple but quite interesting, please enjoy it!