by Michael Eaton

技术工具箱:C#

(百度N久,终于找到了,大多是残篇,费了大功夫,汇集起来,最后一个图仍然没找到)

你可以用几种方法在.NET中编程来生成打印输出结果(如报表)。对Windows程序员来说,Visual Studio提供的Crystal Reports实际上是人们常用的打印报表的工具,但对不太复杂的报表来说,这个工具就有些大材小用了。

你可以用几种方法在.NET中编程来生成打印输出结果(如报表)。对Windows程序员来说,Visual Studio提供的Crystal Reports实际上是人们常用的打印报表的工具,但对不太复杂的报表来说,这个工具就有些大材小用了。当然,你可以用很好的Win32 API调用,但是尽管API可以让你有完全的控制权,它同时也把你锁定到一个单一的平台上了。如果Microsoft或另外的公司(如拥有Mono项目的Ximian公司)把Framework转移到另外的平台上,那么运用API的程序仍会锁定在Windows上,除非你为新的平台重新编写它们。

.NET Framework可以让你以一种新的方式来使用这些打印方法,System.Drawing.Printing名字空间的类将Win32 API的细粒度控制(fine-grain control)与相对简单的Visual Basic传统的Printer对象结合了起来(见表下)。

fine-grain control(精细控制)与相对简单的Visual Basic传统的Printer对象结合了起来(见表下)。

 表1   研究.NET的众多的打印类.

说 明

PrintDocument

可以让你定义一个对象,该对象把输出发送到一台打印机。

PrintEventArgs

为BeginPrint和EndPrint事件提供所有的必需的信息。

PrintPageEventArgs

为PrintPage事件提供所有必需的信息。

QueryPageSettingsEventArgs

为QueryPageSettings事件提供信息。

PrintController

控制一个PrintDocument是如何打印的。

StandardPrintController

派生于PrintController。

PreviewPrintController

派生于PrintController。

PreviewPageInfo

PreviewPrintController 经常运用这个类。它为一个单独的页面指定了预览信息。

PageSettings

指定一个单独的打印页面的设置。

Margins

可以让你指定一个打印页面的页边距。页面的顶部、左边、右边和底部边距属性是以英寸(×100)的形式返回的。

MarginsConverter

可以让你把一个Margins对象转换成另外的类型,把另外的类型转换成一个Margins对象。

PaperSize

指定一页纸的大小。当同一个PageSettings对象一起使用时,它指的是一个页面的纸张大小。当用于PrinterSettings时,它可以让你得到打印机上可以用的纸张大小。

PaperSizeCollection

PaperSize对象的一个集合。

PaperSource

像PaperSize类一样,PaperSource 是由一个PageSettings对象和一个PrinterSettings对象使用的。当用于PageSettings时,它可以让你为一个特定页面得到纸张来源。当用于PrinterSettings时,它可以让你得到打印机运用的所有纸张来源。

PaperSourceCollection

PaperSource 对象的一个集合。

PrinterSettings

指定一个文件是如何打印的,包括文件在哪个打印机上打印。它是与特定的PrintDocument相应的。

PrinterResolution

可以让你得到横向的和纵向的DPI,以及实际的打印机分辨率(draft, high, low,等等)。

PrinterResolutionCollection

PrinterResolution 对象的一个集合。

InvalidPrinterException

表示将抛出的异常(如果你用无效的设置来访问一台打印机)。

PrintingPermission

控制对打印机的使用权限。

PrintingPermissionAttribute

允许检测打印权限。

运用.NET Framework的System.Drawing.Printing名字空间,你就可以程序化地处理许多打印任务,该名字空间包含20多个类、7个枚举类型和3个委托类型(delegate)。让我们来看看对每个类的简要说明吧!

在此,我将重点讲述该名字空间的主要的类,它们可以让你创建复杂程度适度的报表。PrintDocument类是这些类中最重要的。它可以让你定义一个对象,该对象发送输出结果到一个目的地,可以是一台打印机,或者是显示一个打印预览(运用PrintPreviewDialog类)。我还会讲述PrinterSettings类,它可以让你控制文件是如何打印的。

你可以很容易地在C#中创建一个PrintDocument对象,并把它附到一个事件处理程序上(实际处理打印的代码):

PrintDocument doc = new  PrintDocument();
doc.PrintPage += new  PrintPageEventHandler(doc_PrintPage);

PrintPage事件处理程序有一个PrintPageEventArgs类型的参数。这个参数包含与该事件相关的数据,包括当前页面的页面设置、页边距信息以及是否有更多的页需要打印。每个页面触发该事件一次,直到ev.HasMorePages等于false:

private void doc_PrintPage(object sender, PrintPageEventArgs ev)

将Graphics用于Fonts和Fills

ev参数引用了你用来输出数据的Graphics制图区。Graphics有用来打印图象、文本、形状和线条的方法。你可以用DrawString方法来定义你要用的font(字体)和brush(画刷)。一个brush定义了一个图形的内部是如何填充的。你也需要告诉DrawString方法你想在哪里打印文本。PrintPageEventArgs类有一个读写属性――HasMorePages――它指明是否需要打印更多的页面:

Font f = new Font("Arial", 12);
ev.Graphics.Drawstring("Hello,World.",f, Brushes.Black, 100, 100);
ev.HasMorePages = false;

现在,你已经创建了一个PrintDocument对象并把它和一个事件处理程序联系起来了。你已经给事件处理程序中添加了代码,来打印一个单独的字符串,它的位置是距页面左边一英寸、距页面顶部一英寸,用的是12磅、 Arial的字体。现在我们来打印文件:

doc.Print();

在缺省设置下,PrintDocument类的Print方法在缺省打印机上打印结果,除非你另外指定。你可以用PrintDialog类来另外指定,它是System.Windows.Forms.CommonDialog名字空间的一部分。PrintDialog可以让你选择打印机,选择打印文件的哪部分,选择打印份数,来随意地打印一个文件。

PrintDialog类的PrinterSettings属性可以让你将诸如copies、from page和to page的属性放置到一个特定文件的PrinterSettings对象中。换句话说,单独的PrintDocument对象有一个PrinterSettings对象,它指定打印的份数、打印的范围、要运用的打印机的名字以及关于打印机本身的信息。

IPrinterSettings类中的一个bug会导致Copies属性总是返回一个为1的值,而不管你在PrintDialog中输入了多少份数。然而,PrintDocument.Print()方法仍然打印正确的份数,所以只有当你想将这个值用于其它地方时,才显示这个bug。当你执行Print方法时,系统运用这些设置。你可以提供一个实际的PrinterSettings对象或提供一个Document对象:

PrintDialog pd = new PrintDialog();
pd.Document = doc;
pd.ShowDialog();

然后,运用CommonDialog名字空间的PageSetupDialog,你可以指定纸张大小、纸张来源、打印方向和页边距。PageSetupDialog和PrintDialog都需要你提供一个Document对象或一个PageSettings对象。PageSettings对象适用于一个单独的打印页面,可以处理页边距、纸张大小以及是否用颜色打印页面:

PageSetupDialog ps = new  PageSetupDialog();
ps.Document = doc;
ps.ShowDialog();

打印一个文件

当然,许多应用程序打印存储在一个文件或某种数据库中的信息,所以现在我将讲述一个更复杂的例子:打印一个以逗号分隔的联系清单文本文件。你可以将一个数据集、甚至一个XML文件中数据所运用的方法用在这里。本例的数据来自Northwind数据库的Customers表,格式如下:

Name, Title, Phone, Fax

通过在类的级别声明一个StreamReader对象,然后将一个文件分配给它,你就可以从一个文本文件打印该例子了。打开文件,修改PrintPage事件处理程序来打印文件的每一行,按需要格式化数据。

PrintDocument类有好几个事件。你已经用了PrintPage事件了;现在我们来添加更多的事件。当开始一个打印任务时(在实际打印任何东西前),触发BeginPrint事件。相应的事件是EndPrint,该事件是在所有页面结束打印时触发的。创建PrintPage事件需要的任何对象,或在BeginPrint中打开任何数据源,然后在EndPrint中关闭或释放(deallocate)它们。不要忘记将这些事件绑定到PrintDocument对象(列表1)。

C#:创建和部署
列表 1.

PrintDocument对象提供了几个事件。BeginPrint是在实际打印页面前触发的,可以给你提供机会来配置对象或打开文件。EndPrint在打印完最后一页时触发。不要忘记将事件绑定到你的PrintDocument对象。

// At the class level
private Font bodyFont;
private Font headerFont;
private StreamReader data;
private PrintDocument doc;private void MainForm_Load(object sender, System.EventArgs e) {doc = new PrintDocument();// shows up in Print Managerdoc.DocumentName = "Contact List";doc.BeginPrint += new PrintEventHandler(doc_BeginPrint);doc.EndPrint += new PrintEventHandler(doc_EndPrint);
}private void doc_BeginPrint(object sender, PrintEventArgs pv) {data = new StreamReader("contacts.csv");Font bodyFont = new Font("Arial", 12);Font headerFont = new Font("Arial", 24);
}private void doc_EndPrint(object sender, PrintEventArgs pv) {data.Close();bodyFont.Dispose();headerFont.Dispose();
}

作为选择,你也可以把所有的打印功能封装到PrintDocument派生的一个单独的类中,然后重载触发相应事件的方法。你可以用你自定义的类,而不用实例化一个PrintDocument对象(见列表2)。这是一个很好的方法,但是为了保持一致,使代码清晰,我将继续讲述事件绑定方法。

C#:继承 PrintDocument
列表 2
.
从PrintDocument派生一个新类,这样你就可以把所有打印功能封装在一个单独的地方,从而提高代码的重用性。

public class CustomPrintDocument : PrintDocument {private StreamReader dataToPrint;public CustomPrintDocument(StreamReader data) :base(){dataToPrint = data;}protected override void OnBeginPrint(PrintEventArgs ev){base.OnBeginPrint(ev) ;}protected override void OnEndPrint(PrintEventArgs ev){base.OnEndPrint(ev);}protected override void OnQueryPageSettings(QueryPageSettingsEventArgs ev) {base.OnQueryPageSettings(ev);}protected override void  OnPrintPage(PrintPageEventArgs ev) {base.OnPrintPage(ev);ev.Graphics.DrawString("this is a test", new Font("Arial", 24), Brushes.Black, 100, 100);ev.HasMorePages = false;}
}

PrintDocument类没有制图工具,所以创建报表需要花些时间——但这是值得的。创建一个新的报表的最好的方法是用一张空白的纸。在了解了报表的目的后,你就可以在纸上通过画方框来代表不同的区域进行设计了,如页眉、正文和页脚(见图1)。然后花些时间详细编写每个区域的数据将来自哪里,以及各个数据将放置在什么位置。可以说这个时候是你确保最终用户所看到的页面与你设计的页面是否是一致的最佳时刻。用户对报表比对应用程序的任何部分的挑剔都要多,所以你应该尽可能多花些时间来设计它。一旦你花了很多时间来设计报表并对它的打印结果了如指掌后,那么写代码就不会花很多时间了。

   图1   显示你的报表

写代码 

Rectangle对象提供了最快、最简单的方法来将你的页面设计转换成代码。这些对象可以让你几乎很准确地在屏幕上模拟你的设计。在页面上定义一个区域,指定坐标(有一定的高度和宽度)。Rectangle对象可以给你提供指定的点,在这个点上,你可以用Graphics类的Draw方法放置文本和图形。特别的是,你可以用DrawRectangle方法来查看该区域在页面的什么位置。该方法需要一个Pen对象(用来画直线和曲线)。将所有的版面设计代码放在PrintPage事件过程中:

// print a red line around the border
// of the page
ev.Graphics.DrawRectangle(Pens.Red, leftMargin, topMargin,pageWidth, pageHeight);

.NET Framework 1.0不能得到一台打印机的“hard”margins(实际可以打印到的页面最外面的区域)。但是,PrintPageEventArgs可以让你通过MarginBounds属性得到类似的功能。不幸的是,MarginBounds不考虑hard margins,所以你的输出可能不能在你期望的位置上结束。你必须用P/Invoke并调用Win32 GetDeviceCaps函数来得到打印机的hard margins(见列表3)。

C#:用P/Invoke得到页边距
列表 3.

.NET Framework不提供方法得到一台打印机的hard margins,所以你需要用P/Invoke并调用Win32的GetDeviceCaps函数。这个类的这个方法中包含一个设备驱动程序代码(hDc),然后用你需要的信息来填充类成员。

[DllImport("gdi32.dll")]
private static extern Int16 GetDeviceCaps([In][MarshalAs (UnmanagedType.U4)] int hDc, [In] [MarshalAs(UnmanagedType.U2)] Int16 funct);
private float _leftMargin = 0;
private float _topMargin = 0;
private float _rightMargin = 0;
private float _bottomMargin = 0;const short HORZSIZE      = 4;
const short VERTSIZE      = 6;
const short HORZRES       = 8;
const short VERTRES       = 10;
const short PHYSICALOFFSETX = 112;
const short PHYSICALOFFSETY = 113;public marginInfo(int deviceHandle) {float offx = Convert.ToSingle(GetDeviceCaps(deviceHandle, PHYSICALOFFSETX));float offy = Convert.ToSingle(GetDeviceCaps(deviceHandle, PHYSICALOFFSETY));float resx = Convert.ToSingle(GetDeviceCaps(deviceHandle, HORZRES));GetDeviceCaps(deviceHandle, VERTRES));float hsz = Convert.ToSingle(GetDeviceCaps(deviceHandle, HORZSIZE))/25.4f;float vsz = Convert.ToSingle(GetDeviceCaps(deviceHandle,VERTSIZE))/25.4f;float ppix = resx/hsz;float ppiy = resy/vsz;_leftMargin  = (offx/ppix) * 100.0f;_topMargin   = (offy/ppix) * 100.0f;_bottomMargin  = _topMargin + (vsz * 100.0f);_rightMargin  = _leftMargin + (hsz * 100.0f);
}

在得到hard margins后,你就可以开始创建Rectangle对象并在你的报表上打印信息了(见列表4)。

                                                              C#:设计报表的版面
                                                                        列表 4.

任何报表的基本格式至少必须包含一个页眉、正文和页脚区域。运用Rectangle对象可以很容易地设计你的报表版面。通过添加更多的Rectangle对象,你就可以提供这些报表的复杂程度。

// create the header
int headerHeight = hf.GetHeight(ev.Graphics);
RectangleF header = new RectangleF(leftMargin, topMargin,pageWidth, headerHeight);// create the footer
int bodyFontHeight =bodyFont.GetHeight(ev.Graphics);
RectangleF footer = new RectangleF(leftMargin, body.Bottom, pageWidth, bodyFontHeight);
// create the body section
RectangleF body = new RectangleF(leftMargin, header.Bottom, pageWidth, pageHeight - bodyFontHeight);

现在你已经创建了长方形边框(rectangles),你就可以在这个位置上打印你的数据了。一次打印一页数据,所以你需要定义一个页面有多大。用一个标准行的高度来划分可打印的区域(本例中你的正文区),从而计算每个页面的行数。通过用你运用的Font对象的GetHeight方法来确定一个行的高度。GetHeight是个属于Font类的重载的方法。你运用的方法需要一个Graphics对象参数。PrintPage事件的PrintPageEventArgs参数提供了这个Graphics对象:

int linesPerPage = Convert.ToInt32(body.Height / bodyFont.GetHeight(ev.Graphics));

一旦你确定了构成一个页面的行数,你就只需要进行简单的循环就行了,直到一个页面结束。然后设置ev.HasMorePages为true,或者一直等到打印的数据结束。在循环内部运用Graphics对象的Draw方法来打印你的数据。

你也需要确保DrawString方法将文本放置在了正确的位置上。通过用你选择的字体的高度乘以你用来跟踪已经打印了多少行的计数器,你就可以在每打印一行时计算下一行的位置了。然后为顶部的页边距添加值(见列表5)。
 C#:PrintPage是打印的关键
列表 5.

当运用System.Drawing.Printing对象来打印时, PrintPage是你要用到的主要的事件。该事件为每个页面触发一次,直到你将ev.HasMorePages的值设置成false。用来得到hard margins的代码弥补了.NET Framework中的不足。

private void doc_PrintPage(object sender,System.Drawing.Printing.PrintPageEventArgs ev) {_currentPage++;String headerText = "Northwinds Customer Contacts";IntPtr hDc = ev.Graphics.GetHdc();ev.Graphics.ReleaseHdc(hDc);marginInfo mi = new marginInfo(hDc.ToInt32());// take the hard margins into account?float leftMargin = ev.MarginBounds.Left - mi.Left;float rightMargin = ev.MarginBounds.Right;float topMargin = ev.MarginBounds.Top - mi.Left;float bottomMargin = ev.MarginBounds.Bottom;float pageHeight = bottomMargin - topMargin;float pageWidth = rightMargin - leftMargin;float headerHeight = headerFont.GetHeight(ev.Graphics);float footerHeight = bodyFont.GetHeight(ev.Graphics);// report headerRectangleF ReportheaderR = new RectangleF(leftMargin,topMargin, pageWidth, headerHeight);// report bodyRectangleF bodyR = new RectangleF(leftMargin,ReportheaderR.Bottom, pageWidth, pageHeight - ReportheaderR.Height - footerHeight);  // report footerRectangleF ReportfooterR = new RectangleF(leftMargin,bodyR.Bottom, pageWidth, footerHeight * 2);// results of using the Split function on the textString[] el;// a line of text from our filestring text = "";// print the header once per pagecenterText(ev.Graphics, headerText, headerFont,defaultBrush, ReportheaderR);// the header is equal to 2 normal linesint currentLine = 2;// how many lines can we fit on a page?              int linesPerPage = Convert.ToInt32(bodyR.Height / bodyFont.GetHeight(ev.Graphics)) - 1;float bodyFontHeight = bodyFont.GetHeight(ev.Graphics);float currentY;// Print each line of the file.while(currentLine < linesPerPage && ((text=data.ReadLine()) != null)) {el = text.Split(',');currentY = getCurrentY(currentLine, topMargin,bodyFontHeight);ev.Graphics.DrawString(el[0], bodyFont,defaultBrush, bodyR.Left, currentY);currentLine++;currentY = getCurrentY(currentLine, topMargin, bodyFontHeight);ev.Graphics.DrawString(el[1], bodyFont, defaultBrush, bodyR.Left + 20, currentY);currentLine++;currentY = getCurrentY(currentLine, topMargin,  bodyFontHeight);ev.Graphics.DrawString("Phone: " + el[2], bodyFont, defaultBrush, bodyR.Left + 20, currentY);currentLine++;currentY = getCurrentY(currentLine, topMargin, bodyFontHeight);ev.Graphics.DrawString("Fax: " + el[3], bodyFont,defaultBrush, bodyR.Left + 20,currentY);currentLine++;currentY = getCurrentY(currentLine, topMargin, bodyFontHeight);ev.Graphics.DrawLine(Pens.Black, leftMargin,currentY, ev.MarginBounds.Right, currentY);}// page numbercenterText(ev.Graphics, "Page " + currentPage.ToString(), bodyFont, defaultBrush, ReportfooterR);if (text != null) {ev.HasMorePages = true;}else {// no more pages to printev.HasMorePages = false;}
}private float getCurrentY(int currentLine, float topMargin, float fontHeight) {return topMargin + (currentLine * fontHeight);
}private void centerText(Graphics g, string t, Font f, Brush b, RectangleF rect) {StringFormat sf = new StringFormat();sf.Alignment =  StringAlignment.Center;g.DrawString(t, f, b, rect, sf);
}

你运用的DrawString方法也接受一个StringFormat对象。StringFormat类可以让你控制文本的布局——包括对齐和行间距——以及省略符号的插入(如果一个给定的字符串对于你的长方形边框来说太长了时)。通过创建StringFormat对象,并设置其Alignment属性为StringAlignment.Center,你就可以使你的文本居中;然后将对象用于你调用的DrawString方法中。为你的联系清单页眉写以下代码:

StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
ev.Graphics.DrawString("Northwinds Customer Contacts", headerFont, defaultBrush, body, sf);

正如你所看到的,一旦你确定了报表的布局并创建了长方形边框来包含数据,实际的打印并不是很难。
                                          图2. 预览打印

PrintPreviewControl和PrintPreviewDialog类在Printing名字空间中提供了很好的功能。PrintPreviewDialog封装了PrintPreviewControl类,并提供了一个很好的用户界面,用来在页面间导航、改变缩放比例、选择一次可以预览的页数(见图2)。你可以用PrintPreviewControl来创建一个与你的应用程序其它部分相一致的打印预览窗口。一旦你定义了你的PrintDocument,并为必需的打印事件编写了代码后,添加打印预览就很简单了:

private void preview_Click(object sender, System.EventArgs e) {PrintPreviewDialog pd = new PrintPreviewDialog();pd.Document = doc;pd.ShowDialog();
}

我希望我已经给你们提供了研究System.Drawing.Printing名字空间的动力。我发现这个名字空间是用来自动生成许多重复性的打印项目(尤其是报表)的最好的方法。尝试用这种方法来完成一个打印任务吧,我敢打赌在用过一次后,你就会立刻将这个方法用于所有的打印任务了。

关于作者: 
       Michael Eaton是位专攻Microsoft技术的独立顾问。自1994年来,他一直在从事软件开发工作,并于1995年获得MCSD。他主要用VB、SQL Server和ASP进行开发,但在.NET SDK发布后,他开始沉迷于用C#进行开发。他的Email是mike@sitedev.com。

掌握.NET中的日常打印相关推荐

  1. excel表格打印每页都有表头_表头如何自动编号?日常工作中的表格打印常见问题解答...

    打印是我们学习与工作中需要经常用到的. 对于很多人来说,打印就是一件「放放纸张,点点打印机,没有什么技术含量」的事. 但 Excel 表格的打印可没有你想象的那么简单-- 今天小管家就来教你如何打印E ...

  2. 中琅条码标签打印软件中打印设置中的相关问题

    在日常使用中琅条码标签打印软件时,部分用户经常在打印数量上出错犯糊涂,不知道中琅软件中的标签数量和标签份数两者具体有什么区别,导致在打印过程中出现一系列错误.今天就来详细介绍一下中琅条码标签打印软件的 ...

  3. linux文件扫描并打印,Linux系统中扫描、打印的实现(转)

    Linux系统中扫描.打印的实现(转)[@more@] 扫描图片是日常办公中进行的比较频繁的工作,如何在Linux中使用扫描仪就成为了一个问题.下面笔者就详细介绍一下在Linux中如何进行扫描. 常见 ...

  4. 关于在web项目中实现本地打印

    1    问题描述 在web项目,打印功能一直是一个老大难问题,而想进行套打,则更加上难上加难.而我在最近的项目中就遇到的条形码打印的需求,需要调用客户端的打印机发送指令进行打印.在由于该项目的用户在 ...

  5. python将dict中的unicode打印成中文

    python将dict中的unicode打印成中文 import json a = {u'content': {u'address_detail': {u'province': u'\u5409\u6 ...

  6. excel数据库_中琅条码打印软件数据库连接详解

    用过中琅条码打印软件的小伙伴都知道软件多种数据库类型,比如TXT.Excel,MySQL,Access,SQLServer,MySQL,Oracle,CSV,Sybase,DB2,SQLite,DBF ...

  7. 算法练习day9——190327(“之” 字形打印矩阵、在行列都排好序的矩阵中找数、打印两个有序链表的公共部分、判断一个链表是否为回文结构)

    1."之" 字形打印矩阵 [题目] 给定一个矩阵matrix, 按照"之" 字形的方式打印这个矩阵, 例如: 1 2 3 4 5 6 7 8 9 10 11 1 ...

  8. 产生10个1-100的随机数,并放到一个数组中, 把数组中大于等于10的数字放到一个list集合中,并打印到控制台。

    代码 import java.util.ArrayList; import java.util.List; import java.util.Random;/*1.产生10个1-100的随机数,并放到 ...

  9. 在eclipse中利用条件断点打印log

    我们写代码偶尔会遇到不方便用断点调试的情况,比如有超时机制的时候,而频繁的修改代码来打印状态信息又是一件非常繁琐的事情.这时我们可以借助eclipse中条件断点来打印. 首先设置断点,打开Breakp ...

最新文章

  1. Win7让你的程序变得更加漂亮,同样的程序在Win7操作系统下的效果对比
  2. 构造 Codeforces Round #275 (Div. 2) C. Diverse Permutation
  3. NATAPP本地地址映射到外网
  4. 荣耀开年第一机!荣耀60 SE今日官宣:搭载天玑900处理器
  5. Python 安装pythoncom库和pyHook
  6. Leetcode811.Subdomain Visit Count子域名访问计数
  7. Linux学习笔记二十——系统裁剪之二
  8. 高通宣称其语音识别系统准确率高达95%
  9. python函数参数传递切片_将DataFrame切片作为参数传递给函数而不使用“SettingWithCopyWarning”...
  10. 全国各地收货详细地址_2020高考成绩在哪里查询 2020全国各地高考分数查询时间地址最新...
  11. 锚定本地化:电子签杀入下半场
  12. 求解不定方程 (扩展欧几里得算法)
  13. java源文件结构_Java源文件结构详解
  14. java uclinux_Java在基于uclinux的嵌入式系统中的应用
  15. PL3369C-ASEMI原边电源IC芯片PL3369C
  16. 投稿英文国际会议论文经验总结
  17. 通过同花顺股票程序化交易接口的止损方法有哪些?
  18. css3 transition属性造成文字抖动
  19. Jmeter(二十三) - 从入门到精通 - JMeter函数 - 上篇(详解教程)
  20. chrome安装vysor webgl不支持

热门文章

  1. TriSun PDF 13.0中文版本,TriSun PDF15的发布
  2. 选定区域着色html,PS怎么填充颜色到选中区域?PS填充颜色到选中区域的方法
  3. KW-Software MULTIPROG平台通过赫优讯cifX板卡实现 集成PROFIBUS-DP主站的软PLC控制器
  4. 芯片在计算机中作用是什么,芯片的主要作用
  5. CSS选择器补充,CSS三大特性以及字体、文本样式。
  6. 小米10等UFS字库备份与基带分区说明
  7. 百度搜索稳定性问题分析的故事(上)
  8. 安卓手机管理软件_留言帮忙找:手机清理软件合集 Android
  9. 纤亿通带你了解GPON和EPON的区别
  10. 《Unity开发实战》——2.4节自定义镜头光晕效果