cad.net 讀寫PC3,PMP打印機文件
動圖演示

簡述
有人問avlisp能不能修改打印機紙張大小?
回答:你若能調(diào)用解壓包,解壓PMP即可,若不能,請使用c#,cpp語言,因為這樣有人家做好的庫.
畢竟我看過有人可以直接操作內(nèi)存,能做出來也不出奇.
我,青蛙,e大三個人聊天時候意外發(fā)現(xiàn)PC3和PMP是個壓縮包,
我們用txt直接打開了它,發(fā)現(xiàn)了一些字符串頭說明,
然后e大找到了這個github的工程: https://github.com/phusband/PiaNO
這說明了,修改打印機紙張大小有戲!
然后我做了大量中文函數(shù)翻譯的工程和幾個函數(shù)的增設(shè)調(diào)改...
因為這個歪果仁更新已經(jīng)過了很久了,
而且中文也不宜和純英文工程合并,所以我另建了一個工程,
上傳了這個項目到gitee,叫做<Acad打印配置解析庫>
地址是: https://gitee.com/inspirefunction/PianNoCN
至于我為什么沒有想到做成一個Nuget包,
因為我最近才想到,但是不想做了...
C庫: https://github.com/paolo-caroni/LibrePIA.git
利用pianoCN現(xiàn)在可以讀改PC3/PMP,STB/CTB(打印樣式)四種格式的文件.
也可以去這里看看我是怎么打印的: https://www.bilibili.com/video/BV1oA411J7yd/
打印的終點:
部署一臺服務(wù)器,通過監(jiān)控文件夾實現(xiàn)自動打印.
拖拽項目文件夾或者壓縮包放進去這個文件夾,然后就自動解壓.
自動讀取項目文件夾-配置
-線型文件,存入cad對應(yīng)目錄.
-字體文件,存入cad字體目錄.
然后并行打開多個cad進程,打開多份圖紙開始打印.
打印完成之后你就可以清理釋放的垃圾.
打印成為一張一張PDF再自動合并成一個,然后啟動郵箱功能發(fā)送到你的郵箱.
你就可以直接轉(zhuǎn)發(fā)給不同的人了.
下面是一步步實現(xiàn)的概念.
打印發(fā)布引擎
此項目并不包含打印發(fā)布引擎,
也由于我的打印發(fā)布引擎上面有很多漏洞,我就不展示給大家了.
可參考kean博客中的這篇,來寫自己的打印引擎:
https://through-the-interface.typepad.com/through_the_interface/2007/09/driving-a-multi.html
也可以去明經(jīng)通道找,
然后通過本文給你的打印機附魔.
需要備注的是:
A: 雖然打印發(fā)布引擎是全版本通用的,
但是我是建立在Acad2019的(用最新的Acad),
因為最新的DWG To PDF.PC3打印機打印出來的文件
比PdfFactory和Acad2008要清晰和文件小.
中間什么版本開始清晰我就不知道了...
B: 打印機高低版本之間有很多差異,
無論是低版本還是高版本我都統(tǒng)一使用了循環(huán)發(fā)布``單頁打印.
因為Acad08低版本配置多頁打印會出現(xiàn)上頁圖元跑下頁去.
C: 我制作的時候發(fā)現(xiàn)不可以用模態(tài)對話框,
否則打印預(yù)覽的時候會卡死.
(這個是我實現(xiàn)成功的方式,可能不一定非模態(tài)...)
D: 打印之后是一張一張的PDF,
調(diào)用合并多個PDF的Nuget包功能就行(網(wǎng)上搜搜).
任意紙張大小的實現(xiàn)概念
首先說明是PC3/PMP是同一種格式,它有個格式頭,
導(dǎo)致它并不像Nuget包一樣可以用解壓軟件解壓,
但是它本質(zhì)上就是一個壓縮包.(似乎是某種工業(yè)標準?)
我會根據(jù)CAD的PC3文件來創(chuàng)建一個PMP文件,
這個過程就是仿照CAD內(nèi)部運行的一個操作.
為什么要根據(jù)PC3?因為它有系統(tǒng)紙張,不能丟掉!否則致命錯誤或者閃退!
甚至我會將此PMP文件新建在CAD放置PMP的同文件目錄上,
這樣可以令CAD的ctrl+p打印時候直接調(diào)用到.
而解壓后的PMP文件有點像json,通過文本描述的形式來實現(xiàn)對各類設(shè)備參數(shù)的描述.
我便可修改PMP中的用戶紙張部分,從而創(chuàng)建了一段與圖框長高一樣的數(shù)據(jù).
這個過程頗為復(fù)雜,
有序列化(解壓),文件修改,反序列化(壓縮),發(fā)布引擎調(diào)用...多個部分組成.
序列化(解壓)
引用Nuget包
在項目引用SharpZipLib人家已經(jīng)寫好的解壓包.
我把項目從github在遷移到gitee的時候,
順帶升級到.net standard工程,它會自動下載包.
所以這里的舊文給.net framework的用戶留個印記.
PMP文件修改的注意事項
[PMP]注意事項:
不能改:
系統(tǒng)紙張數(shù)量
系統(tǒng)紙張的名稱
只能改:
系統(tǒng)紙張邊界范圍,在 mod:description下
用戶紙張的大小,在 udm:添加size,添加description
[PMP]解析:
mod:media:size: 本地中文名稱和英文名稱對照表
mod:media:description: 是紙張大小和紙張邊界的描述--這里就是修改紙張大小
del: 估計是刪除紙張的..
udm: 用戶定義的紙張
hidden:隱藏紙張,主要作用是手選打印的時候可以不顯示那么多紙張.
[pmp]用戶表解析:
udm{ 這里就是用戶定義的
size{ 中英兌換表
0{
caps_type=2
name="UserDefinedMetric (2222.00 x 2222.00毫米)
localized_name="用戶 1 (2222.00 x 2222.00 毫米) 這里文字可以隨便寫的
media_description_name="UserDefinedMetric 橫向 2222.00W x 2222.00H - (5, 4) x (2215, 2218) =4896479 毫米
media_group=15
landscape_mode=TRUE
}
}
description{ 紙張信息表,注意所有的小數(shù)點存在
0{
caps_type=2
name="UserDefinedMetric 橫向 2222.00W x 2222.00H - (5, 4) x (2215, 2218) =4896479 毫米
media_bounds_urx=2222.0
media_bounds_ury=2222.0
printable_bounds_llx=5.0999999046 //注意所有的小數(shù)點必須存在
printable_bounds_lly=4.0999999046 //注意所有的小數(shù)點必須存在
printable_bounds_urx=2215.8999023 //注意所有的小數(shù)點必須存在
printable_bounds_ury=2218.8999023 //注意所有的小數(shù)點必須存在
printable_area=4896479.8408
dimensional=TRUE
}
}
[我的PMP設(shè)置]
我在2019 dwgToPdf打印機先
恢復(fù)了-默認值,再-過濾圖紙尺寸,
然后剩下A0 A1 A2 A3 A4 去掉邊界值,這一步就可以手動打印無邊了.
ISO A0 (841.00 x 1189.00 毫米) 建議用
ISO_expand_A0_(841.00_x_1189.00_MM) 這種cad2008用這種紙張會有邊界靠左的問題,2019就沒有問題.
修改紙張的邊界偏移的時候,
左推到右:圖形會以右邊中點進行等比縮放,
下推到上:圖形會以上邊中點進行等比縮放,
然后此時要重設(shè)圖形原點.否則圖紙是偏的.
PC3/PMP翻譯
Acad2008的
meta{
關(guān)聯(lián)到PMP的位置 user_defined_model_pathname="
用戶定義的模型庫名稱 user_defined_model_basename="
驅(qū)動程序路徑名 driver_pathname="C:\Program Files (x86)\AutoCAD 2008\drv\gdiplot9.hdi
驅(qū)動程序版本 driver_version="1.1-9.1.51.0
驅(qū)動標簽線 driver_tag_line ="Windows 系統(tǒng)驅(qū)動程序 - 由 Autodesk 提供
工具包版本 toolkit_version=1
驅(qū)動程序類型 driver_type=1
規(guī)范家庭名稱 canonical_family_name="System
先顯示自定義 show_custom_first=TRUE
類型是文本 truetype_as_text=TRUE
規(guī)范模型名稱 canonical_model_name="System
本地家庭名稱 localized_family_name="系統(tǒng)
本地模型名稱 localized_model_name="系統(tǒng)
只有文件 file_only=FALSE
模型能力 model_abilities="555555555055
UDM描述 udm_description="
視窗系統(tǒng)設(shè)備名稱 win_device_name="pdfFactory Pro
視窗系統(tǒng)設(shè)備名稱 win_driver_name= "pdfFactory 6
短的網(wǎng)絡(luò)名稱 short_net_name="pdfFactory Pro
友好的網(wǎng)絡(luò)名稱 friendly_net_name="FPP6:
dm驅(qū)動程序版本 dm_driver_version=1555
默認系統(tǒng)配置(猜測是從系統(tǒng)繼承打印機) default_system_cfg=FALSE
平臺 platform ="2,6,1
地區(qū) locale="4B00409
}
mod{
media{
能力 abilities="100004455400144444000005005005000400000000000005000
狀態(tài) caps_state caps="00000
擁有人 ui_owner="22212222121111212112221
紙張最大的規(guī)格的x size_max_x=914.40002441 ( 0#.3C$ &E@)
紙張最大的規(guī)格的y size_max_y=1219.2000732 ( X,P,DT 5'@)
description{
0{
caps_type=1
name="ISO_A4_Portrait_210.00W_x_297.00H_-_(5,_17)_x_(205,_280)_=52600_MM
media_bounds_urx=210.0
media_bounds_ury=297.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=210.0
printable_bounds_ury=297.0
printable_area=62370.0
dimensional=TRUE
}
//其他的都是每個紙張的信息
1{
caps_type=1
name="ISO_A4_Landscape_297.00W_x_210.00H_-_(5,_17)_x_(292,_193)_=50512_MM
media_bounds_urx=297.0
media_bounds_ury=210.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=297.0
printable_bounds_ury=210.0
printable_area=62370.0
dimensional=TRUE
}
2{
caps_type=1
name="ISO_A3_Portrait_297.00W_x_420.00H_-_(5,_17)_x_(292,_403)_=110782_MM
media_bounds_urx=297.0
media_bounds_ury=420.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=297.0
printable_bounds_ury=420.0
printable_area=124740.0
dimensional=TRUE
}
3{
caps_type=1
name="ISO_A3_Landscape_420.00W_x_297.00H_-_(5,_17)_x_(415,_280)_=107830_MM
media_bounds_urx=420.0
media_bounds_ury=297.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=420.0
printable_bounds_ury=297.0
printable_area=124740.0
dimensional=TRUE
}
4{
caps_type=1
name="ISO_A2_Portrait_420.00W_x_594.00H_-_(5,_17)_x_(415,_577)_=229600_MM
media_bounds_urx=420.0
media_bounds_ury=594.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=420.0
printable_bounds_ury=594.0
printable_area=249480.00000 ( $!T#D$:G )
dimensional=TRUE
}
5{
caps_type=1
name="ISO_A2_Landscape_594.00W_x_420.00H_-_(5,_17)_x_(589,_403)_=225424_MM
media_bounds_urx=594.0
media_bounds_ury=420.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=594.0
printable_bounds_ury=420.0
printable_area=249480.00000 ( $!T#D$:G )
dimensional=TRUE
}
6{
caps_type=1
name="ISO_A1_Portrait_594.00W_x_841.00H_-_(5,_17)_x_(589,_824)_=471288_MM
media_bounds_urx=594.0
media_bounds_ury=841.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=594.0
printable_bounds_ury=841.0
printable_area=499554.00000 ( (A]'D&X?P)
dimensional=TRUE
}
7{
caps_type=1
name="ISO_A1_Landscape_841.00W_x_594.00H_-_(5,_17)_x_(836,_577)_=465360_MM
media_bounds_urx=841.0
media_bounds_ury=594.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=841.0
printable_bounds_ury=594.0
printable_area=499554.00000 ( (A]'D&X?P)
dimensional=TRUE
}
8{
caps_type=1
name="ISO_expand_A1_Portrait_594.00W_x_841.00H_-_(5,_10)_x_(589,_831)_=479464_MM
media_bounds_urx=594.0
media_bounds_ury=841.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=594.0
printable_bounds_ury=841.0
printable_area=499554.00000 ( (A]'D&X?P)
dimensional=TRUE
}
9{
caps_type=1
name="ISO_expand_A1_Landscape_841.00W_x_594.00H_-_(5,_10)_x_(836,_584)_=476994_MM
media_bounds_urx=841.0
media_bounds_ury=594.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=841.0
printable_bounds_ury=594.0
printable_area=499554.00000 ( (A]'D&X?P)
dimensional=TRUE
}
10{
caps_type=1
name="ISO_A0_Portrait_841.00W_x_1189.00H_-_(5,_17)_x_(836,_1172)_=959805_MM
media_bounds_urx=841.0
media_bounds_ury=1189.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=841.0
printable_bounds_ury=1189.0
printable_area=999949.00000 ( !J$+D$QEP)
dimensional=TRUE
}
11{
caps_type=1
name="ISO_expand_A0_Portrait_841.00W_x_1189.00H_-_(5,_10)_x_(836,_1179)_=971439_MM
media_bounds_urx=841.0
media_bounds_ury=1189.0
printable_bounds_llx=0.0
printable_bounds_lly=0.0
printable_bounds_urx=841.0
printable_bounds_ury=1189.0
printable_area=999949.00000 ( !J$+D$QEP)
dimensional=TRUE
}
}
}
}
del{
media{
abilities="100004455400144444000005005005000400000000000005000
caps_state ="00000
ui_owner="22212222121111212112221
size_max_x =914.40002441 ( 0#.3C$ &E@)
size_max_y=1219.2000732 ( X,P,DT 5'@)
}
}
udm{
calibration{
_x=1.0
_y=1.0
}
media{
abilities="100004455400144444000005005005000400000000000005000
caps_state="00000
ui_owner="22212222121111212112221
size_max_x=914.40002441 ( 0#.3C$ &E@)
size_max_y=1219.2000732 ( X,P,DT 5'@)
}
}
hidden{
media{
abilities="04455400144444000005005005000400000000000005000
caps_state="00000
ui_owner="22212222121111212112221
size_max_x=914.40002441 ( 0#.3C$ &E@)
size_max_y=1219.2000732 ( X,P,DT 5'@)
}
}
Acad2019的
meta{
關(guān)聯(lián)到PMP的位置 user_defined_model_pathname="G:\K01.驚驚連盒\(zhòng)04.工作小工具\2019dwgToPdf打印機\DWG To PDF.pmp
用戶定義的模型庫名稱 user_defined_model_basename="
驅(qū)動程序路徑名 driver_pathname="C:\Program Files\Autodesk\AutoCAD 2019\drv\pdfplot15.hdi
驅(qū)動程序版本 driver_version="1.1-15.0.61.0 [v018-1] [v018-1]
驅(qū)動標簽線 driver_tag_line="PDF ePlot - by Autodesk
工具包版本 toolkit_version=1
驅(qū)動類型 driver_type=3
規(guī)范家庭名稱 canonical_family_name="Autodesk ePlot
先顯示自定義 show_custom_first=FALSE
以文本形式輸入 truetype_as_text=TRUE
規(guī)范模型名稱 canonical_model_name="pdf
本地家庭名稱 localized_family_name="Autodesk ePlot (PDF)
本地模型名稱 localized_model_name="DWG To PDF
是否打印到文件(false就是后臺打印?) file_only=TRUE
模型能力 model_abilities="000550055000
udm描述 udm_description="
短的網(wǎng)絡(luò)名稱 short_net_name="
友好的網(wǎng)絡(luò)名稱 friendly_net_name="
dm驅(qū)動程序版本 dm_driver_version=0
默認系統(tǒng)配置(猜測是從系統(tǒng)繼承打印機) default_system_cfg=FALSE
平臺 platform="2,10,0
地區(qū) locale="4B0040
配置說明 config_description="
配置自動線軸 config_autospool=FALSE
}
media{
選擇方法 selection_method=2
類型 type="
dm方向 dm_orientation=1
實際打印x邊界偏移 actual_printable_bounds_llx=0.0
實際打印y邊界偏移 actual_printable_bounds_lly=0.0
實際打印x邊界范圍 actual_printable_bounds_urx=210.0
實際打印y邊界范圍 actual_printable_bounds_ury=297.0
份數(shù)副本 number_of_copies=1
size{
name="ISO_A4_(210.00_x_297.00_MM)
group=4
情景模式 landscape_mode=FALSE
長打印_減少 longplot_reduction=1.0
媒介描述 media_description{
實際打印x邊界偏移 printable_bounds_llx=5.0
實際打印y邊界偏移 printable_bounds_lly=17.0
實際打印x邊界范圍 printable_bounds_urx=205.0
實際打印y邊界范圍 printable_bounds_ury=280.0
實際打印面積 printable_area=52600.0
尺寸的 dimensional=TRUE
媒介界限 media_bounds{
紙張范圍 urx=210.0
紙張范圍 ury=297.0
}
}
}
}
io{
type=2
pathname="
allsysvalid=FALSE
plot_to_file=TRUE
}
res_color_mem{
name="RGB
num_colors=16777216
color_depth=24
num_undithered_colors=16777216
color_system=1
dm_color=1
lines_overwrite=TRUE
resolution{
name="Default
phys_resolution_x=600.0
phys_resolution_y=600.0
addr_resolution_x=1.0
addr_resolution_y=1.0
effective_resolution_x=600.0
effective_resolution_y=600.0
}
}
custom{
0{
name="Create_Bookmarks
value=TRUE
}
1{
name="Thumbnail_Title
value=TRUE
}
2{
name="Sheet_Links
value=TRUE
}
3{
name="Rasterize_Geometry
value=FALSE
}
4{
name="View_New_File
value=TRUE
}
5{
name="Custom_Raster_Resolution
value=FALSE
}
6{
name="Custom_DWF_Resolution
value=FALSE
}
7{
name="Custom_Monochrome_Resolution
value=FALSE
}
8{
name="Custom_Gradient_Resolution
value=FALSE
}
9{
name="Gradient_Limit
value=600
}
10{
name="Monochrome_Raster_Limit
value=400
}
11{
name="Raster_Limit
value=400
}
12{
name="All_As_Geometry
value=FALSE
}
13{
name="Capture
value=2
}
14{
name="Font_Capture
value=TRUE
}
15{
name="Hardcopy_Resolution
value=600
}
16{
name="Include_Layer
value=TRUE
}
17{
name="Resolution
value=14
}
}
代碼
創(chuàng)建PMP并附著路徑到PC3內(nèi)
using JoinBoxCurrency;
using PiaNO;
using System.IO;
namespace JoinBox;
public class CreatePMP {
public string Path_pmp { set; get; }
public string Path_pc3 { set; get; }
public string Dwgtopdf = "DWG To PDF";
public string DwgtopdfPC3 = Dwgtopdf + ".PC3";
/// <summary>
/// 創(chuàng)建PMP文件
/// </summary>
public CreatePMP() {
// 打印機PC3位置
string plottersPath = CadSystem.Getvar("PrinterConfigDir") + "\\";
Path_pc3 = plottersPath + DwgtopdfPC3;
if (!File.Exists(Path_pc3)) return;
// 驅(qū)動位置
string drvFilePath = "";
string theFolderPath = CadSystem.Getvar("ACADDRV");
if (Directory.Exists(theFolderPath)) {
drvFilePath = Directory.GetFiles(theFolderPath)
.FirstOrDefault(file => Path.GetExtension(file).Equals(".HDI", StringComparison.OrdinalIgnoreCase)
&& Path.GetFileName(file).IndexOf("pdfplot", StringComparison.OrdinalIgnoreCase) >= 0);
drvFilePath = drvFilePath ?? "";
}
// 不存在就新建一個文件夾
var pmpfiles = plottersPath + "PMP Files";
if (!Directory.Exists(pmpfiles)) Directory.CreateDirectory(pmpfiles);
PlotterConfiguration pdfConfig = new(Path_pc3) {
ModelPath = pmpfiles,
DriverPath = drvFilePath,
TruetypeAsText = true
};
var names = new string[] { "media", "io", "res_color_mem", "custom" };
foreach (var name in names) {
pdfConfig.Remove(name);
}
// 解壓打印機信息后,遍歷打印機節(jié)點...此處是字典嗎?
var na = PdfConfig.FirstOrDefault(nodeA => nodeA.NodeName=="meta");
na?.Values.Remove("config_description_str");
na?.Values.Remove("config_autospool");
string str =
"{\nabilities=\"500005500500505555000005550000000550000500000500000\n" +
"caps_state=\"000000000000000000000000000000000000000000000000000\n" +
"ui_owner=\"11111111111111111111110\n" +
"size_max_x=320000.00000\n" +
"size_max_y=320000.00000\n}";
pdfConfig.Add("mod", "").Add("media", str);
pdfConfig.Add("del", "", true);
pdfConfig.Add("udm", "", true).Add("media", str);
pdfConfig.Add("hidden", "", true);
Path_pmp = pmpfiles + "\\" + Dwgtopdf + ".PMP";
pdfConfig.Saves(Path_pmp);
}
/// <summary>
/// 附著PMP路徑到PC3
/// </summary>
public void ChangeUserDefinedModel() {
// 獲取這個打印機的完整路徑
var paths = new string[] { Path_pc3, Path_pmp };
var ns = paths.Where(path => File.Exists(path));
foreach (var path in ns) {
var pcf = new PlotterConfiguration(path);
// 解壓打印機信息后,遍歷打印機節(jié)點
var na = pcf.FirstOrDefault(nodeA => nodeA.NodeName == "meta");
na?.ValueChang("user_defined_model_pathname" + "_str", Path_pmp);
pcf.Saves();
}
}
}
添加紙張
public class Printer {
// 節(jié)點名稱-紙張中英兌換表
public const string str_size = "size";
// 節(jié)點名稱-紙張邊界信息
public const string str_description = "description";
/// <summary>
/// 打印紙張全球名
/// </summary>
public string Name { private set; get; }
/// <summary>
/// 打印紙張本地名(中文名)
/// </summary>
public string Localized_name => Name.Replace("_", " ").Replace("MM", "毫米");
/// <summary>
/// 打印紙張顯示名(英文)
/// </summary>
public string Media_description_name { private set; get; }
// 偏移量
double Offset_Left = 0;
double Offset_Down = 0;
// 紙張大小
double PaperX = 0;
double PaperY = 0;
PlotterConfiguration PdfConfig;
/// <summary>
/// 添加紙張
/// </summary>
/// <param name="ext">紙張范圍</param>
/// <param name="offset_Left">左偏移量</param>
/// <param name="offset_Down">下偏移量</param>
public Printer(Extents2d ext, double offset_Left = 0, double offset_Down = 0) {
var ve2 = ext.MinPoint.GetVectorTo(ext.MaxPoint);
PaperX = ve2.X;
PaperY = ve2.Y;
Offset_Left = offset_Left;
Offset_Down = offset_Down;
}
/// <summary>
/// 添加紙張
/// </summary>
/// <param name="ve2">紙張范圍</param>
/// <param name="offset_Left">偏移量</param>
/// <param name="offset_Down">偏移量</param>
public Printer(Vector2d ve2,
double offset_Left = 0, double offset_Down = 0)
: this(ve2.X, ve2.Y, offset_Left, offset_Down) { }
/// <summary>
/// 添加紙張
/// </summary>
/// <param name="paperx">紙張橫向長度</param>
/// <param name="papery">紙張縱向高度</param>
/// <param name="offset_Left">偏移量</param>
/// <param name="offset_Down">偏移量</param>
public Printer(double paperx, double papery,
double offset_Left = 0, double offset_Down = 0) {
PaperX = paperx;
PaperY = papery;
Offset_Left = offset_Left;
Offset_Down = offset_Down;
}
/// <summary>
/// 生成紙張PMP
/// </summary>
/// <param name="dwgtopdfpmp">打印機PMP文件路徑</param>
/// <returns></returns>
public PlotterConfiguration AddPrinter(string dwgtopdfpmp) {
Name = $"JBS_PDF_({PaperY:#0.00}_x_{PaperX:#0.00}_MM)";
// JoinBoxStandard 嘻嘻
// (5,_17)這個是默認偏移量
// media_description_name="ISO_A0_Portrait_841.00W_x_1189.00H_-_(5,_17)_x_(836,_1172)_=959805_MM
// 實際打印面積
// 雖然因為偏移值是0,等于長乘寬就可以,
// 為了日后我忘記這里怎么算的,還是算個例子吧
double area = (PaperY - (Offset_Left * 2)) * (PaperX - (Offset_Down * 2));
// 如果沒有小數(shù)點保留,可能cad閃退!
var des = new StringBuilder();
des.Append($"JBS_PDF_Portrait_{PaperY:#0.00}W_x_{PaperX:#0.00}H");
des.Append("_-_");
des.Append($"({Offset_Left:#0.00},_{Offset_Down:#0.00})");//偏移量
des.Append("_x_");
des.Append($"({PaperY - Offset_Left:#0.00},_{PaperX - Offset_Down:#0.00})_");
des.Append($"={area:#0.00}_MM");
Media_description_name = des.ToString();
PdfConfig = new PlotterConfiguration(dwgtopdfpmp) {
TruetypeAsText = true
};
//解壓了打印機信息之后,遍歷打印機節(jié)點
var pc = PdfConfig.Where(nodeA => nodeA.NodeName == "udm")
.Where(nodeA => nodeA.Count() > 0);// 這個是根據(jù)pc3生成pmp使用
foreach (var nodeA in pc) {
var mediaNode = nodeA.FirstOrDefault(n => n.NodeName == "media");
if (mediaNode is null) continue;
// 遍歷是否有節(jié)點
var piaNode_size = mediaNode.FirstOrDefault(nodeC => nodeC.NodeName == str_size);
var piaNode_description = mediaNode.FirstOrDefault(nodeC => nodeC.NodeName == str_description);
// 找不到就添加節(jié)點
piaNode_size ??= mediaNode.Add(str_size);
piaNode_description ??= mediaNode.Add(str_description);
// 在節(jié)點中添加/修改信息
AddPaperEnAndCn(piaNode_size);
AddPaperDescription(piaNode_description);
}
PdfConfig.Saves();
return PdfConfig;
}
/// <summary>
/// 添加PMP紙張-中英兌換表
/// </summary>
/// <param name="nodeC"></param>
void AddPaperEnAndCn(PiaNode node) {
// 圖紙數(shù)量+1就是新建一張圖
string name = node.Count().ToString();
string[] paper = new string[] {
name+ "{",
$"caps_type=2", // 1是系統(tǒng)的,2是用戶的.這里嚴格,可不可以在打印紙看見就是這里了
$"name=\"{Name}",
$"localized_name=\"{Localized_name}",
$"media_description_name=\"{Media_description_name}",
$"media_group=15", // 4是系統(tǒng)的,15是用戶的...網(wǎng)友說15是毫米,16是像素.
"landscape_mode=TRUE\n}", // false是系統(tǒng)的,true是用戶的
};
PlusNode(node, name, string.Join("\n ", paper) + '\n');
}
/// <summary>
/// 判斷是否已有同名節(jié)點,有就不加入
/// </summary>
/// <param name="node">節(jié)點</param>
/// <param name="name">名稱</param>
/// <param name="paperAll">加入對象</param>
void PlusNode(PiaNode node, string name, string paperAll) {
if (node.FirstOrDefault(nodeA =>
nodeA.Values.TryGetValue("media_description_name_str", out var v)
&& v == Media_description_name) is null) {
node.Add(name, paperAll);
}
}
/// <summary>
/// 添加PMP紙張-信息
/// </summary>
/// <param name="nodeC"></param>
private void AddPaperDescription(PiaNode nodeC) {
var spl = '\n';
int count = nodeC.Count();
string name = count.ToString();
string[] paper = new string[] {
name + "{",
$"caps_type=2", // 1是系統(tǒng)的,2是用戶的.這里嚴格,可不可以在打印紙看見就是這里了
$"name=\"{Media_description_name}",
$"media_bounds_urx={LimitDosDecimalPrecision(PaperX)}",
$"media_bounds_ury={LimitDosDecimalPrecision(PaperY)}",
$"printable_bounds_llx={LimitDosDecimalPrecision(Offset_Left)}",
$"printable_bounds_lly={LimitDosDecimalPrecision(Offset_Down)}",
$"printable_bounds_urx={LimitDosDecimalPrecision(PaperX)}",
$"printable_bounds_ury={LimitDosDecimalPrecision(PaperY)}",
$"printable_area={LimitDosDecimalPrecision((PaperX - 2*Offset_Left)*(PaperY - 2*Offset_Down))}",
"dimensional=TRUE\n}",
};
string paperAll = string.Join(spl + " ", paper) + spl;
PlusNode(nodeC, name, paperAll);
}
/// <summary>
/// 保證數(shù)字在12位內(nèi)
/// </summary>
/// <param name="dos"></param>
/// <returns></returns>
string LimitDosDecimalPrecision(double dos) {
var str = string.Format("{0:0.0#########}", dos);
if (str.Length >= 12) str = str.Substring(0, 12);
return str;
}
}
移除紙張
public static class PrinterTool {
/// <summary>
/// 移除紙張
/// </summary>
/// <param name="plot"></param>
/// <param name="dwgtopdfpmp">PMP名稱</param>
/// <param name="printerNames">要移除的紙張名稱</param>
/// <param name="db">數(shù)據(jù)庫</param>
/// <param name="tr">事務(wù)</param>
public static void RemovePrinters(this Plot plot,
string dwgtopdfpmp, string[] printerNames,
Database db, Transaction tr) {
var pdfConfig = new PlotterConfiguration(dwgtopdfpmp) {
TruetypeAsText = true
};
pdfConfig.RemovePrinters(printerNames);
pdfConfig.Saves();
// 需要刷新一次打印機設(shè)備紙張,不然會有殘留顯示.
using var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
foreach (ObjectId btrId in bt) {
using var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead, false);
if (!btr.IsLayout) continue; // 是布局才進入
using var layout = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);
plot.RefreshLists(new PlotSettings(layout.ModelType));
}
}
/// <summary>
/// 移除紙張
/// </summary>
/// <param name="pdfConfig">PMP的解析</param>
/// <param name="printerNames">要移除的紙張名稱</param>
static void RemovePrinters(this PlotterConfiguration pdfConfig, string[] printerNames) {
//解壓了打印機信息之后,遍歷打印機節(jié)點
var udmNode = pdfConfig.FirstOrDefault(nodeA => nodeA.NodeName == "udm");
if (udmNode is null) return;
var mediaNode = udmNode.FirstOrDefault(nodeB => nodeB.NodeName == "media");
if (mediaNode is null) return;
foreach (PiaNode nodeC in mediaNode) {
if (nodeC.NodeName == Printer.str_size
|| nodeC.NodeName == Printer.str_description)
nodeC.RemoveChildNodes(printerNames);
}
}
}
青蛙的代碼
青蛙說我上面有些寫的不對,但是我已經(jīng)不在維護了,
刪除之后要重排紙張序號,否則跨編號之后不顯示,不過他也沒有設(shè)計好,應(yīng)該有序結(jié)構(gòu)儲存.
偏移量的計算,這個我貌似一開始也沒有做好.
public string GetPaperString(int countName)
{
var spl = '\n';
string[] paper =
[
countName + "{",
$"caps_type=2", // 1是系統(tǒng)的,2是用戶的.這里嚴格,可不可以在打印紙看見就是這里了
$"name=\"{MediaDescriptionName}",
$"media_bounds_urx={LimitDosDecimalPrecision(PaperX)}",
$"media_bounds_ury={LimitDosDecimalPrecision(PaperY)}",
$"printable_bounds_llx={LimitDosDecimalPrecision(OffsetLeft)}",
$"printable_bounds_lly={LimitDosDecimalPrecision(OffsetDown)}",
$"printable_bounds_urx={LimitDosDecimalPrecision(PaperX - OffsetLeft - OffsetRight)}",
$"printable_bounds_ury={LimitDosDecimalPrecision(PaperY - OffsetUp - OffsetDown)}",
$"printable_area={LimitDosDecimalPrecision((PaperX - OffsetLeft - OffsetRight) * (PaperY - OffsetUp - OffsetDown))}",
"dimensional=TRUE\n}"
];
var paperAll = string.Join(spl + " ", paper) + spl;
return paperAll;
}
/// <summary>
/// 打印紙張顯示名(英文)
/// </summary>
public string MediaDescriptionName
{
get
{
double area = (PaperY - (OffsetLeft + OffsetRight)) * (PaperX - (OffsetDown + OffsetUp));
// 如果沒有小數(shù)點保留,可能cad閃退!
var des = new StringBuilder();
des.Append($"JBS_PDF_Portrait_{PaperX:#0.00}W_x_{PaperY:#0.00}H");
des.Append("_-_");
des.Append($"({OffsetLeft:#0.00},_{OffsetDown:#0.00})"); //偏移量
des.Append("_x_");
des.Append($"({PaperX},_{PaperY})_");
des.Append($"={area:#0.00}_MM");
return des.ToString();
}
}
// 偏移量
public double OffsetLeft;
public double OffsetDown;
public double OffsetRight;
public double OffsetUp;
/// <summary>
/// 移除紙張
/// </summary>
/// <param name="pdfConfig">PMP的解析</param>
/// <param name="papaerIndexs">要移除的紙張索引集合</param>
public static void RemovePapers(PlotterConfiguration pdfConfig, string[] papaerIndexs)
{
//解壓了打印機信息之后,遍歷打印機節(jié)點
var udmNode = pdfConfig.FirstOrDefault(nodeA => nodeA.NodeName == "udm");
if (udmNode is null) return;
var mediaNode = udmNode.FirstOrDefault(nodeB => nodeB.NodeName == "media");
if (mediaNode is null) return;
foreach (PiaNode nodeC in mediaNode)
{
if (nodeC.NodeName == STR_SIZE
|| nodeC.NodeName == STR_DESCRIPTION)
nodeC.RemoveChildNodes(papaerIndexs);
//刪除后需要把索引重排,否則再cad環(huán)境下會從第一個不連續(xù)的序號處開始丟失紙張
if (nodeC.NodeName == STR_SIZE|| nodeC.NodeName == STR_DESCRIPTION)
{
var count = nodeC.ChildNodes.Count;
for (int i = 0; i < count; i++)
{
nodeC.ChildNodes[i].NodeName = i.ToString();
}
}
}
pdfConfig.Save();
}
}
/// <summary>
/// 修改紙張
/// </summary>
/// <param name="pdfConfig"></param>
/// <param name="index"></param>
/// <param name="prNew"></param>
public static void ChangePaper(PlotterConfiguration pdfConfig, int index, PaperRecord prNew)
{
var pc = pdfConfig.Where(nodeA => nodeA.NodeName == "udm")
.Where(nodeA => nodeA.Any()); // 這個是根據(jù)pc3生成pmp使用
foreach (var nodeA in pc)
{
var mediaNode = nodeA.FirstOrDefault(n => n.NodeName == "media");
if (mediaNode is null) continue;
// 遍歷是否有節(jié)點
var piaNodeSize = mediaNode.FirstOrDefault(nodeC => nodeC.NodeName == STR_SIZE);
var piaNodeDescription = mediaNode.FirstOrDefault(nodeC => nodeC.NodeName == STR_DESCRIPTION);
// 找不到就添加節(jié)點
piaNodeSize ??= mediaNode.Add(STR_SIZE);
piaNodeDescription ??= mediaNode.Add(STR_DESCRIPTION);
// 在節(jié)點中添加/修改信息
EditPaperEnAndCn(piaNodeSize, index, prNew);
EditPaperDescription(piaNodeDescription, index, prNew);
}
pdfConfig.Save();
}
/// <summary>
/// 添加PMP紙張-中英兌換表
/// </summary>
/// <param name="node"></param>
/// <param name="pr"></param>
static void AddPaperEnAndCn(PiaNode node, PaperRecord pr)
{
// 圖紙數(shù)量+1就是新建一張圖
var name = node.Count();
AddNode(node, pr.GetPaperStringEnAndCn(name));
}
static void EditPaperEnAndCnAt(PiaNode node, int index, PaperRecord pr)
{
EditNodeAt(node, index, pr.GetPaperStringEnAndCn(index));
}
/// <summary>
/// 判斷是否已有同名節(jié)點,有就不加入
/// </summary>
/// <param name="node">節(jié)點</param>
/// <param name="paperAll">加入對象</param>
static void AddNode(PiaNode node, string paperAll)
{
node.Add(node.Count().ToString(), paperAll);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
/// <param name="index">紙張的序號,是唯一標識符</param>
/// <param name="paperAll"></param>
static void EditNodeAt(PiaNode node, int index, string paperAll)
{
var nd = node.ChildNodes[index];
nd?.SetValue(index.ToString(), paperAll);
}
后話
最后發(fā)現(xiàn)一個問題沒有,并不能改系統(tǒng)的紙張.
所以這個系統(tǒng)紙張是哪里改到呢?我們認為是在.hdi這個驅(qū)動上面.
啊?打開它的方式?那我怎么知道嘞?
(完)
浙公網(wǎng)安備 33010602011771號