How to flip alignment of drawn content in a panel

2019-09-03 14:59发布

问题:

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?

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:

回答1:

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.



回答2:

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.