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

[tut 9] hand tool (part 2) navigator panel

0.00/5 (No votes)
3 Jul 2016 1  
we will continue the functionality of the hand tool with having a navigator panel which works as a map, we will also have a red rectangle which tells the user where he is actually viewing inside the whole form, also it can be moved to pan the form

Introduction

This is the Ninth tutorial of a series of tutorials of how to build a graphics program using C# in Windows 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:

we will continue the functionality of the hand tool with having a navigator panel which works as a map,

we will also have a red rectangle which tells the user where he is actually viewing inside the whole form,  also it can be moved to pan the form

this navigator panel would be able to : when you pan the form , the navigator panel would be updated

also it would enable the user to click at any place in the navigator panel , and the form would be panned

also it would enable the user to drag and drop the red rectangle which would pan he form 

Background

 


Map of the tut

  1. add a tab control inside the super_form
  2. create a form and name it Navigator_form , edit some of its proprieties , and add it to the  tab control inside the super_form
  3. in the super_form change some variables to be static
  4. in the Navigator_form , create a button to have a click function to refresh the navigator_form , and in Form1 work in the Onpaint to refresh the navigator form
  5. in the Navigator_form work on getting the value for the graphics to be scaled down by , so that the big graphics(shapes and lines ) would view in a smaller area inside the Navigator_form
  6. in the Navigator_form work with the OnPaint function to view the shapes and the lines 
  7. in the Navigator_form create a red rectangle and move it with the value of the scroll value in the form 
  8. in the Navigator_form create a MouseDown function to make the behavior of enabling the user to click at any place in the navigator panel , and the form would be panned
  9. in the Navigator_form create a MouseMove function to make the behavior of enabling the user to drag and drop the red rectangle which would pan he form 

 

1-add a tab control inside the super_form

get the tab_control from the tool box

add it in the the super_form[Desgin] to the left of the old tabcontrol

 

from the proprieties of the new added tab_contol , click on the tabPages

 

remove all pages inside the tabPages 

 


2-create a form and name it Navigator_form , edit some of its proprieties , and add it to the  tab control inside the super_form

create a form and name it Navigator_form

edit some of its proprieties

change its back color to make it white

and make a special cursor for this form, so when the mouse enters this form the cursor would be changed, lets make the default hand cursor 

change the form border size as we don't need

but we need it to be 

so we would change Navigator_form proprieties 

and we would change its size to be 

 

now we need to add this newly created Form , to the tabControl inside the super_form

so work on the constructor of super_form

public super_form()
       {
           InitializeComponent();

          .

          .//old code

          .


           //new code
           Navigator_form nav = new Navigator_form();   //create a new object of Navigator_form 
           AddNewTab_nav(nav); //would be discussed 
           //new code

       }

now we need to create the function itself that adds the form to the tabControl 

private void AddNewTab_nav(Form frm)
{
    TabPage tab = new TabPage(frm.Text);
    frm.TopLevel = false;
    frm.Parent = tab;
    frm.Visible = true;

    tabControl2.TabPages.Add(tab);
    //tabControl2 is the tabControl that we have just created
}

 

 


 

3-in the super_form change some variables to be static

let the integer that tells which form was selected to be static ,so that it would be used in the navigator_form , as we need the navigator form to be the map of the only selected form , as we need the navigator form to be the map for each form

public static int selected_tab=0;

and change form_list to be static

public static List<Form1> form_list=new List<Form1>();

 


 

4-in the Navigator_form , create a button to have a click function to refresh the navigator_form , and in Form1 work in the Onpaint to refresh the navigator form

as we would need the Onpaint function to be called from an another form , we would need the Onpaint function to be static , but this can't be done, so there is a method around this , by making the click function on a static button, and inside this click call the Onpaint

so first lets create an Onpaint

then we would create a static button

public static Button invalidate_button=new Button();

then in the constructor of the Navigator_form , assign a click function for this button

public Navigator_form()
      {
          InitializeComponent();
          invalidate_button.Click += Invalidate_button_Click;
       }

this function would simply refresh the form

private void Invalidate_button_Click(object sender, EventArgs e)
{
    Invalidate();
}

then in the Form1 in its OnPaint function we would simply call the click function of that button to refresh the Navigator_form 

protected override void OnPaint(PaintEventArgs e)
      {

          .

          .//old code

          .


          Navigator_form.invalidate_button.PerformClick();
      }

 


 

5-in the Navigator_form work on getting the value for the graphics to be scaled down by , so that the big graphics(shapes and lines ) would view in a smaller area inside the Navigator_form

first in the Navigator_form create two new int

double div_h;
double div_w;

in the constructor of the Navigator_form 

public Navigator_form()
        {
            InitializeComponent();
            invalidate_button.Click += Invalidate_button_Click;
            DoubleBuffered = true;  //to make the drawing more smooth

            Form1 selected_form = super_form.form_list.ElementAt<Form1>(super_form.selected_tab); 
            //know which form is selected , use the static selected_tab

            Size siize = selected_form.AutoScrollMinSize;//get size of the selected form 
            div_h = (double)this.Size.Height /(double) siize.Height ;
            div_w = (double)this.Size.Width / (double)siize.Width ;

            //divide the size of the navigator form by the size of the selected form 
            //do it for horizontal and vertical

            div_h = Math.Round(div_h, 1); 
            div_w = Math.Round(div_w, 1); 

            //approximate to the first decimal place 
            //if it was 0.19523---> 0.2

        }

 


 

6-in the Navigator_form work with the OnPaint function to view the shapes and the lines 

private  void Navigator_form_Paint(object sender, PaintEventArgs e)
      {
          Graphics g = e.Graphics;

          Form1 selected_form = super_form.form_list.ElementAt<Form1>(super_form.selected_tab);
          //know which form is selected , use the static selected_tab

          Matrix m = new Matrix();//to scale down the graphics we would use a Matrix

          m.Scale((float)div_h, (float)div_w, MatrixOrder.Append);
          //define the matrix with values previously calculated
          g.Transform = m;
          //actually scale down te graphics

          //draw the lines
          foreach (lines l in selected_form.lines_list)
          {
              g.DrawPath(l.pen, l.path_line);
              g.FillPath(Brushes.Black, l.arrow_path_line);
          }

          //draw the shapes
          foreach (shapes sh in selected_form.shape_list)
          {
              Svg.ISvgRenderer render = null; ;

              g.DrawPath(new Pen(Brushes.Black, 2), sh.draw_svg().Path(render));
              g.FillPath(Brushes.Khaki, sh.draw_svg().Path(render));
          }

      }

7-in the Navigator_form create a red rectangle and move it with the value of the scroll value in the form 

in the Navigator_form , create a rectangle

public  Rectangle border = new Rectangle();

and in the Navigator_form , edit the OnPaint 

       private  void Navigator_form_Paint(object sender, PaintEventArgs e)
        {

            .

            .//old code

            .

            //first calculate the location of the red rectangle which would simply 
            //  be the opposite of the scroll value of the selected form

            Point offset_point = new Point(-selected_form.AutoScrollPosition.X,
                                                              -selected_form.AutoScrollPosition.Y);
            border.Location = offset_point;

 

            //set the size of the red rectangle to be the same size of what the user 
            //can see without panning which is 1000 * 700 
            //don't forget that all graphics would be scaled down

            Size siize = new System.Drawing.Size(1000, 700);
            border.Size = siize;


            //then draw the rectangle in a red color
            e.Graphics.DrawRectangle(new Pen(Brushes.Red, 1), border);
}

now the navigator would be refreshed when working in the Form1 

now we need to expand the features of the navigator form to enable clicking and dragging and drapog the red rectangle


8-in the Navigator_form create a MouseDown function to make the behavior of enabling the user to click at any place in the navigator panel , and the form would be panned

in the Navigator_form create a MouseDown function

then in the back code in the Navigator_form in the Navigator_form_MouseDown

private void Navigator_form_MouseDown(object sender, MouseEventArgs e)
{
    Form1 selected_form = super_form.form_list.ElementAt<Form1>(super_form.selected_tab);
    //know which form is selected , use the static selected_tab

    Point p = new Point(e.Location.X * 5, e.Location.Y * 5);
    //get the position of the mouse 
    //and scale it up by multiplying it by 5, because we have scaled down the graphics before

    selected_form.AutoScrollPosition = p;
    //move (pan) the selected form 
}

 

so thee result would be 

 


9-in the Navigator_form create a MouseMove function to make the behavior of enabling the user to drag and drop the red rectangle which would pan he form 

in the Navigator_form create a MouseMove function

then in the back code in the Navigator_form in the Navigator_form_MouseMove

        private void Navigator_form_MouseMove(object sender, MouseEventArgs e)
        {

           //only work when the mouse moves and clicks the left button 
           //would implement the drag & drop functionality

            if (e.Button == MouseButtons.Left)
            {

                //same code as in function of Navigator_form_MouseDown

                Form1 selected_form = super_form.form_list.ElementAt<Form1>(super_form.selected_tab);

                Point p = new Point(e.Location.X * 5, e.Location.Y * 5);
                selected_form.AutoScrollPosition = p;
            }
        }

so the result would be 

 

 

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