Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

[tut 8] Hand tool

0.00/5 (No votes)
29 Jun 2016 1  
we would create Hand_tool to pan through the drawing form, and we would use a custom cursor of open and closed hands

Introduction

This is the Eighth tutorial of a series of tutorials of how to build a graphics program using C# inWindows form that exports the artwork in a vector format.

.... also, you would understand how to move, delete, ctrl z your vector art and save it in a special format to be read by your program again.

Also, we will learn how to save XML files... how to export in verilog format... how to use a star algorithm... how to use hand tool... how to manually create the ctrl z technique.

What you will be capable of building:

Map of tut

  1. edit super_form to add Hand tool icon, add new action for this new tool, create a function for clicking this new tool, and use a new custom cursor for this new tool, 
  2. in Form1 ,define a bigger size than th actual Form size visible to the user ,called AutoScrollMinSize.
  3. in Form1 ,edit Form1_MouseMove and add a new section for the new tool, this would be the core of the tool.
  4. in Form1 ,create a Form1_MouseDown , to complete the functionality of the tool.
  5. in Form1 ,edit OnPaint to create an offset for the drawn shapes
  6. change the cursor when the user clicks down the mouse when choosing the hand_tool, this would be made by a connection between Form1 and super_form.
  7. in Form1. when releasing the mouse after panning , reset the mouse to be open hand 
  8. in Form1 ,edit all previous sections that we have discussed before in the previous tuts to work well with the the new tool.
  9. enable a shortcut (space bar) to use the new hand tool. 
  10. in Form1 ,work with OnPaint to view the circle around points ,and outline of the lines when panning th form

 


Background


 

Update

added two sections :

       9-enable a shortcut (space bar) to use the new hand tool. 

     10-in Form1 ,work with OnPaint to view the circle around points ,and outline of the lines when panning th                form

and updated the images of the explanation of the importance of using offset for selecting and moving lines and objects because of an error found in the previous images but now is fixed.

 

 


1-edit super_form to add Hand tool icon, add new action for this new tool, create a function for clicking this new tool, and use a new custom cursor for this new tool.

work with the super_form[desgin] , add a button.

set the icon of the button to this image

just change the name to Hand_tool

so the result would be

now we would work with the super_form.cs

begin with editing the action enum to have a new action 

public enum action
   {
       star, heart, line, move,point,hand, none
   }

then we would add a click function for the new button for the new Hand tool.

private void Hand_tool_Click(object sender, EventArgs e)
{
    super_action = action.hand;
    toolStrip2.Visible = false;//make the toolbar of the line proprieties invisible when
                               //clicking this tool
}

now we need to add a new custom cursor for the Hand_tool

so add this icon as a resource like discussed before in this tut 

open_hand.zip

and then edit the previously written function of Hand_tool_Click to be 

        private void Hand_tool_Click(object sender, EventArgs e)
        {
            super_action = action.hand;

//new code
            cursor_super = new Cursor(drag_and_drop_and_delete.Properties.Resources.open_hand.Handle);
            this.Cursor = cursor_super;
//new code 

            toolStrip2.Visible = false;
        }

 


2-in Form1 ,define a bigger size than th actual Form size visible to the user ,called AutoScrollMinSize.

  public Form1()
        {
            InitializeComponent();


            this.Size = new Size(1000, 700);

//new code
            this.AutoScrollMinSize = new Size(2000, 1000);
             // you must define an AutoScrollMinSize with a size bigger than that of the size of the
             // Form, as it tells the actual size of the form , but not all of this space is really
             // visible to the user at once, as the size(1000, 700) is the actual size visible to the
             // user without need to use the hand tool, but the AutoScrollMinSize is the actual size
             // the user can draw but with use of the hand tool
//new code
                  


            this.DoubleBuffered = true;
            Invalidate();
        }

 


3-in Form1 , edit Form1_MouseMove and add a new section for the new tool, this would be the core of the tool.

we would work with Form1, to work on the functionality itself of the hand tool, but first we would need to define some variables

public Point prevScrollPoint;
public int pointX, pointY;
public int offsetX, offsetY;

then lets work with Form1_MouseMove 

add a new condition 

private void Form1_MouseMove(object sender, MouseEventArgs e)
     {

              .

              .//old code

              .

         //new code
         else if (super_form.super_action.Equals(action.hand) )
         {
             if (e.Button == MouseButtons.Left)
             //only occurs when this user clicks the left mouse click
             {
             }

         }
         //new code

    }

then inside this condition you would use the previously written variables

   private void Form1_MouseMove(object sender, MouseEventArgs e)
        {

                 .

                 .//old code

                 .

            else if (super_form.super_action.Equals(action.hand) )
            {
                if (e.Button == MouseButtons.Left)
                {
                    //new code
                    offsetX = e.X - prevScrollPoint.X;
                    offsetY = e.Y - prevScrollPoint.Y;

                    pointX = -(this.AutoScrollPosition.X);
                    pointY = -(this.AutoScrollPosition.Y);

                    pointX += -offsetX;
                    pointY += -offsetY;

                    this.AutoScrollPosition = new Point(pointX, pointY);

                    prevScrollPoint = e.Location;

                    Invalidate();
                    //new code
                }

            }

       }

 


4-in Form1 ,create a Form1_MouseDown , to complete the functionality of the tool.

the functionality of the hand tool is not yet completed , you must create a MouseDown function

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && super_form.super_action.Equals(action.hand))
    {
        prevScrollPoint = e.Location;
    }
}

 


5-in Form1 ,edit OnPaint to create an offset for the drawn shapes

we must edit OnPaint to really transform objects with the value of the AutoScrollPosition as an offset.

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            //new code

            g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);

            //new code

        .

        .//old code

        .

      }

 

 


6-change the cursor when the user clicks down the mouse when choosing the hand_tool, this would be made by a connection between Form1 and super_form.

.

we would need to change the cursor to be closed hand when the mouse is clicked

to do this we must change the cursor inside the super_form , but the cursor of the super_form is not static variable, so you must pass the super_form to all Form1 elements, this would be very costing memory wise, so there is another way i use 

which is using a static button inside the super_form , and assigning a click function to this button, this click function would simply change te cursor of the super_form to be the same as the static super_cursor

we will work within the super_form 

from the previous tuts we would have 

public static Cursor cursor_super;

and today we would create a static button

        public  static Button change_cursor_static_button;

in the constructor of the super_form 

public super_form()
      {
          InitializeComponent();

        .

        .//old code


        .

          //new code
          change_cursor_static_button = new Button();
          change_cursor_static_button.Click += change_cursor_static_button_function;
                                          // assign a function to this button
          //new code


      }

then this function would simply be , just assigning the cursor_super to the cursor of the super_form 

private void change_cursor_static_button_function(object sender, EventArgs e)
{
    this.Cursor = cursor_super;
}

then now we would work with Form1

we would edit the function of Form1_MouseDown

we would add a new cursor of the closed hand

closed_hand.zip

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && super_form.super_action.Equals(action.hand))
    {
        prevScrollPoint = e.Location;

        Cursor new_cursor
        = new Cursor(drag_and_drop_and_delete.Properties.Resources.closed_hand.Handle);

        super_form.cursor_super = new_cursor;
         //load this new cursor to the cursor_super of the super_cursor

        super_form.change_cursor_static_button.PerformClick();
    }
}

 


7-in Form1. when releasing the mouse after panning , reset the mouse to be open hand 

simply in Form1 we would create a mouseUp function

we would use the cursor of the open_hand 

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    if (super_form.super_action.Equals(action.hand))
    {
        Cursor new_cursor =
        new Cursor(drag_and_drop_and_delete.Properties.Resources.open_hand.Handle);

        super_form.cursor_super = new_cursor;
        super_form.change_cursor_static_button.PerformClick();
    }
 }

 

 


 

Now the functionality of the hand tool is done, But we must make the old code of the old tuts work well with this new tool

8-in Form1 ,edit all previous sections that we have discussed before in the previous tuts to work well with the the new tool.

 

 

so there must be an offset for for

  1. moving and selecting points inside the lines,
  2. and the concept would work with clicking the line as a whole,
  3. and also with moving and selecting objects
  4. and drawing objects (star, heart)
  5. and drawing lines

1-clicking points inside the lines

work with Form1_MouseMove 

  private void Form1_MouseMove(object sender, MouseEventArgs e)
        {

               .

               .//old code

               .

            else if (super_form.super_action.Equals(action.point))
            {

                   if (e.Button == m)
                   {
//new code

                    Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X,
                                                  e.Y - 10 - AutoScrollPosition.Y);
//new code

                       .

                       .//old code
  
                       .

                   }

               .

               .//old code

               .

          }

}

and selecting point in the line

work with Form1_MouseClick 

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {

          .

          .//old code

          .

            else if (super_form.super_action.Equals(action.point))
            {

                if (e.Button == m)
                {

                    Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X,
                                                  e.Y - 10 - AutoScrollPosition.Y);

          .

          .//old code

          .

               }

          .

          .//old code

          .

            }

          .

          .//old code

          .

}

2- clicking the line as a whole,

&

3-moving and selecting objects

work with Form1_MouseMove 

 private void Form1_MouseMove(object sender, MouseEventArgs e)
        {

 if (super_form.super_action.Equals(action.move))
            {
                //new code
                Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X, 
                                              e.Y - 10 - AutoScrollPosition.Y);
                //new code

                    .

                    .//old code

                    .
                if (is_selected && e.Button == m)
                {
                    selected_recatngle.Location = e.Location;
                    if (selected_type.Equals("shape"))
                    {
                        shape_list.ElementAt<shapes>(selected).translateX = e.X- AutoScrollPosition.X;
                        shape_list.ElementAt<shapes>(selected).translateY = e.Y- AutoScrollPosition.Y;
                    }
                }


            }

}

and for selecting objects we would work with Form1_MouseClick

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {

               .

               .//old code

               .
            else if (super_form.super_action.Equals(action.move))
            {

               .

               .//old code

               .

                //new hand
                Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X, 
                                              e.Y - 10 - AutoScrollPosition.Y);
                //new hand

               .

               .//old code

               .

           }

               .

               .//old code

               .

}

4-drawing objects (star, heart)

work with Form1_MouseClick 

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        { 
            if (super_form.super_action.Equals(action.star))
            {
                shapes sh = new shapes();
                star st = new star();
                sh = st;

                //new code
                sh.translateX = e.X- AutoScrollPosition.X;
                sh.translateY = e.Y - AutoScrollPosition.Y;
                //new code

                shape_list.Add(st);

                Invalidate();
            }

            else if (super_form.super_action.Equals(action.heart))
            {
                shapes sh = new shapes();
                heart h = new heart();
                sh = h;

                //new code
                sh.translateX = e.X- AutoScrollPosition.X;
                sh.translateY = e.Y- AutoScrollPosition.Y;
                //new code

                shape_list.Add(h);

                Invalidate();
            }

              .

              .//old code

              .

}

5- drawing lines

work with line_action

private void line_action(MouseEventArgs e)
        {

             .

             .//old code

             .

            //new hand
            Point_line.X = e.Location.X - AutoScrollPosition.X;
            Point_line.Y = e.Location.Y - AutoScrollPosition.Y;
            //new hand

             .

             .//old code

             .

      }

 


9-enable a shortcut (space bar) to use the new hand tool. 

we would use the shortcut for the hand tool found in Adobe Reader, Adobe illustrator , Adobe Photoshop, which is using the space bar just to pan the screen, holding the space button won't lock on the tool of the hand tool, but would just pan the screen , and when the user finishes with panning (finish with holding the space bar) , the old tool would return back to the user .

so this shortcut would be special , because after holding the space bar , the old tool would return back to the user.

 

so in super_form , we would use a public static variable , we would call it old_action

public static action old_action;

then inside the function of tabControl1_KeyDown , we would add a condition for our new shortcut space button . 

        private void tabControl1_KeyDown(object sender, KeyEventArgs e)
        {

             .

             .//old code

             .
//new code
            else if (e.KeyData == Keys.Space)
            {

// we only need this code to run once, as we need a hold action not just click,so we use an if 
condition , if no if condition this code would continuously run as the user holds the space bar which
we don't need

                if (super_action != action.hand)
                {
                    old_action = super_action;//save the current action

                    super_action = action.hand;//change the current action to be hand

                    Cursor new_cursor= 
                    new Cursor(drag_and_drop_and_delete.Properties.Resources.open_hand.Handle);
                    //load the open_hand_cursor to a new cursor variable

                    this.Cursor = new_cursor;
                    //and make the current cursor the open_hand_cursor 

                    toolStrip2.Visible = false;
                    //make the line proprieties menu discussed in previous tut invisible

/////previous tut
////    http://www.codeproject.com/Tips/1105143/tut-Draw-Lines-with-Circle-and-Rectangle-End

 

                }
            }
//new code

             .

             .//old code

             .

     }

now we would work on when the user finish holding the space bar the old tool would be selected , so we would create a KeyUp function in the tabcontrol discussed before in a previous tut 

so in super_form in tabControl1 in proprieties

then the function would be 

private void tabControl1_KeyUp(object sender, KeyEventArgs e)
       {

           super_action = old_action;
           //simply load the old tool that we have just saved it before to
           be the current tool

       }

but the cursor is still the hand tool so we must further edit the tabControl1_KeyUp to also work on resetting the cursor to be the old cursor of the old action .

so we would use the old_action to determine the cursor to be loaded (cursor of the old tool)

        private void tabControl1_KeyUp(object sender, KeyEventArgs e)
        {

            super_action = old_action;

            if(super_action.ToString()=="heart")
            {
                Cursor new_cursor =
                new Cursor(drag_and_drop_and_delete.Properties.Resources.heart_cursor.Handle);
                //load the cursor of the tool that corresponds to the action

                this.Cursor = new_cursor;//load this cusor to be the cursor of the super_form
            }

            //same concept would work on other actions

            else if (super_action.ToString() == "star")
            {
                Cursor new_cursor = 
                new Cursor(drag_and_drop_and_delete.Properties.Resources.star_cursor.Handle);

                this.Cursor = new_cursor;
            }

            else if (super_action.ToString() == "line")
            {
                Cursor new_cursor = 
                new Cursor(drag_and_drop_and_delete.Properties.Resources.Line_cursor.Handle);

                this.Cursor = new_cursor;
            }

            else if (super_action.ToString() == "move")
            {
                Cursor new_cursor = 
                new Cursor(drag_and_drop_and_delete.Properties.Resources.move__cursor.Handle);

                this.Cursor = new_cursor;
            }

            else if (super_action.ToString() == "point")
            {
                Cursor new_cursor = 
                new Cursor(drag_and_drop_and_delete.Properties.Resources.point__cursor.Handle);

                this.Cursor = new_cursor;
            }
        }

 


10-in Form1 ,work with OnPaint to view the circle around points ,and outline of the lines when panning the form

we would work with OnPaint function in Form1 to preserve the outline of lines when the user was using move tool while panning the form

so inside the OnPaint function in Form1

before we only drawn the outline only when super_action = move in super_form 

but now we would also  (so we would use or logic)  draw when old_action = move , as when the hand tool is selected so pan the form the old action would save the previous tool , so if it was a move tool the outline would be visible also when the user uses the hand tool.

<code> </code>

the same concept would also work for viewing the points of the line when the user was using the point_mover_tool and using the hand tool at the same time

before we only drawn the points of line when super_action point , but now we increase with a new condition (with or logic) using  old_action = point

protected override void OnPaint(PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
    int counter_line = 0;

    foreach (lines l in lines_list)
    {
      if (
              super_form.super_action.Equals(action.move) ||
              super_form.old_action.Equals(action.move)
            )
        {
            Pen selection_pen_line = new Pen(Brushes.Blue, 2);
            g.DrawPath(selection_pen_line, l.outline);
        }


        g.DrawPath(l.pen, l.path_line);
        g.FillPath(Brushes.Black, l.arrow_path_line);

        if (
            super_form.super_action.Equals(action.point) ||
            super_form.old_action.Equals(action.point)
            )
        {
            int count = 0;

            foreach (GraphicsPath circle in l.circle_points_list)
            {

                   .

                   .//old code

                   .

   }

 

If you liked the tut Vote it up Smile | :) 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here