Graphics.DrawString center in printdocument width

Tsukasa picture Tsukasa · Aug 29, 2013 · Viewed 10.4k times · Source

I'm attempting to center a string on a printdocument. I've done the following with an image and it works but doesn't seem to work the same with a string.

Here is the code that I used to center the image

e.Graphics.DrawImage(logo, (e.MarginBounds.Width / 2) - (logo.Width / 2), height);

The text i'm trying to center is being supply from a Tab in a TabControl

 using (var sf = new StringFormat())
 {
       height = logo.Height + 15;
       sf.LineAlignment = StringAlignment.Center;
       sf.Alignment = StringAlignment.Center;
       e.Graphics.DrawString(tabData.Text, new Font(this.Font.Name, 10),
            new SolidBrush(tabData.ForeColor),
            (e.MarginBounds.Width / 2) - (txtData.Width / 2), height, sf);
  }

I have also tried below and used string_size.Width /2 in place of txtData.Width

SizeF string_size = e.Graphics.MeasureString(tabData.Text, tabData.Font);

EDIT

Current full code

        float height = 0;
        tabData.Text = "Date Range: 02/02/2010 - 08/09/2013"; //set just for testing
        using (var logo = Properties.Resources.title)
        {
            e.Graphics.DrawImage(logo, e.PageBounds.Left + (e.MarginBounds.Width / 2) - (logo.Width / 2), height);
            height = logo.Height + 15;
        }

        using (var sf = new StringFormat())
        {

            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;
            e.Graphics.DrawString(tabData.Text, new Font(this.Font.Name, 10), new SolidBrush(tabData.ForeColor), e.PageBounds.Left + (e.PageBounds.Width / 2), height, sf);
        }

Don't understand why I have to use a mixture of PageBounds and MarginBounds to center the Image then with the text it will center with either both MarginBounds or both PageBounds

Answer

bjaminn picture bjaminn · Aug 29, 2013

The following works for me. You may need to use PageBounds if your margins are not uniform.

    void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        int w = e.MarginBounds.Width / 2;
        int x = e.MarginBounds.Left;
        int y = e.MarginBounds.Top;
        Font printFont = new Font("Arial", 10);
        Bitmap logo = System.Drawing.SystemIcons.WinLogo.ToBitmap();

        int height = 100 + y;
        string tabDataText = "Hello World";
        var tabDataForeColor = Color.Blue;
        var txtDataWidth = e.Graphics.MeasureString(tabDataText, printFont).Width;

        e.Graphics.DrawImage(logo,
            e.MarginBounds.Left + (e.MarginBounds.Width / 2) - (logo.Width / 2),
            e.MarginBounds.Top + (e.MarginBounds.Height / 2) - (logo.Height));

        using (var sf = new StringFormat())
        {
            height += logo.Height + 15;
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;
            e.Graphics.DrawString(tabDataText, new Font(this.Font.Name, 10),
                 new SolidBrush(tabDataForeColor),
                 e.MarginBounds.Left + (e.MarginBounds.Width / 2),
                 e.MarginBounds.Top + (e.MarginBounds.Height / 2) + (logo.Height / 2) + 15,
                 sf);
        }

        e.HasMorePages = false;
    }

Edit Response

Output using your new code. Are you saying this is what you want?

Or are you wanting this?

The margin is a rectangle that sits inside the page. It is possible that those margins are asymmetrical so if you want the absolute center you should reference PageBounds.

Additionally, your text is center aligned so that makes the reference point of drawing the text in the middle of the String instead of top left like the logo.