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
- 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,
- in
Form1
,define a bigger size than th actual Form size visible to the user ,called AutoScrollMinSize.
- in
Form1
,edit Form1_MouseMove
and add a new section for the new tool, this would be the core of the tool.
- in
Form1
,create a Form1_MouseDown
, to complete the functionality of the tool.
- in
Form1
,edit OnPaint
to create an offset for the drawn shapes
- 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
.
- in
Form1
. when releasing the mouse after panning , reset the mouse to be open hand
- in
Form1
,edit all previous sections that we have discussed before in the previous tuts to work well with the the new tool.
- enable a shortcut (space bar) to use the new hand tool.
- 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; }
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;
cursor_super = new Cursor(drag_and_drop_and_delete.Properties.Resources.open_hand.Handle);
this.Cursor = cursor_super;
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);
this.AutoScrollMinSize = new Size(2000, 1000);
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)
{
.
.
.
else if (super_form.super_action.Equals(action.hand) )
{
if (e.Button == MouseButtons.Left)
{
}
}
}
then inside this condition you would use the previously written variables
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
.
.
.
else if (super_form.super_action.Equals(action.hand) )
{
if (e.Button == MouseButtons.Left)
{
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();
}
}
}
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;
g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
.
.
.
}
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();
.
.
.
change_cursor_static_button = new Button();
change_cursor_static_button.Click += change_cursor_static_button_function;
}
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;
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
- moving and selecting points inside the lines,
- and the concept would work with clicking the line as a whole,
- and also with moving and selecting objects
- and drawing objects (star, heart)
- and drawing lines
1-clicking points inside the lines
work with Form1_MouseMove
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
.
.
.
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);
.
.
.
}
.
.
.
}
}
and selecting point in the line
work with Form1_MouseClick
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
.
.
.
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);
.
.
.
}
.
.
.
}
.
.
.
}
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))
{
Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X,
e.Y - 10 - AutoScrollPosition.Y);
.
.
.
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)
{
.
.
.
else if (super_form.super_action.Equals(action.move))
{
.
.
.
Point with_offset = new Point(e.X - 10 - AutoScrollPosition.X,
e.Y - 10 - AutoScrollPosition.Y);
.
.
.
}
.
.
.
}
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;
sh.translateX = e.X- AutoScrollPosition.X;
sh.translateY = e.Y - AutoScrollPosition.Y;
shape_list.Add(st);
Invalidate();
}
else if (super_form.super_action.Equals(action.heart))
{
shapes sh = new shapes();
heart h = new heart();
sh = h;
sh.translateX = e.X- AutoScrollPosition.X;
sh.translateY = e.Y- AutoScrollPosition.Y;
shape_list.Add(h);
Invalidate();
}
.
.
.
}
5- drawing lines
work with line_action
private void line_action(MouseEventArgs e)
{
.
.
.
Point_line.X = e.Location.X - AutoScrollPosition.X;
Point_line.Y = e.Location.Y - AutoScrollPosition.Y;
.
.
.
}
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)
{
.
.
.
else if (e.KeyData == Keys.Space)
{
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;
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);
this.Cursor = new_cursor; }
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)
{
.
.
.
}
If you liked the tut Vote it up