c# winform 解决PictureBox 无法打印全部图片的问题

作者:沐汐 Vicky
出处:http://www.cnblogs.com/EasyInvoice

一、   问题描述

在页面使用PictureBox 加载资料图片后,点击“打印”,只能打印图片首页,较大图片则无法全部打印。

二、   原因分析

PictureBox中打印图片时没有设置继续打印相关属性,因此每次只能打印第1页。

三、解决方法

PictureBox控件增加打印全部页面属性,如果为True,表示打印全部页面;如果为False,保留原有逻辑不变。

在打印全部页面时,将控件的图片按页面大小切割,打印页面索引小于页面总数时,设置打印属性PrintPageEventArgs. HasMorePages = true继续打印,打印完成后将该属性设置为False结束打印。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.Text;
using System.Windows.Forms;
 
namespace MyClass
{
 
    //public enum OperationState { Default, ZoomIn, ZoomOut };
 
    public partial class UCPictureBox : PictureBox
    {
        //private OperationState operationState;//处理状态
        private HScrollBar hScrollBar;//水平滚动条
        private VScrollBar vScrollBar;//垂直滚动条
        private PrintDocument printDocument;//打印对象
        private Rectangle currRect;//现在矩形对象
        private Bitmap currBmp;//现在图形对象
        //private int hScrollBarMidVal;//水平滚动条中间值
        //private int vScrollBarMidVal;//垂直滚动条中间值
        private RectangleF srcRect;
        private RectangleF destRect;
        private bool isMoveScrollBar;//是否移动滚动条       
        int currentPageIndex = 0;//当前页面
        int pageCount = 0;//打印页数
         
        /// <summary>
        /// 构造函数
        /// </summary>
        public UCPictureBox()
        {
            InitializeComponent();
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 
            //hScrollBarMidVal = 0;
            //vScrollBarMidVal = 0;           
            //operationState = OperationState.Default;
            isMoveScrollBar = false;
            srcRect = new RectangleF();
            destRect = new RectangleF();
            printDocument = new PrintDocument();
            printDocument.PrintPage += new PrintPageEventHandler(printDocument_PrintPage);
 
            //构造水平滚动条
            hScrollBar = new HScrollBar();
            hScrollBar.Visible = false;
            hScrollBar.Dock = DockStyle.Bottom;
            hScrollBar.Scroll += new ScrollEventHandler(scrollBar_Scroll);
            this.Controls.Add(hScrollBar);
 
            //构造垂直滚动条
            vScrollBar = new VScrollBar();
            vScrollBar.Visible = false;
            vScrollBar.Dock = DockStyle.Right;
            vScrollBar.Scroll +=new ScrollEventHandler(scrollBar_Scroll);
            this.Controls.Add(vScrollBar);
        }
 
        #region 公共属性
 
        [Category("外观"), Description("获取或设置图片")]
        public new Image Image
        {
            get { return base.Image; }
            set
            {
                if (value != null)
                {
                    base.Image = value;
                    currRect.Width = base.Image.Width;
                    currRect.Height = base.Image.Height;
                    hScrollBar.Value = 0;
                    vScrollBar.Value = 0;
                    displayScrollBars();
                    setScrollBarsValues();
                    Invalidate();
                }
            }
        }
 
        //缩放比例
        private int scaleSize = 1;
        [Category("其它"), Description("获取或设置图片缩放比例")]
        public Int32 ScaleSize
        {
            get { return scaleSize; }
            set
            {
                if (value > 1 && value < 51)
                {
                    scaleSize = value;
                }
            }
        }
 
        //缩放倍数
        private int scaleScope = 5;
        [Category("其它"), Description("获取或设置图片最大缩放倍数")]
        public int ScaleScope
        {
            get { return scaleScope; }
            set
            {
                if (value > 1 && value < 11)
                {
                    scaleScope = value;
                }
            }
        }
 
        //图片边框颜色
        //private Color borderColor = Color.DarkGray;
        //[Category("其它"), Description("获取或设置图片边框颜色")]
        //public Color BorderColor
        //{
        //    get { return borderColor; }
        //    set { borderColor = value; }
        //}
 
        //图片边框宽度
        private int borderWidth = 5;
        [Category("其它"), Description("获取或设置图片边框宽度")]
        public Int32 BorderWidth
        {
            get { return borderWidth; }
            set { borderWidth = value; }
        }
 
        //打印全部页面
        [Category("其它"),Description("true-打印全部页面,false-打印首页")]
        public bool PrintAllPages { get; set; }
 
        #endregion
 
        #region 内部公共方法
 
        /// <summary>
        /// 从新绘制
        /// </summary>
        protected override void OnPaint(PaintEventArgs pe)
        {
            // TODO: 在此处添加自定义绘制代码
            // 调用基类 OnPaint
            base.OnPaint(pe);
 
            if (this.Image != null)
            {
                if (currBmp != null) { currBmp.Dispose(); }
                currBmp = new Bitmap(currRect.Width + 2 * borderWidth, currRect.Height + 2 * borderWidth);
                //绘制新图片
                using (Graphics g = Graphics.FromImage(currBmp))
                {
                    using (Pen pen = new Pen(BackColor, borderWidth))
                    {
                        g.DrawRectangle(pen, borderWidth * 0.5f, borderWidth * 0.5f,
                                        currRect.Width + borderWidth,
                                        currRect.Height + borderWidth);
                    }
                    g.DrawImage(this.Image, borderWidth, borderWidth, currRect.Width, currRect.Height);
                }
 
                //图片绘制到控件上
                pe.Graphics.Clear(BackColor);
                if (hScrollBar.Visible || vScrollBar.Visible)
                {//滚动条可见
                    drawDisplayedScrollBars(pe.Graphics);
                }
                else
                {//滚动条不可见
                    float x = 0, y = 0;
                    isMoveScrollBar = false;
 
                    //是否绘制到中心点坐标
                    if (this.SizeMode == PictureBoxSizeMode.CenterImage)
                    {
                        x = Math.Abs(ClientSize.Width - currBmp.Width) * 0.5f;
                        y = Math.Abs(ClientSize.Height - currBmp.Height) * 0.5f;
                    }
                    pe.Graphics.DrawImage(currBmp, x, y, currBmp.Width, currBmp.Height);
                }
            }
        }
 
        /// <summary>
        /// 重写控件大小发生改变事件
        /// </summary>
        protected override void OnClientSizeChanged(EventArgs e)
        {
            base.OnClientSizeChanged(e);
            displayScrollBars();
            setScrollBarsValues();
            Invalidate();
        }
 
        #endregion
 
        #region 图片打印与预览
 
        /// <summary>
        /// 打印图片
        /// </summary>
        public void PrintPictrue()
        {
            PrintDialog printDialog = new PrintDialog();
            printDialog.Document = printDocument;
            //added by lky 2017-11-16 修复Windows 7 x64位环境无法弹出打印对话框的问题
            printDialog.UseEXDialog = true;
            if (printDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    printDocument.Print();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "打印出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
        }
 
        /// <summary>
        /// 打印预览
        /// </summary>
        public void PrintPreview()
        {
            PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
            printPreviewDialog.Document = printDocument;
            try
            {
                printPreviewDialog.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "打印出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        /// <summary>
        /// 打印图片事件
        /// </summary>
        private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            if (currBmp == null)
                return;
            try
            {
                if (PrintAllPages)//added by lky 2018-1-15 打印全部页面
                {
                    int pageWith =(int) e.PageSettings.PrintableArea.Width;
                    int pageHeight = (int)e.PageSettings.PrintableArea.Height;
                    int horizontalTimes = (int)Math.Ceiling((decimal)currBmp.Width / pageWith);//水平方向切割页数
                    int verticalTimes = (int)Math.Ceiling((decimal)currBmp.Height / pageHeight);//垂直方向切割页数
                    if (pageCount == 0)
                    {
                        pageCount = horizontalTimes * verticalTimes;//总页数
                        currentPageIndex = 0;
                    }
                    int horizontalCurrentPosition = (currentPageIndex % horizontalTimes);//当前打印的水平偏移页数
                    int verticalCurrentPosition = (int)Math.Floor((decimal)currentPageIndex / horizontalTimes);//当前打印的垂直偏移页数
                    int x = horizontalCurrentPosition * pageWith;//水平方向打印偏移位置
                    int y = verticalCurrentPosition * pageHeight;//垂直方向打印偏移位置
                    int leftX = (currBmp.Width - x) > 0 ? (currBmp.Width - x) : 0;//水平方向未打印尺寸
                    int leftY = (currBmp.Height - y) > 0 ? (currBmp.Height - y) : 0;//垂直方向未打印尺寸
 
                    Bitmap printBmp = (Bitmap)currBmp.Clone(new Rectangle(x, y, (leftX > pageWith ? pageWith : leftX),
                        (leftY > pageHeight ? pageHeight : leftY)), currBmp.PixelFormat); //待打印图片缓存
                    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
 
                    e.Graphics.DrawImage(printBmp, 0, 0, printBmp.Width, printBmp.Height);
                    printBmp.Dispose();
                    currentPageIndex++;
                    e.HasMorePages = currentPageIndex < pageCount;//是否继续打印
                    if (!e.HasMorePages) pageCount = 0;//打印页数置为0
                }
                else //仅打印首页
                {
                    Bitmap printBmp = (Bitmap)currBmp.Clone();
                    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
                    e.Graphics.DrawImage(printBmp, 0, 0, printBmp.Width, printBmp.Height);
                    printBmp.Dispose();
                }
            }
            catch (Exception ex)
            {
                //写日志文件
                LogWriter.Write(LOG_CATEGORY.WIN_UI, LOG_LEVEL.ERROR, "UCPicturBox.PrintPage" + ex.ToString());
            }
        }
 
        #endregion
 
        #region 图片放大、缩小、原始大小、全屏显示、旋转功能
 
        /// <summary>
        /// 放大图片
        /// </summary>
        public void ZoomInPicture()
        {
            if (this.Image != null)
            {
                //operationState = OperationState.ZoomIn;
                double scale = 1 + (scaleSize * 0.01);
                currRect.Width = Convert.ToInt32(currRect.Width * scale);
                currRect.Height = currRect.Width * this.Image.Height / this.Image.Width;
                if (currRect.Width < (this.Image.Width * scaleScope))
                {                   
                    displayScrollBars();
                    setScrollBarsValues();
                    Invalidate();
                }
            }
        }
 
        /// <summary>
        /// 缩小图片
        /// </summary>
        public void ZoomOutPicture()
        {
            if (this.Image != null)
            {
                //operationState = OperationState.ZoomOut;
                double scale = 1 - (scaleSize * 0.01);
                currRect.Width = Convert.ToInt32(currRect.Width * scale);
                currRect.Height = currRect.Width * this.Image.Height / this.Image.Width;
                displayScrollBars();
                setScrollBarsValues();
                Invalidate();
            }
        }
 
        /// <summary>
        /// 原始大小
        /// </summary>
        public void ZoomOriginalPicture()
        {
            if (this.Image != null)
            {
                //operationState = OperationState.Default;
                isMoveScrollBar = false;
                currRect.Width = this.Image.Width;
                currRect.Height = this.Image.Height;
                displayScrollBars();
                setScrollBarsValues();
                Invalidate();
            }
        }
 
        /// <summary>
        /// 全屏显示
        /// </summary>
        public void ZoomShowAllPicture()
        {
            if (this.Image != null)
            {
                if (this.Image.Width > this.Image.Height)
                {
                    currRect.Width = ClientSize.Width - 2 * borderWidth;
                    currRect.Height = currRect.Width * this.Image.Height / this.Image.Width;
                    if ((currRect.Height + 2 * borderWidth) > ClientSize.Height)
                    {
                        currRect.Height = ClientSize.Height - 2 * borderWidth;
                        currRect.Width = currRect.Height * this.Image.Width / this.Image.Height;
                    }
                    //if ((currRect.Height + 2 * borderWidth) > ClientSize.Height)
                    //{
                    //    currRect.Width = ClientSize.Width - 2 * borderWidth - vScrollBar.Width;
                    //    currRect.Height = currRect.Width * this.Image.Height / this.Image.Width;
                    //}
                }
                else
                {
                    currRect.Height = ClientSize.Height - 2 * borderWidth;
                    currRect.Width = currRect.Height * this.Image.Width / this.Image.Height;
                    if ((currRect.Width + 2 * borderWidth) > ClientSize.Width)
                    {
                        currRect.Width = ClientSize.Width - 2 * borderWidth;
                        currRect.Height = currRect.Width * this.Image.Width / this.Image.Height;
                    }
                    //if ((currRect.Width + 2 * borderWidth) > ClientSize.Width)
                    //{
                    //    hScrollBar.Value = 0;
                    //    currRect.Height = ClientSize.Height - 2 * borderWidth - hScrollBar.Height;
                    //    currRect.Width = currRect.Height * this.Image.Width / this.Image.Height;
                    //}
                }
                isMoveScrollBar = false;
                displayScrollBars();
                setScrollBarsValues();
                Invalidate();
            }
        }
 
        /// <summary>
        /// 旋转图片
        /// </summary>
        public void RotatePicture()
        {
            if (this.Image != null)
            {
                isMoveScrollBar = false;
                this.Image.RotateFlip(RotateFlipType.Rotate90FlipNone);
                int tempWidth = currRect.Width;
                currRect.Width = currRect.Height;
                currRect.Height = tempWidth;
                displayScrollBars();
                setScrollBarsValues();
                Invalidate();
            }
        }
 
        /// <summary>
        /// 显示水平滚动条与垂直滚动条
        /// </summary>
        private void displayScrollBars()
        {
            //是否显示水平滚动条
            if ((currRect.Width + 2 * borderWidth) > ClientSize.Width)
            { hScrollBar.Visible = true; }
            else
            { hScrollBar.Visible = false; }
 
            //是否显示垂直滚动条
            if ((currRect.Height + 2 * borderWidth) > ClientSize.Height)
            { vScrollBar.Visible = true; }
            else
            { vScrollBar.Visible = false; }
        }
 
        /// <summary>
        /// 设置水平滚动条与垂直滚动条值
        /// </summary>
        private void setScrollBarsValues()
        {
            //设置水平滚动条值
            if (hScrollBar.Visible)
            {
                hScrollBar.Minimum = 0;
                hScrollBar.Maximum = currRect.Width - ClientSize.Width + 2 * borderWidth;
                hScrollBar.LargeChange = currRect.Width / 10;
                if (vScrollBar.Visible)
                {
                    hScrollBar.Maximum += vScrollBar.Width;
                }
                if (hScrollBar.LargeChange > hScrollBar.Maximum)
                {
                    hScrollBar.LargeChange = hScrollBar.Maximum - 1;
                }
                hScrollBar.SmallChange = hScrollBar.LargeChange / 5;
                hScrollBar.Maximum += hScrollBar.LargeChange;
 
                //绘制坐标为中心点
                if (this.SizeMode == PictureBoxSizeMode.CenterImage)
                {
                    if (hScrollBar.Value == 0 || isMoveScrollBar == false)
                    {
                        hScrollBar.Value = (hScrollBar.Maximum - hScrollBar.LargeChange) / 2;
                    }
                }
            }
            else
            { hScrollBar.Value = 0; }
 
            //设置垂直滚动条值
            if (vScrollBar.Visible)
            {
                vScrollBar.Minimum = 0;
                vScrollBar.Maximum = currRect.Height - ClientSize.Height + 2 * borderWidth;
                vScrollBar.LargeChange = currRect.Height / 10;
                if (hScrollBar.Visible)
                {
                    vScrollBar.Maximum += hScrollBar.Height;
                }
                if (vScrollBar.LargeChange > vScrollBar.Maximum)
                {
                    vScrollBar.LargeChange = vScrollBar.Maximum - 1;
                }
                vScrollBar.SmallChange = vScrollBar.LargeChange / 5;
                vScrollBar.Maximum += vScrollBar.LargeChange;
 
                //绘制坐标为中心点
                if (this.SizeMode == PictureBoxSizeMode.CenterImage)
                {
                    if (vScrollBar.Value == 0 || isMoveScrollBar ==false)
                    {                       
                        vScrollBar.Value = (vScrollBar.Maximum - vScrollBar.LargeChange) / 2;
                    }
                }
            }
            else
            { vScrollBar.Value = 0; }
        }
 
        /// <summary>
        /// 移动水平滚动条事件
        /// </summary>
        private void scrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            isMoveScrollBar = true;
            using (Graphics graphics = this.CreateGraphics())
            {
                drawDisplayedScrollBars(graphics);
            }
            this.Update();
        }
 
        /// <summary>
        /// 从新绘制显示的滚动条
        /// </summary>
        private void drawDisplayedScrollBars(Graphics graphics)
        {
            float x = 0, y = 0;
 
            if (this.SizeMode == PictureBoxSizeMode.CenterImage)
            {
                x = Math.Abs(ClientSize.Width - currBmp.Width - vScrollBar.Width) * 0.5f;
                y = Math.Abs(ClientSize.Height - currBmp.Height - hScrollBar.Height) * 0.5f;
            }
            if (hScrollBar.Visible == false)
            {//水平滚动条不可见
                destRect.X = x;
                destRect.Y = 0;
                srcRect.X = 0;
                srcRect.Y = vScrollBar.Value;
            }
            else if (vScrollBar.Visible == false)
            {//垂直滚动条不可见
                destRect.X = 0;
                destRect.Y = y;
                srcRect.Y = 0;
                srcRect.X = hScrollBar.Value;
            }
            else
            {//两个滚动条都可见
                destRect.X = 0;
                destRect.Y = 0;
                srcRect.X = hScrollBar.Value;
                srcRect.Y = vScrollBar.Value;
            }
            destRect.Width = currBmp.Width;
            destRect.Height = currBmp.Height;
            srcRect.Width = currBmp.Width;
            srcRect.Height = currBmp.Height;
            graphics.DrawImage(currBmp, destRect, srcRect, GraphicsUnit.Pixel);
        }
 
        #endregion
    }
}

以上就是c# winform 解决PictureBox 无法打印全部图片的问题的详细内容,更多关于解决picturebox无法打印图片的问题的资料请关注我们其它相关文章!

(0)

相关推荐

  • C# winform打印excel的方法

    前言 c#做winform程序要求生成并打印Excel报告,为了不安装Office相应组件,我选择了NPOI来生成Excel报告,用winform的PrintDocument控件来触发打印操作,而难点在于如何将excel转换成Graphics对象,在NPOI中我只找到了excel打印的设置(如横向/纵向),还需要打开excel去触发打印操作,但项目要求是一次性直接实现打印,要用PrintDocument控件而不是再去操作excel.不得已重新搜索,发现了类库Spire.xls,最终实现了要求.有

  • C# Winform调用百度接口实现人脸识别教程(附源码)

    百度是个好东西,这篇调用了百度的接口(当然大牛也可以自己写),人脸检测技术,所以使用的前提是有网的情况下.当然大家也可以去参考百度的文档. 话不多说,我们开始: 第一步,在百度创建你的人脸识别应用 打开百度AI开放平台链接: 点击跳转百度人脸检测链接,创建新应用 创建成功成功之后.进行第二步 第二步,使用API Key和Secret Key,获取 AssetToken 平台会分配给你相关凭证,拿到API Key和Secret Key,获取 AssetToken 接下来我们创建一个AccessTo

  • C# WinForm调用Shell_NotifyIcon的示例代码

    public class InnerClass: Form { private Shell_NotifyIconEx servicesClass = null; // 接受主CLASS 的实例句柄 internal InnerClass(Shell_NotifyIconEx _servicesClass) { servicesClass = _servicesClass; } private const int WM_LBUTTONDOWN = 0x0201; // 左键 private con

  • C# winform中窗口关闭按钮的隐藏与禁用详解

    首先说一句: 不存任何一种方式可以单独隐藏关闭按钮,隐藏的话会把所有最大化,最小化,帮助,关闭按钮都给隐藏掉. 第一种:禁用窗口上部的关闭按钮 方法一:在Form1的窗口程序中desigener设计器中重写如下方法:(将此部分粘贴到窗口程序中去就可以了) protected override void WndProc(ref Message m) { const int WM_SYSCOMMAND = 0x0112; const int SC_CLOSE = 0xF060; if (m.Msg

  • C# Winform按钮中图片实现左图右字的效果实例

    设置流程 百度查阅了几个资料感觉没啥用,经过自己一番试验,总结了简单的方法,具体做法是 1.从工具栏拖出一个按钮 2.在vs外部 使用编辑进入到画图中使用 修改其像素值 3.设置按钮的image属性,插入图片 4.设置图片的属性 5.关于按钮Text属性的设置 6.看一下效果 需要注意的点 最好事先知道你需要的按钮的大小,比如我需要把button放入到size高度为40px的panel中,则你的图片最好像素值35以下,不然会出现图片超过边框的效果:如果要将设计好的按钮放置到容器内,需考虑到容器本

  • C# Winform实现波浪滚动效果

    本文实例为大家分享了C# Winform实现波浪滚动效果的具体代码,供大家参考,具体内容如下 设计思路 1.首先,理解一个概念:正弦波,余弦波.相信接受过九年义务教育的同志都清楚, 听说某华大学的高材生表示小学一年级就会计算三角函数,~~~~. 2.本人使用的是C#实现的,至于有人说JAVA效率更高,那也可以使用JAVA,只要原理清晰就ok. 3.碍于本人算法技术的局限,最终产生的效果并不是最优解,人山人海的CSDN里希望能有读者看完我的见解后能提出更好的算法思想!:) 4.既然是平面运动,我们

  • c# winform异步不卡界面的实现方法

    快速阅读 如何在winform程序中,让界面不再卡死. 关于委托和AsyncCallback的使用. 界面卡死的原因是因为耗时任务的计算占用了主线程,导致主界面没有办法进行其它操作,比如拖动.造成界面卡死的现象.我们只需要把耗时任务放在子线程中执行就可以了. 子线程的计算结果 要更新到界面中,怎么更新呢,因为不能操作主线程 ,所以要用委托来实现 . 我们来看个例子. 场景 界面上一个按钮加一人richbox , 点击以后获得当前所在年份 代码实现 定义一个委托实现子线程更新主线程 public

  • C# Winform程序实现防止多开的方法总结【亲测】

    本文实例讲述了C# Winform程序实现防止多开的方法.分享给大家供大家参考,具体如下: 1.Winform启动的时候,检测是否存在同样的进程名,防止程序多开: static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static void Main() { Process[] processes = Process.GetProcesses(); Process current

  • C# WinForm-Timer控件的使用

    比如在窗体中显示时间: 错误思路一:我在窗体结构函数中写入一个死循环,每隔一秒显示一次当前时间 public Form6() { InitializeComponent(); while (true) { label1.Text = DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒"); System.Threading.Thread.Sleep(1000); } } 错误原因:结构函数无限循环,结构函数读不完代码是无法打开窗体的 错误思路二:放置

  • C# Winform中如何绘制动画示例详解

    前言 这里介绍一个.net自身携带的类ImageAnimator,这个类类似于控制动画的时间轴,使用ImageAnimator.CanAnimate可以判断一个图片是否为动画,调用ImageAnimator.Animate可以开始播放动画,即每经过一帧的时间触发一次OnFrameChanged委托,我们只要在该委托中将Image的活动帧选至下一帧再迫使界面重绘就可以实现动画效果了. 为了方便以后的使用,我将这些代码整合到了一起,形成一个AnimateImage类,该类提供了CanAnimate.

随机推荐