0

I am using two panels for drawing ruler along the sides (top and left) of a picture box. It works, but now my requirement is to flip the direction of the ruler so that the line starts from the picture box and the text (numbers) are the top. How can I do this?

enter image description here

My code is as follows:

 private void panel2_Paint(object sender, PaintEventArgs e)//left Panel
    {
        Graphics g = e.Graphics;
        g.PageUnit = GraphicsUnit.Millimeter;
        int step = 1;
        int length = panelleft.Height / 3;
        int small = 5;
        int big = 10;
        int number = 10;
        int scale = 10;
        float stroke = 2.5f;
        for (int i = 0; i < length; i += step)
        {
            float d = 1;
            if (i % small == 0)
            {
                if (i % big == 0)
                {
                    d = 3;
                }
                else
                {
                    d = 2;
                }
            }
            g.DrawLine(this.pen, 0f, i,d * stroke, i);             
            if ((i % number) == 0)
            {
                string text = (i / scale).ToString();
                SizeF size = g.MeasureString(text, this.Font, length, this.format);
                g.DrawString(text, this.Font, Brushes.Black,d * stroke, i - size.Width-1 / 2 , this.format);                  
            }
        }
    }

 private void panel3_Paint(object sender, PaintEventArgs e)// top panel
    {
        Graphics g = e.Graphics;
        g.PageUnit = GraphicsUnit.Millimeter;
        int step = 1;//incremnent
        int length = paneltop.Width / 3; //panelinte  widthinte pakuthi mathi bcs namml oru point gap vittanu line varakunnath     
        int small = 5;//cheriya vark ulla length
        int big = 10;//valiya vark ulla length
        int number = 10;//units 1cm=10 units           
        float stroke = 2.5f;

        for (int i = 0; i < length; i += step)
        {
            float d = 1;
            if (i % small == 0)//cheriya line 
            {
                if (i % big == 0)//valiya line
                {
                    d = 3; //varyude length
                }
                else
                {
                    d = 2;//varyude length
                }
            }
            g.DrawLine(this.pen, i, 0f, i, d * stroke);//lines varakunnu
            if ((i % number) == 0)//0,1,,2
            {
                string text = (i / number).ToString();//1,2,3 ennu ezhuthan
                SizeF size = g.MeasureString(text, this.Font, length, this.format);//ezhuthuna stringnte length ariyan// one digit length 1.618635,2 digit length3.23727
                g.DrawString(text, this.Font, Brushes.Black, i - size.Width / 2, d * stroke, this.format);//Y constant ayirikum (d* stroke) ennu koduthath line kazhinju string varan anu alenkil overlapp cheyum 
                //                                            (        X       )  (     Y   )
            }
        }

    }

I also want to show a horizontal and vertical line, and they must be pointed to the ruler when the user moves the mouse over the image.

Required output sample: enter image description here

Pops
  • 30,199
  • 37
  • 136
  • 151
Jinesh Sam
  • 111
  • 4
  • 20
  • What is `flip`? I fail to imagine end result, can you provide a draft of expected result (consider to tag question as `winforms` on edit)? Regarding mouse, you have to handle mouse events: `MouseMove`, `MouseEnter` and `MouseLeave` to call `Invalidate()` for panel and set flag when to draw lines, while in `Paint` simply [getting mouse position](http://stackoverflow.com/q/1316681/1997232) and drawing lines. – Sinatr Nov 07 '14 at 15:32

2 Answers2

3

Since you have set the Graphics to mm you need to calculate the conversion factor for the controls' pixel sizes:

float dpi = e.Graphics.DpiX;
float factor = 25.4f / dpi;

with this you can simply adapt your DrawString and DrawLine calls like this:

In panel2_Paint:

   float w = panelleft.Width * factor;

   g.DrawLine(this.pen, w - d * stroke, i, w, i);

   g.DrawString(text, this.Font, Brushes.Black, 
                w - d * stroke - size.Width, i - size.Width - 1 / 2, this.format);

and in panel3_Paint:

  float h = paneltop.Height * factor;

  g.DrawLine(this.pen, i, h - d * stroke, i, h);

  g.DrawString(text, this.Font, Brushes.Black, 
               i - size.Width / 2, h - d * stroke - size.Height, this.format);

To show the Cursor lines you can use this:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    Point mp = pictureBox1.PointToClient(Cursor.Position);

    if (e.ClipRectangle.Contains(mp))
    {
        e.Graphics.DrawLine(Pens.Red, 0, mp.Y, e.ClipRectangle.Width, mp.Y);
        e.Graphics.DrawLine(Pens.Red, mp.X, 0, mp.X, e.ClipRectangle.Height);
    }
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    pictureBox1.Invalidate();
}

Here is the result, using a few assumptions:

panelleft = panel2;
paneltop = panel3;
format = StringFormat.GenericTypographic;
pen = new Pen(Color.Black, 0.25f);

In theory you should use dpiX and dpiY respectively to get two factors.

resulting rulers

Pops
  • 30,199
  • 37
  • 136
  • 151
TaW
  • 53,122
  • 8
  • 69
  • 111
  • wait i will check and inform – Jinesh Sam Nov 07 '14 at 16:28
  • @TaW Thanks a ton.. for your effort.. One more help please i need to get the X & Y position in a text box. which event i want to use – Jinesh Sam Nov 07 '14 at 16:46
  • No problem; I liked your question ;-) - For mm you can put code like this into the `MouseMove` of the `PictureBox`: `somecontrolX.Text = ( e.X * factor / 10).ToString("##0.0");` For pixels you don't need to calculate, of course. - But you need to move the __declaration__ (not the assignment) of `float factor` out of the events and to the class level! – TaW Nov 07 '14 at 16:54
  • @TaW can't we use `pictureBox1_Paint` event. i am getting the result is there any drawback for this. – Jinesh Sam Nov 07 '14 at 17:23
  • @TaW one more doubt if suppose i want to remove the cursor lines from right and below what should i do. i need _| like this. – Jinesh Sam Nov 07 '14 at 17:39
  • To make the Lines smaller simply change the coordinate endpoints from `e.ClipRectangle.Width` and `e.ClipRectangle.Height` to `mp.X` and `mp.Y`. – TaW Nov 07 '14 at 22:43
  • @TaW why my question down voted. can you please up vote this question.Now i am not able to post new question. i am getting the message "Sorry, we are no longer accepting questions from this account" – Jinesh Sam Nov 08 '14 at 07:48
  • That is neither accepted here nor would it help. The ban will soon go away, I think. Please try to improve your questions. A few hints: Never say 'It isn't working' without describing how exactly is isn't working (exceptions?, wrong result? (which?), other strange behaviour..) Also watch spelling; many people will automatically downvote posts where the pronoun 'I' is not capitalized because it hurts their eyes. And show how, what and where you have researched before posting questons here!! Also a good title helps. The one for this question is rather misleding. I'll change it now.. – TaW Nov 08 '14 at 08:51
0

For the top one, you want to change your DrawLine and your DrawString calls to be inverse of what they currently are.

In the Panel3 paint:

g.DrawLine(this.pen, i, 0f, i, d * stroke);//lines varakunnu

This draws a line from (i, 0) to (i, d*stroke). We want to invert this line, so we will do:

g.DrawLine(this.pen, i, panel3.Height, i, (panel3.Height - d * stroke));//lines varakunnu

We also want to adjust the label as well, so we will change this:

g.DrawString(text, this.Font, Brushes.Black, i - size.Width / 2, d * stroke, this.format);

to

g.DrawString(text, this.Font, Brushes.Black, i - size.Width / 2, (panel3.Height - d * stroke - size.Height), this.format);

or

g.DrawString(text, this.Font, Brushes.Black, i - size.Width / 2, (panel3.Height - d * stroke), this.format);

I'm not sure if you need to compensate for size.Height or not, since I can't test your code.

lukevp
  • 705
  • 4
  • 16
  • g.DrawLine(this.pen, i, panel3.Height, i, (panel3.Height - d * stroke)); its not drwaing any line. how can i send the code to you. is there any option in SO – Jinesh Sam Nov 07 '14 at 16:02