Solved

Need help with this code...

Posted on 2006-11-17
3
710 Views
Last Modified: 2008-01-16
I have found an article (http://www.devarticles.com/c/a/C-Sharp/Printing-Using-C-sharp/) which develops a "print engine"... I like the theory, but after copying the code, it doesn't seem to work (only prints or previews the header and footer, and the print dialog appears for each line/object to be printed)... I would be willing to double the points (max is 500, so I would submit another question for an additional 500 (for a total of 1000) for the help).  The code is as follows:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //-----------------------------------    class PrintEngine    -----------------------------------
    public class PrintEngine : PrintDocument
    {
        // members...
        private ArrayList _printObjects = new ArrayList();
        public Font PrintFont = new Font("Arial", 10);
        public Brush PrintBrush = Brushes.Black;
        public PrintElement Header;
        public PrintElement Footer;
        private ArrayList _printElements;
        private int _printIndex = 0;
        private int _pageNum = 0;

        public PrintEngine()
        {
            // create the header...
            Header = new PrintElement(null);
            Header.AddText("Report");
            Header.AddText("Page: [pagenum]");
            Header.AddHorizontalRule();
            Header.AddBlankLine();

            // create the footer...
            Footer = new PrintElement(null);
            Footer.AddBlankLine();
            Footer.AddHorizontalRule();
            Footer.AddText("Confidential");
        }

        // AddPrintObject - add a print object the document...
        public void AddPrintObject(IPrintable printObject)
        {
            _printObjects.Add(printObject);
        }

        // OnBeginPrint - called when printing starts
        protected override void OnBeginPrint(PrintEventArgs e)
        {
            // reset...
            _printElements = new ArrayList();
            _pageNum = 0;
            _printIndex = 0;

            // go through the objects in the list and create print elements for each one...
            foreach (IPrintable printObject in _printObjects)
            {
                // create an element...
                PrintElement element = new PrintElement(printObject);
                _printElements.Add(element);

                // tell it to print...
                element.Print();
            }
        }


        // OnPrintPage - called when printing needs to be done...
        protected override void OnPrintPage(PrintPageEventArgs e)
        {

            _pageNum++;  // adjust the page number...

            // now, render the header element...
            float headerHeight = Header.CalculateHeight(this, e.Graphics);
            Header.Draw(this, e.MarginBounds.Top, e.Graphics, e.MarginBounds);
           
            // also, we need to calculate the footer height...
            float footerHeight = Footer.CalculateHeight(this, e.Graphics);
            Footer.Draw(this, e.MarginBounds.Bottom - footerHeight, e.Graphics, e.MarginBounds);
           
            // now we know the header and footer, we can adjust the page bounds...
            Rectangle pageBounds = new Rectangle(e.MarginBounds.Left,(int)(e.MarginBounds.Top + headerHeight), e.MarginBounds.Width,
                  (int)(e.MarginBounds.Height - footerHeight - headerHeight));
            float yPos = pageBounds.Top;
           
            // ok, now we need to loop through the elements...
            bool morePages = false;
            int elementsOnPage = 0;
            while (_printIndex < _printElements.Count)
            {
                // get the element...
                PrintElement element = (PrintElement)_printElements[_printIndex];
                // how tall is the primitive?
                float height = element.CalculateHeight(this, e.Graphics);

                // will it fit on the page?
                if (yPos + height > pageBounds.Bottom)
                {
                    // we don't want to do this if we're the first thing on the page...
                    if (elementsOnPage != 0)
                    {
                        morePages = true;
                        break;
                    }
                }
                // now draw the element...
                element.Draw(this, yPos, e.Graphics, pageBounds);

                // move the ypos...
                yPos += height;

                // next...
                _printIndex++;
                elementsOnPage++;
            }
            // do we have more pages?
            e.HasMorePages = morePages;
        }


        // ReplaceTokens - take a string and remove any tokens replacing them with values...
        public String ReplaceTokens(String buf)
        {
            // replace...
            buf = buf.Replace("[pagenum]", _pageNum.ToString());

            // return...
            return buf;
        }


        // ShowPreview - show a print preview...
        public void ShowPreview()
        {
            // now, show the print dialog...
            PrintPreviewDialog dialog = new PrintPreviewDialog();
            dialog.Document = this;

            // show the dialog...
            dialog.ShowDialog();
        }

    }  //  end class PrintEngine


    //-----------------------------    class Customer    -------------------------------------
    public interface IPrintable
    {
        // Print
        void Print(PrintElement element);
    }


    //--------------------------------    class PrintPrimitiveRule    ---------------------------------
    public interface IPrintPrimitive
    {
        // CalculateHeight - work out how tall the primitive is...
        float CalculateHeight(PrintEngine engine, Graphics graphics);

        // Print - tell the primitive to physically draw itself...
        void Draw(PrintEngine engine, float yPos, Graphics graphics, Rectangle elementBounds);
    }

    public class PrintPrimitiveRule : IPrintPrimitive
    {
        // CalculateHeight - work out how tall the primitive is...
        public float CalculateHeight(PrintEngine engine, Graphics graphics)
        {
            // we're always five units tall...
            return 5;
        }

        // Print - draw the rule...
        public void Draw(PrintEngine engine, float yPos, Graphics graphics, Rectangle elementBounds)
        {
            // draw a line...
            Pen pen = new Pen(engine.PrintBrush, 1);
            graphics.DrawLine(pen, elementBounds.Left, yPos + 2,
                          elementBounds.Right, yPos + 2);
        }
    }


    //--------------------------    class PrintPrimitiveText    ---------------------------------------
    public class PrintPrimitiveText : IPrintPrimitive
    {
        // members...
        public String Text;

        public PrintPrimitiveText(String buf)
        {
            Text = buf;
        }
        // CalculateHeight - work out how tall the primitive is...
        public float CalculateHeight(PrintEngine engine, Graphics graphics)
        {
            // return the height...
            return engine.PrintFont.GetHeight(graphics);
        }
        // Print - draw the text...
        public void Draw(PrintEngine engine, float yPos, Graphics graphics, Rectangle elementBounds)
        {
            // draw it...
            graphics.DrawString(engine.ReplaceTokens(Text), engine.PrintFont,
            engine.PrintBrush, elementBounds.Left, yPos, new StringFormat());
        }
    }


    //------------------------------    class PrintElement    ---------------------------------------------
    public class PrintElement
    {
        // members...
        private ArrayList _printPrimitives = new ArrayList();
        private IPrintable _printObject;

        public PrintElement(IPrintable printObject)  //  constructor
        {
            _printObject = printObject;
        }

        public void Print()
        {
            // now, show the print dialog...
            PrintDialog dialog = new PrintDialog();
            //   dialog.Document = this;

            // show the dialog...
            dialog.ShowDialog();
        }

        // AddText - add text to the element...
        public void AddText(String buf)
        {
            // add the text...
            AddPrimitive(new PrintPrimitiveText(buf));
        }

        // AddPrimitive - add a primitive to the list...
        public void AddPrimitive(IPrintPrimitive primitive)
        {
            // add it...
            _printPrimitives.Add(primitive);
        }

        // AddData - add data to the element...
        public void AddData(String dataName, String dataValue)
        {
            // add this data to the collection...
            AddText(dataName + ": " + dataValue);
        }

        // AddHorizontalRule - add a rule to the element...
        public void AddHorizontalRule()
        {
            // add a rule object...
            AddPrimitive(new PrintPrimitiveRule());
        }

        // AddBlankLine - add a blank line...
        public void AddBlankLine()
        {
            // add a blank line...
            AddText("");
        }

        // AddHeader - add a header...
        public void AddHeader(String buf)
        {
            AddText(buf);
            AddHorizontalRule();
        }

        public float CalculateHeight(PrintEngine engine, Graphics graphics)
        {
            // loop through the print height...
            float height = 0;
            foreach (IPrintPrimitive primitive in _printPrimitives)
            {
                // get the height...
                height += primitive.CalculateHeight(engine, graphics);
            }

            // return the height...
            return height;
        }

        // Draw - draw the element on a graphics object...
        public void Draw(PrintEngine engine, float yPos, Graphics graphics, Rectangle pageBounds)
        {
            // where...
            float height = CalculateHeight(engine, graphics);
            Rectangle elementBounds = new Rectangle(pageBounds.Left, (int)yPos, pageBounds.Right - pageBounds.Left, (int)height);

            // now, tell the primitives to print themselves...
            foreach (IPrintPrimitive primitive in _printPrimitives)
            {
                // render it...
                primitive.Draw(engine, yPos, graphics, elementBounds);

                // move to the next line...
                yPos += primitive.CalculateHeight(engine, graphics);
            }
        }
    }  //  end class


    public class ListContents : IPrintable
    {
        // members...
        public String bookNumber;
        public String title;
        public String ISBN;
        public String location;
        public String price;
        public String status;

        // Print...
        public void Print(PrintElement element)
        {
            // tell the engine to draw a header...
            element.AddHeader("Contents of List");

            // now, draw the data...
            element.AddData("Book Nbr", bookNumber);
            element.AddData("Title", title);
            element.AddData("ISBN", ISBN);
            element.AddData("Location", location);
            element.AddData("Price", price);
            element.AddData("Status", status);

            // finally, add a blank line...
            element.AddBlankLine();
        }
    }
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
and the calling code is as follows:


    public class ListContents : IPrintable
    {
        // members...
        public String bookNumber;
        public String title;
        public String ISBN;
        public String location;
        public String price;
        public String status;

        // Print...
        public void Print(PrintElement element)
        {
            // tell the engine to draw a header...
            element.AddHeader("Contents of List");

            // now, draw the data...
            element.AddData("Book Nbr", bookNumber);
            element.AddData("Title", title);
            element.AddData("ISBN", ISBN);
            element.AddData("Location", location);
            element.AddData("Price", price);
            element.AddData("Status", status);

            // finally, add a blank line...
            element.AddBlankLine();
        }
    }

            PrintEngine _engine = new PrintEngine();

            SqlCommand cmd = new SqlCommand(inclusiveSearchString);
            cmd.Connection = bookConn;
            SqlDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read())
            {
                ListContents lc = new ListContents();
               
                lc.bookNumber = (string)rdr["BookNbr"];
                lc.title = (string)rdr["Title"];
                lc.ISBN = (string)rdr["ISBN"];
                lc.location = (string)rdr["Locn"];
                lc.price = rdr["Price"].ToString();
                lc.status = (string)rdr["Stat"];
                _engine.AddPrintObject(lc);  //  add item to the list to print

            }

            _engine.ShowPreview();

        }
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0
Comment
Question by:rmmarsh
  • 2
3 Comments
 
LVL 15

Accepted Solution

by:
ozymandias earned 500 total points
ID: 17969052
>>after copying the code, it doesn't seem to work
You seem to have a got the code from that articel all mixed up.

>>print dialog appears for each line/object to be printed
That's becauase in the PrintElement class you have a Print method which calls a PrintDialog and shows it.
Then in the PrintEngine Class in OnBeginPrint you call that method for every PrintElement in the document in a loop...why ?

foreach (IPrintable printObject in _printObjects)
{
    // create an element...
    PrintElement element = new PrintElement(printObject);
    _printElements.Add(element);

    // tell it to print...
    element.Print();      <---- what are you doing here ?
}

>>only prints or previews the header and footer
That is because you have no Draw method in your PrintElement so it has no way of rendering itself onto the PrintDoument's graphics space.

You need to read the article thoroughly so that you understand what each piece of code is actually doing then you will be able to assemble the code correctly from the article.
0
 

Author Comment

by:rmmarsh
ID: 17969557
Well, I think I would rather had you do what you did (made me read the article and re-copy the code) than fix it yourself... I learned more... and did find one error which I was able to fix myself... one is never too old to learn new things...

Thank you so much for your advice and help... it works like a champ...
0
 
LVL 15

Expert Comment

by:ozymandias
ID: 17970824
Thanks.
Well done for taking the longer, harder route.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Printing 1 60
C# winforms programmitically move panels 6 44
C# Gridview 1 49
linq .concat equivalent with expression syntax 4 8
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question