C#打印高手请进来指导一下

时间:2022-03-28 11:27:02
我的软件有几种报告打印格式,但是有60%的内容每个格式都相同,比如生成一些背景网格之类。所以我希望这一部分只执行一次,以后每次打印都直接调用生成的对象。我的想法跟Form中一样,先生成重复使用的bitmap,然后需要的地方再用DrawImage(bitmap,0,0)的方式贴图。
下面是原先的代码,目的是在打印纸上对角线画条直线,分辨率600DPI。
e.Graphics.PageUnit = GraphicsUnit.Pixel;
Pen pen = new Pen(Brushes.Black, 1);
Graphics grfx = e.Graphics;
grfx.DrawLine(pen, 0, 0, (int)grfx.VisibleClipBounds.Width, (int)grfx.VisibleClipBounds.Height);
上面的代码运行正常,打印很清晰。

下面的代码使用bitmap。
e.Graphics.PageUnit = GraphicsUnit.Pixel;
Graphics grfx = e.Graphics;
Bitmap bmp = new Bitmap((int)grfx.VisibleClipBounds.Width, (int)grfx.VisibleClipBounds.Height);
Graphics grfx1 = Graphics.FromImage(bmp);
Pen pen = new Pen(Brushes.Black, 1);
grfx1.DrawLine(pen, 0, 0, bmp.Width, bmp.Height);
grfx1.DrawLine(pen, bmp.Width, 0, 0, bmp.Height);
Rectangle re = new Rectangle(0, 0, bmp.Width, bmp.Height);
grfx.DrawImage(bmp, new Rectangle(0, 0, (int)grfx.VisibleClipBounds.Width, (int)grfx.VisibleClipBounds.Height), re, GraphicsUnit.Pixel);

上面的代码可以正常缩放,但是打印出来的直线效果很差,不知道应该如何处理。

10 个解决方案

#1


up

#2


//换个思想吧??
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PrintDataGirdView
{
    public partial class Form1 : Form
    {
        JobDataSet ds = new JobDataSet();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.printDocument1.Print();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.printPreviewDialog1.ShowDialog();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            JobDataSetTableAdapters.jobsTableAdapter da = new PrintDataGirdView.JobDataSetTableAdapters.jobsTableAdapter();
            da.Fill(ds.jobs);
            this.dataGridView1.DataSource = ds.jobs;
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            Font font = new Font("宋体", 10);
            e.Graphics.DrawString("jobs表记录信息",font, Brushes.Black, 400, 20);
            e.Graphics.DrawString("时间:" + DateTime.Now.ToLongDateString(), font,Brushes.Black, 20, 40);
            e.Graphics.DrawString("编号", font, Brushes.Black, 140, 80);
            e.Graphics.DrawString("职务", font, Brushes.Black, 200, 80);
            e.Graphics.DrawString("最小值", font, Brushes.Black, 400, 80);
            e.Graphics.DrawString("最大值", font, Brushes.Black, 550, 80);

            DataTable dt=(DataTable)this.dataGridView1.DataSource;
            int startX = 140, startY = 100, offsetX = 160, offsexY = 20;
            for (int i = 0; i <dt.Rows.Count; i++)
            {
               DataRow row=dt.Rows[i];
               startY += offsexY;
               startX = offsetX;
               for (int j = 0; j < dt.Columns.Count; j++)
               {
                   e.Graphics.DrawString(row[j].ToString(), font, Brushes.Black,startX,startY);
                   startX += offsetX;
               }
               
            }

        }
    }
}

#3


楼上可能没有看明白我的问题,我的意思是某些部分的内容只运行一次,而不是用程序填充。

#4


加上

   grfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                grfx.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;

看看.

#5


还真不能插值 因为需要的是1:1

#6


你的打印机的DPI 和系统PrintDocument的DPI不同把.

#7


e.Graphics.PageUnit = GraphicsUnit.Pixel;之后
e.Graphics.VisibleClipBounds就变成对应于600dpi的数值了。
我就创建一个跟VisibleClipBounds一样尺寸的bitmap,然后在这个bitmap上绘图,最后再用e.Graphics.DrawImage(bmp,0,0)帖回,但是没有得到预想的结果。

1、这种方式在屏幕绘图操作中没有问题,因为肯定的说单位不会有任何区别。
2、这种方式在打印绘图中确实有些问题难以搞明白,就是不知道这个时候两个Graphics是个什么关系,是不是1:1

#8


该回复于2011-05-13 20:14:50被版主删除

#9


问题解决 

#10


问题虽然解决 但是没有达到预期的目的,因为直接用bitmap打印的话打印文件相当的大,达到90多MB,反而降低了打印速度。

#1


up

#2


//换个思想吧??
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PrintDataGirdView
{
    public partial class Form1 : Form
    {
        JobDataSet ds = new JobDataSet();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.printDocument1.Print();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.printPreviewDialog1.ShowDialog();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            JobDataSetTableAdapters.jobsTableAdapter da = new PrintDataGirdView.JobDataSetTableAdapters.jobsTableAdapter();
            da.Fill(ds.jobs);
            this.dataGridView1.DataSource = ds.jobs;
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            Font font = new Font("宋体", 10);
            e.Graphics.DrawString("jobs表记录信息",font, Brushes.Black, 400, 20);
            e.Graphics.DrawString("时间:" + DateTime.Now.ToLongDateString(), font,Brushes.Black, 20, 40);
            e.Graphics.DrawString("编号", font, Brushes.Black, 140, 80);
            e.Graphics.DrawString("职务", font, Brushes.Black, 200, 80);
            e.Graphics.DrawString("最小值", font, Brushes.Black, 400, 80);
            e.Graphics.DrawString("最大值", font, Brushes.Black, 550, 80);

            DataTable dt=(DataTable)this.dataGridView1.DataSource;
            int startX = 140, startY = 100, offsetX = 160, offsexY = 20;
            for (int i = 0; i <dt.Rows.Count; i++)
            {
               DataRow row=dt.Rows[i];
               startY += offsexY;
               startX = offsetX;
               for (int j = 0; j < dt.Columns.Count; j++)
               {
                   e.Graphics.DrawString(row[j].ToString(), font, Brushes.Black,startX,startY);
                   startX += offsetX;
               }
               
            }

        }
    }
}

#3


楼上可能没有看明白我的问题,我的意思是某些部分的内容只运行一次,而不是用程序填充。

#4


加上

   grfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                grfx.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;

看看.

#5


还真不能插值 因为需要的是1:1

#6


你的打印机的DPI 和系统PrintDocument的DPI不同把.

#7


e.Graphics.PageUnit = GraphicsUnit.Pixel;之后
e.Graphics.VisibleClipBounds就变成对应于600dpi的数值了。
我就创建一个跟VisibleClipBounds一样尺寸的bitmap,然后在这个bitmap上绘图,最后再用e.Graphics.DrawImage(bmp,0,0)帖回,但是没有得到预想的结果。

1、这种方式在屏幕绘图操作中没有问题,因为肯定的说单位不会有任何区别。
2、这种方式在打印绘图中确实有些问题难以搞明白,就是不知道这个时候两个Graphics是个什么关系,是不是1:1

#8


该回复于2011-05-13 20:14:50被版主删除

#9


问题解决 

#10


问题虽然解决 但是没有达到预期的目的,因为直接用bitmap打印的话打印文件相当的大,达到90多MB,反而降低了打印速度。