C# + Ext.Net打印

本文介绍了一种用于模板套打的技术方案,通过调整字体大小和图片缩放比例来适应固定尺寸的打印模板。文章详细展示了如何根据文本内容自适应调整字体,并通过代码示例说明了如何生成和处理图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近期做了一套打印的功能,主要实现模板套打。因为模板中每个信息项的位置和尺寸都是固定的,所有有些不定长的文本就需要使用图片来实现等比例缩放

我的技术解决方案就是:

根据要求的文本信息得出需要的画布大小,在根据模板区域的大小缩放生成的图片以适应模板

参数:文本内容、字体、字号、字体样式(枚举)、字体方向、模板区域大小

代码如下:

/// <summary>
		/// 根据原画布尺寸和内容获取适应的字体
		/// </summary>
		/// <param name="width">原画宽</param>
		/// <param name="height">原画高</param>
		/// <param name="content">内容</param>
		/// <param name="isVertical">文字方向</param>
		/// <param name="fontName">字体</param>
		/// <param name="fontSize">字号</param>
		/// <param name="fstyle">字体样式</param>
		/// <returns>调整后的字体</returns>
		public Font GetAdaptiveFont(int width, int height, string content, bool isVertical, string fontName, int fontSize, FontStyle fstyle) {
			Font myFont = new Font(fontName, fontSize, FontStyle.Bold);
			Image imSource = new Bitmap(width, height);
			Graphics gSource = Graphics.FromImage(imSource);
			Size iNeed = gSource.MeasureString(content, myFont).ToSize();
			int iLen = content.Length;
			if (!isVertical) {
				if ((int)iNeed.Height > imSource.Height) {
					while (myFont.Size > 1) {
						myFont = new Font(fontName, fontSize, fstyle);
						iNeed = gSource.MeasureString(content, myFont).ToSize();
						if ((int)iNeed.Height <= imSource.Height) {
							break;
						}
						fontSize -= 2;
					}
				}
			} else {
				iNeed = gSource.MeasureString(content.Substring(0, 1), myFont).ToSize();
				if ((int)iNeed.Width > imSource.Width) {
					while (myFont.Size > 1) {
						myFont = new Font(fontName, fontSize, fstyle);
						iNeed = gSource.MeasureString(content.Substring(0, 1), myFont).ToSize();
						if ((int)iNeed.Width <= imSource.Width) {
							break;
						}
						fontSize -= 2;
					}
				}
			}
			return myFont;
		}

此方法根据以上参数调整字体以适应画布,之后根据调整后的字体生成图片:
/// <summary>
		/// 画图
		/// </summary>
		/// <param name="myFont">字体</param>
		/// <param name="myBrush">字体颜色</param>
		/// <param name="content">内容</param>
		/// <returns>画好的图片</returns>
		private Image DrawImage(Font myFont, SolidBrush myBrush, string content) {
			Image image = new Bitmap(1, 1);
			Graphics g = Graphics.FromImage(image);
			Size iNeed = g.MeasureString(content, myFont).ToSize();
			image = new Bitmap(iNeed.Width, iNeed.Height);
			g = Graphics.FromImage(image);
			g.Clear(Color.White);
			g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
			g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
			g.DrawString(content, myFont, myBrush, 0f, 0f);
			return image;
		}

下一步要做的是根据模板区域大小对图片进行缩放处理:
/// <summary>
		/// 获得缩放后的图片
		/// </summary>
		/// <param name="isVertical">文字方向</param>
		/// <param name="imSource">原画尺寸</param>
		/// <param name="imNeed">实际尺寸</param>
		/// <param name="content">内容</param>
		/// <returns></returns>
		public Image GetStrukImage(bool isVertical, Image imSource, Image imNeed, string content) {
			Graphics gSource = Graphics.FromImage(imSource);
			if (!isVertical) {
				//字体高度 = 画布高度,宽度拉伸
				if ((int)imNeed.Width > imSource.Width) {
					gSource.DrawImage(imNeed, new Rectangle(0, 0, imSource.Width, imSource.Height), new Rectangle(0, 0, imNeed.Width, imNeed.Height), GraphicsUnit.Pixel);
				} else {
					imSource = imNeed;
				}
			} else {
				int iLen = content.Length;
				//字体宽度 = 画布看度,高度拉伸
				if ((int)imNeed.Height > imSource.Height) {
					gSource.DrawImage(imNeed, new Rectangle(0, 0, imSource.Width, imSource.Height), new Rectangle(0, 0, imNeed.Width, imNeed.Height), GraphicsUnit.Pixel);
				} else {
					imSource = imNeed;
				}
			}
			return imSource;
		}

因为是套打,打印的纸张有背景图,所以生成的图片就要做透明处理,去掉图片的底色,以免覆盖套打模板:
/// <summary>
		/// 返回一个透明背景的位图
		/// </summary>
		/// <param name="image">要设置透明的位图</param>
		/// <param name="color">要设置透明的颜色</param>
		/// <returns>透明背景的位图</returns>
		public Image MakeTransparentGif(Image image, Color color) {
			byte R = color.R;
			byte G = color.G;
			byte B = color.B;
			MemoryStream fin = new MemoryStream();
			image.Save(fin, System.Drawing.Imaging.ImageFormat.Gif);
			MemoryStream fout = new MemoryStream((int)fin.Length);
			int count = 0;
			byte[] buf = new byte[256];
			byte transparentIdx = 0;
			fin.Seek(0, SeekOrigin.Begin);
			//header
			count = fin.Read(buf, 0, 13);
			if ((buf[0] != 71) || (buf[1] != 73) || (buf[2] != 70))
				return null; //GIF
			fout.Write(buf, 0, 13);
			int i = 0;
			if ((buf[10] & 0x80) > 0) {
				i = 1 << ((buf[10] & 7) + 1) == 256 ? 256 : 0;
			}
			for (; i != 0; i--) {
				fin.Read(buf, 0, 3);
				if ((buf[0] == R) && (buf[1] == G) && (buf[2] == B)) {
					transparentIdx = (byte)(256 - i);
				}
				fout.Write(buf, 0, 3);
			}
			bool gcePresent = false;
			while (true) {
				fin.Read(buf, 0, 1);
				fout.Write(buf, 0, 1);
				if (buf[0] != 0x21)
					break;
				fin.Read(buf, 0, 1);
				fout.Write(buf, 0, 1);
				gcePresent = (buf[0] == 0xf9);
				while (true) {
					fin.Read(buf, 0, 1);
					fout.Write(buf, 0, 1);
					if (buf[0] == 0)
						break;
					count = buf[0];
					if (fin.Read(buf, 0, count) != count)
						return null;
					if (gcePresent) {
						if (count == 4) {
							buf[0] |= 0x01;
							buf[3] = transparentIdx;
						}
					}
					fout.Write(buf, 0, count);
				}
			}
			while (count > 0) {
				count = fin.Read(buf, 0, 1);
				fout.Write(buf, 0, 1);
			}
			fin.Close();
			fout.Flush();
			return new Bitmap(fout);
		}

接下来就是逻辑部分了,将图片做数据流返回:
MemoryStream ms = new MemoryStream();
			imNeed.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
			imNeed.Dispose();

			Byte[] fileBytes = ms.GetBuffer();
			ms.Close();
			Context.Response.BinaryWrite(fileBytes);

在这里还要做一下说明:有些图片格式是不能够做透明处理的,我试过了好像只有png和bmp可以

接下来要说一下Ext.Net打印的部分了,这部门主要是页面的处理,Ext.Net本身有样式,在打印的时候布局很难调整,如果使用windows的ifreame且页面不带Ext.Net的任何控件,则一点问题没有,我直接贴代码了,没什么好说的,我现在的问题就是会多打出来一份空白页,不知道该怎么解决,还请高手指导一下:

<ext:Viewport runat="server" Layout="FitLayout">
		<Items>
			<ext:Panel ID="pnlMain" runat="server" Layout="FitLayout">
				<TopBar>
					<ext:Toolbar ID="tbrTool" runat="server" LabelWidth="30">
						<Items>
							<ext:ComboBox ID="cmbTemplate" runat="server" FieldLabel="模板">
								<Listeners>
									<Select Handler="GetTemplate()" />
								</Listeners>
							</ext:ComboBox>
							<ext:CompositeField ID="CompositeField1" runat="server" FieldLabel="缩放" Width="200" Flex="1">
								<Items>
									<ext:SliderField ID="ZoomSlider" runat="server">
										<Slider ID="sdZoom" runat="server" Width="100" MinValue="50" MaxValue="150" Increment="10" Value="100">
											<Listeners>
												<Change Fn="PageZoom" />
												<AfterRender Handler="txtZoom.setValue(this.value);" />
											</Listeners>
											<Plugins>
												<ext:SliderTip ID="SliderTip1" runat="server">
													<GetText Handler="return thumb.value.toString()+'%';" />
												</ext:SliderTip>
											</Plugins>
										</Slider>
									</ext:SliderField>
									<ext:SpinnerField runat="server" ID="txtZoom" Width="50" MinValue="50" MaxValue="150" IncrementValue="10" AnchorHorizontal="100%">
										<Listeners>
											<Change Handler="zoom();" />
											<SpinDown Handler="zoom();" />
											<SpinUp Handler="zoom();" />
										</Listeners>
									</ext:SpinnerField>
								</Items>
							</ext:CompositeField>
							<ext:ToolbarSeparator />
							<ext:Button ID="btnPrint" runat="server" Text="打印" Icon="Printer" OnClientClick="Print()" />
						</Items>
					</ext:Toolbar>
				</TopBar>
				<AutoLoad Url="about:blank" Mode="IFrame" />
			</ext:Panel>
		</Items>
	</ext:Viewport>

打印之前需要调整缩放,打印之后要还原回来,OK



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值