コード例 #1
0
        private void btnFirstPrototype_Click(object sender, EventArgs e)
        {
            int pagecount;

            if (!int.TryParse(txtNumberPages.Text, out pagecount))
            {
                MessageBox.Show("Number of Pages is required", "Number of Pages is required", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (pagecount < 1 || pagecount > 99)
            {
                MessageBox.Show("Number of Pages must be between 1-99", "Invalid Number of Pages", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // todo: take this out of the UI thread, put it in a class and run on a worker thread
            // and also rename this button - it's been a long time since this was my original prototype

            string previousCaption = this.Text;

            btnFirstPrototype.Enabled = false;
            this.Text = "GENERATING...";

            this.UseWaitCursor = true;

            // todo: move all the grunt work in to a nice proper Threaded situation
            // meanwhile, DoEvents is called here to allow the wait cursor, form caption and other "I'm busy..." indicators to be shown to the user before we get into the hard stuff that takes a few moments
            Application.DoEvents();

            string outputFile  = txtOutputFile.Text;
            string logFilePath = string.Format("{0} - LOG {1}.txt", outputFile, DateTime.Now.ToString("yyyy-MM-dd HHmmss"));

            StreamWriter logFile = new StreamWriter(logFilePath);

            CoinDef thiscoin = new CoinDef(bundle.template.CoinName, bundle.template.CoinAddressType, bundle.template.CoinIsWIFstupid);

            logFile.WriteLine(string.Format("Paper Wallet Printer version {0}", Application.ProductVersion));
            logFile.WriteLine(string.Format("Generating wallets for coin {0}", thiscoin.ToString()));
            logFile.WriteLine("Using template: " + bundle.template.TemplateDescription.Replace("\n", " ")); // removes any line breaks from template description as it writes it to the log file

            bundle.template.LayoutDebugging = layoutDebuggingToolStripMenuItem.Checked;

            if (bundle.template.LayoutDebugging)
            {
                logFile.WriteLine("Layout Debugging is enabled - printed wallets are not intended for live use");
            }

            // make a pdfSharp document
            PdfDocument doc         = new PdfDocument();
            int         batchNumber = 1;
            bool        crashingOut = false;

            XImage imgArtwork = XImage.FromGdiPlusImage(bundle.getArtworkImage());

            // loop for each page
            for (int pageNumber = 1; pageNumber <= pagecount; pageNumber++)
            {
                // and put a page on it
                PdfPage page = doc.AddPage();

                // note: if you change anything that gets written to logFile from this point until the end-marker is written, this will probably cause
                // compatibility issues with the Loader tool, which expects to be able to parse the log between these points
                logFile.WriteLine(string.Format("Generating Page {0} of {1}", pageNumber, pagecount));
                logFile.WriteLine("Generated Addresses:");
                logFile.WriteLine();

                page.Size = bundle.template.pagePrintPaperSize;

                using (XGraphics gfx = XGraphics.FromPdfPage(page, XPageDirection.Downwards))
                {
                    // LOOP Down
                    for (int y = 0; y < bundle.template.pagePrintRows; y++)
                    {
                        // LOOP Across
                        for (int x = 0; x < bundle.template.pagePrintCols; x++)
                        {
                            try
                            {
                                // get PrivKey and Address for this new Wallet
                                KeyPair kp = KeyPair.CreateX(ExtraEntropy.GetEntropy(), false, bundle.template.CoinAddressType, bundle.template.CoinIsWIFstupid);

                                KeyCollectionItem item = new KeyCollectionItem(kp);

                                string address = item.GetAddressBase58();

                                logFile.WriteLine(address);

                                // get an XForm of our Wallet
                                using (XForm walletForm = getSingleWallet(doc, bundle, imgArtwork, address, item.PrivateKey, batchNumber, bundle.template.LayoutDebugging))
                                {
                                    // decide where on the page to draw this wallet XForm object
                                    XUnit walletLeft = XUnit.FromMillimeter(bundle.template.pagePrintLeftMarginMM + ((bundle.template.widthMM + bundle.template.pagePrintColGap) * x));
                                    XUnit walletTop  = XUnit.FromMillimeter(bundle.template.pagePrintTopMarginMM + ((bundle.template.heightMM + bundle.template.pagePrintRowGap) * y));

                                    XPoint whereToPutTheForm = new XPoint(walletLeft.Point, walletTop.Point);
                                    gfx.DrawImage(walletForm, whereToPutTheForm);
                                }

                                batchNumber++;
                            }
                            catch (Exception ex)
                            {
                                // well, damn...
                                logFile.WriteLine("--- CRASH! ---");
                                logFile.WriteLine("Encountered Unhandled Exception inside primary Y-X Print Loop");
                                logFile.WriteLine("Exception:");
                                logFile.WriteLine(ex.Message);
                                logFile.WriteLine(ex.Source);
                                logFile.WriteLine(ex.StackTrace);

                                crashingOut = true;

                                break;
                            }
                        }

                        if (crashingOut)
                        {
                            break;
                        }
                    }
                }

                if (crashingOut)
                {
                    break;
                }

                logFile.WriteLine();
                logFile.WriteLine("end");
                logFile.WriteLine();
            }

            if (!crashingOut)
            {
                logFile.WriteLine("Internal PDF Generation completed OK");

                if (File.Exists(outputFile))
                {
                    File.Delete(outputFile);
                }

                try
                {
                    doc.Save(outputFile);
                }
                catch (Exception ex)
                {
                    logFile.WriteLine("--- CRASH! ---");
                    logFile.WriteLine("Encountered Unhandled Exception when Saving PDF from Object to File");
                    logFile.WriteLine("Exception:");
                    logFile.WriteLine(ex.Message);
                    logFile.WriteLine(ex.Source);
                    logFile.WriteLine(ex.StackTrace);

                    crashingOut = true;
                }

                logFile.WriteLine("PDF saved to File OK - all done");
            }


            logFile.Close();

            // if we have failed in generating the PDF in to memory, or failed when saving it to file - show an error to the user, directing them to to the log file
            if (crashingOut)
            {
                this.Text = previousCaption;
                btnFirstPrototype.Enabled = true;
                this.UseWaitCursor        = false;

                string errmsg = string.Format("Sorry, Wallet Printing has failed. See the log file for details.\n\nLog file:\n{0}", logFilePath);

                MessageBox.Show(errmsg, "Printing Failed, Internal Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }



            if (chkOpenAfterGenerating.Checked)
            {
                // note the current datetime, for comparison if we're trying to wait for PDF Viewer
                DateTime timeOfStartingViewer = DateTime.Now;

                System.Diagnostics.Process procViewer = System.Diagnostics.Process.Start(outputFile);

                if (chkWipeOutputAfterViewing.Checked)
                {
                    btnFirstPrototype.Enabled = false;

                    this.Text = "WAITING FOR PDF VIEWER TO CLOSE";

                    procViewer.WaitForExit();

                    // ok, we *think* that maybe their PDF viewer has closed. But that might not be true.

                    // check to see if we were delayed by a Suspiciously Short length of time
                    TimeSpan timeWaitedForViewer = DateTime.Now - timeOfStartingViewer;

                    if (timeWaitedForViewer.TotalSeconds < 15)
                    {
                        MessageBox.Show("I think your PDF viewer closed really quickly - or I cannot detect if you are done with the generated PDF.\n\nPlease click OK when you are ready for me to delete the generated PDF.", "Ready to delete PDF file?", MessageBoxButtons.OK, MessageBoxIcon.Question);
                    }

                    // overwrite contents of PDF with junk, then delete. This won't be secure against serious forensic attack in all situations, but it's better than just-delete
                    FileInfo info = new FileInfo(outputFile);

                    byte[] junkbytes = new byte[info.Length];
                    MemSet(junkbytes, 255);
                    File.WriteAllBytes(outputFile, junkbytes);

                    File.Delete(outputFile);
                }
            }

            this.Text = previousCaption;
            btnFirstPrototype.Enabled = true;
            this.UseWaitCursor        = false;
        }