Click here to Skip to main content
Licence GPL3
First Posted 19 Jun 2011
Views 5,288
Downloads 613
Bookmarked 5 times

A Graphics Drawing Tool by using WPF

By | 23 Jun 2011 | Article
Graphics Drawing Tool by WPF

Introduction

This is an article about WPF and its drawing tool.

The code structure is similar as that of my other article at code project, the link is at:

WinForm Versions of GraphicsDrawingTool.aspx

Background

To understand this article, you need to understand a few WPF technologies. Concept such as DrawingContext, FrameworkElement class, and their usages, and of course how to write XAML GUI stuff.

Using the code

This project first create a tool box, like following:

wpf2.jpg

Then user can draw their selected shape on screen, like following:

wpf1.jpg

The drawing then can be exported as xml file or jpg file.

<?xml version="1.0" encoding="utf-8"?>
<ShapeList xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>">
  <ShapeList>
    <LeShape xsi:type="LeRectangle">
      <ShowBorder>true</ShowBorder>
      <LeBorderColor>
        <A>255</A>
        <R>0</R>
        <G>0</G>
        <B>0</B>
      </LeBorderColor>
      <BorderWidth>1</BorderWidth>
      <Rect>
        <X>300</X>
        <Y>157</Y>
        <Width>79</Width>
        <Height>65</Height>
      </Rect>
      <LeFromColor>
        <A>30</A>
        <R>255</R>
        <G>0</G>
        <B>0</B>
      </LeFromColor>
      <LeToColor>
        <A>30</A>
        <R>255</R>
        <G>255</G>
        <B>255</B>
      </LeToColor>
      <LightAngle>225</LightAngle>
      <Fill>true</Fill>
    </LeShape>
    <LeShape xsi:type="RoundRectShape">
      <ShowBorder>true</ShowBorder>
      <LeBorderColor>
        <A>255</A>
        <R>0</R>
        <G>0</G>
        <B>0</B>
      </LeBorderColor>
      <BorderWidth>1</BorderWidth>
      <Rect>
        <X>174</X>
        <Y>230</Y>
        <Width>84</Width>
        <Height>74</Height>
      </Rect>
      <LeFromColor>
        <A>255</A>
        <R>0</R>
        <G>0</G>
        <B>0</B>
      </LeFromColor>
      <LeToColor>
        <A>255</A>
        <R>127</R>
        <G>255</G>
        <B>212</B>
      </LeToColor>
      <LightAngle>225</LightAngle>
      <Fill>true</Fill>
      <Radius>10</Radius>
    </LeShape>
    <LeShape xsi:type="ZoneShape">
      <ShowBorder>true</ShowBorder>
      <LeBorderColor>
        <A>255</A>
        <R>0</R>
        <G>0</G>
        <B>0</B>
      </LeBorderColor>
      <BorderWidth>1</BorderWidth>
      <Rect>
        <X>132</X>
        <Y>97</Y>
        <Width>90</Width>
        <Height>84</Height>
      </Rect>
      <LeFromColor>
        <A>30</A>
        <R>255</R>
        <G>0</G>
        <B>0</B>
      </LeFromColor>
      <LeToColor>
        <A>30</A>
        <R>255</R>
        <G>255</G>
        <B>255</B>
      </LeToColor>
      <LightAngle>225</LightAngle>
      <Fill>true</Fill>
      <TextField>
        <ShowBorder>true</ShowBorder>
        <LeBorderColor>
          <A>255</A>
          <R>0</R>
          <G>0</G>
          <B>0</B>
        </LeBorderColor>
        <BorderWidth>1</BorderWidth>
        <Rect>
          <X>237</X>
          <Y>112</Y>
          <Width>58</Width>
          <Height>22</Height>
        </Rect>
        <LeFromColor>
          <A>30</A>
          <R>255</R>
          <G>0</G>
          <B>0</B>
        </LeFromColor>
        <LeToColor>
          <A>30</A>
          <R>255</R>
          <G>255</G>
          <B>255</B>
        </LeToColor>
        <LightAngle>225</LightAngle>
        <Fill>true</Fill>
        <Caption>Shape 2</Caption>
        <LeTextFont>
          <Size>10</Size>
          <Name>Tahoma</Name>
          <Style>Regular</Style>
        </LeTextFont>
        <LeTextColor>
          <A>255</A>
          <R>255</R>
          <G>0</G>
          <B>0</B>
        </LeTextColor>
        <TextSize>10</TextSize>
      </TextField>
      <Caption>Shape 2</Caption>
    </LeShape>
  </ShapeList>
</ShapeList>

This xml file then can be reopened later by this project, end user can edit their drawings again.

Following is the explaination of this project's source code.

The project first create a canvas on GUI by using following lines:

<Border Margin="10" CornerRadius="3" Grid.Row="1" Grid.Column="1" Background="Beige">
   <Border.BitmapEffect>
      <DropShadowBitmapEffect />
   </Border.BitmapEffect>
   <Canvas Margin="3" x:Name="DrawingCanvas" Background="AliceBlue" Opacity="1" Visibility="Visible">
   <local:CustomRender Canvas.Top="0" Canvas.Left="0" x:Name="shapeCollection">
    <local:CustomRender.BitmapEffect>
      <DropShadowBitmapEffect />
    </local:CustomRender.BitmapEffect>
   </local:CustomRender>
   </Canvas>
</Border>
         

The code above first create a Border, with a drop shadow, Border was inside a Grid control, so it will fill the grid's cell. Then what's inside of this border, it's a canvas control, what's inside this Canvas is just one framework element, our DLL (CustomRender), it is just one element, then we use this element's DrawingContext, draw all our shapes manually. The DrawingContext is like WinForm's Graphics object.

Our customrender is just a framework element, it only accept visuals objects. Most importantly it implemented following 2 functions:

// Provide a required override for the VisualChildrenCount property.
        protected override int VisualChildrenCount
        {
            get { return childrens.Count; }
        }
       // Provide a required override for the GetVisualChild method.
        protected override Visual GetVisualChild(int index)
        {
            if (index < 0 || index >= childrens.Count)
            {
                throw new ArgumentOutOfRangeException();
            }
            return childrens[index];
        }  

Then at our code, we only need to add visual object to this collections of visual object, .netframework will render this CustomRender object for us.

We used reflection to add shape to our controller class, first only create a shape, then add shape's visual object to above CustomRender class.

  Point pt = e.GetPosition(myCanvas);

  ConstructorInfo constructor = myTool.GetConstructor(new Type[] { typeof(Point) });
  CurShape = constructor.Invoke(new object[] { pt }) as LeShape;


  shapeCollection.AddObject(CurShape.myVisual);

When we want to draw this Shape, we can call following method at anytime:

  DrawingContext dc = myVisual.RenderOpen();
  Draw(dc);

  if (selected)
  {
     if (bounds.Width > 5 && bounds.Height >5)
     {
         DrawPoints(dc, bounds);
     }
  }
  dc.Close();

RenderOpen method of DrawingVisual will open a DrawingContext for us, then we can Draw our object, if shape is selected, then I draw several track points for it. After all these, we have to call DrawingContext Close method, this to tell we have finished drawing of this visual.

This the principles of WPF version of my drawing tool, if you are intertested you can get more information on my WinForms version of this drawing tool as well.


Points of Interest

Did you learn anything interesting/fun/annoying while writing the code? Did you do anything particularly clever or wild or zany?

History

Keep a running update of any changes or improvements you've made here.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

Lewis Liu (yyiu002)

Software Developer (Senior)

Australia Australia

Member

Senior Software programmer, familiar with C, C++, C#, Java, Delphi, VB, PHP, JavaScript and Java.
 
Familiar with WinForms and WPF, ASP.NET, CSS, jQuery, QT, AJax.
Familiar with Linux Message queue, Linux kernel module, TCP/IP stack, FAT, etc.

http://www.findastuff.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questionhow can I rotate a shape Pinmemberferfr18:42 14 Nov '11  
AnswerRe: how can I rotate a shape PinmemberLewis Liu (yyiu002)22:11 14 Nov '11  
QuestionDali would be proud PinmvpSacha Barber22:15 23 Jun '11  
GeneralMy vote of 1 PinmemberPhil J Pearson3:21 21 Jun '11  
QuestionCan you please include a screenshot? PingroupAmarnath S2:08 20 Jun '11  
QuestionThis is not an article! PinmemberPerry Bruins18:51 19 Jun '11  
AnswerRe: This is not an article! PinmemberLewis Liu (yyiu002)23:03 19 Jun '11  
GeneralRe: This is not an article! PinmemberSlacker0070:16 20 Jun '11  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 23 Jun 2011
Article Copyright 2011 by Lewis Liu (yyiu002)
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid