Search code examples
c#winformsprintingprint-preview

Prevent printing blank pages


I just need to reset "border" after print previewing. I preview the page I wantted to print correctly but when I do printing it gives blank pages because "border" wasnt reset. Where should I put "border=0"?("border" is no. rows in a datagridview)

  private void button5_Click(object sender, EventArgs e)
    {
       PrintDocument pd = new PrintDocument();
        pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);           
        PrintPreviewDialog ppd = new PrintPreviewDialog();
        ppd.Document = pd;
        ppd.ShowDialog();

    }
  private void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
  prntt(sender, e);
     }
   public void prntt(object sender, PrintPageEventArgs e)
    {
           for (; border < ViewA.RowCount; border++)
        {
            if (ustsin + yuk > e.MarginBounds.Bottom - 400f)
            {

                e.HasMorePages = true;                  

                return;
            }



            texts = ViewA.Rows[border].Cells["Persons"].Value.ToString();
            ...
            graphics.DrawString(texts, font, Brushes.Black, new RectangleF(e.MarginBounds.Left, ustsin, 115f, 90f));               
            ...

            float hoho = (float)e.Graphics.MeasureString(texts, font, 115, StringFormat.GenericTypographic).Height;
            ...
            var mesele = new float[] { hoho, koko, moko };
            float kapa = mesele.OrderByDescending(s => s).First();

            ustsin += kapa + yuk;             

        }            

        e.HasMorePages = false;
     }

if I can close when we press the print button in print preview, can I reset in its closing event?

edit: I did this, it seems to work but when I send it to xps, it shows 2 pages in the screen. like this https://i.sstatic.net/3i9QZ.png . How can I make this show 1 page?

    private void printDocument1_EndPrint(object sender, PrintEventArgs e)
    {


        border = 0;
    }

Solution

  • initially set it to 0 and reset it after ppd.ShowDialog();

    ppd.ShowDialog();
    border = 0;
    

    UPDATE

    Looks like PrintPreviewDialog doesn't support much as you (and many others expect), it's up to the user (not to programmer). You can try this a little hacky stuff:

    //code in your button5_Click
    ToolStripButton onePageButton = ((ToolStrip)ppd.Controls[1]).Items[3] as ToolStripButton;
    BeginInvoke((Action)(() => onePageButton.PerformClick()));
    ppd.ShowDialog();
    

    UPDATE

    To intercept the Clicking on the Print button, you have to add a little much more code. You have to detect the click before the Click is fired on the item (print button), show the message box asking for confirmation and re-click the item if user agrees. Here is the code for you:

    //Use this class to add message interceptor into your ToolStrip message loop
    public class NativeToolStrip : NativeWindow {
        ToolStrip ts;
        bool letClicked;
        protected override void OnHandleChange() {
            base.OnHandleChange();
            Control c = Control.FromHandle(Handle);
            ts = c as ToolStrip;
        }
        protected override void WndProc(ref Message m) {                
          if (m.Msg == 0x202&&!letClicked) {//WM_LBUTTONUP = 0x202
               int x = m.LParam.ToInt32() & 0x00ff;
               int y = m.LParam.ToInt32() >> 16;
               ToolStripItem item = ts.GetItemAt(new Point(x, y));                    
               //check if the first item (the Print Button) is clicked
               if (item != null && ts.Items.IndexOf(item) == 0) {
                 if (MessageBox.Show("Do you want to print?", "Print confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                     return;//discard message
                 else {
                        letClicked = true;
                        item.PerformClick();
                  }
                }
           }
           base.WndProc(ref m);
           if (letClicked) letClicked = false;
        }
    }
    //This code should be done somewhere like in your form constructor
    //BUT your PrintPreviewDialog should also be declared once in the form scope
    //You can also place this in your button5_Click BUT it's not recommended
    ToolStrip ts = (ToolStrip)ppd.Controls[1];
    new NativeToolStrip().AssignHandle(ts.Handle);