忘记mysql的root用户密码怎么办? - 帮助中心 - LuManager(LUM)官方授权代理商[双赢网络]

mikel阅读(1160)

来源: 忘记mysql的root用户密码怎么办? – 帮助中心 – LuManager(LUM)官方授权代理商[双赢网络]

#停止mySQL
mySQL-stop
#用–skip-grant-tables参数启动mysql
/usr/local/mysql/bin/mysqld_safe –user=lu_mysql –datadir=/home/mysql_data –skip-grant-tables &
#由于使用了–skip-grant-tables,可不用密码直接登陆mysql
/usr/local/mysql/bin/mysql
#切换到mysql数据库
use mysql
#更新密码为zijidelu
update user set password=password(“zijidelu”) where user=”root”;
#刷新权限
flush privileges;
到此,密码更改完成,按ctrl+c退出,然后执行mysql-restart重启mysql

注意:如果修改密码后,导致lum后台登陆报Access denied for user \’root\’@\’localhost\’ (using password: YES)错误
请再修改一下/home/lum_safe_files/config.php中的数据库连接密码便可
报错是应为手动修改mysql密码后,config.php里面的密码没有同步所致

忘记资料重置WordPress密码为123456的2个方法 | 一路发发→满意沟通的博客收藏夹

mikel阅读(1937)

忘记资料重置Wordpress密码为123456的2个方法

来源: 忘记资料重置Wordpress密码为123456的2个方法 | 一路发发→满意沟通的博客收藏夹

知道资料自己修改密码的太简单了…

 能登陆ftp的:通过改PHP文件重置Wordpress登陆密码

1、找到当前在用主题所在目录的functions.php这个文件 下载

2、通过文本编辑器编辑 functions.php文件,在文件开头的<?php下面添加一行代码:

wp_set_password(‘123456’,1);

123456为你要设置的密码,1为用户uid默认的管理员是1

3、上传functions.php文件覆盖原文件。
4、打开WordPress首页(或其他任意WordPress页面),WordPress将自动重置密码。

5、删除
functions.php
文件里面刚才添加的代码,上传覆盖后就搞定了.

能登陆mySQL/phpmyadmin的:

登陆phpmyadmin,改Wordpress的数据库的users下的user_pass

为:

$P$B8E85d5cWudk9nzbm0aanpv0PrJwo51

密码就被改为123456了,登陆一下自己再改一下密码

 

注:以上2个方法我都亲测有效

之前在网上搜的几个有的太复杂,有的是转帖别人的,数据没给对

有的是用全角的”代替半角的”

Fiddler 4 中如何post数据 - kunpengku - 博客频道 - CSDN.NET

mikel阅读(1282)

 

来源: Fiddler 4 中如何post数据 – kunpengku – 博客频道 – CSDN.NET

关于这个问题的 解决 参看
http://stackoverflow.com/questions/7075125/check-post-request-with-fiddler

关键 是要在 头部 增加
Content-Type: application/x-www-form-urlencoded

这里有个坑
http://jingyan.baidu.com/article/dca1fa6fa07000f1a44052f6.html
百度经验的这篇文章, 最后说 要加 ContentType:application/x-www-form-urlencoded, 你如果仔细看, 会发现 少了一个 横杠, 坑啊。

还可以参考这个网页
https://www.blackbaud.com/files/support/guides/infinitydevguide/content/InfinityWebAPI/coUsingFiddlerCreateHTTPRequest.htm

Tutorial: Using Fiddler to Compose HTTP SOAP Requests to the AppFxWebService.asmx

This tutorial will guide you through the steps to create and execute an HTTP request with Fiddler. According to its website, Fiddler is a free web Debugging proxy for any browser, system or platform. Fiddler logs all HTTP(s) traffic between your computer and the Internet. Using Fiddler you can also compose your own HTTP requests to run through Fiddler. It’s a great tool for experimenting with HTTP Requests to the Blackbaud AppFx Web Service (AppFxWebService.asmx).

SOAP stands for Simple Object Access Protocol and it is one way to format XML messages to allow Internet based communications between two programs.The SOAP protocol is most commonly used in conjunction with HTTP(s).  Together, SOAP and HTTP provide some strong advantages:

  • Communication is allowed through firewalls
  • Allows communication between applications running on different operating systems since HTTP and XML is OS independent
  • HTTP is supported by most modern programming languages which include their own flavor of libraries or classes which implement the client side of the HTTP/HTTPS protocols.

Learning how to compose HTTP SOAP Requests to the AppFxWebService is a great way to learn how our API works. What you learn here will easily translate to your own programming language. Let’s get started!

What we will build

We will use the built in AppFxWebService documentation to call a simple feature such as a View Data Form. We will use the Individual Biographical View Form (system record id of 48cefdc3-a719-4fef-bd61-3108a5971d2b) to pull some data from the Infinity database. View Data Forms are used to retrieve data for display within Blackbaud CRM/Research Point. But they are dual purposed as they can also be used to programmatically retrieve data. This particular view data form pulls data from the CONSTITUENT, CONSTITUENTJOBINFO, and DECEASEDCONSTITUENT tables for a given constituent id. You can see this view data form within Blackbaud CRM versions 2.94 or 3.0 (I haven’t check earlier versions) within the Constituent page’s Personal info tab:

Prerequisites

The tutorial continues the discussion of Crafting HTTP Requests to the AppFxWebService.asmx. If you have not already done so, go back and read this content and related materials before attempting this tutorial.

If you are new to working with the APIs related to Infinity-based products, you may want to review the following content:

Step by Step Tutorial

Step 1 –  If you have not already done so, download and install Fiddler .

Step 2 –  Start Fiddler. To capture traffic from the IE, Chrome, or Safari browser, make sure that Capture Traffic is enabled in the File menu. This tutorial uses Google’s Chrome web browser. To capture traffic from Opera, start Fiddler before starting Opera. For other browsers, such as Firefox see Configure Browsers in the Fiddler online documentation.

Step 3 –  Next, click on the Composer tab on the right side of the program. The Composer allows you to craft custom requests to send to a server. For more information see Fiddler’s online documentation for Creating a New Request using Composer.

Step 4 –  Set the HTTP verb to `POST`, and enter the full URL to your instance of AppFxWebService.asmx.

Step 5 –  Preparing the Headers in Fiddler. Let’s take a look at the Endpoint description page above the SOAP request example for a DataFormLoad operation.

  • To find the example, navigate to the Endpoints page:

  • Select the link to the Blackbaud AppFx Web Service:

  • Select the appropriate operation. Since we are keeping it simple in this tutorial we will attempt to load the data from a View Data Form without any parameters.  Select the DataFormLoad operation from the list:

  • Copy the header from the top of the SOAP 1.1 sample request. Note that I grab the Host, Content-Type, Content-Length, and SOAPAction pieces from the header while leaving out the POST section at the very top of the header.

  • Next, within Fiddler’s Composer tab, you will need to paste the header information into the box titled Request Headers. Each header item should be on its own line: At this point your Composer tab should look like this:

Step 6 –  Adding an Authorization Header

The API is only available to authenticated users, and that includes your application. For Basic Authentication we will create string containing a ‘domain\username:password’ combination for the Infinity log-in credentials. The user name should have rights to use the feature and the data you wish to retrieve within the Infinity application.

So, let’s say I have a user named ‘TestUser’ in an Active Directory domain called ‘FLAGSHIP’ with a password of ‘Inf1nit3’. The ‘username:password’ combination will look like this ‘FLAGSHIP\TestUser:Inf1nit3’.

  • Make sure you have permissions to use the Individual Biographical View Form (system record id of 48cefdc3-a719-4fef-bd61-3108a5971d2b). If your Application User account is designated as a System Administrator then you will have access to all features. A good rule of thumb is to view or use the feature within the application. If you can, you have permission to use the feature.
  • Take the ‘domain\username:password’ combination string and Base64 encode it. There are a lot of free utilities that will Base64 encode a string. Once of them can be found at http://www.string-functions.com/base64encode.aspx

  • Once you have Base64 encoded the credentials you should append the Base64 string as part of the following header:
Authorization: Basic YOURBASE64ENCODEDAUTHENTICATIONSTRING

So, using the dummy credentials above our completed header would look like this:

Authorization: Basic RkxBR1NISVBcVGVzdFVzZXI6SW5mMW5pdDM=
  • Add the string at the end of the Request Header within Fiddler. Our modified headers within the Fiddler Composer’s Request Headers box should look something like this (You will need to be sure and provide your own Base64 encoded authentication string in place of the one displayed below) :
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: 1055
SOAPAction: "Blackbaud.AppFx.WebService.API.1/DataFormLoad"
Authorization: Basic YOURBASE64ENCODEDAUTHENTICATIONSTRING

Step 7 –  Preparing the Request Body

  • Next, we will take the SOAP body xml from the DataFormLoad sample and place the xml into the Request Body section of Fiddler’s Composer.

  • Strip out unnecessary xml elements from the request body such as the <SecurityContext> element,<SanitizeHtmlFieldValues> element, and <ContextRecordID> element.  At this point, your xml in the Request Body should look like this:

Step 8 –  Identifying the feature in the SOAP message body

Next we will need to tell the web server the name of the view data form we wish to use for the data pull. You can use either the <FormID> or <FormName> elements within the Request Body to identify the view data form. If you have system administrator rights, you can use Design Mode to view the feature metadata for the view data form and discover either the name of the feature or the value for the system record id. By toggling design mode on, we can select the button within the section holding our Individual Biographical View Form which navigates us to the feature page for the view data form..

Tip: For more information about Design Mode, see the Blackbaud CRM Page Designer Guide.

Here we can see both the name of the data form and its system record id. I will elect to use the system record id to identify the data form.

  • Copy the guid for the system record id from the feature page and paste it in the request body for the value of the <FormID> element.
  • Remove the <FormName> element from the request body since we are using FormID.

Step 9 –  Identify the record to retrieve

Next we need to provide a value for the <RecordID> element in the request body. This will indicate to the View Data Form the record to retrieve. For most data forms, this value represents a primary key value for a table within the Infinity database. In a real world scenario, you will need to determine how you will retrieve the id for the record you wish to retrieve. In order to determine the type of record to pass to the View Data Form, you need to know the Record Type of the form. You can think of Record Type as a logical name for the entity associated with the View Data Form. The Record Type will help guide you to the underlying base table in SQL Server that holds the primary key value. Viewing the feature page for the Individual Biographical View Form reveals a record type of Constituent.

Selecting the link on Constituent navigates you to the Record Type feature page where the underlying base table is revealed along with other data forms, data lists, search lists, pages, etc. that share a relationship with the record type. In this way, a developer can discover how the various different types of features and how they relate to one another to form the overall application.

From an Infinity perspective, there are various feature types that can provide an id for a record such as a Search List, Data List, Simple Data List, or Data Form to name a few. You have to ensure the feature you use to retrieve the primary key value shares the same Record Type as the data form. In our case this record type is Constituent. I am going to pull the data for Robert Hernandez. Since I have access to the database via SQL Server Management studio, I will grab his primary key value from the CONSTITUENT table and use it for the <RecordID> element’s value. If you do not have access to the database, you will need to use a feature such as a Search List, Simple Data List, or Data Form to retrieve the ID of the record you wish to retreive.

  • Within the Request Body, add the GUID representing the constituent as the value of the RecordID element. At this point your Request Body should look like this:

Step 10 –  Set the remaining values for the Request Body

IncludeMetaData Element

  • Let’s set the value for the IncludeMetaData element to true.

Setting the IncludeMetaData element to true will return the MetaData element which contains all kind of useful information that’s associated with the form including the form’s definition (form fields, UI Model, UI Fields), form mode, help key, code table permissions, form header, and record type. The most valuable information returned is the form fields. Within the MetaData element, you will find information on each form field such as the FieldID, DataType, MaxLength, and Caption. There may be additional information associated with a form field. For example, if the form field is associated with a code table, we will receive the name of the database table that drives the list of values. Or, if the form field is associated with a value list (enumeration), we will receive a list of each item value and labels (translation values), etc. Consider using the information within this metadata to verify the data type or to help establish a basic user interface for your own software.

Tip: If you are unfamiliar with the concept of form meta data check out Form Metadata, FormField Element, and FormField Elements.

IncludeDataFormAddIns Element

  • We do not need this information and therefore will set this to false.

Setting the IncludeDataFormAddIns element’s value to true will return a list of Data Form Add-Ins associated with the data form by listing the ComponentIdentifier elements which contain UIModel assemblies and related classes. Data Form Add-Ins enable 3rd party developers the ability to add user interface behavior to an existing UI Model data form.

For educational purposes, an example of what is returned in the reply when the IncludeDataFormAddIns element’s value is set to true is displayed below.

Tip: For more information see UI Model for Data Forms, Extensibility, and Data Form Add-Ins.

IncludeDataFormsExtensions Element

  • We do not need this information and therefore will set this to false.

Setting the IncludeDataFormExtensions element’s value to true will return a list of Data Form extensions associated with the data form. Data Form Extensions allow a 3rd party developer to extend an existing data form with custom data form.

Tip: For more information see UI Model for Data Forms, Extensibility, and Data Form Extensions.

ExcludeValueTranslations Element

  • Set this value to false.

Setting this value to true will cause only the ID of the value to be returned in the reply. This applies when the form meta data for the feature contains form fields that are driven by one of the various types of lists such as a code table, value list, or simple data list. Setting the value to false will cause both the ID AND the value translation to be returned.

For educational purposes , an example of setting the ExcludeValueTranslations element to false has been displayed below for a call to the Individual Biographical Edit Form 3 (system record id (Form ID): 788ab947-26ed-40c4-865e-8fe29577e593).

IncludeFieldCharacteristics

  • Set this value to false.

Allows the caller to indicate that custom field characteristics data should be returned with the reply. At this time, no further information is available on this element.

Step 11 –  Building the ClientAppInfo Element for the Request Body

Last but certainly not least is the critical ClientAppInfo element. Unfortunately, the built in documentation sample for the operation of the AppFxWebService.asmx does not describe this element that must be included. Its format is as follows:

<ClientAppInfo 
        REDatabaseToUse="YOUR DATABASE IDENTIFIER/KEY" 
        ClientAppName="THE NAME OF YOUR REQUESTING APPLICATION" 
        TimeOutSeconds="THE NUMBER OF SECONDS BEFORE A REQUEST TIMES OUT"
        />

Tip: For more information on ClientAppInfo’s various attributes, see the section titled ClientAppInfo within Crafting HTTP Requests to the AppFxWebService.asmx

  • Read through the definition of each attribute for the ClientAppInfo element below and review the section titled ClientAppInfo within Crafting HTTP Requests to the AppFxWebService.asmx.
  • Provide the appropriate values for the REDatabasetoUse, ClientAppName, and TimeOutSeconds attributes.

REDatabaseToUse

Your database identifier/key will vary. For this example, I am using ‘BBInfinity’.

This is the identifier of the database your Infinity product uses. This is also known as the ‘database key’. You can find this value in the URL when you are using the product. For example, on the landing page of Blackbaud CRM/Research Point the URL is

http://localhost/.../webshellpage.aspx?databasename=BBInfinity

and we can see that the database identifier is `BBInfinity`.

ClientAppName

Let’s use ‘HTTP Fiddler Test’ for the ClientAppName value.

This is a name that you should come up with to identify your application to the API. It should be unique and specific to your application. The Infinity application can use this application name for auditing purposes when additions, edits, or deletes occur to the data within the database tables.

TimeOutSeconds

The number of seconds before the request times out. I will use 120 seconds for this setting.

  • Place the completed the ClientAppInfo element into the Request Body within Fiddler’s Composer tab. Place the element as a child element within the DataFormLoadRequest Element.  At this point your Request Body should look similar to this:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
  <DataFormLoadRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="Blackbaud.AppFx.WebService.API.1">
  <ClientAppInfo REDatabaseToUse="BBInfinity" ClientAppName="HTTP Fiddler Test"  TimeOutSeconds="120" />
  <FormID>48cefdc3-a719-4fef-bd61-3108a5971d2b</FormID>
  <RecordID>4a1321df-c787-47f6-a6f0-6484838833e1</RecordID>
  <IncludeMetaData>true</IncludeMetaData>
  <IncludeDataFormAddIns>false</IncludeDataFormAddIns>
  <IncludeDataFormExtensions>false</IncludeDataFormExtensions>
  <ExcludeValueTranslations>false</ExcludeValueTranslations>
  <IncludeFieldCharacteristics>false</IncludeFieldCharacteristics>
</DataFormLoadRequest>
  </soap:Body>
</soap:Envelope>

Step 12 –  Review your Request Body in Fiddler’s Composer and Execute the request

At this point your request headers and body should look like this. Of course you need to replace the YOURBASE64ENCODEDAUTHENTICATIONSTRING with your own Base64 encoded authentication string before executing the request.

  • Within Fiddler’s Composer tab, click the Execute button

After you execute the composed HTTP request, an item will be added to the list on the right hand pane. The result code will display in the Result column of the list. A result code of 200 is good. This means the request was processed successfully. Fiddler will direct you automatically to the Inspectors tab where you can explore the values within the reply.

  • Double click the item in the list. This will cause the reply to be displayed. In our case, its a DataFormLoadReply. Here you can inspect the values of each DataFormItem (form field values) and MetaData for the view data form.

And that’s it. I have placed the entire Request Header and Request Body below. Again, you will need to be sure and provide your own Base64 encoded authentication string in place of the one displayed below.

Request Header

Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: 973
SOAPAction: "Blackbaud.AppFx.WebService.API.1/DataFormLoad"
Authorization: Basic YOURBASE64ENCODEDAUTHENTICATIONSTRING

Request Body

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
  <DataFormLoadRequest 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="Blackbaud.AppFx.WebService.API.1">
  <ClientAppInfo REDatabaseToUse="BBInfinity" ClientAppName="HTTP Fiddler Test"  TimeOutSeconds="120" />
  <FormID>48cefdc3-a719-4fef-bd61-3108a5971d2b</FormID>
  <RecordID>4a1321df-c787-47f6-a6f0-6484838833e1</RecordID>
  <IncludeMetaData>true</IncludeMetaData>
  <IncludeDataFormAddIns>false</IncludeDataFormAddIns>
  <IncludeDataFormExtensions>false</IncludeDataFormExtensions>
  <ExcludeValueTranslations>false</ExcludeValueTranslations>
  <IncludeFieldCharacteristics>false</IncludeFieldCharacteristics>
</DataFormLoadRequest>
  </soap:Body>
</soap:Envelope>

php 的定界符 <<

mikel阅读(1221)

PHP是一个Web编程语言,在编程过程中难免会遇到用echo来输出大段的html和JavaScript脚本的情况,如果用传统的输出方法 ——按字符串输出的话,肯定要有大量的转义符来对字符串中的引号等特殊字符进行转义,以免出现语法错误。如果是一两处还可以容忍,但是要是一个完整的 html文本或者是一个200行的js我想是谁都会崩溃的。这就是PHP为什么要引入一个定界符的原因——至少一大部分原因是这样的。
1.PHP定界符的作用就是按照原样,包括换行格式什么的,输出在其内部的东西;
2.在PHP定界符中的任何特殊字符都不需要转义;
3.PHP定界符中的PHP变量会被正常的用其值来替换。

PHP中的定界符格式是这样的:

<<<Eof
……
Eof;

 

报错的原因:

不仅EOF;前边不能有空格,而且echo<<<EOF后面也不能有空格。

<?php
$v=  time();
echo <<<Eof
<li><a href=”tabsPage.html” target=”navTab”>框架面板{$v}</a>
……….
Eof;
?>

PHP: Array 数组 - Manual

mikel阅读(1058)

数组(Array) 的赋值总是会涉及到值的拷贝。使用引用运算符通过引用来拷贝数组。

来源: PHP: Array 数组 – Manual

数组(Array) 的赋值总是会涉及到值的拷贝。使用引用运算符通过引用来拷贝数组。

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
// $arr1 is still array(2, 3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>

网页WEB打印控件制作 - SDP开发平台 - 博客园

mikel阅读(1839)

来源: 网页WEB打印控件制作 – SDP开发平台 – 博客园

在WEB系统中,打印的确是比较烦人的问题,如果我们能制作一个属于自己的自定义的打印插件,那么我们在后续自定义打印的时候能随心所欲的控制打印,这样 的效果对于程序员来说是非常开心的一件事件,本文将自己开发编写的C# 制作的HTML打印插件分享出来,让有同样需求的朋友提供一个参考;此插件是基于Microsoft .NET Framework 2.0 开发的,缺点是每台客户端在安装插件时,必须要安装Microsoft .NET Framework 2.0 ;本插件能实现 页眉、页脚、表头、标题、表尾的分页打印;支持纸张类型、自动补充空行等功能;由于技术有限,肯定有很多不足的地方,请批评指正!

由于本打印插件是基于我们开发平台的报表基础来开发设计的,所以打印控件的原理:通过JS将页面表格数据生成固定格式的XML字符串(图片通过 64base图片格式)传送给打印插件,有打印插件自主绘图生成打印页面。E_Print插件可以在WEB或WinForm中使用:

打印插件完整源码:E_Print.rar   (包含插件源码、打包程序、winform调试DEMO)

下面贴出源码:(在源码中有详细的注释说明)

1、PrintControl 打印插件类

 

复制代码
   1 using System;
   2 using System.Collections.Generic;
   3 using System.ComponentModel;
   4 using System.Drawing;
   5 using System.Data;
   6 using System.Text;
   7 using System.Windows.Forms;
   8 using System.Runtime.InteropServices;
   9 using System.Drawing.Printing;
  10 using System.Xml;
  11 using System.Security;
  12 using System.Drawing.Drawing2D;
  13 using System.Drawing.Text;
  14 using System.Text.RegularExpressions;
  15 
  16 namespace E_Print
  17 {
  18     /// <summary>
  19     /// 打印控件
  20     /// 实现IObjectSafety接口
  21     /// 网页上所有所使用到的GUID  通过Guid工具生成的唯一编码
  22     /// 74D1ED1D-B1A7-4039-A060-6F544FBE99EC 编码以后不允许修改
  23     /// </summary>
  24     [Guid("74D1ED1D-B1A7-4039-A060-6F544FBE99EC"), ProgId("EReportPrint"), ComVisible(true)]
  25     public partial class PrintControl : UserControl, IObjectSafety
  26     {
  27         #region 私有变量
  28 
  29         #region 通用参数
  30 
  31         /// <summary>
  32         /// 缩放比例
  33         /// </summary>
  34         private float Zoom = 1;
  35 
  36         /// <summary>
  37         /// 网页高度 像素 px
  38         /// </summary>
  39         private float HtmlHeight = 0;
  40 
  41         /// <summary>
  42         /// 网页宽度 像素 px
  43         /// </summary>
  44         private float HtmlWidth = 0;
  45 
  46         /// <summary>
  47         /// 报表区域矩形
  48         /// </summary>
  49         private RectangleF TableRect = new RectangleF();
  50 
  51         /// <summary>
  52         /// 报表绘制实例
  53         /// </summary>
  54         private ReportDraw RptDraw = new ReportDraw();
  55 
  56         #endregion
  57 
  58         #region 页边距
  59 
  60         /// <summary>
  61         /// 左边距 
  62         /// 毫米 mm(一位小数)
  63         /// </summary>
  64         private float _marginLeft = 9.9f;
  65 
  66         /// <summary>
  67         /// 右边距
  68         /// </summary>
  69         private float _marginRight = 9.9f;
  70 
  71         /// <summary>
  72         /// 上边距
  73         /// </summary>
  74         private float _marginTop = 9.9f;
  75 
  76         /// <summary>
  77         /// 下边距
  78         /// </summary>
  79         private float _marginBottom = 9.9f;
  80 
  81         #endregion
  82 
  83         #region 版型方向
  84 
  85         /// <summary>
  86         /// 版型方向 Landscape: true 横向;false 纵向
  87         /// </summary>
  88         private bool _landscape = false;
  89 
  90         #endregion
  91 
  92         #region 纸型大小
  93 
  94         /// <summary>
  95         /// 纸张类型
  96         /// </summary>
  97         private string _paperName = "A4";
  98 
  99         /// <summary>
 100         /// 纸张宽度
 101         /// </summary>
 102         private int _paperWidth = 210;    // 毫米
 103 
 104         /// <summary>
 105         /// 纸张高度
 106         /// </summary>
 107         private int _paperHeight = 297;   // 毫米
 108 
 109         #endregion
 110 
 111         #region 打印参数
 112 
 113         /// <summary>
 114         /// 自适应纸张大小方法 
 115         /// null: 无
 116         /// row:   横向
 117         /// col:  纵向
 118         /// </summary>
 119         private string _zoomType = "null";
 120 
 121         /// <summary>
 122         /// 是否每页打印标题
 123         /// </summary>
 124         private bool _isTblTitleAllPage = false;
 125 
 126         /// <summary>
 127         /// 是否每页打印表头
 128         /// </summary>
 129         private bool _isTblHeadAllPage = false;
 130 
 131         /// <summary>
 132         /// 是否每页打印表尾
 133         /// </summary>
 134         private bool _isTblFootAllPage = false;
 135 
 136         /// <summary>
 137         /// 最后一页自动补行
 138         /// </summary>
 139         private bool _isAutoFillRow = false;
 140 
 141         /// <summary>
 142         /// 字符溢出是否换行缩小处理方式
 143         /// </summary>
 144         private bool _isOverFlow = false;
 145 
 146         /// <summary>
 147         /// 打印数据
 148         /// </summary>
 149         private string _dataXml = "";
 150 
 151         #endregion
 152 
 153         #region 页眉参数
 154 
 155         /// <summary>
 156         /// 页眉--绘制页眉
 157         /// </summary>
 158         private bool _headDraw = false;
 159 
 160         /// <summary>
 161         /// 页眉--高度 毫米
 162         /// 默认 10 刚好
 163         /// </summary>
 164         private float _headHeight = 10.0f;
 165 
 166         /// <summary>
 167         /// 页眉--左侧文字
 168         /// </summary>
 169         private string _headLeft = "";
 170 
 171         /// <summary>
 172         /// 页眉--中间文字
 173         /// </summary>
 174         private string _headCenter = "";
 175 
 176         /// <summary>
 177         /// 页眉--右侧文字
 178         /// </summary>
 179         private string _headRight = "";
 180 
 181         /// <summary>
 182         /// 页眉--字体名称
 183         /// </summary>
 184         private string _headFontName = "宋体";
 185 
 186         /// <summary>
 187         /// 页眉--字体大小
 188         /// </summary>
 189         private string _headFontSize = "9pt";
 190 
 191         /// <summary>
 192         /// 页眉--字体颜色
 193         /// </summary>
 194         private string _headFontColor = "Black";
 195 
 196         /// <summary>
 197         /// 页眉--字体--粗体
 198         /// </summary>
 199         private bool _headFontBold = false;
 200 
 201         /// <summary>
 202         /// 页眉--字体--斜体
 203         /// </summary>
 204         private bool _headFontItalic = false;
 205 
 206         /// <summary>
 207         /// 页眉--字体--删除线
 208         /// </summary>
 209         private bool _headFontStrikeout = false;
 210 
 211         /// <summary>
 212         /// 页眉--字体--下划线
 213         /// </summary>
 214         private bool _headFontUnderline = false;
 215 
 216         /// <summary>
 217         /// 页眉--绘制分隔线
 218         /// </summary>
 219         private bool _headLineDraw = false;
 220 
 221         /// <summary>
 222         /// 页眉--分隔线宽度
 223         /// </summary>
 224         private float _headLineWidth = 1.0f;
 225 
 226         /// <summary>
 227         /// 页眉--分隔线线型
 228         /// </summary>
 229         private string _headLineDash = "solid";
 230 
 231         /// <summary>
 232         /// 页眉--分隔线颜色
 233         /// </summary>
 234         private string _headLineColor = "Black";
 235 
 236         #endregion
 237 
 238         #region 页脚参数
 239 
 240         /// <summary>
 241         /// 页脚--绘制页脚
 242         /// </summary>
 243         private bool _footDraw = false;
 244 
 245         /// <summary>
 246         /// 页脚--高度 毫米
 247         /// </summary>
 248         private float _footHeight = 10.0f;
 249 
 250         /// <summary>
 251         /// 页脚--左侧文字
 252         /// </summary>
 253         private string _footLeft = "";
 254 
 255         /// <summary>
 256         /// 页脚--中间文字
 257         /// </summary>
 258         private string _footCenter = "";
 259 
 260         /// <summary>
 261         /// 页脚--右侧文字
 262         /// </summary>
 263         private string _footRight = "";
 264 
 265         /// <summary>
 266         /// 页脚--字体名称
 267         /// </summary>
 268         private string _footFontName = "宋体";
 269 
 270         /// <summary>
 271         /// 页脚--字体大小
 272         /// </summary>
 273         private string _footFontSize = "9pt";
 274 
 275         /// <summary>
 276         /// 页脚--字体颜色
 277         /// </summary>
 278         private string _footFontColor = "Black";
 279 
 280         /// <summary>
 281         /// 页脚--字体--粗体
 282         /// </summary>
 283         private bool _footFontBold = false;
 284 
 285         /// <summary>
 286         /// 页脚--字体--斜体
 287         /// </summary>
 288         private bool _footFontItalic = false;
 289 
 290         /// <summary>
 291         /// 页脚--字体--删除线
 292         /// </summary>
 293         private bool _footFontStrikeout = false;
 294 
 295         /// <summary>
 296         /// 页脚--字体--下划线
 297         /// </summary>
 298         private bool _footFontUnderline = false;
 299 
 300         /// <summary>
 301         /// 页脚--绘制分隔线
 302         /// </summary>
 303         private bool _footLineDraw = false;
 304 
 305         /// <summary>
 306         /// 页脚--分隔线宽度
 307         /// </summary>
 308         private float _footLineWidth = 1.0f;
 309 
 310         /// <summary>
 311         /// 页脚--分隔线线型
 312         /// </summary>
 313         private string _footLineDash = "solid";
 314 
 315         /// <summary>
 316         /// 页脚--分隔线颜色
 317         /// </summary>
 318         private string _footLineColor = "Black";
 319 
 320         #endregion
 321 
 322         #endregion
 323 
 324         #region 构造方法
 325 
 326         /// <summary>
 327         /// 打印控件构造函数
 328         /// </summary>
 329         public PrintControl()
 330         {
 331             InitializeComponent();
 332             Init_PageSetting();
 333         }
 334 
 335         #endregion
 336 
 337         #region 接口实现
 338 
 339         private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
 340         private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
 341         private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
 342         private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
 343         private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
 344 
 345         private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
 346         private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
 347         private const int S_OK = 0;
 348         private const int E_FAIL = unchecked((int)0x80004005);
 349         private const int E_NOINTERFACE = unchecked((int)0x80004002);
 350 
 351         private bool _fSafeForScripting = true;
 352         private bool _fSafeForInitializing = true;
 353 
 354         public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
 355         {
 356             int Rslt = E_FAIL;
 357 
 358             string strGUID = riid.ToString("B");
 359             pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
 360             switch (strGUID)
 361             {
 362                 case _IID_IDispatch:
 363                 case _IID_IDispatchEx:
 364                     Rslt = S_OK;
 365                     pdwEnabledOptions = 0;
 366                     if (_fSafeForScripting == true)
 367                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
 368                     break;
 369                 case _IID_IPersistStorage:
 370                 case _IID_IPersistStream:
 371                 case _IID_IPersistPropertyBag:
 372                     Rslt = S_OK;
 373                     pdwEnabledOptions = 0;
 374                     if (_fSafeForInitializing == true)
 375                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
 376                     break;
 377                 default:
 378                     Rslt = E_NOINTERFACE;
 379                     break;
 380             }
 381 
 382             return Rslt;
 383         }
 384 
 385         public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
 386         {
 387             int Rslt = E_FAIL;
 388             string strGUID = riid.ToString("B");
 389             switch (strGUID)
 390             {
 391                 case _IID_IDispatch:
 392                 case _IID_IDispatchEx:
 393                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
 394                         Rslt = S_OK;
 395                     break;
 396                 case _IID_IPersistStorage:
 397                 case _IID_IPersistStream:
 398                 case _IID_IPersistPropertyBag:
 399                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
 400                         Rslt = S_OK;
 401                     break;
 402                 default:
 403                     Rslt = E_NOINTERFACE;
 404                     break;
 405             }
 406 
 407             return Rslt;
 408         }
 409 
 410         #endregion
 411 
 412         #region 属性方法
 413 
 414         #region 页边距
 415 
 416         /// <summary>
 417         /// 获取--设置--左边距
 418         /// 计量单位 毫米(mm)
 419         /// </summary>
 420         public float MARGINLEFT
 421         {
 422             get { return _marginLeft; }
 423             set { _marginLeft = value; }
 424         }
 425 
 426         /// <summary>
 427         /// 获取--设置--右边距
 428         /// 计量单位 毫米(mm)
 429         /// </summary>
 430         public float MARGINRIGHT
 431         {
 432             get { return _marginRight; }
 433             set { _marginRight = value; }
 434         }
 435 
 436         /// <summary>
 437         /// 获取--设置--上边距
 438         /// 计量单位 毫米(mm) 
 439         /// </summary>
 440         public float MARGINTOP
 441         {
 442             get { return _marginTop; }
 443             set { _marginTop = value; }
 444         }
 445 
 446         /// <summary>
 447         /// 获取--设置--下边距
 448         /// 计量单位 毫米(mm) 
 449         /// </summary>
 450         public float MARGINBOTTOM
 451         {
 452             get { return _marginBottom; }
 453             set { _marginBottom = value; }
 454         }
 455 
 456         #endregion
 457 
 458         #region 版型方向
 459 
 460         /// <summary>
 461         /// 获取--设置--版型方向
 462         /// Landscape: true 横向; false 纵向
 463         /// </summary>
 464         public bool LANDSCAPE
 465         {
 466             get { return _landscape; }
 467             set { _landscape = value; }
 468         }
 469 
 470         #endregion
 471 
 472         #region 纸张属性
 473 
 474         /// <summary>
 475         /// 获取--设置--纸张类型
 476         /// </summary>
 477         public string PAPERNAME
 478         {
 479             get { return _paperName; }
 480             set { _paperName = value; }
 481         }
 482 
 483         /// <summary>
 484         /// 获取--设置--纸张高度
 485         /// 计量单位 毫米(mm)
 486         /// </summary>
 487         public int PAPERHEIGHT
 488         {
 489             get { return _paperHeight; }
 490             set { _paperHeight = value; }
 491         }
 492 
 493         /// <summary>
 494         /// 获取--设置--纸张宽度
 495         /// 计量单位 毫米(mm)
 496         /// </summary>
 497         public int PAPERWIDTH
 498         {
 499             get { return _paperWidth; }
 500             set { _paperWidth = value; }
 501         }
 502 
 503         #endregion
 504 
 505         #region 页眉参数
 506 
 507         /// <summary>
 508         /// 获取--设置--页眉是否绘制
 509         /// </summary>
 510         public bool HEADDRAW
 511         {
 512             get { return _headDraw; }
 513             set { _headDraw = value; }
 514         }
 515 
 516         /// <summary>
 517         /// 获取--设置--页眉高度
 518         /// 单位:毫米整数类型
 519         /// </summary>
 520         public float HEADHEIGHT
 521         {
 522             get { return _headHeight; }
 523             set { _headHeight = value; }
 524         }
 525 
 526         /// <summary>
 527         /// 获取--设置--页眉左侧文字
 528         /// </summary>
 529         public string HEADLEFT
 530         {
 531             get { return _headLeft; }
 532             set { _headLeft = value; }
 533         }
 534 
 535         /// <summary>
 536         /// 获取--设置--页眉中间文字
 537         /// </summary>
 538         public string HEADCENTER
 539         {
 540             get { return _headCenter; }
 541             set { _headCenter = value; }
 542         }
 543 
 544         /// <summary>
 545         /// 获取--设置--页眉右侧文字
 546         /// </summary>
 547         public string HEADRIGHT
 548         {
 549             get { return _headRight; }
 550             set { _headRight = value; }
 551         }
 552 
 553         /// <summary>
 554         /// 获取--设置--页眉字体名称
 555         /// </summary>
 556         public string HEADFONTNAME
 557         {
 558             get { return _headFontName; }
 559             set { _headFontName = value; }
 560         }
 561 
 562         /// <summary>
 563         /// 获取--设置--页眉字体大小
 564         /// </summary>
 565         public string HEADFONTSIZE
 566         {
 567             get { return _headFontSize; }
 568             set { _headFontSize = value; }
 569         }
 570 
 571         /// <summary>
 572         /// 获取--设置--页眉字体颜色
 573         /// </summary>
 574         public string HEADFONTCOLOR
 575         {
 576             get { return _headFontColor; }
 577             set { _headFontColor = value; }
 578         }
 579 
 580         /// <summary>
 581         /// 获取--设置--页眉字体--粗体
 582         /// </summary>
 583         public bool HEADFONTBOLD
 584         {
 585             get { return _headFontBold; }
 586             set { _headFontBold = value; }
 587         }
 588 
 589         /// <summary>
 590         /// 获取--设置--页眉字体--斜体
 591         /// </summary>
 592         public bool HEADFONTITALIC
 593         {
 594             get { return _headFontItalic; }
 595             set { _headFontItalic = value; }
 596         }
 597 
 598         /// <summary>
 599         /// 获取--设置--页眉字体--删除线
 600         /// </summary>
 601         public bool HEADFONTSTRIKEOUT
 602         {
 603             get { return _headFontStrikeout; }
 604             set { _headFontStrikeout = value; }
 605         }
 606 
 607         /// <summary>
 608         /// 获取--设置--页眉字体--下划线
 609         /// </summary>
 610         public bool HEADFONTUNDERLINE
 611         {
 612             get { return _headFontUnderline; }
 613             set { _headFontUnderline = value; }
 614         }
 615 
 616         /// <summary>
 617         /// 获取--设置--是否绘制分割线
 618         /// </summary>
 619         public bool HEADLINEDRAW
 620         {
 621             get { return _headLineDraw; }
 622             set { _headLineDraw = value; }
 623         }
 624 
 625         /// <summary>
 626         /// 获取--设置--页眉分隔线宽度
 627         /// </summary>
 628         public float HEADLINEWIDTH
 629         {
 630             get { return _headLineWidth; }
 631             set { _headLineWidth = value; }
 632         }
 633 
 634         /// <summary>
 635         /// 获取--设置--页眉分隔线线型
 636         /// </summary>
 637         public string HEADLINEDASH
 638         {
 639             get { return _headLineDash; }
 640             set { _headLineDash = value; }
 641         }
 642 
 643         /// <summary>
 644         /// 获取--设置--页眉分隔线颜色
 645         /// </summary>
 646         public string HEADLINECOLOR
 647         {
 648             get { return _headLineColor; }
 649             set { _headLineColor = value; }
 650         }
 651 
 652         #endregion
 653 
 654         #region 页脚参数
 655 
 656         /// <summary>
 657         /// 获取--设置--页脚是否绘制
 658         /// </summary>
 659         public bool FOOTDRAW
 660         {
 661             get { return _footDraw; }
 662             set { _footDraw = value; }
 663         }
 664 
 665         /// <summary>
 666         /// 获取--设置--页脚高度
 667         /// 单位:毫米整数类型
 668         /// </summary>
 669         public float FOOTHEIGHT
 670         {
 671             get { return _footHeight; }
 672             set { _footHeight = value; }
 673         }
 674 
 675         /// <summary>
 676         /// 获取--设置--页脚左侧文字
 677         /// </summary>
 678         public string FOOTLEFT
 679         {
 680             get { return _footLeft; }
 681             set { _footLeft = value; }
 682         }
 683 
 684         /// <summary>
 685         /// 获取--设置--页脚中间文字
 686         /// </summary>
 687         public string FOOTCENTER
 688         {
 689             get { return _footCenter; }
 690             set { _footCenter = value; }
 691         }
 692 
 693         /// <summary>
 694         /// 获取--设置--页脚右侧文字
 695         /// </summary>
 696         public string FOOTRIGHT
 697         {
 698             get { return _footRight; }
 699             set { _footRight = value; }
 700         }
 701 
 702         /// <summary>
 703         /// 获取--设置--页脚字体名称
 704         /// </summary>
 705         public string FOOTFONTNAME
 706         {
 707             get { return _footFontName; }
 708             set { _footFontName = value; }
 709         }
 710 
 711         /// <summary>
 712         /// 获取--设置--页脚字体大小
 713         /// </summary>
 714         public string FOOTFONTSIZE
 715         {
 716             get { return _footFontSize; }
 717             set { _footFontSize = value; }
 718         }
 719 
 720         /// <summary>
 721         /// 获取--设置--页脚字体颜色
 722         /// </summary>
 723         public string FOOTFONTCOLOR
 724         {
 725             get { return _footFontColor; }
 726             set { _footFontColor = value; }
 727         }
 728 
 729         /// <summary>
 730         /// 获取--设置--页脚字体--粗体
 731         /// </summary>
 732         public bool FOOTFONTBOLD
 733         {
 734             get { return _footFontBold; }
 735             set { _footFontBold = value; }
 736         }
 737 
 738         /// <summary>
 739         /// 获取--设置--页脚字体--斜体
 740         /// </summary>
 741         public bool FOOTFONTITALIC
 742         {
 743             get { return _footFontItalic; }
 744             set { _footFontItalic = value; }
 745         }
 746 
 747         /// <summary>
 748         /// 获取--设置--页脚字体--删除线
 749         /// </summary>
 750         public bool FOOTFONTSTRIKEOUT
 751         {
 752             get { return _footFontStrikeout; }
 753             set { _footFontStrikeout = value; }
 754         }
 755 
 756         /// <summary>
 757         /// 获取--设置--页脚字体--下划线
 758         /// </summary>
 759         public bool FOOTFONTUNDERLINE
 760         {
 761             get { return _footFontUnderline; }
 762             set { _footFontUnderline = value; }
 763         }
 764 
 765         /// <summary>
 766         /// 获取--设置--是否绘制分割线
 767         /// </summary>
 768         public bool FOOTLINEDRAW
 769         {
 770             get { return _footLineDraw; }
 771             set { _footLineDraw = value; }
 772         }
 773 
 774         /// <summary>
 775         /// 获取--设置--页脚分隔线宽度
 776         /// </summary>
 777         public float FOOTLINEWIDTH
 778         {
 779             get { return _footLineWidth; }
 780             set { _footLineWidth = value; }
 781         }
 782 
 783         /// <summary>
 784         /// 获取--设置--页脚分隔线线型
 785         /// </summary>
 786         public string FOOTLINEDASH
 787         {
 788             get { return _footLineDash; }
 789             set { _footLineDash = value; }
 790         }
 791 
 792         /// <summary>
 793         /// 获取--设置--页脚分隔线颜色
 794         /// </summary>
 795         public string FOOTLINECOLOR
 796         {
 797             get { return _footLineColor; }
 798             set { _footLineColor = value; }
 799         }
 800 
 801         #endregion
 802 
 803         #region 打印参数
 804 
 805         /// <summary>
 806         /// 获取--设置--打印数据
 807         /// 前台传入的XML格式的打印数据
 808         /// </summary>
 809         public string DATAXML
 810         {
 811             get { return _dataXml; }
 812             set { _dataXml = value; }
 813         }
 814 
 815         /// <summary>
 816         /// 获取--设置--是否每页打印标题
 817         /// </summary>
 818         public bool ISTBLTITLEALLPAGE
 819         {
 820             get { return _isTblTitleAllPage; }
 821             set { _isTblTitleAllPage = value; }
 822         }
 823 
 824         /// <summary>
 825         /// 获取--设置--是否每页打印表头
 826         /// </summary>
 827         public bool ISTBLHEADALLPAGE
 828         {
 829             get { return _isTblHeadAllPage; }
 830             set { _isTblHeadAllPage = value; }
 831         }
 832 
 833         /// <summary>
 834         /// 获取--设置--是否每页打印表尾
 835         /// </summary>
 836         public bool ISTBLFOOTALLPAGE
 837         {
 838             get { return _isTblFootAllPage; }
 839             set { _isTblFootAllPage = value; }
 840         }
 841 
 842         /// <summary>
 843         /// 获取--设置--末页自动补行
 844         /// </summary>
 845         public bool ISAUTOFILLROW
 846         {
 847             get { return _isAutoFillRow; }
 848             set { _isAutoFillRow = value; }
 849         }
 850 
 851         /// <summary>
 852         /// 获取--设置--缩放方向
 853         /// 参数:以下三种;默认null
 854         /// null: 无
 855         /// row:   横向
 856         /// col:  纵向
 857         /// </summary>
 858         public string ZOOMTYPE
 859         {
 860             get { return _zoomType; }
 861             set { _zoomType = value; }
 862         }
 863 
 864         /// <summary>
 865         /// 获取--设置--字符溢出是否缩小换行处理方式
 866         /// </summary>
 867         public bool ISOVERFLOW
 868         {
 869             get { return _isOverFlow; }
 870             set { _isOverFlow = value; }
 871         }
 872 
 873         #endregion
 874 
 875         #region 加载参数
 876 
 877         /// <summary>
 878         /// 加载打印参数
 879         /// </summary>
 880         public void INITPRINTPARAM()
 881         {
 882             Init_PageSetting();
 883         }
 884 
 885         #endregion
 886 
 887         #endregion
 888 
 889         #region 加载事件
 890 
 891         /// <summary>
 892         /// 初始化--页面设置参数
 893         /// </summary>
 894         private void Init_PageSetting()
 895         {
 896             this.E_PrintDocument.DefaultPageSettings.Margins.Left = (int)Math.Round(MARGINLEFT * 10);     // 左边距
 897             this.E_PrintDocument.DefaultPageSettings.Margins.Right = (int)Math.Round(MARGINRIGHT * 10);   // 右边距
 898             this.E_PrintDocument.DefaultPageSettings.Margins.Top = (int)Math.Round(MARGINTOP * 10);       // 上边距
 899             this.E_PrintDocument.DefaultPageSettings.Margins.Bottom = (int)Math.Round(MARGINBOTTOM * 10); // 下边距
 900 
 901             this.E_PrintDocument.PrinterSettings.Copies = 1;                                               // 打印份数
 902             this.E_PrintDocument.DefaultPageSettings.Landscape = this.LANDSCAPE;                           // 版型方向      
 903             PaperSize size = GetPaperSize(PAPERNAME);                                                      // 纸张类型
 904             if (size != null)
 905                 this.E_PrintDocument.DefaultPageSettings.PaperSize = size;
 906             else
 907                 this.E_PrintDocument.DefaultPageSettings.PaperSize = new PaperSize(this.PAPERNAME, (int)Math.Round(this.PAPERWIDTH / 25.4 * 100), (int)Math.Round(this.PAPERHEIGHT / 25.4 * 100));
 908         }
 909 
 910         /// <summary>
 911         /// 获取--纸张类型
 912         /// </summary>
 913         /// <param name="paperName">纸张类型名称</param>
 914         /// <returns></returns>
 915         private PaperSize GetPaperSize(string paperName)
 916         {
 917             PaperSize paper = null;
 918             foreach (PaperSize ps in this.E_PrintDocument.PrinterSettings.PaperSizes)
 919             {
 920                 if (ps.PaperName.ToLower() == paperName.ToLower()) // 检查打印机是否有指定的纸张类型
 921                 {
 922                     paper = ps;
 923                     break;
 924                 }
 925             }
 926             return paper;
 927         }
 928 
 929         #endregion
 930 
 931         #region 打印事件
 932 
 933         /// <summary>
 934         /// 直接打印
 935         /// 此处加入了再次调用打印设置界面,因为用户可能需要选择那种打印机
 936         /// </summary>
 937         /// <returns></returns>
 938         public string PRINT()
 939         {
 940             // 直接打印时,直接调用printDocument的Print()方法
 941             // 因为用户可能在打印之前还要再更改打印设置所以需再次显示打印设置对话框
 942             if (this.E_PrintDialog.ShowDialog() == DialogResult.OK)
 943             {
 944                 try
 945                 {
 946                     this.Init_Printer();
 947                     this.E_PrintDocument.Print();
 948                 }
 949                 catch (Exception ex)
 950                 {
 951                     this.E_PrintDocument.PrintController.OnEndPrint(this.E_PrintDocument, new PrintEventArgs());
 952                     return ex.Message.ToString();
 953                 }
 954             }
 955             return "";
 956         }
 957 
 958         /// <summary>
 959         /// 打印预览
 960         /// 将打印的数据进行预览
 961         /// </summary>
 962         public string PREVIEW()
 963         {
 964             try
 965             {
 966                 this.Init_Printer();
 967                 this.E_PrintPreviewDialog.ShowDialog();
 968             }
 969             catch (Exception ex)
 970             {
 971                 return ex.Message.ToString();
 972             }
 973 
 974             return "";
 975         }
 976 
 977         /// <summary>
 978         /// 页面设置
 979         /// 设置打印的页面的纸张大小、纸型、页面边距
 980         /// </summary>
 981         public void PAGESTE()
 982         {
 983             // 页面设置对话框中使用的是公制长度计量单位 (厘米)
 984             // 在.net中采用的是英制的计量单位 (英寸)
 985             // 1英寸约等于2.54厘米,1厘米=10毫米
 986             // 所以在下面中需要加入转换信息 将对话框中设置的页边距进行转换保存
 987             // 设置传入的纸张信息
 988             if (this.E_PageSetupDialog.ShowDialog() == DialogResult.OK)                          // 弹出页面设置对话框
 989             {
 990                 if (System.Globalization.RegionInfo.CurrentRegion.IsMetric)                      // 转换页边距计量单位
 991                     this.E_PageSetupDialog.PageSettings.Margins = PrinterUnitConvert.Convert(this.E_PageSetupDialog.PageSettings.Margins, PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter);
 992                 this.E_PrintDocument.DefaultPageSettings = this.E_PageSetupDialog.PageSettings;  // 更新页面设置参数值
 993 
 994                 // 更新参数
 995                 this.LANDSCAPE = this.E_PrintDocument.DefaultPageSettings.Landscape;                           // 版型方向  
 996                 this.PAPERNAME = this.E_PrintDocument.DefaultPageSettings.PaperSize.PaperName;                 // 纸张类型
 997                 PaperSize tmPSize = this.E_PrintDocument.DefaultPageSettings.PaperSize;                        // 纸张尺寸
 998                 this.PAPERWIDTH = (int)Math.Round(tmPSize.Width * 25.4 / 100);                                 // 纸张宽度
 999                 this.PAPERHEIGHT = (int)Math.Round(tmPSize.Height * 25.4 / 100);                               // 纸张高度
1000                 this.MARGINLEFT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Left / 10f, 1);     // 左边距
1001                 this.MARGINRIGHT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Right / 10f, 1);   // 右边距
1002                 this.MARGINTOP = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Top / 10f, 1);       // 上边距
1003                 this.MARGINBOTTOM = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Bottom / 10f, 1); // 下边距
1004             }
1005         }
1006 
1007         /// <summary>
1008         /// 打印设置
1009         /// 设置打印机的信息(选择打印机、设置打印份数等信息)
1010         /// </summary>
1011         public void PRINTSET()
1012         {
1013             this.E_PrintDialog.ShowDialog();
1014         }
1015 
1016         #endregion
1017 
1018         #region 绘制对象
1019 
1020         /// <summary>
1021         /// 打印及打印前初始化数据
1022         /// </summary>
1023         private void Init_Printer()
1024         {
1025             HtmlHeight = 0;                                      // 网页报表高度
1026             HtmlWidth = 0;                                       // 网页报表宽度
1027             CalcTableRect();                                     // 计算区域矩形
1028             RptDraw = new ReportDraw();                          // 报表绘制实例
1029             RptDraw.IsAllPrintTitle = this._isTblTitleAllPage;   // 每页打印标题
1030             RptDraw.IsAllPrintHead = this._isTblHeadAllPage;     // 每页打印表头
1031             RptDraw.IsAllPrintFoot = this._isTblFootAllPage;     // 每页打印表尾
1032             RptDraw.IsAutoFillRow = this._isAutoFillRow;         // 末页自动补行
1033             RptDraw.IsOverFlow = this._isOverFlow;               // 字符溢出缩小
1034             RptDraw.ReptRect = TableRect;                        // 赋值报表矩形
1035             if (!ParseXML()) return;                             // 解析报表数据
1036             CalcReportZoom();                                    // 计算缩小比例
1037             CalcZoomAllSize();                                   // 按比计算尺寸
1038             RptDraw.Zoom = this.Zoom;                            // 赋值缩小比例         
1039             RptDraw.CalcPaging();                                // 计算打印分页
1040         }
1041 
1042         /// <summary>
1043         /// PrintDocument 对象打印绘制事件
1044         /// </summary>
1045         /// <param name="sender"></param>
1046         /// <param name="e"></param>
1047         private void E_PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
1048         {
1049             Graphics g = e.Graphics;
1050             g.Clear(Color.White);
1051             DrawHeader(g);
1052             DrawFooter(g);
1053             if (RptDraw.DrawReport(g))
1054                 e.HasMorePages = true;
1055             else
1056                 e.HasMorePages = false;
1057 
1058         }
1059 
1060         /// <summary>
1061         /// 绘制页眉
1062         /// </summary>
1063         /// <param name="g">绘图对象</param>
1064         private void DrawHeader(Graphics g)
1065         {
1066             // 是否绘制
1067             if (_headDraw)
1068             {
1069                 // 页眉实例
1070                 PageHeader pgHeader = new PageHeader();
1071 
1072                 // 页眉矩形
1073                 RectangleF pgHeaderRect = new RectangleF(TableRect.X,                          // X 坐标
1074                                                          TableRect.Y - mmToPixel(_headHeight), // Y 坐标      
1075                                                          TableRect.Width,                      // W 宽度
1076                                                          mmToPixel(_headHeight)                // H 高度
1077                                                          );
1078 
1079                 // 页眉赋值
1080                 pgHeader.HeadRect = pgHeaderRect;
1081                 pgHeader.StrLeft = ReplacePageNum(_headLeft);     // 左侧文本
1082                 pgHeader.StrCenter = ReplacePageNum(_headCenter); // 中间文本 
1083                 pgHeader.StrRight = ReplacePageNum(_headRight);   // 右侧文本
1084                 FontStyle fontStyle = FontStyle.Regular;          // 字体样式
1085                 if (_headFontBold) fontStyle |= FontStyle.Bold;
1086                 if (_headFontItalic) fontStyle |= FontStyle.Italic;
1087                 if (_headFontStrikeout) fontStyle |= FontStyle.Strikeout;
1088                 if (_headFontUnderline) fontStyle |= FontStyle.Underline;
1089 
1090                 pgHeader.StrFont = new Font(_headFontName, (float)Convert.ToDouble(_headFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
1091                 pgHeader.StrColor = (Color)PrintTool.StrToColor(_headFontColor);
1092                 if (_headLineDraw)                                // 绘制分割线
1093                 {
1094                     pgHeader.LineDraw = _headLineDraw;
1095                     pgHeader.LineWidth = _headLineWidth;
1096                     pgHeader.LineColor = (Color)PrintTool.StrToColor(_headLineColor);
1097                     pgHeader.LineDash = PrintTool.GetDashStyle(_headLineDash);
1098                 }
1099 
1100                 // 页眉绘制
1101                 pgHeader.Draw(g);
1102             }
1103         }
1104 
1105         /// <summary>
1106         /// 绘制页脚
1107         /// </summary>
1108         /// <param name="g">绘图对象</param>
1109         private void DrawFooter(Graphics g)
1110         {
1111             // 是否绘制
1112             if (_footDraw)
1113             {
1114                 // 页脚实例
1115                 PageFooter pgFooter = new PageFooter();
1116 
1117                 // 页脚矩形
1118                 RectangleF pgFooterRect = new RectangleF(TableRect.X,                     // X 坐标
1119                                                          TableRect.Y + TableRect.Height,  // Y 坐标      
1120                                                          TableRect.Width,                // W 宽度
1121                                                          mmToPixel(_footHeight)           // H 高度
1122                                                          );
1123                 // 页脚赋值
1124                 pgFooter.FootRect = pgFooterRect;
1125                 pgFooter.StrLeft = ReplacePageNum(_footLeft);     // 左侧文本
1126                 pgFooter.StrCenter = ReplacePageNum(_footCenter); // 中间文本 
1127                 pgFooter.StrRight = ReplacePageNum(_footRight);   // 右侧文本
1128                 FontStyle fontStyle = FontStyle.Regular;          // 字体样式
1129                 if (_footFontBold) fontStyle |= FontStyle.Bold;
1130                 if (_footFontItalic) fontStyle |= FontStyle.Italic;
1131                 if (_footFontStrikeout) fontStyle |= FontStyle.Strikeout;
1132                 if (_footFontUnderline) fontStyle |= FontStyle.Underline;
1133 
1134                 pgFooter.StrFont = new Font(_footFontName, (float)Convert.ToDouble(_footFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
1135                 pgFooter.StrColor = (Color)PrintTool.StrToColor(_footFontColor);
1136                 if (_footLineDraw)                                // 绘制分割线
1137                 {
1138                     pgFooter.LineDraw = _footLineDraw;
1139                     pgFooter.LineWidth = _footLineWidth;
1140                     pgFooter.LineColor = (Color)PrintTool.StrToColor(_footLineColor);
1141                     pgFooter.LineDash = PrintTool.GetDashStyle(_footLineDash);
1142                 }
1143 
1144                 // 页脚绘制
1145                 pgFooter.Draw(g);
1146             }
1147         }
1148 
1149         #endregion
1150 
1151         #region 辅助方法
1152 
1153         /// <summary>
1154         /// 毫米 TO 像素
1155         /// </summary>
1156         /// <param name="mmValue">毫米值</param>
1157         /// <returns></returns>
1158         public static float mmToPixel(float mmValue) //mmValue是毫米,1厘米=10毫米
1159         {
1160             return (mmValue / 25.4f * 100f);
1161         }
1162 
1163         /// <summary>
1164         /// 替换 当前页码、总共页数两个变量
1165         /// </summary>
1166         /// <param name="str"></param>
1167         /// <returns></returns>
1168         private string ReplacePageNum(string str)
1169         {
1170             string retStr = "";
1171             if (str == null || str.Trim() == "")
1172                 return retStr;
1173             retStr = str;
1174             int t = 0;
1175             while (t >= 0)
1176             {
1177                 t = retStr.IndexOf("[curpage]", StringComparison.OrdinalIgnoreCase);
1178                 if (t >= 0)
1179                 {
1180                     retStr = retStr.Substring(0, t) + RptDraw.CurPageNum.ToString() + retStr.Substring(t + "[curpage]".Length);
1181                 }
1182             }
1183 
1184             t = 0;
1185             while (t >= 0)
1186             {
1187                 t = retStr.IndexOf("[allpage]", StringComparison.OrdinalIgnoreCase);
1188                 if (t >= 0)
1189                 {
1190                     retStr = retStr.Substring(0, t) + RptDraw.AllPageNum.ToString() + retStr.Substring(t + "[allpage]".Length);
1191                 }
1192             }
1193             return retStr;
1194         }
1195 
1196         /// <summary>
1197         /// 解析XML文件
1198         /// </summary>
1199         /// <returns>返回成功与否</returns>
1200         private bool ParseXML()
1201         {
1202             if (this.DATAXML == null || this.DATAXML.Trim() == "") return false;
1203             XmlDataDocument xmlDoc = new XmlDataDocument();
1204             try
1205             {
1206                 xmlDoc.LoadXml(this.DATAXML);
1207                 XmlNode rootNode = xmlDoc.DocumentElement;
1208                 if (rootNode.ChildNodes.Count == 0) return false;
1209                 if (rootNode.ChildNodes[0].Name.ToLower() != "table") return false;
1210 
1211                 XmlNode tableNode = rootNode.ChildNodes[0]; // 表格节点
1212                 HtmlHeight = float.Parse(tableNode.Attributes["height"].Value);
1213                 HtmlWidth = float.Parse(tableNode.Attributes["width"].Value);
1214 
1215                 int tmRowIndex = 0;
1216                 foreach (XmlNode trNode in tableNode.ChildNodes)
1217                 {
1218                     if (trNode.Name.ToLower() != "tr") continue;
1219 
1220                     // 解析表格行
1221                     Row tmRow = new Row();
1222                     tmRow.RowIndex = tmRowIndex;
1223                     tmRow.RowHeight = float.Parse(trNode.Attributes["height"].Value);
1224                     tmRow.RowType = trNode.Attributes["rowtype"].Value.ToLower();
1225 
1226                     // 解析单元格
1227                     foreach (XmlNode tdNode in trNode.ChildNodes)
1228                     {
1229                         Cell tmCell = new Cell();
1230 
1231                         #region 合并\坐标\矩形
1232 
1233                         tmCell.RowSpan = Convert.ToInt32(tdNode.Attributes["rowspan"].Value);
1234                         tmCell.ColSpan = Convert.ToInt32(tdNode.Attributes["colspan"].Value);
1235                         tmCell.RowIndex = Convert.ToInt32(tdNode.Attributes["r"].Value);
1236                         tmCell.ColIndex = Convert.ToInt32(tdNode.Attributes["c"].Value);
1237                         tmCell.RectX = float.Parse(tdNode.Attributes["x"].Value);
1238                         tmCell.RectY = float.Parse(tdNode.Attributes["y"].Value);
1239                         tmCell.RectW = float.Parse(tdNode.Attributes["w"].Value);
1240                         tmCell.RectH = float.Parse(tdNode.Attributes["h"].Value);
1241 
1242                         #endregion
1243 
1244                         #region 设置单元格字体
1245 
1246                         FontStyle tmStyle = new FontStyle();
1247                         tmStyle = FontStyle.Regular;
1248                         if (tdNode.Attributes["italic"].Value.ToString() == "1") tmStyle |= FontStyle.Italic;
1249                         if (tdNode.Attributes["bold"].Value.ToString() == "1") tmStyle |= FontStyle.Bold;
1250                         if (tdNode.Attributes["strikeout"].Value.ToString() == "1") tmStyle |= FontStyle.Strikeout;
1251                         if (tdNode.Attributes["underline"].Value.ToString() == "1") tmStyle |= FontStyle.Underline;
1252                         tmCell.CellFont = new Font(tdNode.Attributes["fontname"].Value, float.Parse(tdNode.Attributes["fontsize"].Value.Replace("pt", "").Replace("px", "")), tmStyle, GraphicsUnit.Point);
1253                         tmCell.FontColor = (Color)PrintTool.StrToColor(tdNode.Attributes["fontcolor"].Value);
1254                         tmCell.BackColor = (Color)PrintTool.StrToColor(tdNode.Attributes["backcolor"].Value);
1255 
1256                         StringFormat tmFormat = new StringFormat();
1257                         switch (tdNode.Attributes["align"].Value.ToLower())     // 水平对齐方式
1258                         {
1259                             case "center":
1260                                 tmFormat.Alignment = StringAlignment.Center;
1261                                 break;
1262                             case "right":
1263                                 tmFormat.Alignment = StringAlignment.Far;
1264                                 break;
1265                             default:
1266                                 tmFormat.Alignment = StringAlignment.Near;
1267                                 break;
1268                         }
1269                         switch (tdNode.Attributes["valign"].Value.ToLower())   // 垂直对齐方式
1270                         {
1271                             case "middle":
1272                                 tmFormat.LineAlignment = StringAlignment.Center;
1273                                 break;
1274                             case "bottom":
1275                                 tmFormat.LineAlignment = StringAlignment.Far;
1276                                 break;
1277                             default:
1278                                 tmFormat.LineAlignment = StringAlignment.Near;
1279                                 break;
1280                         }
1281                         tmCell.strFormat = tmFormat;
1282 
1283                         #endregion
1284 
1285                         #region 内嵌图片-属性
1286 
1287                         tmCell.IsImage = tdNode.Attributes["isimage"].Value.ToString() == "1" ? true : false;
1288                         if (tmCell.IsImage)
1289                             tmCell.ImageUrl = tdNode.Attributes["imageurl"].Value;
1290                         #endregion
1291 
1292                         #region 单元格边框属性
1293 
1294                         // 左边框线
1295                         string tmVal = tdNode.Attributes["leftwidth"].Value;
1296                         if (tmVal.IndexOf("px") >= 0)
1297                         {
1298                             tmCell.LeftBorder = new BorderLine(
1299                                                                 float.Parse(tmVal.Replace("px", "")),
1300                                                                 (Color)PrintTool.StrToColor(tdNode.Attributes["leftcolor"].Value),
1301                                                                 PrintTool.GetDashStyle(tdNode.Attributes["leftdash"].Value)
1302                                                                );
1303                         }
1304 
1305                         // 上边框线
1306                         tmVal = tdNode.Attributes["topwidth"].Value;
1307                         if (tmVal.IndexOf("px") >= 0)
1308                         {
1309                             tmCell.TopBorder = new BorderLine(
1310                                                                 float.Parse(tmVal.Replace("px", "")),
1311                                                                 (Color)PrintTool.StrToColor(tdNode.Attributes["topcolor"].Value),
1312                                                                  PrintTool.GetDashStyle(tdNode.Attributes["topdash"].Value)
1313                                                               );
1314 
1315                         }
1316 
1317                         // 右边框线
1318                         tmVal = tdNode.Attributes["rightwidth"].Value;
1319                         if (tmVal.IndexOf("px") >= 0)
1320                         {
1321                             tmCell.RightBorder = new BorderLine(
1322                                                                   float.Parse(tmVal.Replace("px", "")),
1323                                                                   (Color)PrintTool.StrToColor(tdNode.Attributes["rightcolor"].Value),
1324                                                                   PrintTool.GetDashStyle(tdNode.Attributes["rightdash"].Value)
1325                                                                );
1326                         }
1327 
1328                         // 下边框线
1329                         tmVal = tdNode.Attributes["bottomwidth"].Value;
1330                         if (tmVal.IndexOf("px") >= 0)
1331                         {
1332                             tmCell.BottomBorder = new BorderLine(
1333                                                                   float.Parse(tmVal.Replace("px", "")),
1334                                                                   (Color)PrintTool.StrToColor(tdNode.Attributes["bottomcolor"].Value),
1335                                                                   PrintTool.GetDashStyle(tdNode.Attributes["bottomdash"].Value)
1336                                                                 );
1337                         }
1338 
1339                         #endregion
1340 
1341                         #region 单据格数据数值
1342 
1343                         tmCell.Value = tdNode.InnerText;
1344 
1345                         #endregion
1346 
1347                         // 加入对应的行内
1348                         tmRow.RowCells.Add(tmCell);
1349                     }
1350 
1351                     RptDraw.RowsList.Add(tmRow);
1352 
1353                     tmRowIndex++;
1354                 }
1355             }
1356             catch
1357             {
1358                 return false;
1359             }
1360             finally
1361             {
1362                 xmlDoc = null;
1363             }
1364 
1365             return true;
1366         }
1367 
1368         /// <summary>
1369         /// 计算报表区域矩形
1370         /// 真实的绘制报表的区域
1371         /// </summary>
1372         private void CalcTableRect()
1373         {
1374             // 重新初始化实例
1375             TableRect = new RectangleF();
1376 
1377             // 左顶点 X坐标
1378             TableRect.X = mmToPixel(_marginLeft);
1379 
1380             // 左顶点 Y坐标
1381             TableRect.Y = mmToPixel(_marginTop);
1382             if (_headDraw) // 需要绘制页眉
1383                 TableRect.Y += mmToPixel(_headHeight);
1384 
1385             // 报表矩形宽度高度
1386             if (this.LANDSCAPE)  // 版型方向 横向
1387             {
1388                 // 颠倒 宽高
1389                 TableRect.Width = mmToPixel((float)_paperHeight - _marginLeft - _marginRight);
1390                 TableRect.Height = mmToPixel((float)_paperWidth - _marginTop - _marginBottom);
1391             }
1392             else // 版型方向 纵向
1393             {
1394                 TableRect.Width = mmToPixel((float)_paperWidth - _marginLeft - _marginRight);
1395                 TableRect.Height = mmToPixel((float)_paperHeight - _marginTop - _marginBottom);
1396             }
1397 
1398             // 报表矩形高度缩减
1399             if (_headDraw) // 需要绘制页眉
1400                 TableRect.Height -= mmToPixel(_headHeight);
1401             if (_footDraw) // 需要绘制页脚
1402                 TableRect.Height -= mmToPixel(_footHeight);
1403         }
1404 
1405         /// <summary>
1406         /// 计算缩放比例
1407         /// </summary>
1408         private void CalcReportZoom()
1409         {
1410             if (this.ZOOMTYPE.ToLower() == "row")
1411             {
1412                 if (Convert.ToInt32(TableRect.Width) >= HtmlWidth)
1413                     this.Zoom = 1;
1414                 else
1415                     this.Zoom = TableRect.Width / HtmlWidth;
1416             }
1417             else if (this.ZOOMTYPE.ToLower() == "col")
1418             {
1419                 if (Convert.ToInt32(TableRect.Height) >= HtmlHeight)
1420                     this.Zoom = 1;
1421                 else
1422                     this.Zoom = TableRect.Height / HtmlHeight;
1423             }
1424             else
1425             {
1426                 this.Zoom = 1;
1427             }
1428         }
1429 
1430         /// <summary>
1431         /// 转换所有的尺寸
1432         /// 根据缩放比例
1433         /// </summary>
1434         private void CalcZoomAllSize()
1435         {
1436             if (this.Zoom != 1)
1437             {
1438                 // 转换HTML 高度宽度
1439                 HtmlWidth = HtmlWidth * Zoom;
1440                 HtmlHeight = HtmlHeight * Zoom;
1441 
1442                 // 转换所有行号
1443                 foreach (Row zRow in this.RptDraw.RowsList)
1444                 {
1445                     // 行高缩小
1446                     zRow.RowHeight = zRow.RowHeight * Zoom;
1447 
1448                     // 转换所有单元格 
1449                     foreach (Cell zCell in zRow.RowCells)
1450                     {
1451                         zCell.RectX = zCell.RectX * Zoom;
1452                         zCell.RectY = zCell.RectY * Zoom;
1453                         zCell.RectW = zCell.RectW * Zoom;
1454                         zCell.RectH = zCell.RectH * Zoom;
1455 
1456                         zCell.TopBorder.LineWidth = zCell.TopBorder.LineWidth * Zoom;
1457                         zCell.BottomBorder.LineWidth = zCell.BottomBorder.LineWidth * Zoom;
1458                         zCell.LeftBorder.LineWidth = zCell.LeftBorder.LineWidth * Zoom;
1459                         zCell.RightBorder.LineWidth = zCell.RightBorder.LineWidth * Zoom;
1460 
1461                         // 字体相应缩小
1462                         zCell.CellFont = new Font(zCell.CellFont.Name, zCell.CellFont.Size * Zoom, zCell.CellFont.Style, GraphicsUnit.Point);
1463 
1464                     }
1465                 }
1466             }
1467         }
1468 
1469         #endregion
1470 
1471     }
1472 }
复制代码

 

2、ReportDraw 打印绘制类

复制代码
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Drawing;
  4 using System.Drawing.Drawing2D;
  5 using System.IO;
  6 
  7 namespace E_Print
  8 {
  9     /// <summary>
 10     /// 报表绘制
 11     /// </summary>
 12     public class ReportDraw
 13     {
 14         #region 私有成员
 15 
 16         /// <summary>
 17         /// 当前页码
 18         /// </summary>
 19         private int _curPageNum;
 20 
 21         /// <summary>
 22         /// 总共页数
 23         /// </summary>
 24         private int _allPageNum;
 25 
 26         /// <summary>
 27         /// 表格矩形
 28         /// </summary>
 29         private RectangleF _reptRect;
 30 
 31         /// <summary>
 32         /// 报表全部行集
 33         /// </summary>
 34         private List<Row> _rowsList;
 35 
 36         /// <summary>
 37         /// 分页页面数组
 38         /// </summary>
 39         private List<PagingItem> _pageList;
 40 
 41         /// <summary>
 42         /// 是否每页打印标题
 43         /// </summary>
 44         private bool _isAllPrintTitle;
 45 
 46         /// <summary>
 47         /// 是否每页打印表头
 48         /// </summary>
 49         private bool _isAllPrintHead;
 50 
 51         /// <summary>
 52         /// 是否每页打印表尾
 53         /// </summary>
 54         private bool _isAllPrintFoot;
 55 
 56         /// <summary>
 57         /// 是否末页自动补行
 58         /// </summary>
 59         private bool _isAutoFillRow;
 60 
 61         /// <summary>
 62         /// 缩小比例
 63         /// </summary>
 64         private float _zoom;
 65 
 66         /// <summary>
 67         /// 字符溢出处理方式
 68         /// </summary>
 69         private bool _isOverFlow;
 70 
 71         /// <summary>
 72         /// 每页打印的标题+表头的高度
 73         /// </summary>
 74         private float _headPix;
 75 
 76         /// <summary>
 77         /// 每页打印的表尾高度
 78         /// </summary>
 79         private float _footPix;
 80 
 81         #endregion
 82 
 83         #region 构造方法
 84 
 85         /// <summary>
 86         /// 构造函数
 87         /// </summary>
 88         public ReportDraw()
 89         {
 90             _curPageNum = 1;
 91             _allPageNum = 1;
 92             _reptRect = new RectangleF();
 93             _rowsList = new List<Row>();
 94             _pageList = new List<PagingItem>();
 95 
 96             _isAllPrintTitle = false;
 97             _isAllPrintHead = false;
 98             _isAllPrintFoot = false;
 99             _isAutoFillRow = false;
100 
101             _zoom = 1;
102             _isOverFlow = false;
103             _headPix = 0;
104             _footPix = 0;
105         }
106 
107         /// <summary>
108         /// 构造函数
109         /// </summary>
110         /// <param name="printTitle">每页打印标题</param>
111         /// <param name="printHead">每页打印表头</param>
112         /// <param name="printFoot">每页打印表位</param>
113         /// <param name="fillRows">自动补全空行</param>
114         /// <param name="tableRect">报表尺寸矩形</param>
115         /// <param name="overFlow">字符溢出处理</param>
116         public ReportDraw(bool printTitle, bool printHead, bool printFoot, bool fillRows, RectangleF tableRect, bool overFlow)
117         {
118 
119             _reptRect = tableRect;
120             _isAllPrintTitle = printTitle;
121             _isAllPrintHead = printHead;
122             _isAllPrintFoot = printFoot;
123             _isAutoFillRow = fillRows;
124             _isOverFlow = overFlow;
125 
126             _curPageNum = 1;
127             _allPageNum = 1;
128             _zoom = 1;
129             _rowsList = new List<Row>();
130             _pageList = new List<PagingItem>();
131 
132             _headPix = 0;
133             _footPix = 0;
134         }
135 
136         #endregion
137 
138         #region 属性方法
139 
140         /// <summary>
141         /// 获取--设置--当前页码
142         /// </summary>
143         public int CurPageNum
144         {
145             get { return _curPageNum; }
146             set { _curPageNum = value; }
147         }
148 
149         /// <summary>
150         /// 获取--设置--总共页数
151         /// </summary>
152         public int AllPageNum
153         {
154             get { return _allPageNum; }
155             set { _allPageNum = value; }
156         }
157 
158         /// <summary>
159         /// 获取--设置--表格矩形
160         /// </summary>
161         public RectangleF ReptRect
162         {
163             get { return _reptRect; }
164             set { _reptRect = value; }
165         }
166 
167         /// <summary>
168         /// 获取--设置--报表全部行集
169         /// </summary>
170         public List<Row> RowsList
171         {
172             get { return _rowsList; }
173             set { _rowsList = value; }
174         }
175 
176         /// <summary>
177         /// 获取--设置--分页页面数组
178         /// </summary>
179         public List<PagingItem> PageList
180         {
181             get { return _pageList; }
182             set { _pageList = value; }
183         }
184 
185         /// <summary>
186         /// 获取--设置--是否每页打印标题
187         /// </summary>
188         public bool IsAllPrintTitle
189         {
190             get { return _isAllPrintTitle; }
191             set { _isAllPrintTitle = value; }
192         }
193 
194         /// <summary>
195         /// 获取--设置--是否每页打印表头
196         /// </summary>
197         public bool IsAllPrintHead
198         {
199             get { return _isAllPrintHead; }
200             set { _isAllPrintHead = value; }
201         }
202 
203         /// <summary>
204         /// 获取--设置--是否每页打印表尾
205         /// </summary>
206         public bool IsAllPrintFoot
207         {
208             get { return _isAllPrintFoot; }
209             set { _isAllPrintFoot = value; }
210         }
211 
212         /// <summary>
213         /// 获取--设置--末页是否自动补行
214         /// </summary>
215         public bool IsAutoFillRow
216         {
217             get { return _isAutoFillRow; }
218             set { _isAutoFillRow = value; }
219         }
220 
221         /// <summary>
222         /// 获取--设置--缩小比例
223         /// </summary>
224         public float Zoom
225         {
226             get { return _zoom; }
227             set { _zoom = value; }
228         }
229 
230         /// <summary>
231         /// 获取--设置--字符溢出处理方式
232         /// </summary>
233         public bool IsOverFlow
234         {
235             get { return _isOverFlow; }
236             set { _isOverFlow = value; }
237         }
238 
239         /// <summary>
240         /// 获取--设置--每页打印的标题+表头高度
241         /// </summary>
242         public float HeadPix
243         {
244             get { return _headPix; }
245             set { _headPix = value; }
246         }
247 
248         /// <summary>
249         /// 获取--设置--每页打印的表尾高度
250         /// </summary>
251         public float FootPix
252         {
253             get { return _footPix; }
254             set { _footPix = value; }
255         }
256 
257         #endregion
258 
259         #region 计算分页
260 
261         /// <summary>
262         /// 计算分页
263         /// </summary>
264         public void CalcPaging()
265         {
266             // 分页实例
267             PagingCalc insCalc = new PagingCalc();
268             insCalc.TableRect = this.ReptRect;
269             insCalc.RowsList = this.RowsList;
270             insCalc.IsAllPrintTitle = this.IsAllPrintTitle;
271             insCalc.IsAllPrintHead = this.IsAllPrintHead;
272             insCalc.IsAllPrintFoot = this.IsAllPrintFoot;
273 
274             // 分页计算
275             _pageList = insCalc.CalcPages();
276             this._allPageNum = _pageList.Count;
277             this._curPageNum = 1;
278 
279             this._headPix = insCalc.MyHeadPix;
280             this._footPix = insCalc.MyFootPix;
281         }
282 
283         #endregion
284 
285         #region 绘制方法
286 
287         /// <summary>
288         /// 绘制报表
289         /// </summary>
290         /// <param name="g"></param>
291         /// <returns>返回是否结束</returns>
292         public bool DrawReport(Graphics g)
293         {
294             bool isMorePage = false;
295             float offsetX = _reptRect.X;  // X 偏移量
296             float offsetY = _reptRect.Y;  // Y 偏移量
297 
298             bool isCanFillRow = false;    // 是否需要补行
299             bool isFillFlag = false;      // 是否已经补过
300             int isFillRowNum = 0;         // 需要补充几行
301 
302             PagingItem nowPage = GetPageItem(CurPageNum);              // 当前页
303             if (nowPage != null)
304             {
305                 #region 判定高度不足是否自动补行
306 
307                 // 判定补行条件  报表设置了末页不足自动补行、同时 为最后一页
308                 if (_isAutoFillRow == true && CurPageNum == AllPageNum)
309                 {
310                     // 判定页面高度 与 数据高度
311                     float N_PageHeith = ReptRect.Height;                   // 当前页面高度
312                     float N_DataHeith = GetThisPageDataRowsHeight();       // 当前数据高度
313 
314                     // 补行行高21
315                     while ((N_DataHeith + (isFillRowNum + 1) * 21 * Zoom) < N_PageHeith)
316                     {
317                         isFillRowNum++;
318                     }
319 
320                     if (isFillRowNum > 0)
321                         isCanFillRow = true;
322                 }
323 
324                 #endregion
325 
326                 #region 首先绘制上一页补充单元格
327 
328                 if (CurPageNum > 1)
329                 {
330                     PagingItem prePage = GetPageItem(CurPageNum - 1); // 上一页
331                     if (prePage != null)
332                     {
333                         foreach (PagingMakeUp tmMk in prePage.MakeupList)
334                         {
335                             // 绘制补充单元格(上页中未绘制完成的单元格)
336                             DrawTD(g, tmMk.MakeupCell, offsetX, offsetY, true, tmMk.MakeupHeight, false);
337                         }
338                     }
339                 }
340 
341                 #endregion
342 
343                 #region 其次绘制当前页面的单元格
344 
345                 // 其次绘制当前页的单元格
346                 for (int ii = 0; ii < nowPage.IndexList.Count; ii++)
347                 {
348                     // 先绘制 TD CELL 单元格
349                     Row rowTR = GetRow(nowPage.IndexList[ii]);
350 
351                     #region 执行补行
352 
353                     if (isCanFillRow == true && rowTR.RowType.ToLower().Trim() == "f")  // 需要补行 行标志为F 表尾前进行补充空行
354                     {
355                         Row fillRow = new Row();
356                         if (ii == 0)
357                             fillRow = rowTR;
358                         else
359                             fillRow = GetRow(nowPage.IndexList[ii - 1]);
360                         if (fillRow != null) // 绘制自动补充的空行单元格
361                         {
362                             // 开始补充空行                  
363                             for (int fi = 1; fi <= isFillRowNum; fi++)
364                             {
365                                 bool bcFlag = true;
366                                 // 绘制单元格
367                                 foreach (Cell fillTdCell in fillRow.RowCells)
368                                 {
369                                     if (bcFlag)
370                                     {
371                                         // 绘制边框线(合并单元格的情况才用到)
372                                         if (fillTdCell.RectX > 0)
373                                         {
374                                             DrawLine(g, offsetX, offsetY, offsetX, offsetY + 21.0F * Zoom);  // 最左边竖线
375                                             DrawLine(g, offsetX, offsetY + 21.0F * Zoom, offsetX + fillTdCell.RectX, offsetY + 21.0F * Zoom);
376                                         }
377                                         bcFlag = false;
378                                     }
379                                     DrawTD(g, fillTdCell, offsetX, offsetY, false, 0, true);
380                                 }
381 
382                                 // 再将偏移量+行号 补充的行高全部为21px
383                                 offsetY += 21 * Zoom;
384                             }
385                         }
386 
387                         isFillFlag = true;
388                     }
389 
390                     #endregion
391 
392                     #region 正常绘制
393 
394                     foreach (Cell td in rowTR.RowCells)
395                     {
396                         DrawTD(g, td, offsetX, offsetY, false, 0, false);
397                     }
398 
399                     // 再将偏移量+行号
400                     offsetY += rowTR.RowHeight;
401 
402                     #endregion
403                 }
404 
405                 // 判定是否补过;没有补充过,则在最后进行补充空行
406                 if ((isCanFillRow == true) && (isFillFlag == false) && (nowPage.IndexList.Count > 0))
407                 {
408                     Row fillRow = GetRow(nowPage.IndexList[nowPage.IndexList.Count - 1]);
409                     if (fillRow != null) // 绘制自动补充的空行单元格
410                     {
411                       
412                         // 开始补充空行
413                         for (int fi = 1; fi <= isFillRowNum; fi++)
414                         {
415                             bool newFlag = true;
416                             foreach (Cell fillTdCell in fillRow.RowCells)
417                             {
418                                 if (newFlag)
419                                 {
420                                     // 绘制边框线(合并单元格的情况才用到)
421                                     if (fillTdCell.RectX > 0)
422                                     {
423                                         DrawLine(g, offsetX, offsetY, offsetX, offsetY + 21.0F * Zoom);  // 最左边竖线
424                                         DrawLine(g, offsetX, offsetY + 21.0F * Zoom, offsetX + fillTdCell.RectX, offsetY + 21.0F * Zoom);
425                                     }
426                                     newFlag = false;
427                                 }
428                                 DrawTD(g, fillTdCell, offsetX, offsetY, false, 0, true);
429                             }
430                             offsetY += 21 * Zoom;  // 再将偏移量+行号 补充的行高全部为21px
431                         }
432                     }
433                 }
434 
435                 #endregion
436 
437                 if (CurPageNum < AllPageNum)
438                 {
439                     isMorePage = true;  // 还有下页
440                     CurPageNum++;       // 页码增加
441                 }
442             }
443             return isMorePage;
444         }
445 
446         /// <summary>
447         /// 绘制单元格
448         /// </summary>
449         /// <param name="g">绘图对象</param>
450         /// <param name="tdCell">单元格</param>
451         /// <param name="setX">X偏移量</param>
452         /// <param name="setY">Y坐标值</param>
453         /// <param name="isMakeup">是否补充单元格</param>
454         /// <param name="mkH">补充单元格高度</param>
455         /// <param name="fillCell">自动补行的单元格</param>
456         private void DrawTD(Graphics g, Cell tdCell, float setX, float setY, bool isMakeup, float mkH, bool fillCell)
457         {
458             #region 参数变量
459 
460             Pen pen;
461             Brush brush;
462 
463             // 获取单元格绘制坐标矩形信息
464             float tdX = tdCell.RectX + setX;
465             float tdY = setY;
466             float tdW = tdCell.RectW;
467             float tdH = 0;
468 
469             if (fillCell)
470             {
471                 tdH = 21 * Zoom;  // 自动补行的单元格的高度固定为21px
472             }
473             else
474             {
475                 if (isMakeup)            // 补充单元格
476                 {
477                     tdH = mkH;
478                     tdY = tdY + HeadPix; // 如果是补充单元格,则此单元格的Y坐标:如果每页打印标题或表头,则Y坐标 需要下移 HeadPix
479                 }
480                 else                     // 实际单元格
481                 {
482                     tdH = tdCell.RectH;
483                 }
484                 if (tdCell.RowSpan > 1)  // 判定单元格高度是否超过底线
485                 {
486                     tdH = Calc_CellOverHeight(tdCell, tdY, tdH);
487                 }
488             }
489 
490             #endregion
491 
492             #region 绘制背景
493 
494             // 填充颜色
495             brush = new SolidBrush(tdCell.BackColor);
496             g.FillRectangle(brush, tdX + 1.0f * Zoom, tdY + 1.0f * Zoom, tdW - 2.0f * Zoom, tdH - 2.0f * Zoom);
497 
498             #endregion
499 
500             #region 绘制边框
501 
502             // 左边框线
503             if (tdCell.LeftBorder.LineWidth > 0)
504             {
505                 pen = new Pen(tdCell.LeftBorder.LineColor);
506                 pen.DashStyle = tdCell.LeftBorder.LineDash;
507                 pen.Width = tdCell.LeftBorder.LineWidth;
508                 g.DrawLine(pen, tdX, tdY, tdX, tdY + tdH);
509             }
510 
511             // 上边框线
512             if (tdCell.TopBorder.LineWidth > 0)
513             {
514                 pen = new Pen(tdCell.TopBorder.LineColor);
515                 pen.DashStyle = tdCell.TopBorder.LineDash;
516                 pen.Width = tdCell.TopBorder.LineWidth;
517                 g.DrawLine(pen, tdX, tdY, tdX + tdW, tdY);
518             }
519 
520             // 右边框线
521             if (tdCell.RightBorder.LineWidth > 0)
522             {
523                 pen = new Pen(tdCell.RightBorder.LineColor);
524                 pen.DashStyle = tdCell.RightBorder.LineDash;
525                 pen.Width = tdCell.RightBorder.LineWidth;
526                 g.DrawLine(pen, tdX + tdW, tdY, tdX + tdW, tdY + tdH);
527             }
528 
529             // 下边框线
530             if (tdCell.BottomBorder.LineWidth > 0)
531             {
532                 pen = new Pen(tdCell.BottomBorder.LineColor);
533                 pen.DashStyle = tdCell.BottomBorder.LineDash;
534                 pen.Width = tdCell.BottomBorder.LineWidth;
535                 g.DrawLine(pen, tdX, tdY + tdH, tdX + tdW, tdY + tdH);
536             }
537 
538             #endregion
539 
540             #region 绘制文字
541 
542             if (!fillCell)
543             {
544                 RectangleF rect = new RectangleF(tdX, tdY, tdW, tdH);
545                 if (tdCell.IsImage)
546                 {
547                     this.DrawImg(g, rect, tdCell.ImageUrl);
548                 }
549                 else
550                 {
551                     brush = new SolidBrush(tdCell.FontColor);
552                     this.DrawStr(g, rect, brush, tdCell.CellFont, tdCell.strFormat, tdCell.Value);
553                 }
554             }
555 
556             #endregion
557         }
558 
559         /// <summary>
560         /// 绘制字符串
561         /// 溢出时,换行缩小字符
562         /// 字体缩小到的最小值不得小于
563         /// </summary>
564         /// <param name="g">绘图对象</param>
565         /// <param name="strRect">文本区域</param>
566         /// <param name="strBrush">文本笔画</param>
567         /// <param name="strFont">文本字体</param>
568         /// <param name="strFormat">文本格式</param>
569         /// <param name="strValue">文本字符</param>
570         /// <returns></returns>
571         private void DrawStr(Graphics g, RectangleF strRect, Brush strBrush, Font strFont, StringFormat strFormat, string strValue)
572         {
573             // 报表设置:字符溢出不做处理
574             if (!this.IsOverFlow)
575             {
576                 g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
577             }
578             else  // 需要处理
579             {
580                 // 测量字体的宽度和高度 会发现误差很大,如果一个一个的测量,误差就实在太大,所以这里就用简单的方式来进行处理
581                 SizeF sf = g.MeasureString(strValue, strFont);   // 此种方式测量误差很大,如果
582                 if (strRect.Width > sf.Width)
583                 {
584                     g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
585                 }
586                 else
587                 {
588                     // 计算换行后字符的全部高度是否满足
589                     int maxLines = 0; // 计算当前字符当前字体最大打印的行数
590                     maxLines = (int)Math.Ceiling((double)sf.Width / (double)strRect.Width);
591                     if (strRect.Height >= maxLines * sf.Height)
592                     {
593                         g.DrawString(strValue, strFont, strBrush, strRect, strFormat);
594                     }
595                     else
596                     {
597                         float tmScale = strRect.Height / (maxLines * sf.Height);
598                         Font tmNewFont = new Font(strFont.Name, strFont.Size * tmScale, strFont.Style, GraphicsUnit.Point);
599                         g.DrawString(strValue, tmNewFont, strBrush, strRect, strFormat);
600                     }
601                 }
602             }
603 
604         }
605 
606         /// <summary>
607         /// 绘制图片
608         /// 将Base64图片流字符串转换成图片并进行绘制
609         /// </summary>
610         /// <param name="g"></param>
611         /// <param name="strRect"></param>
612         /// <param name="base64Img"></param>
613         private void DrawImg(Graphics g, RectangleF strRect, string base64Img)
614         {
615             if (base64Img.Trim() == "") return;
616             string imgStr = base64Img.Replace("data:image/gif;base64,", "").Trim();
617             if (imgStr == "") return;
618 
619             // 生成图片
620             try
621             {
622                 MemoryStream stream = new MemoryStream(Convert.FromBase64String(imgStr));
623                 Bitmap picImg = new Bitmap(stream);
624 
625                 RectangleF imgRectF = new RectangleF(0f, 0f, (float)picImg.Width, (float)picImg.Height);                // 原始图片矩形
626                 RectangleF newRectF = new RectangleF(strRect.X + 1f, strRect.Y + 1f, (float)strRect.Width - 2f, (float)strRect.Height - 2f);  // 绘制图片矩形
627                 g.DrawImage(picImg, newRectF, imgRectF, GraphicsUnit.Pixel);               // 绘制缩放图片
628                 stream.Close();
629             }
630             catch
631             {
632                 return;
633             }
634         }
635 
636         /// <summary>
637         /// 绘制线条
638         /// </summary>
639         /// <param name="g">绘图对象</param>
640         /// <param name="start_X">开始X</param>
641         /// <param name="start_Y">开始Y</param>
642         /// <param name="end_X">结束X</param>
643         /// <param name="end_Y">结束Y</param>
644         private void DrawLine(Graphics g, float start_X, float start_Y, float end_X, float end_Y)
645         {
646             Pen linePen = new Pen(Color.Black, 1.0f);
647             linePen.DashStyle = DashStyle.Solid;
648             g.DrawLine(linePen, start_X, start_Y, end_X, end_Y);
649         }
650 
651         private float ChangeUnit(float vSize)
652         {
653             return (vSize * 72f / 96f * 72f / 75f);
654         }
655 
656         /// <summary>
657         /// 获取行对象
658         /// </summary>
659         /// <param name="rowIndex"></param>
660         /// <returns></returns>
661         private Row GetRow(int rowIndex)
662         {
663             foreach (Row retRow in _rowsList)
664             {
665                 if (retRow.RowIndex == rowIndex)
666                     return retRow;
667             }
668             return null;
669         }
670 
671         /// <summary>
672         /// 获取分页页面
673         /// </summary>
674         /// <param name="pNo">页码</param>
675         /// <returns></returns>
676         private PagingItem GetPageItem(int pNo)
677         {
678             foreach (PagingItem retPItem in PageList)
679             {
680                 if (retPItem.PageNum == pNo)
681                     return retPItem;
682             }
683 
684             return null;
685         }
686 
687         /// <summary>
688         /// 计算绘制高度
689         /// 判定并且计算单元格高度是否超过当前页面所有行高度的底线
690         /// </summary>
691         /// <param name="mCell">单元格</param>
692         /// <param name="mY">Y 轴坐标值</param>
693         /// <param name="mH">H 当前高度</param>
694         /// <returns></returns>
695         private float Calc_CellOverHeight(Cell mCell, float mY, float mH)
696         {
697             float returnHeight = 0;                                      // 返回高度
698             float tm_AllTrHeight = GetThisPageDataRowsHeight();          // 当前页面内所有数据行的高度
699             float tm_RealY = 0;                                          // 相对最大Y值
700             float tm_AbsY = 0;                                           // 实际最大Y值
701             float tm_OverPlus = 0;                                       // 单元格剩余高度
702             tm_RealY = mY + mH;                                          // 实际最大Y值
703             if (IsAllPrintFoot)                                          // 每页打印表尾
704                 tm_AbsY = ReptRect.Y + (tm_AllTrHeight - FootPix);       // 需要减去表尾高度
705             else
706                 tm_AbsY = tm_AllTrHeight + ReptRect.Y;
707 
708             if (tm_RealY > tm_AbsY)
709             {
710                 returnHeight = tm_AbsY - mY;      // 当前页面实际最大高度-单元格的当前Y坐标值 = 返回单元格在本页内需要绘制的高度
711                 tm_OverPlus = mH - returnHeight;  // 当前高度-单元格当前页面需要绘制的高度=下页需要绘制的补充高度
712 
713                 // 将当前单元格添加到后页需要补充绘制数组中去
714                 PagingItem nPageItem = GetPageItem(CurPageNum);
715                 PagingMakeUp nMakeUp = new PagingMakeUp();
716                 nMakeUp.MakeupCell = mCell;
717                 nMakeUp.MakeupHeight = tm_OverPlus;
718                 nPageItem.MakeupList.Add(nMakeUp);
719             }
720             else
721             {
722                 returnHeight = mH;
723             }
724 
725             return returnHeight;
726         }
727 
728         /// <summary>
729         /// 获取本页内所有数据行的高度
730         /// </summary>
731         /// <returns></returns>
732         private float GetThisPageDataRowsHeight()
733         {
734             float retHeight = 0;
735             PagingItem oThisPage = GetPageItem(CurPageNum);     // 当前页
736 
737             foreach (int oRowIndex in oThisPage.IndexList)
738             {
739                 Row oThisRow = GetRow(oRowIndex);
740                 retHeight += oThisRow.RowHeight;
741             }
742 
743             return retHeight;
744         }
745 
746         /// <summary>
747         /// 获取页内某一项所属行的高度
748         /// </summary>
749         /// <param name="itemPage">页面对象</param>
750         /// <param name="itemIndex">本页行数组中的某一项的序号</param>
751         /// <returns></returns>
752         private float GetThisPageOneRowHeight(PagingItem itemPage, int itemIndex)
753         {
754             float retHeight = 0;
755             if (itemIndex < itemPage.IndexList.Count && itemIndex >= 0)
756             {
757                 Row oThisRow = GetRow(itemPage.IndexList[itemIndex]);
758                 retHeight = oThisRow.RowHeight;
759             }
760             return retHeight;
761         }
762 
763         #endregion
764 
765     }
766 }
复制代码

3、PagingCalc 分页计算类

复制代码
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Drawing;
  5 
  6 namespace E_Print
  7 {
  8     /// <summary>
  9     /// 分页计算
 10     /// </summary>
 11     public class PagingCalc
 12     {
 13         #region 私有变量
 14 
 15         /// <summary>
 16         /// 表格区域
 17         /// </summary>
 18         private RectangleF _tableRect;
 19 
 20         /// <summary>
 21         /// 报表行集
 22         /// </summary>
 23         private List<Row> _rowsList;
 24 
 25         /// <summary>
 26         /// 是否每页打印标题
 27         /// </summary>
 28         private bool _isAllPrintTitle;
 29 
 30         /// <summary>
 31         /// 是否每页打印表头
 32         /// </summary>
 33         private bool _isAllPrintHead;
 34 
 35         /// <summary>
 36         /// 是否每页打印表尾
 37         /// </summary>
 38         private bool _isAllPrintFoot;
 39 
 40         /// <summary>
 41         /// 标题行集
 42         /// </summary>
 43         private List<Row> TitleList;
 44 
 45         /// <summary>
 46         /// 表头前行集
 47         /// </summary>
 48         private List<Row> HForeList;
 49 
 50         /// <summary>
 51         /// 表头行集
 52         /// </summary>
 53         private List<Row> HeadList;
 54 
 55         /// <summary>
 56         /// 数据行集
 57         /// </summary>
 58         private List<Row> DataList;
 59 
 60         /// <summary>
 61         /// 表尾行集
 62         /// </summary>
 63         private List<Row> FootList;
 64 
 65         /// <summary>
 66         /// 每页打印标题+表头高度
 67         /// </summary>
 68         private float _myHeadPix;
 69 
 70         /// <summary>
 71         /// 每页打印表尾高度
 72         /// </summary>
 73         private float _myFootPix;
 74 
 75         #endregion
 76 
 77         #region 构造方法
 78 
 79         /// <summary>
 80         /// 构造函数
 81         /// </summary>
 82         public PagingCalc()
 83         {
 84             _tableRect = new RectangleF();
 85             _rowsList = new List<Row>();
 86 
 87             _isAllPrintTitle = false;
 88             _isAllPrintHead = false;
 89             _isAllPrintFoot = false;
 90 
 91             TitleList = new List<Row>();
 92             HForeList = new List<Row>();
 93             HeadList = new List<Row>();
 94             DataList = new List<Row>();
 95             FootList = new List<Row>();
 96 
 97             _myHeadPix = 0;
 98             _myFootPix = 0;
 99         }
100 
101         #endregion
102 
103         #region 属性方法
104 
105         /// <summary>
106         /// 获取--设置--表格区域
107         /// </summary>
108         public RectangleF TableRect
109         {
110             get { return _tableRect; }
111             set { _tableRect = value; }
112         }
113 
114         /// <summary>
115         /// 获取--设置--表格行集
116         /// </summary>
117         public List<Row> RowsList
118         {
119             get { return _rowsList; }
120             set { _rowsList = value; }
121         }
122 
123         /// <summary>
124         /// 获取--设置--是否每页打印标题
125         /// </summary>
126         public bool IsAllPrintTitle
127         {
128             get { return _isAllPrintTitle; }
129             set { _isAllPrintTitle = value; }
130         }
131 
132         /// <summary>
133         /// 获取--设置--是否每页打印表头
134         /// </summary>
135         public bool IsAllPrintHead
136         {
137             get { return _isAllPrintHead; }
138             set { _isAllPrintHead = value; }
139         }
140 
141         /// <summary>
142         /// 获取--设置--是否每页打印表尾
143         /// </summary>
144         public bool IsAllPrintFoot
145         {
146             get { return _isAllPrintFoot; }
147             set { _isAllPrintFoot = value; }
148         }
149 
150         /// <summary>
151         /// 获取--设置--每页打印标题+表头高度
152         /// </summary>
153         public float MyHeadPix
154         {
155             get { return _myHeadPix; }
156             set { _myHeadPix = value; }
157         }
158 
159         /// <summary>
160         /// 获取--设置--每页打印表尾巴高度
161         /// </summary>
162         public float MyFootPix
163         {
164             get { return _myFootPix; }
165             set { _myFootPix = value; }
166         }
167 
168         #endregion
169 
170         #region 计算方法
171 
172         /// <summary>
173         /// 分页计算
174         /// </summary>
175         /// <returns></returns>
176         public List<PagingItem> CalcPages()
177         {
178             List<PagingItem> retPages = new List<PagingItem>();
179 
180             // 无需分页
181             if (Get_TableAllHeight() <= TableRect.Height)
182             {
183                 PagingItem tmItem0 = new PagingItem();
184                 tmItem0.PageNum = 1;
185                 for (int y = 0; y < RowsList.Count; y++)
186                 {
187                     tmItem0.IndexList.Add(y);
188                 }
189                 retPages.Add(tmItem0);
190             }
191             else  // 需要分页
192             {
193                 // 有设置了 每页打印标题、表头、表位 其中的任意一个
194                 if (Get_IsCusSet_THDF())  // 则执行每页相对分页
195                 {
196                     Paging_Relative(0, ref retPages);
197 
198                     // 计算每页打印头尾高度
199                     MyHeadPix = 0;
200                     if (IsAllPrintTitle)
201                     {
202                         MyHeadPix += Get_TableTileHeight();
203                     }
204 
205                     if (IsAllPrintHead)
206                     {
207                         MyHeadPix += Get_TableHeadHeight();
208                     }
209 
210                     if (IsAllPrintFoot)
211                     {
212                         MyFootPix = Get_TableFootHeight();
213                     }
214                 }
215                 else  // 执行直接数据分页
216                 {
217                     Paging_Direct(0, ref retPages);
218                 }
219             }
220 
221             return retPages;
222         }
223 
224         /// <summary>
225         /// 直接分页
226         /// </summary>
227         /// <param name="startR">开始行号</param>
228         /// <param name="pages">页面数组</param>
229         private void Paging_Direct(int startR, ref  List<PagingItem> pages)
230         {
231             float p_Height = TableRect.Height;
232             PagingItem p_Item = new PagingItem();
233             p_Item.PageNum = pages.Count + 1;
234             for (int t = startR; t < RowsList.Count; t++)
235             {
236                 // 检查行内单元格是否不允许分页两种情况:条形码,图片
237                 if (Paging_CheckCell(RowsList[t], p_Height))
238                 {
239                     startR = t;
240                     pages.Add(p_Item);
241                     Paging_Direct(startR, ref pages);
242                     break;
243                 }
244                 else
245                 {
246                     p_Height -= RowsList[t].RowHeight;
247                     if (p_Height <= 0)
248                     {
249                         startR = t;
250                         pages.Add(p_Item);
251                         Paging_Direct(startR, ref pages);
252                         break;
253                     }
254                     else
255                     {
256                         p_Item.IndexList.Add(t);
257                         if (t == RowsList.Count - 1)
258                         {
259                             pages.Add(p_Item);
260                         }
261                     }
262                 }
263             }
264         }
265 
266         /// <summary>
267         /// 相对分页
268         /// </summary>
269         /// <param name="startR">开始序号</param>
270         /// <param name="pages">页面数组</param>
271         private void Paging_Relative(int startR, ref  List<PagingItem> pages)
272         {
273             SplitReportArea();                     // 拆分表行
274             float p_Height = TableRect.Height;     // 页面总高
275             PagingItem p_Item = new PagingItem();  // 分页页面
276             p_Item.PageNum = pages.Count + 1;      // 分页页码
277             bool runNext = false;                  // 继续分页
278 
279             #region 每页打印标题
280 
281             // 每页打印标题
282             if (IsAllPrintTitle)
283             {
284                 p_Height -= Get_TableTileHeight();
285                 foreach (Row p_Row in TitleList)
286                     p_Item.IndexList.Add(p_Row.RowIndex);
287             }
288             else
289             {
290                 if (p_Item.PageNum == 1)  // 第一页特殊处理
291                 {
292                     p_Height -= Get_TableTileHeight();
293                     foreach (Row p_Row in TitleList)
294                         p_Item.IndexList.Add(p_Row.RowIndex);
295                 }
296             }
297 
298             #endregion
299 
300             #region 每页打印表头
301 
302             // 每页打印表头
303             if (IsAllPrintHead)
304             {
305                 if (p_Item.PageNum == 1)  // 第一页特殊处理
306                 {
307                     // 计算表头前的行高
308                     p_Height -= Get_TableHForHeight();
309                     foreach (Row p_Row in HForeList)
310                         p_Item.IndexList.Add(p_Row.RowIndex);
311                 }
312 
313                 // 计算表头行的高度
314                 p_Height -= Get_TableHeadHeight();
315                 foreach (Row p_Row in HeadList)
316                     p_Item.IndexList.Add(p_Row.RowIndex);
317             }
318             else
319             {
320                 if (p_Item.PageNum == 1)  // 第一页特殊处理
321                 {
322                     // 计算表头前的行高
323                     p_Height -= Get_TableHForHeight();
324                     foreach (Row p_Row in HForeList)
325                         p_Item.IndexList.Add(p_Row.RowIndex);
326 
327                     // 计算表头行的高度
328                     p_Height -= Get_TableHeadHeight();
329                     foreach (Row p_Row in HeadList)
330                         p_Item.IndexList.Add(p_Row.RowIndex);
331                 }
332             }
333 
334             #endregion
335 
336             #region 每页数据区域
337 
338             // 每页数据划分
339             if (IsAllPrintFoot)
340             {
341                 p_Height -= Get_TableFootHeight();             // 表格高度 先减去表尾的高度
342             }
343             for (int t = startR; t < DataList.Count; t++)
344             {
345                 // 检查行内单元格是否不允许分页两种情况:条形码,图片
346                 if (Paging_CheckCell(DataList[t], p_Height))  // 此情况下,单元格不能分割,并且高度超过页面剩余高度,所以要启动新的一页
347                 {
348                     startR = t;
349                     runNext = true;
350                     break;
351                 }
352                 else
353                 {
354                     p_Height -= DataList[t].RowHeight;
355                     if (p_Height <= 0)
356                     {
357                         startR = t;
358                         runNext = true;
359                         break;
360                     }
361                     else
362                     {
363                         p_Item.IndexList.Add(DataList[t].RowIndex);
364                     }
365                 }
366             }
367 
368             #endregion
369 
370             #region 每页打印表尾
371 
372             // 每页打印表尾
373             if (IsAllPrintFoot)
374             {
375                 foreach (Row p_Row in FootList)
376                     p_Item.IndexList.Add(p_Row.RowIndex);
377             }
378 
379             #endregion
380 
381             #region 添加分页页面
382 
383             pages.Add(p_Item);
384             if (runNext)
385             {
386                 Paging_Relative(startR, ref pages);
387             }
388 
389             #endregion
390         }
391 
392         /// <summary>
393         /// 检查行内单元格如果是图片
394         /// 并且合并行数大于1
395         /// </summary>
396         /// <param name="cRow"></param>
397         /// <param name="cHeight"></param>
398         /// <returns></returns>
399         private bool Paging_CheckCell(Row cRow, float cHeight)
400         {
401             foreach (Cell cCell in cRow.RowCells)
402             {
403                 if (cCell.IsImage == true)
404                 {
405                     if (cCell.RectH > cHeight)
406                         return true;
407                 }
408             }
409             return false;
410         }
411 
412         #endregion
413 
414         #region 辅助方法
415 
416         /// <summary>
417         /// 获取--报表全部高度
418         /// </summary>
419         /// <returns></returns>
420         private float Get_TableAllHeight()
421         {
422             float retHight = 0;
423             for (int k = 0; k < RowsList.Count; k++)
424             {
425                 Row t_Row = RowsList[k];
426                 retHight += t_Row.RowHeight;
427             }
428             return retHight;
429         }
430 
431         /// <summary>
432         /// 获取是否设置了标题、表头、表尾 中的任意一个
433         /// </summary>
434         /// <returns></returns>
435         private bool Get_IsCusSet_THDF()
436         {
437             string tmType = "";
438             foreach (Row cusRow in this.RowsList)
439             {
440                 tmType = cusRow.RowType.ToLower().Trim();
441                 if (tmType == "t" || tmType == "h" || tmType == "f")
442                     return true;
443             }
444 
445             return false;
446         }
447 
448         /// <summary>
449         /// 获取--报表标题高度
450         /// </summary>
451         /// <returns></returns>
452         private float Get_TableTileHeight()
453         {
454             float retHight = 0;
455             for (int k = 0; k < TitleList.Count; k++)
456                 retHight += TitleList[k].RowHeight;
457 
458             return retHight;
459         }
460 
461         /// <summary>
462         /// 获取--报表表头前高度
463         /// </summary>
464         /// <returns></returns>
465         private float Get_TableHForHeight()
466         {
467             float retHight = 0;
468             for (int k = 0; k < HForeList.Count; k++)
469                 retHight += HForeList[k].RowHeight;
470 
471             return retHight;
472         }
473 
474         /// <summary>
475         /// 获取--报表表头高度
476         /// </summary>
477         /// <returns></returns>
478         private float Get_TableHeadHeight()
479         {
480             float retHight = 0;
481             for (int k = 0; k < HeadList.Count; k++)
482                 retHight += HeadList[k].RowHeight;
483             return retHight;
484         }
485 
486         /// <summary>
487         /// 获取--报表表尾高度
488         /// </summary>
489         /// <returns></returns>
490         private float Get_TableFootHeight()
491         {
492             float retHight = 0;
493             for (int k = 0; k < FootList.Count; k++)
494                 retHight += FootList[k].RowHeight;
495             return retHight;
496         }
497 
498         /// <summary>
499         /// 拆分报表区域
500         /// </summary>
501         public void SplitReportArea()
502         {
503             TitleList = new List<Row>();
504             HForeList = new List<Row>();
505             HeadList = new List<Row>();
506             DataList = new List<Row>();
507             FootList = new List<Row>();
508 
509             for (int m = 0; m < RowsList.Count; m++)
510             {
511                 Row mmRow = RowsList[m];
512                 switch (mmRow.RowType.ToLower())
513                 {
514                     case "t": // 标题
515                         TitleList.Add(mmRow);
516                         break;
517                     case "h": // 表头
518                         HeadList.Add(mmRow);
519                         break;
520                     case "f": // 表尾
521                         FootList.Add(mmRow);
522                         break;
523                     case "d": // 数据
524                     default:
525                         DataList.Add(mmRow);
526                         break;
527                 }
528             }
529 
530 
531             // 设置表头前行集
532             if (TitleList.Count == 0 && HeadList.Count > 0)
533             {
534                 List<Row> tmpList = new List<Row>();
535                 for (int n = 0; n < DataList.Count; n++)
536                 {
537                     if (DataList[n].RowIndex < HeadList[0].RowIndex)
538                     {
539                         HForeList.Add(DataList[n]);
540                         tmpList.Add(DataList[n]);
541                     }
542                 }
543 
544                 for (int n = 0; n < tmpList.Count; n++)
545                 {
546                     DataList.Remove(tmpList[n]);
547                 }
548 
549                 tmpList.Clear();
550             }
551 
552             // 重设表尾  不是每页打印表尾情况下,那么表位就去掉
553             if (!IsAllPrintFoot)
554             {
555                 foreach (Row tRow in FootList)
556                     DataList.Add(tRow);
557                 FootList.Clear();
558             }
559         }
560 
561         #endregion
562     }
563 }
复制代码

4、PagingMakeUp 分页补充绘制类

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 
 5 namespace E_Print
 6 {
 7     /// <summary>
 8     /// 下页需要补充绘制
 9     /// </summary>
10     public class PagingMakeUp
11     {
12         /// <summary>
13         /// 补充单元格
14         /// </summary>
15         private Cell _makeupCell;
16 
17         /// <summary>
18         /// 补充高度
19         /// </summary>
20         private float _makeupHeight;
21 
22         /// <summary>
23         /// 构造函数
24         /// </summary>
25         public PagingMakeUp()
26         {
27             _makeupCell = new Cell();
28             _makeupHeight = 0;
29         }
30 
31         /// <summary>
32         /// 获取--设置--补充单元格
33         /// </summary>
34         public Cell MakeupCell
35         {
36             get { return _makeupCell; }
37             set { _makeupCell = value; }
38         }
39 
40         /// <summary>
41         /// 获取--设置--补充高度
42         /// </summary>
43         public float MakeupHeight
44         {
45             get { return _makeupHeight; }
46             set { _makeupHeight = value; }
47         }
48 
49     }
50 }
复制代码

5、IObjectSafety 抽象接口类

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using System.Runtime.InteropServices;
 5 
 6 namespace E_Print
 7 {
 8     /// <summary>
 9     /// 接口抽象基类
10     /// </summary>
11     [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
12     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
13     public interface IObjectSafety
14     {
15         [PreserveSig]
16         int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
17 
18         [PreserveSig()]
19         int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
20     }
21 }
复制代码

6、预览效果

7、我们可以通过源码中的 EPrintTest.exe 打印Winform 实例 ,来执行示范,

通过WEB前端js 生成打印的TABLE的 RptData.xml格式 数据,在WINForm中直接使用

如果在网页中,通过JS 直接传给打印控件就OK

Android Studio 错误: 无法访问android.support.v7.app.ActionBarActivity 找不到 类文件 - suirosu的专栏 - 博客频道 - CSDN.NET

mikel阅读(2836)

Android RecyclerView 使用完全解析概述RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。那么有了ListView、GridView为什么还需要RecyclerView这

来源: Android Studio 错误: 无法访问android.support.v7.app.ActionBarActivity 找不到 类文件 – suirosu的专栏 – 博客频道 – CSDN.NET

错误发生在执行:

D:\AndroidStudioProjects\NdkSample\app\src\main>javah -d jni -classpath C:\AndroidSdk\Android-sdk\platforms\android-18\android.jar;..\..\build\intermediates\classes\Debug [空格]com.NdkSample.MainActivity

后来发现MainActivity中的”import android.support.v7.app.ActionBarActivity;”改为:“import android.app.Activity;”

就成功了!

之前以为是SDK版本 build tool版本引起的,弄了半天

No resource identifier found for attribute 'showAsAction' in package 'android' - 欢醉 - 博客园

mikel阅读(1154)

来源: No resource identifier found for attribute ‘showAsAction’ in package ‘android’ – 欢醉 – 博客园

运行一个项目时在一个menu.xml文件item属性Android:showAsAction 报错 No resource identifier found for attribute ‘showAsAction’ in package ‘Android

google了下,老外说是版本问题,showAsAction was added in API level 11要将API提升到11,添加 “android-support-v7-appcompat.jar” 到Android库( Private Libraries)

android:showAsAction = “never”

当你的应用程序目标设为蜂巢平台时,你可以利用Action Bar部件提供的全部功能,将你的选项菜单项放在Action Bar的右上角,对用户来说使用更方便,控制该行为的主菜单项属性是android:showAsAction。
  这个属性可接受的值有:
  1、always:这个值会使菜单项一直显示在Action Bar上。
  2、ifRoom:如果有足够的空间,这个值会使菜单项显示在Action Bar上。
  3、never:这个值使菜单项永远都不出现在Action Bar上。
  4、withText:这个值使菜单项和它的图标,菜单文本一起显示。

不过这里没有用到这高版本,此处删除这个属性就OK了。

理解netty对protocol buffers的编码解码 - tankaixiong - 博客园

mikel阅读(1191)

来源: 理解netty对protocol buffers的编码解码 – tankaixiong – 博客园

一,netty+protocol buffers简要说明

Netty是业界最流行的NIO框架之一
优点:
1)API使用简单,开发门槛低;
2)功能强大,预置了多种编解码功能,支持多种主流协议;
3)定制能力强,可以通过ChannelHandler对通信框架进行灵活的扩展;
4)性能高,通过与其它业界主流的NIO框架对比,Netty的综合性能最优;
5)成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦恼;
6)社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入;
7)经历了大规模的商业应用考验,质量已经得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它可以完全满足不同行业的商业应用。

 

Protocol Buffers是Google公司开发的一种以有效并可扩展的格式编码结构化数据的方式。
可用于数据存储、通信协议等方面,它不依赖于语言和平台并且可扩展性极强。
现阶段官方支持C++、JAVA、Python等三种编程语言,但可以找到大量的几乎涵盖所有语言的第三方拓展包。

优点
1)二进制消息,性能好/效率高(空间和时间效率都很不错)
2)proto文件生成目标代码,简单易用
3)序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)
4)支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
5)支持多种语言

 二,认识varint

proto 消息格式如:Length + Protobuf Data (消息头+消息数据)

消息头描述消息数据体的长度。为了更减少传输量,消息头采用的是varint 格式。

什么是varint?

Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。
Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,会用两个字节。

例如整数1的表示,仅需一个字节:

0000 0001

例如300的表示,需要两个字节:

1010 1100 0000 0010

采 用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。

下图演示了 Google Protocol Buffer 如何解析两个 bytes。注意到最终计算前将两个 byte 的位置相互交换过一次,这是因为 Google Protocol Buffer 字节序采用 little-endian 的方式。

PB Varint

三,通信的编码解码

netty 默认提供了对protocol buffers 的支持,所以整合起来很简单。整合的关系,关键在于对编码解码的理解。

2.11 服务器端起用一个服务基本的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boosGroup, workGroup).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100).childHandler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());// 解码(处理半包)
                            ch.pipeline().addLast(new ProtobufDecoder(MsgProto.Packet.getDefaultInstance()));
                            ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());//加长度
                            ch.pipeline().addLast(new ProtobufEncoder());// 编码
                            ch.pipeline().addLast(new ServerChannelHandlerAdapter());// 业务处理handler
                        }
                    });
            // 绑定端口
            ChannelFuture future = bootstrap.bind(2015).sync();
            // 等待关闭
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            LOG.error("{}", e);
        } finally {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

 

2.21 重点查看编码解码源码类,ProtobufVarint32FrameDecoder,ProtobufVarint32LengthFieldPrepender,ProtobufEncoder

编码类:

ProtobufEncoder:这里只是把proto 对象直接写入out

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Sharable
public class ProtobufEncoder extends MessageToMessageEncoder<MessageLiteOrBuilder> {
    @Override
    protected void encode(
            ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception {
        if (msg instanceof MessageLite) {
            out.add(wrappedBuffer(((MessageLite) msg).toByteArray()));
            return;
        }
        if (msg instanceof MessageLite.Builder) {
            out.add(wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()));
        }
    }
}

关键是ProtobufVarint32LengthFieldPrepender类:

* BEFORE DECODE (300 bytes) AFTER DECODE (302 bytes)
* +—————+ +——–+—————+
* | Protobuf Data |————–>| Length | Protobuf Data |
* | (300 bytes) | | 0xAC02 | (300 bytes) |
* +—————+ +——–+—————+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//数据格式为=数据长度(头部)+ 真正的数据
@Sharable
public class ProtobufVarint32LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
    @Override
    protected void encode(
            ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
        int bodyLen = msg.readableBytes();
        int headerLen = CodedOutputStream.computeRawVarint32Size(bodyLen);
        out.ensureWritable(headerLen + bodyLen);//确保可写长度(头部长度+数据长度)
        //数据长度写入头部
        CodedOutputStream headerOut =
                CodedOutputStream.newInstance(new ByteBufOutputStream(out), headerLen);
        headerOut.writeRawVarint32(bodyLen);
        headerOut.flush();
        //写数据
        out.writeBytes(msg, msg.readerIndex(), bodyLen);
    }
}

 

 

对应的解码类 ProtobufVarint32FrameDecoder

做的事情如类注解:

* BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)
* +——–+—————+ +—————+
* | Length | Protobuf Data |—–>| Protobuf Data |
* | 0xAC02 | (300 bytes) | | (300 bytes) |
* +——–+—————+ +—————+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//半包粘包处理
public class ProtobufVarint32FrameDecoder extends ByteToMessageDecoder {
    // TODO maxFrameLength + safe skip + fail-fast option
    //      (just like LengthFieldBasedFrameDecoder)
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        in.markReaderIndex();//标记读取的位置
        final byte[] buf = new byte[5];//varint32 最大5个字节
        for (int i = 0; i < buf.length; i ++) {
            if (!in.isReadable()) {
                in.resetReaderIndex();
                return;
            }
            buf[i] = in.readByte();
            if (buf[i] >= 0) {
                int length = CodedInputStream.newInstance(buf, 0, i + 1).readRawVarint32();//varint表示的格式 转 实际长度int
                if (length < 0) {
                    throw new CorruptedFrameException("negative length: " + length);
                }
                if (in.readableBytes() < length) {//长度不够,回滚标记
                    in.resetReaderIndex();
                    return;
                } else {
                    out.add(in.readBytes(length));//正确读取返回
                    return;
                }
            }
        }
        // Couldn't find the byte whose MSB is off.
        throw new CorruptedFrameException("length wider than 32-bit");
    }
}

 

 

 

四,总结

 

netty 默认已经帮我们实现了protocol buffers 的编码解码,所以使用起来很方便。

但如果有特殊需要,如加密等,自己定义编码解码则需要理解编码解码的规则和参考它的默认实现。

upupw php套件 微擎安装教程1|UPUPW合作版PHP套件-UPUPW论坛

mikel阅读(1338)

upupw php套件 微擎安装教程:微擎安装步骤总览:1、解压UPUPW_MicroEngine文件夹到任意不含空格的非中文路径下

来源: upupw php套件 微擎安装教程1|UPUPW合作版PHP套件-UPUPW论坛

微擎安装步骤总览:
1、解压UPUPW_MicroEngine文件夹到任意不含空格的非中文路径下
2、打开UPUPW面板输入s1回车
3、打开浏览器输入127.0.0.1即可访问htdocs目录下的微擎网站

下面进入微擎详细教程:
microengine安装步骤1
microengine安装步骤1:
双击打开压缩包,解压UPUPW_MicroEngine文件夹到任意不含空格的非中文路径下。

microengine安装步骤2
微擎安装步骤2:
找到upupw.exe程序,双击打开

microengine安装步骤3
微擎安装步骤3:
在UPUPW面板主界面输入s1并回车

microengine安装步骤4
微擎安装步骤4:
等待全部服务提示启动成功,可关闭upupw面板。
如有服务提示不成功,请参照面板提示解决,如有防护软件拦截请选择允许运行。

microengine安装步骤5
微擎安装步骤5:
打开浏览器输入127.0.0.1或已经解析到服务器的域名进入微擎首页登录界面,用户名和密码请查看程序目录密码及安全说明.txt

microengine安装步骤6
微擎安装步骤6:
成功登陆微擎后台,具体功能和内容请慢慢享用吧!

备注:
1、运行前请确保电脑上已安装.NET Framework 2.0或3.5支持库
2、服务器部署请先把域名解析到服务器IP,然后外网可以通过域名访问微擎