幸运星空

Lucker的程序人生

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

C#中,通常涉及到打印,我们一般都会用到PrintDocument类,用该类来实现打印真是又方便又强大.程序员可以非常轻松的控制打印内容.然而PrintDocument类提供了打印"取消"功能,却没有为我们提供打印的"暂停"与"继续".这对与想在打印过程中实现对打印任务的控制的初学者来说,制造了不少麻烦.

其实,实现打印任务的"暂停"与"继续".我们可以借助于API函数"SetJob"来实现.这个函数可以对一个打印作业的状态进行控制,它在VB中的声明如下:

Declare Function SetJob Lib "winspool.drv" Alias "SetJobA" (ByVal hPrinter As Long, ByVal JobId As Long, ByVal Level As Long, pJob As Byte, ByVal Command As Long) As Long

返回值及相关参数说明请参考有关资料,这本不想过多的阐述.因为本文想着重讲的是在C#中如何简单有效的控制打印任务.

由打印任务的暂停与继续我们可能很自然的想到了C#中线程的暂停与继续.而如果把打印任务运行在某个线程上,然后控制该线程的暂停与继续,不就可以实现对打印任务的控制了吗?

想到这里,那我们就动手测试一下吧:

打印暂停时的界面:
image

以下为关键代码:

        Thread th;
        private int pageCounter;
        public delegate void invoke();

        private void button1_Click(object sender, System.EventArgs e)
        {
            pageCounter = 0;
//开始一个新的线程来完成打印任务:
            th = new Thread( new ThreadStart( printDocumentWithAHardJob.Print));
            th.Start();
//打印开始以后,原"打印"按钮不可用,后"暂停"变得可用.
            button1.Enabled = false;
            button3.Enabled = true;
        }

//这是实现打印内容的关键方法.每打印一页,都会执行一次该方法.注意啦,该方法已经运行在新创建的th线程上了.
        private void printDocumentWithAHardJob_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
//每页打印前小停一会,以便我们观察打印过程,实际打印中可以不要这一句
            System.Threading.Thread.Sleep(Convert.ToInt32(numericUpDownDelay.Value));
//以下几句在页面上画一个图形,做为打印输入的页面内容
            e.Graphics.DrawRectangle(Pens.Black, e.MarginBounds);
            e.Graphics.DrawLine(Pens.Black, e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.X + e.MarginBounds.Width, e.MarginBounds.Y + e.MarginBounds.Height);
            e.Graphics.DrawLine(Pens.Black, e.MarginBounds.X + e.MarginBounds.Width, e.MarginBounds.Y, e.MarginBounds.X, e.MarginBounds.Y + e.MarginBounds.Height);

            pageCounter++;
//检查是否打印完成
            if (pageCounter == numericUpDownPages.Value)
            {
                e.HasMorePages = false;
//以下为调用委托方法来完成对主线程上几个按钮可用性的设置(线程间的操作,不可以直接访问非当前线程上创建的控件)
                invoke InvokeMothed=new invoke(SetButton);
                this.Invoke(InvokeMothed);               
            }
            else
                e.HasMorePages = true;
        }
//委托方法
        private void SetButton()
        {
            button1.Enabled = true;
            button3.Enabled = false;
        }
//根据th线程的状态来控制打印任务(即th线程)的挂起与恢复
        private void button3_Click(object sender, EventArgs e)
        {
            if (th.ThreadState == ThreadState.Suspended)
            {
                th.Resume();
                button3.Text = "暂停";
            }
            else if(th.IsAlive)
            {
                th.Suspend();
                button3.Text = "继续";
            }
        }

经测试,这种方法完全能满足我们打印任务的控制要求.

测试源码:https://files.cnblogs.com/luckeryin/PrintTest.rar

posted on 2009-07-13 18:28  Lucker  阅读(2625)  评论(0编辑  收藏  举报