├── .gitignore ├── Bing.EasyPrint.sln ├── LICENSE ├── Publish.bat ├── README.md ├── asset ├── images │ └── icon.png └── props │ ├── misc.props │ ├── package.props │ ├── sourcelink.env.props │ └── target.feature.props ├── common.props ├── common.tests.props ├── src ├── Bing.EasyPrint.Templates │ ├── Bing.EasyPrint.Templates.csproj │ ├── Bing.EasyPrint.Templates.xml │ ├── Bing │ │ └── EasyPrint │ │ │ ├── Elements │ │ │ ├── BpBarcodeElement.cs │ │ │ ├── BpElement.cs │ │ │ ├── BpElementAll.cs │ │ │ ├── BpFontElement.cs │ │ │ ├── BpImageElement.cs │ │ │ └── BpQrCodeElement.cs │ │ │ └── Model │ │ │ ├── BgField.cs │ │ │ ├── BpBorder.cs │ │ │ ├── BpCell.cs │ │ │ ├── BpCoordinate.cs │ │ │ ├── BpFont.cs │ │ │ ├── BpMargin.cs │ │ │ ├── BpRange.cs │ │ │ ├── BpRow.cs │ │ │ ├── BpTemplate.cs │ │ │ ├── BpText.cs │ │ │ ├── FeedLine.cs │ │ │ └── PrintBatchParam.cs │ ├── project.dependency.props │ └── project.props └── Bing.EasyPrint │ ├── Bing.EasyPrint.csproj │ ├── Bing.EasyPrint.xml │ ├── Bing │ └── EasyPrint │ │ ├── CPCL │ │ └── Metadata │ │ │ └── PrintCommandStruct.cs │ │ ├── IPrintValue.cs │ │ └── IPrintValueDescriptor.cs │ ├── CPCL │ ├── CPCLCommandInfo.cs │ ├── CPCLPrintCommand.Advanced.cs │ ├── CPCLPrintCommand.Barcode.cs │ ├── CPCLPrintCommand.Base.cs │ ├── CPCLPrintCommand.Component.cs │ ├── CPCLPrintCommand.Graphics.cs │ ├── CPCLPrintCommand.QrCode.cs │ ├── CPCLPrintCommand.Text.cs │ ├── CPCLPrintCommand.cs │ ├── Components │ │ ├── Barcode1DComponent.cs │ │ ├── BoxComponent.cs │ │ ├── DashLineComponent.cs │ │ ├── ImageComponent.cs │ │ ├── LineComponent.cs │ │ ├── QRCodeComponent.cs │ │ ├── SplitLineComponent.cs │ │ └── TextComponent.cs │ ├── Helper.cs │ └── Metadata │ │ ├── ComponentMetadata.cs │ │ ├── MetadataBase.cs │ │ ├── MetadataType.cs │ │ └── RawMetadata.cs │ ├── Core │ └── BufferWriter.cs │ ├── DefaultEasyPrint.cs │ ├── Enums │ ├── BarcodeType.cs │ ├── FontSize.cs │ ├── LineStyle.cs │ ├── PrintColor.cs │ ├── PrintOrientation.cs │ ├── QrCodeCorrectionLevel.cs │ ├── QrCodeUnitSize.cs │ ├── RotationAngle.cs │ └── TextStyle.cs │ ├── Extensions │ ├── Extensions.IBufferWriter.cs │ ├── Extensions.IEasyPrint.cs │ ├── Extensions.IPrintComponent.cs │ └── Extensions.Service.cs │ ├── IBufferWriter.cs │ ├── IEasyPrint.cs │ ├── IPrintCommand.cs │ └── IPrintComponent.cs ├── tests └── Bing.EasyPrint.Tests │ ├── Bing.EasyPrint.Tests.csproj │ ├── Biz │ ├── BizLabelTest.cs │ ├── Images │ │ └── logo.jpg │ ├── Label │ │ ├── PrintPriceLabelBase.cs │ │ ├── PrintPriceLabelBy15mm.cs │ │ ├── PrintPriceLabelBy70mm.cs │ │ └── PrintPriceLabelBy90mm.cs │ ├── PriceLabel.cs │ ├── PrintPageType.cs │ └── ShippingLabel.cs │ ├── BufferWriterTest.cs │ ├── CPCL │ ├── CPCLPrintCommandTest.Advanced.cs │ ├── CPCLPrintCommandTest.Component.cs │ ├── CPCLPrintCommandTest.Graphics.cs │ ├── CPCLPrintCommandTest.Other.cs │ ├── CPCLPrintCommandTest.QrCode.cs │ └── CPCLPrintCommandTest.cs │ ├── RawPrinterHelper.cs │ ├── SimpleTest.cs │ └── TestBase.cs └── version.props /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /Bing.EasyPrint.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33530.505 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.EasyPrint", "src\Bing.EasyPrint\Bing.EasyPrint.csproj", "{A202D824-3223-4E7B-A79B-96303192CAEB}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.EasyPrint.Tests", "tests\Bing.EasyPrint.Tests\Bing.EasyPrint.Tests.csproj", "{FE2CAB1A-E0EF-4775-AF4C-901314DF2939}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_SolutionItems", "_SolutionItems", "{814AC42F-7E98-49C3-8ADD-FB14BE172923}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "asset", "asset", "{9F52451E-CCA8-45DD-BA5D-C2CACA07CF77}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "props", "props", "{3C915628-5110-495E-B561-63C8BCEF3240}" 15 | ProjectSection(SolutionItems) = preProject 16 | asset\props\misc.props = asset\props\misc.props 17 | asset\props\package.props = asset\props\package.props 18 | asset\props\sourcelink.env.props = asset\props\sourcelink.env.props 19 | asset\props\target.feature.props = asset\props\target.feature.props 20 | EndProjectSection 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.EasyPrint.Templates", "src\Bing.EasyPrint.Templates\Bing.EasyPrint.Templates.csproj", "{441B45FB-76F8-4E61-9CA4-0E5BAB44B64F}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{8D7519A2-B1A1-4E91-B18E-32B3DA392DE5}" 25 | ProjectSection(SolutionItems) = preProject 26 | asset\images\icon.png = asset\images\icon.png 27 | EndProjectSection 28 | EndProject 29 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{2757A100-98D6-443E-ACB0-EA6065A7BE88}" 30 | ProjectSection(SolutionItems) = preProject 31 | Publish.bat = Publish.bat 32 | EndProjectSection 33 | EndProject 34 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{6F0DFB0A-D54A-4992-873F-73E16A2FB258}" 35 | ProjectSection(SolutionItems) = preProject 36 | .gitignore = .gitignore 37 | common.props = common.props 38 | common.tests.props = common.tests.props 39 | LICENSE = LICENSE 40 | version.props = version.props 41 | EndProjectSection 42 | EndProject 43 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{58F59A06-E35F-476A-8A8B-E6E315926B68}" 44 | ProjectSection(SolutionItems) = preProject 45 | README.md = README.md 46 | EndProjectSection 47 | EndProject 48 | Global 49 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 50 | Debug|Any CPU = Debug|Any CPU 51 | Release|Any CPU = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 54 | {A202D824-3223-4E7B-A79B-96303192CAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {A202D824-3223-4E7B-A79B-96303192CAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {A202D824-3223-4E7B-A79B-96303192CAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {A202D824-3223-4E7B-A79B-96303192CAEB}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {FE2CAB1A-E0EF-4775-AF4C-901314DF2939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {FE2CAB1A-E0EF-4775-AF4C-901314DF2939}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {FE2CAB1A-E0EF-4775-AF4C-901314DF2939}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {FE2CAB1A-E0EF-4775-AF4C-901314DF2939}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {441B45FB-76F8-4E61-9CA4-0E5BAB44B64F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {441B45FB-76F8-4E61-9CA4-0E5BAB44B64F}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {441B45FB-76F8-4E61-9CA4-0E5BAB44B64F}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {441B45FB-76F8-4E61-9CA4-0E5BAB44B64F}.Release|Any CPU.Build.0 = Release|Any CPU 66 | EndGlobalSection 67 | GlobalSection(SolutionProperties) = preSolution 68 | HideSolutionNode = FALSE 69 | EndGlobalSection 70 | GlobalSection(NestedProjects) = preSolution 71 | {9F52451E-CCA8-45DD-BA5D-C2CACA07CF77} = {814AC42F-7E98-49C3-8ADD-FB14BE172923} 72 | {3C915628-5110-495E-B561-63C8BCEF3240} = {9F52451E-CCA8-45DD-BA5D-C2CACA07CF77} 73 | {8D7519A2-B1A1-4E91-B18E-32B3DA392DE5} = {9F52451E-CCA8-45DD-BA5D-C2CACA07CF77} 74 | {2757A100-98D6-443E-ACB0-EA6065A7BE88} = {814AC42F-7E98-49C3-8ADD-FB14BE172923} 75 | {6F0DFB0A-D54A-4992-873F-73E16A2FB258} = {814AC42F-7E98-49C3-8ADD-FB14BE172923} 76 | {58F59A06-E35F-476A-8A8B-E6E315926B68} = {814AC42F-7E98-49C3-8ADD-FB14BE172923} 77 | EndGlobalSection 78 | GlobalSection(ExtensibilityGlobals) = postSolution 79 | SolutionGuid = {01422DBE-8356-4DFA-9C0B-4A15E1B0A46F} 80 | EndGlobalSection 81 | EndGlobal 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Bing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Publish.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo ======================================================================= 4 | echo Bing.EasyPrint 5 | echo ======================================================================= 6 | 7 | ::create nuget_packages 8 | if not exist nuget_packages ( 9 | md nuget_packages 10 | echo Create nuget_packages folder. 11 | ) 12 | 13 | ::clear nuget_packages 14 | for /R "nuget_packages" %%s in (*) do ( 15 | del %%s 16 | ) 17 | echo Cleaned up all nuget packages. 18 | echo. 19 | 20 | ::start to package all projects 21 | 22 | ::EasyPrint 23 | dotnet pack src/Bing.EasyPrint -c Release -o nuget_packages 24 | 25 | for /R "nuget_packages" %%s in (*symbols.nupkg) do ( 26 | del %%s 27 | ) 28 | 29 | echo. 30 | echo. 31 | 32 | set /p key=input key: 33 | set source=https://api.nuget.org/v3/index.json 34 | 35 | for /R "nuget_packages" %%s in (*.nupkg) do ( 36 | call dotnet nuget push %%s -k %key% -s %source% 37 | echo. 38 | ) 39 | 40 | pause -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bing-framework/Bing.EasyPrint/4edfb2ed74d875f221cefaf8ec11f6a26c2c2fca/README.md -------------------------------------------------------------------------------- /asset/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bing-framework/Bing.EasyPrint/4edfb2ed74d875f221cefaf8ec11f6a26c2c2fca/asset/images/icon.png -------------------------------------------------------------------------------- /asset/props/misc.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /asset/props/package.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 简玄冰 4 | 简玄冰 5 | 简玄冰 6 | https://github.com/bing-framework/Bing.EasyPrint 7 | git 8 | https://github.com/bing-framework/Bing.EasyPrint 9 | icon.png 10 | LICENSE 11 | bing;print;easyprint;cpcl;escpos; 12 | 13 | -------------------------------------------------------------------------------- /asset/props/sourcelink.env.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /asset/props/target.feature.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | disable 5 | 6 | 7 | 8 | enable 9 | disable 10 | 11 | 12 | 13 | enable 14 | disable 15 | 16 | 17 | 18 | enable 19 | disable 20 | 21 | 22 | -------------------------------------------------------------------------------- /common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0;net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1; 4 | 5 | 6 | 7 | 8 | latest 9 | $(NoWarn);CS1591;NETSDK1138 10 | $(NoWarn);CS1591;NETSDK1138 11 | 12 | 13 | 14 | $(MSBuildThisFileDirectory)/output/debug/ 15 | 16 | 17 | 18 | $(MSBuildThisFileDirectory)/output/release/ 19 | 20 | 21 | 22 | $(AssemblyName).xml 23 | 24 | 25 | 26 | $(AssemblyName).xml 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /common.tests.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | latest 4 | $(NoWarn);CS1591;NETSDK1138 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 2.4.5 14 | 2.4.3 15 | 2.4.3 16 | 2.4.3 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | all 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing.EasyPrint.Templates.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing.EasyPrint.Templates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bing.EasyPrint.Templates 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 | 1=文字;2=图片;3=二维码;4=条形码 32 | 33 | 34 | 35 | 显示的属性信息 36 | 37 | 38 | 39 | 40 | 元素显示间距 41 | 42 | 43 | 44 | 45 | 左上角起始坐标 46 | 47 | 48 | 49 | 50 | 右下角终止坐标 51 | 52 | 53 | 54 | 55 | 显示元素扩展。便于存储元素所有属性信息,只有其中一个不为空 56 | 57 | 58 | 59 | 60 | 图片显示元素 61 | 62 | 63 | 64 | 65 | 文字显示元素 66 | 67 | 68 | 69 | 70 | 二维码显示元素 71 | 72 | 73 | 74 | 75 | 条码显示元素 76 | 77 | 78 | 79 | 80 | 文字显示元素 81 | 82 | 83 | 84 | 85 | 字体大小 86 | 87 | 88 | 89 | 90 | 字体风格 91 | 92 | 93 | 94 | 95 | 字体名称 96 | 97 | 98 | 99 | 100 | 字体加粗 101 | 102 | 103 | 104 | 105 | 图片元素 106 | 107 | 108 | 109 | 110 | 宽度 111 | 112 | 113 | 114 | 115 | 高度 116 | 117 | 118 | 119 | 120 | 是否压缩 121 | 122 | 123 | 124 | 125 | 二维码元素 126 | 127 | 128 | 129 | 130 | 宽度 131 | 132 | 133 | 134 | 135 | 高度 136 | 137 | 138 | 139 | 140 | 字段 141 | 142 | 143 | 144 | 145 | 标题 146 | 147 | 148 | 149 | 150 | 字段属性名 151 | 152 | 153 | 154 | 155 | 属性值 156 | 157 | 158 | 159 | 160 | 是否自动换行 161 | 162 | 163 | 164 | 165 | 是否自适应宽度 166 | 167 | 168 | 169 | 170 | 属性取值函数 171 | 172 | 173 | 174 | 175 | 边框样式 176 | 177 | 178 | 179 | 180 | 顶部线条类型。 181 | 182 | 1=实线;2=虚线 183 | 184 | 185 | 186 | 右部线条类型。 187 | 188 | 1=实线;2=虚线 189 | 190 | 191 | 192 | 左部线条类型。 193 | 194 | 1=实线;2=虚线 195 | 196 | 197 | 198 | 下部线条线条类型。 199 | 200 | 1=实线;2=虚线 201 | 202 | 203 | 204 | 背景颜色 205 | 206 | 1=白色;2=黑色;3=黄色 207 | 208 | 209 | 210 | 单元格 211 | 212 | 213 | 214 | 215 | 宽度 216 | 217 | 218 | 219 | 220 | 边框样式 221 | 222 | 223 | 224 | 225 | 单元行列表。列拆行 226 | 227 | 228 | 229 | 230 | 显示的元素列表 231 | 232 | 233 | 234 | 235 | 显示的元素,便于存储显示元素全量信息(只用于前端和存储,不参与运算逻辑) 236 | 237 | 238 | 239 | 240 | 坐标 241 | 242 | 243 | 244 | 245 | X轴坐标 246 | 247 | 248 | 249 | 250 | Y轴坐标 251 | 252 | 253 | 254 | 255 | 字体 256 | 257 | 258 | 259 | 260 | 字体大小 261 | 262 | 263 | 264 | 265 | 字体风格 266 | 267 | 268 | 269 | 270 | 字体名称 271 | 272 | 273 | 274 | 275 | 字体加粗 276 | 277 | 278 | 279 | 280 | 字体放大 281 | 282 | 283 | 284 | 285 | 是否自动换行 286 | 287 | 288 | 289 | 290 | 是否自适应宽度 291 | 292 | 293 | 294 | 295 | 间距 296 | 297 | 298 | 299 | 300 | 上间距 301 | 302 | 303 | 304 | 305 | 左间距 306 | 307 | 308 | 309 | 310 | 右间距 311 | 312 | 313 | 314 | 315 | 下间距 316 | 317 | 318 | 319 | 320 | 范围 321 | 322 | 323 | 324 | 325 | 左上角起始坐标 326 | 327 | 328 | 329 | 330 | 右下角终止坐标 331 | 332 | 333 | 334 | 335 | 单元行 336 | 337 | 338 | 339 | 340 | 高度 341 | 342 | 343 | 344 | 345 | 边框类型 346 | 347 | 348 | 349 | 350 | 单元格列表 351 | 352 | 353 | 354 | 355 | 模板 356 | 357 | 358 | 359 | 360 | 纸张类型 361 | 362 | 1=A4 363 | 364 | 365 | 366 | 宽度 367 | 368 | 369 | 370 | 371 | 高度 372 | 373 | 374 | 375 | 376 | 背景颜色 377 | 378 | 1=白色;2=黑色;3=黄色 379 | 380 | 381 | 382 | 边框颜色 383 | 384 | 385 | 386 | 387 | 单元行列表 388 | 389 | 390 | 391 | 392 | 文本 393 | 394 | 395 | 396 | 397 | 文字大小 398 | 399 | 400 | 401 | 402 | 文字类型 403 | 404 | 405 | 406 | 407 | 文字风格 408 | 409 | 410 | 411 | 412 | 分割线 413 | 414 | 415 | 416 | 417 | 行 418 | 419 | 420 | 421 | 422 | 高度 423 | 424 | 425 | 426 | 427 | 打印批量参数 428 | 429 | 类型 430 | 431 | 432 | 433 | 模板 434 | 435 | 436 | 437 | 438 | 打印主数据。注:属性值不支持List,Map,类对象 439 | 440 | 441 | 442 | 443 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpBarcodeElement.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Elements 2 | { 3 | /// 4 | /// 条码元素 5 | /// 6 | public class BpBarcodeElement : BpElement 7 | { 8 | /// 9 | /// 宽度 10 | /// 11 | public int Width { get; set; } 12 | 13 | /// 14 | /// 高度 15 | /// 16 | public int Height { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpElement.cs: -------------------------------------------------------------------------------- 1 | using Bing.EasyPrint.Model; 2 | 3 | namespace Bing.EasyPrint.Elements 4 | { 5 | /// 6 | /// 最小显示元素 7 | /// 8 | public class BpElement 9 | { 10 | /// 11 | /// 类型 12 | /// 13 | /// 1=文字;2=图片;3=二维码;4=条形码 14 | public int Type { get; set; } 15 | 16 | /// 17 | /// 显示的属性信息 18 | /// 19 | public BgField Field { get; set; } 20 | 21 | /// 22 | /// 元素显示间距 23 | /// 24 | public BpMargin Margin { get; set; } 25 | 26 | /// 27 | /// 左上角起始坐标 28 | /// 29 | public BpCoordinate StartCoordinate { get; set; } 30 | 31 | /// 32 | /// 右下角终止坐标 33 | /// 34 | public BpCoordinate EndCoordinate { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpElementAll.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Elements 2 | { 3 | /// 4 | /// 显示元素扩展。便于存储元素所有属性信息,只有其中一个不为空 5 | /// 6 | public class BpElementAll 7 | { 8 | /// 9 | /// 图片显示元素 10 | /// 11 | public BpImageElement ImageElement{ get; set; } 12 | 13 | /// 14 | /// 文字显示元素 15 | /// 16 | public BpFontElement FontElement { get; set; } 17 | 18 | /// 19 | /// 二维码显示元素 20 | /// 21 | public BpQrCodeElement QrCodeElement{ get; set; } 22 | 23 | /// 24 | /// 条码显示元素 25 | /// 26 | public BpBarcodeElement BarcodeElement{ get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpFontElement.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Bing.EasyPrint.Elements 3 | { 4 | /// 5 | /// 文字显示元素 6 | /// 7 | public class BpFontElement : BpElement 8 | { 9 | /// 10 | /// 字体大小 11 | /// 12 | public int FontSize { get; set; } 13 | 14 | /// 15 | /// 字体风格 16 | /// 17 | public int FontStyle { get; set; } 18 | 19 | /// 20 | /// 字体名称 21 | /// 22 | public int FontName { get; set; } 23 | 24 | /// 25 | /// 字体加粗 26 | /// 27 | public bool Bold { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpImageElement.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Elements 2 | { 3 | /// 4 | /// 图片元素 5 | /// 6 | public class BpImageElement : BpElement 7 | { 8 | /// 9 | /// 宽度 10 | /// 11 | public int Width{ get; set; } 12 | 13 | /// 14 | /// 高度 15 | /// 16 | public int Height{ get; set; } 17 | 18 | /// 19 | /// 是否压缩 20 | /// 21 | public bool IsCompress { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Elements/BpQrCodeElement.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Elements 2 | { 3 | /// 4 | /// 二维码元素 5 | /// 6 | public class BpQrCodeElement : BpElement 7 | { 8 | /// 9 | /// 宽度 10 | /// 11 | public int Width { get; set; } 12 | 13 | /// 14 | /// 高度 15 | /// 16 | public int Height { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BgField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Bing.EasyPrint.Model 4 | { 5 | /// 6 | /// 字段 7 | /// 8 | public class BgField 9 | { 10 | /// 11 | /// 标题 12 | /// 13 | public string Title { get; set; } 14 | 15 | /// 16 | /// 字段属性名 17 | /// 18 | public string Name { get; set; } 19 | 20 | /// 21 | /// 属性值 22 | /// 23 | public string Value { get; set; } 24 | 25 | /// 26 | /// 是否自动换行 27 | /// 28 | public bool NeedFeedLine { get; set; } = true; 29 | 30 | /// 31 | /// 是否自适应宽度 32 | /// 33 | public bool Fit { get; set; } = false; 34 | 35 | /// 36 | /// 属性取值函数 37 | /// 38 | public Func ValueFunc { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpBorder.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 边框样式 5 | /// 6 | public class BpBorder 7 | { 8 | /// 9 | /// 顶部线条类型。 10 | /// 11 | /// 1=实线;2=虚线 12 | public int TopStyle { get; set; } 13 | 14 | /// 15 | /// 右部线条类型。 16 | /// 17 | /// 1=实线;2=虚线 18 | public int RightStyle { get; set; } 19 | 20 | /// 21 | /// 左部线条类型。 22 | /// 23 | /// 1=实线;2=虚线 24 | public int LeftStyle { get; set; } 25 | 26 | /// 27 | /// 下部线条线条类型。 28 | /// 29 | /// 1=实线;2=虚线 30 | public int BottomStyle { get; set; } 31 | 32 | /// 33 | /// 背景颜色 34 | /// 35 | /// 1=白色;2=黑色;3=黄色 36 | public int Color { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpCell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Bing.EasyPrint.Elements; 7 | 8 | namespace Bing.EasyPrint.Model 9 | { 10 | /// 11 | /// 单元格 12 | /// 13 | public class BpCell 14 | { 15 | /// 16 | /// 宽度 17 | /// 18 | public int Width { get; set; } 19 | 20 | /// 21 | /// 边框样式 22 | /// 23 | public BpBorder Border{ get; set; } 24 | 25 | /// 26 | /// 单元行列表。列拆行 27 | /// 28 | public List Rows { get; set; } 29 | 30 | /// 31 | /// 显示的元素列表 32 | /// 33 | public List Elements { get; set; } 34 | 35 | /// 36 | /// 显示的元素,便于存储显示元素全量信息(只用于前端和存储,不参与运算逻辑) 37 | /// 38 | public List ElementAlls { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpCoordinate.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 坐标 5 | /// 6 | public class BpCoordinate 7 | { 8 | /// 9 | /// X轴坐标 10 | /// 11 | public int X { get; set; } 12 | 13 | /// 14 | /// Y轴坐标 15 | /// 16 | public int Y { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpFont.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Bing.EasyPrint.Model 8 | { 9 | /// 10 | /// 字体 11 | /// 12 | public class BpFont 13 | { 14 | /// 15 | /// 字体大小 16 | /// 17 | public int FontSize{ get; set; } 18 | 19 | /// 20 | /// 字体风格 21 | /// 22 | public int FontStyle { get; set; } 23 | 24 | /// 25 | /// 字体名称 26 | /// 27 | public int FontName { get; set; } 28 | 29 | /// 30 | /// 字体加粗 31 | /// 32 | public bool Bold { get; set; } 33 | 34 | /// 35 | /// 字体放大 36 | /// 37 | public int Mag { get; set; } 38 | 39 | /// 40 | /// 是否自动换行 41 | /// 42 | public bool NeedFeedLine { get; set; } 43 | 44 | /// 45 | /// 是否自适应宽度 46 | /// 47 | public bool Fit { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpMargin.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 间距 5 | /// 6 | public class BpMargin 7 | { 8 | /// 9 | /// 上间距 10 | /// 11 | public int Top{ get; set; } 12 | 13 | /// 14 | /// 左间距 15 | /// 16 | public int Left { get; set; } 17 | 18 | /// 19 | /// 右间距 20 | /// 21 | public int Right{ get; set; } 22 | 23 | /// 24 | /// 下间距 25 | /// 26 | public int Bottom { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpRange.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 范围 5 | /// 6 | public class BpRange 7 | { 8 | /// 9 | /// 左上角起始坐标 10 | /// 11 | public BpCoordinate StartCoordinate { get; set; } 12 | 13 | /// 14 | /// 右下角终止坐标 15 | /// 16 | public BpCoordinate EndCoordinate { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpRow.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Bing.EasyPrint.Model 4 | { 5 | /// 6 | /// 单元行 7 | /// 8 | public class BpRow 9 | { 10 | /// 11 | /// 高度 12 | /// 13 | public int Height { get; set; } 14 | 15 | /// 16 | /// 边框类型 17 | /// 18 | public BpBorder Border { get; set; } 19 | 20 | /// 21 | /// 单元格列表 22 | /// 23 | public List Cells { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpTemplate.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Bing.EasyPrint.Model 4 | { 5 | /// 6 | /// 模板 7 | /// 8 | public class BpTemplate 9 | { 10 | /// 11 | /// 纸张类型 12 | /// 13 | /// 1=A4 14 | public int PaperType { get; set; } 15 | 16 | /// 17 | /// 宽度 18 | /// 19 | public int Width { get; set; } 20 | 21 | /// 22 | /// 高度 23 | /// 24 | public int Height{ get; set; } 25 | 26 | /// 27 | /// 背景颜色 28 | /// 29 | /// 1=白色;2=黑色;3=黄色 30 | public int Color{ get; set; } 31 | 32 | /// 33 | /// 边框颜色 34 | /// 35 | public BpBorder Border { get; set; } 36 | 37 | /// 38 | /// 单元行列表 39 | /// 40 | public List Rows { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/BpText.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 文本 5 | /// 6 | public class BpText 7 | { 8 | /// 9 | /// 文字大小 10 | /// 11 | public int Size { get; set; } 12 | 13 | /// 14 | /// 文字类型 15 | /// 16 | public string Type { get; set; } 17 | 18 | /// 19 | /// 文字风格 20 | /// 21 | public string Style { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/FeedLine.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Model 2 | { 3 | /// 4 | /// 分割线 5 | /// 6 | public class FeedLine 7 | { 8 | /// 9 | /// 行 10 | /// 11 | public string Line { get; set; } 12 | 13 | /// 14 | /// 高度 15 | /// 16 | public int Height{ get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/Bing/EasyPrint/Model/PrintBatchParam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Bing.EasyPrint.Model 8 | { 9 | /// 10 | /// 打印批量参数 11 | /// 12 | /// 类型 13 | public class PrintBatchParam 14 | { 15 | /// 16 | /// 模板 17 | /// 18 | public T Template{ get; set; } 19 | 20 | /// 21 | /// 打印主数据。注:属性值不支持List,Map,类对象 22 | /// 23 | public List Params { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/project.dependency.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint.Templates/project.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | Bing.EasyPrint.Templates 4 | Bing.EasyPrint.Templates 5 | Bing.EasyPrint.Templates是Bing应用框架的小票打印命令生成库支持模板的方式。 6 | 7 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Bing.EasyPrint.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Bing.EasyPrint 4 | Bing.EasyPrint 5 | Bing.EasyPrint是Bing应用框架的小票打印命令生成库。 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <_Parameter1>$(MSBuildProjectName).Tests 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Bing/EasyPrint/CPCL/Metadata/PrintCommandStruct.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace Bing.EasyPrint.CPCL; 6 | 7 | /// 8 | /// 打印命令结构 9 | /// 10 | internal class PrintCommandStruct 11 | { 12 | /// 13 | /// 初始化一个类型的实例 14 | /// 15 | public PrintCommandStruct() 16 | { 17 | Content = new List(); 18 | } 19 | 20 | /// 21 | /// 开始命令 22 | /// 23 | public MetadataBase Begin { get; set; } 24 | 25 | /// 26 | /// 页宽命令 27 | /// 28 | public MetadataBase PageWidth { get; set; } 29 | 30 | /// 31 | /// 命令内容 32 | /// 33 | public List Content { get; set; } 34 | 35 | /// 36 | /// 结束命令 37 | /// 38 | public MetadataBase End { get; set; } 39 | 40 | /// 41 | /// 添加 42 | /// 43 | /// 元数据 44 | public void Add(MetadataBase metadata) 45 | { 46 | if (metadata.MetadataType == MetadataType.Raw) 47 | { 48 | Add(metadata as RawMetadata); 49 | return; 50 | } 51 | Content.Add(metadata); 52 | } 53 | 54 | /// 55 | /// 添加 56 | /// 57 | /// 命令 - 元数据 58 | public void Add(RawMetadata rawMetadata) 59 | { 60 | // 检查开始命令 61 | if (CheckBeginCommand(rawMetadata.Raw)) 62 | { 63 | Begin = rawMetadata; 64 | return; 65 | } 66 | // 检查结束命令 67 | if (CheckEndCommand(rawMetadata.Raw)) 68 | { 69 | End = rawMetadata; 70 | return; 71 | } 72 | // 检查页宽命令 73 | if (CheckPageWidthCommand(rawMetadata.Raw)) 74 | { 75 | PageWidth = rawMetadata; 76 | return; 77 | } 78 | Content.Add(rawMetadata); 79 | } 80 | 81 | /// 82 | /// 添加命令 83 | /// 84 | /// 命令 85 | public void AddRaw(string raw) => AddRaw(raw, false); 86 | 87 | /// 88 | /// 添加命令并换行 89 | /// 90 | /// 命令 91 | public void AddRawLine(string raw) => AddRaw(raw, true); 92 | 93 | /// 94 | /// 添加命令 95 | /// 96 | /// 命令 97 | /// 是否换行 98 | public void AddRaw(string raw, bool newLine) => Add(new RawMetadata(raw, newLine)); 99 | 100 | /// 101 | /// 检查开始命令 102 | /// 103 | /// 原文 104 | private bool CheckBeginCommand(string raw) 105 | { 106 | if (string.IsNullOrWhiteSpace(raw)) 107 | return false; 108 | if (Regex.IsMatch(raw, "^!\\s[0-9]\\s[0-9]+\\s[0-9]+\\s[0-9]+\\s[0-9]+\\s{0,1}$")) 109 | return true; 110 | return false; 111 | } 112 | 113 | /// 114 | /// 检查结束命令 115 | /// 116 | /// 原文 117 | private bool CheckEndCommand(string raw) 118 | { 119 | if (string.IsNullOrWhiteSpace(raw)) 120 | return false; 121 | if (Regex.IsMatch(raw, "^PRINT\\s{0,1}$")) 122 | return true; 123 | return false; 124 | } 125 | 126 | /// 127 | /// 检查页宽命令 128 | /// 129 | /// 原文 130 | private bool CheckPageWidthCommand(string raw) 131 | { 132 | if (string.IsNullOrWhiteSpace(raw)) 133 | return false; 134 | if (Regex.IsMatch(raw, "^(PAGE-WIDTH|PW)\\s[0-9]+\\s{0,1}$")) 135 | return true; 136 | return false; 137 | } 138 | 139 | /// 140 | /// 清空 141 | /// 142 | public void Clear() 143 | { 144 | Content.Clear(); 145 | Begin = null; 146 | End = null; 147 | PageWidth = null; 148 | } 149 | 150 | /// 151 | /// 安全初始化 152 | /// 153 | /// CPCL命令信息 154 | public void SafeInit(CPCLCommandInfo info) 155 | { 156 | InitBeginCommand(info.Offset, info.Height, info.Qty); 157 | InitPageWidth(info.Width); 158 | InitEndCommand(); 159 | } 160 | 161 | /// 162 | /// 初始化开始命令 163 | /// 164 | /// 偏移量。整个标签的横向偏移值 165 | /// 高度。标签的最大高度。 166 | /// 标签数量。打印标签数量 167 | private void InitBeginCommand(int offset, int height, int qty) 168 | { 169 | if (Begin != null) 170 | return; 171 | AddRawLine($"! {offset} 200 200 {height} {qty}"); 172 | } 173 | 174 | /// 175 | /// 初始化页宽命令 176 | /// 177 | /// 宽度 178 | private void InitPageWidth(int width) 179 | { 180 | if (PageWidth != null) 181 | return; 182 | AddRawLine($"PAGE-WIDTH {width}"); 183 | } 184 | 185 | /// 186 | /// 初始化结束命令 187 | /// 188 | private void InitEndCommand() 189 | { 190 | if (End != null) 191 | return; 192 | AddRawLine("PRINT"); 193 | } 194 | 195 | /// 196 | /// 构建 197 | /// 198 | /// CPCL打印命令 199 | public void Build(CPCLPrintCommand command) 200 | { 201 | Begin.Build(command); 202 | PageWidth.Build(command); 203 | Content.ForEach(x => x.Build(command)); 204 | End.Build(command); 205 | } 206 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Bing/EasyPrint/IPrintValue.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Bing.EasyPrint; 4 | 5 | /// 6 | /// 打印值 7 | /// 8 | public interface IPrintValue 9 | { 10 | /// 11 | /// 数据 12 | /// 13 | byte[] Data { get; } 14 | 15 | /// 16 | /// 获取字符串 17 | /// 18 | string GetString(); 19 | 20 | /// 21 | /// 获取字符串 22 | /// 23 | /// 字符编码 24 | string GetString(Encoding encoding); 25 | 26 | /// 27 | /// 获取16进制字符串 28 | /// 29 | string GetHexString(); 30 | 31 | /// 32 | /// 获取16进制字符串 33 | /// 34 | /// 是否大写字母 35 | string GetHexString(bool uppercase); 36 | 37 | /// 38 | /// 获取Base64字符串 39 | /// 40 | string GetBase64String(); 41 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Bing/EasyPrint/IPrintValueDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Bing.EasyPrint; 4 | 5 | /// 6 | /// 打印值描述符 7 | /// 8 | public interface IPrintValueDescriptor 9 | { 10 | /// 11 | /// 获取字符串 12 | /// 13 | string GetString(); 14 | 15 | /// 16 | /// 获取字符串 17 | /// 18 | /// 字符编码 19 | string GetString(Encoding encoding); 20 | 21 | /// 22 | /// 获取16进制字符串 23 | /// 24 | string GetHexString(); 25 | 26 | /// 27 | /// 获取16进制字符串 28 | /// 29 | /// 是否大写字母 30 | string GetHexString(bool uppercase); 31 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLCommandInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL命令信息 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | public class CPCLCommandInfo 8 | { 9 | /// 10 | /// 是否已设置初始化页面信息 11 | /// 12 | public bool HasBegin{ get; internal set; } 13 | 14 | /// 15 | /// 是否设置结尾信息。如:PRINT 16 | /// 17 | public bool HasEnd { get; internal set; } 18 | 19 | /// 20 | /// 偏移量。整个标签的横向偏移值 21 | /// 22 | /// 此值可以使所有域以指定的单位数量进行横向偏移 23 | public int Offset { get; internal set; } = 0; 24 | 25 | /// 26 | /// 宽度 27 | /// 28 | public int Width { get; internal set; } 29 | 30 | /// 31 | /// 高度。标签的最大高度。 32 | /// 33 | /// 34 | /// 标签最大高度的计算方法是,先测出从第 1 个黑条(或标签间隙)底部到下一个黑条(或标签间隙)顶部之间的距离。 35 | /// 然后从中减去 1/16 英寸(1.5 毫米),所得结果即大高度。(以点为单位时:对于 203 d.p.i 打印机,减去 12 点;对于 306 d.p.i. 打印机,减去 18 点) 36 | /// 37 | public int Height { get; internal set; } 38 | 39 | /// 40 | /// 标签数量。打印标签数量 41 | /// 42 | /// 最大值 = 1024 43 | public int Qty { get; internal set; } = 1; 44 | 45 | /// 46 | /// 纸张旋转角度 47 | /// 48 | public int PagerRotate { get; internal set; } 49 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.Advanced.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 高级指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// CONTRAST 命令 11 | /// 12 | /// 对比度级别。
13 | /// 0 - 默认值
14 | /// 1 - 中
15 | /// 2 - 暗
16 | /// 3 - 非常暗 17 | /// 18 | /// CONTRAST 命令用于指定整个标签的打印黑度。亮的打印输出为对比度级别 0。暗的对比度级别为 3。打印 机在开机时的默认对比度级别为 0。必须为每个标签文件指定对比度级别。 19 | public CPCLPrintCommand Contrast(int level) => WriteRawLine($"CONTRAST {level}"); 20 | 21 | /// 22 | /// TONE 命令 23 | /// 24 | /// 色调级别。选择介于 -99 到 200 之间的值 25 | /// TONE 命令可用于替代 CONTRAST 命令来指定所有标签的打印黑度。亮的打印输出为色调级别 -99。暗的 色调级别为 200。打印机在开机时的默认色调级别为 0。色调级别设置在更改前对所有打印任务保持有效。TONE 和 CONTRAST 命令不能彼此组合使用。 26 | public CPCLPrintCommand Tone(int level) => WriteRawLine($"TONE {level}"); 27 | 28 | /// 29 | /// 对齐命令 - 居中对齐 30 | /// 31 | /// 对齐的结束点。如果未输入参数,则对于横向打印,对齐命令将使用打印头的宽度;而对于纵向打印,对 齐命令将使用零(页头)。 32 | /// 使用对齐命令可以控制字段的对齐方式。默认情况下,打印机将左对齐所有字段。对齐命令将对所有后续字段保持 有效,直至指定了其他对齐命令。 33 | public CPCLPrintCommand Center(int? end = null) => WriteRawLine($"CENTER{(end == null ? string.Empty : $" {end}")}"); 34 | 35 | /// 36 | /// 对齐命令 - 左对齐 37 | /// 38 | /// 使用对齐命令可以控制字段的对齐方式。默认情况下,打印机将左对齐所有字段。对齐命令将对所有后续字段保持 有效,直至指定了其他对齐命令。 39 | public CPCLPrintCommand Left() => WriteRawLine("LEFT"); 40 | 41 | /// 42 | /// 对齐命令 - 右对齐 43 | /// 44 | /// 对齐的结束点。如果未输入参数,则对于横向打印,对齐命令将使用打印头的宽度;而对于纵向打印,对 齐命令将使用零(页头)。 45 | /// 使用对齐命令可以控制字段的对齐方式。默认情况下,打印机将左对齐所有字段。对齐命令将对所有后续字段保持 有效,直至指定了其他对齐命令。 46 | public CPCLPrintCommand Right(int? end = null) => WriteRawLine($"RIGHT{(end == null ? string.Empty : $" {end}")}"); 47 | 48 | /// 49 | /// PAGE-WIDTH 命令 50 | /// 51 | /// 页面的单位宽度 52 | /// 打印机假定页面宽度为打印机的完整宽度。打印会话的大高度由页面宽度和可用打印内存决定。如果页面宽度小 于打印机的完整宽度,则用户可以通过指定页面宽度来增加大页面高度。 53 | public CPCLPrintCommand PageWidth(int width) => WriteRawLine($"PAGE-WIDTH {width}"); 54 | 55 | /// 56 | /// PACE 命令 57 | /// 58 | /// 此命令可以与批量打印一起使用。在激活 PACE 后,用户必须按下打印机的 FEED(送纸)键才能打印其他标签, 直至完成批次数量。默认情况下,开机时定步功能处于禁用状态。 59 | public CPCLPrintCommand Pace() => WriteRawLine("PACE"); 60 | 61 | /// 62 | /// AUTO-PACE 命令 63 | /// 64 | /// 此命令可用于指示配备了标签存在传感器的打印机延迟打印,直至取走了之前打印的标签。 65 | public CPCLPrintCommand PaceAuto() => WriteRawLine("AUTO-PACE"); 66 | 67 | /// 68 | /// NO-PACE 命令 69 | /// 70 | /// 如果打印机已处于 PACE 或 AUTO-PACE 模式,则此命令可取消 PACE 和 AUTO-PACE 模式。打印机在开机时默 认为 NO-PACE 模式。 71 | public CPCLPrintCommand PaceNo() => WriteRawLine("NO-PACE"); 72 | 73 | /// 74 | /// WAIT 命令 75 | /// 76 | /// 延迟时间。以 1/8 秒为单位 77 | /// 此命令用于在打印一个标签后引入一段延迟。 78 | public CPCLPrintCommand Wait(int delayTime) => WriteRawLine($"WAIT {delayTime}"); 79 | 80 | /// 81 | /// REWIND 命令(开启) 82 | /// 83 | /// 此命令用于打开或关闭回卷(或卷纸)电机。打印机在开机时默认为 REWIND-ON。如果打印机没有配备电机驱动 的回卷机制,则将忽略 REWIND 命令。 84 | public CPCLPrintCommand RewindOn() => WriteRawLine("REWIND-ON"); 85 | 86 | /// 87 | /// REWIND 命令(关闭) 88 | /// 89 | /// 此命令用于打开或关闭回卷(或卷纸)电机。打印机在开机时默认为 REWIND-ON。如果打印机没有配备电机驱动 的回卷机制,则将忽略 REWIND 命令。 90 | public CPCLPrintCommand RewindOff() => WriteRawLine("REWIND-OFF"); 91 | 92 | /// 93 | /// TENSION 命令(打印标签之前) 94 | /// 95 | /// 回卷电机用于收紧衬纸张力的单位长度。当张力调整到位后,回卷电机将滑动(不会为下一个打印周期 用尽所有调整余地)。 96 | /// TENSION 命令用于在打印标签之前和/或之后,通过按预先指定的长度运行回卷电机来调整衬纸张力。对于配备 电机驱动的回卷机制的打印机,此调整操作可以改善剥离器的性能。如果打印机没有配备电机驱动的回卷机制,则将 忽略 TENSION 命令。 97 | public CPCLPrintCommand TensionPre(int length) => WriteRawLine($"PRE-TENSION {length}"); 98 | 99 | /// 100 | /// TENSION 命令(打印标签之后) 101 | /// 102 | /// 回卷电机用于收紧衬纸张力的单位长度。当张力调整到位后,回卷电机将滑动(不会为下一个打印周期 用尽所有调整余地)。 103 | /// TENSION 命令用于在打印标签之前和/或之后,通过按预先指定的长度运行回卷电机来调整衬纸张力。对于配备 电机驱动的回卷机制的打印机,此调整操作可以改善剥离器的性能。如果打印机没有配备电机驱动的回卷机制,则将 忽略 TENSION 命令。 104 | public CPCLPrintCommand TensionPost(int length) => WriteRawLine($"POST-TENSION {length}"); 105 | 106 | /// 107 | /// SPEED 命令 108 | /// 109 | /// 电机的最高速度级别。一个介于 0 到 5 之间的数字,0 表示低速度。 110 | /// 此命令用于设置电机的高速度级别。每一款打印机型号都设置了低和高极限速度。SPEED 命令可以在 0 到 5 的范围内选择速度级别,0 表示低速度。为每一款打印机型号设置的高速度仅可在理想条件下达到。电池或供 电电压、材料厚度、打印黑度、是否使用贴标机、是否使用剥离器以及标签长度等诸多因素均会影响大极限打印速度。 111 | public CPCLPrintCommand Speed(int level) => WriteRawLine($"SPEED {level}"); 112 | 113 | /// 114 | /// SETSP 命令 115 | /// 116 | /// 字符间的单位尺寸。间距的默认值为零。请注意,此命令受单位命令设置的影响。 117 | /// SETSP 命令用于更改文本字符之间的间距。 118 | public CPCLPrintCommand SetSp(int spacing) => WriteRawLine($"SETSP {spacing}"); 119 | 120 | /// 121 | /// UNDERLINE 命令(开启) 122 | /// 123 | /// UNDERLINE 命令用于给文本加下划线。仅当所使用的字体支持下划线时,此命令才会起作用。如果所使用的字体不支 持 UNDERLINE,则将忽略此命令。 124 | public CPCLPrintCommand UnderlineOn() => WriteRawLine("UNDERLINE ON"); 125 | 126 | /// 127 | /// UNDERLINE 命令(关闭) 128 | /// 129 | /// UNDERLINE 命令用于给文本加下划线。仅当所使用的字体支持下划线时,此命令才会起作用。如果所使用的字体不支 持 UNDERLINE,则将忽略此命令。 130 | public CPCLPrintCommand UnderlineOff() => WriteRawLine("UNDERLINE OFF"); 131 | 132 | /// 133 | /// ON-OUT-OF-PAPER 命令 134 | /// 135 | /// 遇到错误操作。
136 | /// PURGE:当遇到打印错误时,在尝试指定的次数之后丢弃标签。
137 | /// WAIT:当遇到打印错误时不丢弃标签。在此模式下,打印机将等待更正错误,更正后才会执行下一打印尝试 138 | /// 139 | /// 指定打印机应尝试打印标签的次数。 140 | /// 可以发出此命令来指示打印机在打印标签期间遇到错误(例如,纸张用完)时要采取的操作。 141 | public CPCLPrintCommand OnOutOfPaper(string action, int retries) => WriteRawLine($"ON-OUT-OF-PAPER {action} {retries}"); 142 | 143 | /// 144 | /// ON-FEED 命令 145 | /// 146 | /// 遇到换页符(0x0c)或FEED(送纸)键操作。
147 | /// IGNORE:当按下 FEED(送纸)键或收到换页符时,不采取任何操作。
148 | /// FEED:当按下 FEED(送纸)键或收到换页符时,切换至下一页顶部。
149 | /// REPRINT:当按下 FEED(送纸)键或收到换页符时,重新打印上一标签。 150 | /// 151 | /// 当按下 FEED(送纸)键或打印机收到换页符 (0x0c) 时,打印机可配置为忽略、换页或重新打印上一标签。 152 | public CPCLPrintCommand OnFeed(string action) => WriteRawLine($"ON-FEED {action}"); 153 | 154 | /// 155 | /// PREFEED 命令 156 | /// 157 | /// 打印机在打印之前将介质向前移动的单位长度 158 | /// PREFEED 命令指示打印机在打印之前将介质向前移动指定长度。 159 | public CPCLPrintCommand PreFeed(int length) => WriteRawLine($"PREFEED {length}"); 160 | 161 | /// 162 | /// POSTFEED 命令 163 | /// 164 | /// 打印机在打印之后将介质向前移动的单位长度 165 | /// POSTFEED 命令指示打印机在打印之后将介质向前移动指定长度。 166 | public CPCLPrintCommand PostFeed(int length) => WriteRawLine($"POSTFEED {length}"); 167 | 168 | /// 169 | /// PRESEND-AT 命令 170 | /// 171 | /// 打印之后介质向前移动以及打印下一标签之前介质回退的单位长度,以点行为单位 172 | /// 打印标签之后打印机在向前移动介质前等待的时间间隔。以 1/8 秒为单位递增。延迟“1”等价于 1/8 秒。延迟“4”等价于 1/2 秒,以此类推。 173 | /// PRESENT-AT 命令可用于将介质定位到打印机的撕纸杆处或者操作人员可以轻松取走打印后的标签的位置。发出 PRESENT-AT 命令后,打印机将打印标签,然后在延迟一段时间后,将介质向前移动指定的距离。在开始新的打印作 业之前,打印机会将介质回退相同的距离。 “delay”参数用于在执行批量打印作业时,避免不必要的向前/回退操作。PRESENT-AT 命令可在标签文件中发 出,也可在实用工具命令会话(!UTILITIES…PRINT) 中发出。 174 | public CPCLPrintCommand PreSentAt(int length, int delay) => WriteRawLine($"PRESENT-AT {length} {delay}"); 175 | 176 | /// 177 | /// COUNTRY 命令 178 | /// 179 | /// 国家/地区名称 180 | /// 使用 COUNTRY 控制命令可以针对指定的国家/地区替代适当的字符集。 181 | public CPCLPrintCommand Country(string name) => WriteRawLine($"COUNTRY {name}"); 182 | 183 | /// 184 | /// DEFINE-FORMAT 命令 185 | /// 186 | /// 格式文件名称。格式文件名可由不超过 8 个的字母或数字组成,格式文件扩展名可由不超过 3 个的字母或数字组成。格式文件名 或扩展名中的所有小写字母将转换为大写字母。 187 | /// 数据 188 | /// DEFINE-FORMAT 和 USE-FORMAT 命令分别用于标识格式和数据。 使用格式文件可以避免为打印的每个标签重新发送相同的格式信息。通过使用预加载的格式,只需向打印机发送 变量数据(例如描述、价格等)
189 | /// 使用“\\”(双反斜杠)作为数据的占位符。 190 | ///
191 | public CPCLPrintCommand DefineFormat(string name, params string[] data) 192 | { 193 | WriteRawLine($"!DF {name}"); 194 | foreach (var item in data) 195 | WriteRawLine(item); 196 | return this; 197 | } 198 | 199 | /// 200 | /// USE-FORMAT 命令 201 | /// 202 | /// 格式文件名称。格式文件名可由不超过 8 个的字母或数字组成,格式文件扩展名可由不超过 3 个的字母或数字组成。格式文件名 或扩展名中的所有小写字母将转换为大写字母。 203 | /// 变量数据 204 | /// USE-FORMAT(或 UF)命令指示打印机使用指定的格式文件。 将使用该格式文件以及 USE-FORMAT 命令后面 提供的数据创建标签。在访问指定的格式文件后,打印机将使用所提供的数据替代“\\”分隔符,从而生成所需的标签。 205 | public CPCLPrintCommand UseFormat(string name, params object[] data) 206 | { 207 | WriteRawLine($"!UF {name}"); 208 | foreach (var item in data) 209 | WriteRawLine(item.ToString()); 210 | return this; 211 | } 212 | 213 | /// 214 | /// BEEP 命令 215 | /// 216 | /// 蜂鸣持续时间,以 1/8 秒为单位递增指定。 217 | /// 此命令用于指示打印机让蜂鸣器发出给定时间长度的声音。未配备蜂鸣器的打印机将忽略此命令。 218 | public CPCLPrintCommand Beep(int length) => WriteRawLine($"BEEP {length}"); 219 | 220 | /// 221 | /// CUT 命令 222 | /// 223 | /// 在配备有切纸器的打印机上,使用此命令可在打印标签之后裁切标签。 224 | public CPCLPrintCommand Cut() => WriteRawLine("CUT"); 225 | 226 | /// 227 | /// PARTIAL-CUT 命令 228 | /// 229 | /// 在配备有切纸器的打印机上,使用此命令可在打印标签之后裁切标签,保留部分标签不进行裁切以便可以轻松撕 开标签剩余部分。 230 | public CPCLPrintCommand PartialCut() => WriteRawLine("PARTIAL-CUT"); 231 | 232 | /// 233 | /// CUT-AT 命令 234 | /// 235 | /// 在执行裁切或部分裁切操作之后,纸张应回退的单位长度。 236 | /// 在配备有切纸器的打印机上,此命令与 CUT 或 PARTIAL-CUT 命令结合使用。此命令可指示打印机按指定长度回 退纸张。未配备切纸器的打印机将忽略此命令。 237 | public CPCLPrintCommand CutAt(int length) => WriteRawLine($"CUT-AT {length}"); 238 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.Barcode.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 条码指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// BARCODE 命令(横向) 11 | /// 12 | /// 条码类型 13 | /// 窄条的单位宽度 14 | /// 宽度与窄条的比率 15 | /// 条码的单位高度 16 | /// 横向起始位置 17 | /// 纵向起始位置 18 | /// 条码数据 19 | /// BARCODE 命令能够以指定的宽度和高度纵向和横向打印条码。 20 | public CPCLPrintCommand Barcode(string type, int width, int ratio, int height, int x, int y, string data) => WriteRawLine($"B {type} {width} {ratio} {height} {x} {y} {data}"); 21 | 22 | /// 23 | /// VBARCODE 命令(纵向) 24 | /// 25 | /// 条码类型 26 | /// 窄条的单位宽度 27 | /// 宽度与窄条的比率 28 | /// 条码的单位高度 29 | /// 横向起始位置 30 | /// 纵向起始位置 31 | /// 条码数据 32 | /// BARCODE 命令能够以指定的宽度和高度纵向和横向打印条码。 33 | public CPCLPrintCommand VBarcode(string type, int width, int ratio, int height, int x, int y, string data) => WriteRawLine($"VB {type} {width} {ratio} {height} {x} {y} {data}"); 34 | 35 | /// 36 | /// BARCODE-TEXT 命令(开启) 37 | /// 38 | /// 注释条码时要使用的字体号 39 | /// 注释条码时要使用的字体大小 40 | /// 文本距离条码的单位偏移量 41 | /// 42 | /// BARCODE-TEXT 命令用于通过创建条码时所用的相同数据来标记条码。这项命令避免了使用单独文本命令注释 条码的必要。文本位于条码下方的中间位置。
43 | /// 使用 BARCODE-TEXT OFF(或 BT OFF)可以禁用它。 44 | ///
45 | public CPCLPrintCommand BarcodeText(string font, int size, int offset) => WriteRawLine($"BT {font} {size} {offset}"); 46 | 47 | /// 48 | /// BARCODE-TEXT 命令(关闭) 49 | /// 50 | /// 51 | /// BARCODE-TEXT 命令用于通过创建条码时所用的相同数据来标记条码。这项命令避免了使用单独文本命令注释 条码的必要。文本位于条码下方的中间位置。
52 | /// 使用 BARCODE-TEXT OFF(或 BT OFF)可以禁用它。 53 | ///
54 | public CPCLPrintCommand BarcodeTextOff() => WriteRawLine("BT OFF"); 55 | 56 | /// 57 | /// BARCODE-RSS 命令 58 | /// 59 | /// 横向起始位置 60 | /// 纵向起始位置 61 | /// 最窄元素的单位宽度 62 | /// 条码线性部分的高度 63 | /// 分隔符的高度 64 | /// 每行的段数 65 | /// RSS/复合子类型 66 | /// 线性数据 67 | /// 2D数据 68 | /// 缩减码型(RSS) 涵盖一系列线性符号,旨在为用户解决特定空间限制和应用需求提供相应功能。RSS 多支持 74 个数据字符的编码。 69 | public CPCLPrintCommand BarcodeRss(int x, int y, int width, int linHeight, int sepHeight, int segments, int subType, string dataLine, string data2D) => WriteRawLine($"B RSS {x} {y} {width} {linHeight} {sepHeight} {segments} {subType} {dataLine}|{data2D}"); 70 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.Base.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 基础指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// 初始化命令 11 | /// 12 | /// 标签横向偏移量 13 | /// 标签宽度 14 | /// 标签高度 15 | /// 打印标签数量 16 | public CPCLPrintCommand InitCommand(int offset, int width, int height, int qty) 17 | { 18 | WriteRawLine($"! {offset} 200 200 {height} {qty}"); 19 | PageWidth(width); 20 | return this; 21 | } 22 | 23 | /// 24 | /// PRINT 命令 25 | /// 26 | /// PRINT 命令作为整个命令集的结束命令,将会启动文件打印。在任何情况下(行式打印模式除外),这项命令都必 须是后一条命令。执行 PRINT 命令时,打印机将从控制会话中退出。确保使用回车和换行字符结束此项及所有命令。 27 | /// 28 | public CPCLPrintCommand Print() => WriteRawLine("PRINT"); 29 | 30 | /// 31 | /// ENCODING 命令 32 | /// 33 | /// 编码。
34 | /// ASCII
35 | /// UTF-8
36 | /// GB18030 37 | /// 38 | /// ENCODING 控制命令可以指定要发送到打印机的数据的编码形式。 39 | public CPCLPrintCommand Encoding(string encoding) => WriteRawLine($"ENCODING {encoding}"); 40 | 41 | /// 42 | /// FORM 命令 43 | /// 44 | /// FORM 命令可以指示打印机在一页打印结束后切换至下一页顶部。 45 | public CPCLPrintCommand Form() => WriteRawLine("FORM"); 46 | 47 | /// 48 | /// JOURNAL 命令 49 | /// 50 | /// 默认情况下,如果在打印周期期间(LABEL 模式)发现明显标记(介质背面的黑色水平条),则打印机会检查介质对 齐情况是否正确。必要时,可以使用 JOURNAL 命令禁用自动校正功能。用户程序负责在 JOURNAL 模式下进行检 查并确保有纸。有关检查缺纸条件的详细信息,请参阅状态询问命令。 51 | public CPCLPrintCommand Journal() => WriteRawLine("JOURNAL"); 52 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.Graphics.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 图形指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// BOX 命令 11 | /// 12 | /// 左上角的 X 坐标 13 | /// 左上角的 Y 坐标 14 | /// 右下角的 X 坐标 15 | /// 右下角的 Y 坐标 16 | /// 形成矩形框的线条的单位宽度。 17 | /// 用户可以使用 BOX 命令生成具有指定线条宽度的矩形。 18 | public CPCLPrintCommand Box(int x0, int y0, int x1, int y1, int width) => WriteRawLine($"BOX {x0} {y0} {x1} {y1} {width}"); 19 | 20 | /// 21 | /// LINE 命令 22 | /// 23 | /// 左上角的 X 坐标 24 | /// 左上角的 Y 坐标 25 | /// 水平轴的右上角、垂直轴的左下角 26 | /// 水平轴的右上角、垂直轴的左下角 27 | /// 线条的单位宽度 28 | /// 使用 LINE 命令可以绘制任何长度、宽度和角度方向的线条。 29 | public CPCLPrintCommand Line(int x0, int y0, int x1, int y1, int width) => WriteRawLine($"L {x0} {y0} {x1} {y1} {width}"); 30 | 31 | /// 32 | /// INVERSE-LINE 命令 33 | /// 34 | /// 左上角的 X 坐标 35 | /// 左上角的 Y 坐标 36 | /// 水平轴的右上角、垂直轴的左下角 37 | /// 水平轴的右上角、垂直轴的左下角 38 | /// 反转线的单位宽度 39 | /// 40 | /// INVERSE-LINE 命令的语法与 LINE 命令相同。 41 | /// 位于 INVERSE-LINE 命令所定义区域内的以前创建的对象的黑色区域将重绘为白色,白色区域将重绘为黑色。
42 | /// 这些对象可以包括文本、条码和/或图形(包括下载的.pcx 文件)。
43 | /// INVERSE-LINE 对在其之后创建的对象不起作用,即使这些对象位于该命令的覆盖区域内也是如此。
44 | /// 在示例 INVERSE2.LBL 中,在 INVERSE-LINE 命令之后创建的文本字段部分仍然为黑色,因此不可见,即使被放置在 INVERSE-LINE 区域内也是如此。 45 | ///
46 | public CPCLPrintCommand InverseLine(int x0, int y0, int x1, int y1, int width) => WriteRawLine($"IL {x0} {y0} {x1} {y1} {width}"); 47 | 48 | /// 49 | /// PATTERN 命令 50 | /// 51 | /// 填充模式。
52 | /// 100 - 填充(实心黑色/默认模式)
53 | /// 101 - 水平线
54 | /// 102 - 垂直线
55 | /// 103 - 向右上升的对角线
56 | /// 104 - 向左上升的对角线
57 | /// 105 - 正方形图案
58 | /// 106 - 剖面线图案
59 | /// 60 | /// 61 | public CPCLPrintCommand Pattern(int number) => WriteRawLine($"PATTERN {number}"); 62 | 63 | /// 64 | /// 图形命令 - EXPANDED-GRAPHICS(横向打印扩展图形) 65 | /// 66 | /// 图像的宽度(以字节为单位) 67 | /// 图形的高度(以点位单位) 68 | /// 横向起始位置 69 | /// 纵向起始位置 70 | /// 图形数据 71 | /// 72 | /// 可以使用图形命令打印位映射图形。扩展图形数据使用 ASCII 十六进制字符来表示(参见示例)。通过对十六进制 数据的等效二进制字符使用 COMPRESSED-GRAPHICS 命令,可以将数据大小减半。如果使用 CG,对于每 8 位图 形数据,将会发送一个 8 位字符。如果使用 EG,将使用两个字符(16 位)来传输 8 位图形数据,因此 EG 的效率会 减半。 但是由于该数据是字符数据,因此比二进制数据更容易处理和传输。 73 | /// 74 | public CPCLPrintCommand ExpandedGraphics(int width, int height, int x, int y, string data) => WriteRawLine($"EG {width} {height} {x} {y} {data}"); 75 | 76 | /// 77 | /// 图形命令 - VEXPANDED-GRAPHICS(纵向打印扩展图形) 78 | /// 79 | /// 图像的宽度(以字节为单位) 80 | /// 图形的高度(以点位单位) 81 | /// 横向起始位置 82 | /// 纵向起始位置 83 | /// 图形数据 84 | /// 85 | /// 可以使用图形命令打印位映射图形。扩展图形数据使用 ASCII 十六进制字符来表示(参见示例)。通过对十六进制 数据的等效二进制字符使用 COMPRESSED-GRAPHICS 命令,可以将数据大小减半。如果使用 CG,对于每 8 位图 形数据,将会发送一个 8 位字符。如果使用 EG,将使用两个字符(16 位)来传输 8 位图形数据,因此 EG 的效率会 减半。 但是由于该数据是字符数据,因此比二进制数据更容易处理和传输。 86 | /// 87 | public CPCLPrintCommand VExpandedGraphics(int width, int height, int x, int y, string data) => WriteRawLine($"VEG {width} {height} {x} {y} {data}"); 88 | 89 | /// 90 | /// 图形命令 - COMPRESSED-GRAPHICS(横向打印压缩图形) 91 | /// 92 | /// 图像的宽度(以字节为单位) 93 | /// 图形的高度(以点位单位) 94 | /// 横向起始位置 95 | /// 纵向起始位置 96 | /// 图形数据 97 | /// 98 | /// 可以使用图形命令打印位映射图形。扩展图形数据使用 ASCII 十六进制字符来表示(参见示例)。通过对十六进制 数据的等效二进制字符使用 COMPRESSED-GRAPHICS 命令,可以将数据大小减半。如果使用 CG,对于每 8 位图 形数据,将会发送一个 8 位字符。如果使用 EG,将使用两个字符(16 位)来传输 8 位图形数据,因此 EG 的效率会 减半。 但是由于该数据是字符数据,因此比二进制数据更容易处理和传输。 99 | /// 100 | public CPCLPrintCommand CompressedGraphics(int width, int height, int x, int y, string data) => WriteRawLine($"CG {width} {height} {x} {y} {data}"); 101 | 102 | /// 103 | /// 图形命令 - VCOMPRESSED-GRAPHICS(横向打印压缩图形) 104 | /// 105 | /// 图像的宽度(以字节为单位) 106 | /// 图形的高度(以点位单位) 107 | /// 横向起始位置 108 | /// 纵向起始位置 109 | /// 图形数据 110 | /// 111 | /// 可以使用图形命令打印位映射图形。扩展图形数据使用 ASCII 十六进制字符来表示(参见示例)。通过对十六进制 数据的等效二进制字符使用 COMPRESSED-GRAPHICS 命令,可以将数据大小减半。如果使用 CG,对于每 8 位图 形数据,将会发送一个 8 位字符。如果使用 EG,将使用两个字符(16 位)来传输 8 位图形数据,因此 EG 的效率会 减半。 但是由于该数据是字符数据,因此比二进制数据更容易处理和传输。 112 | /// 113 | public CPCLPrintCommand VCompressedGraphics(int width, int height, int x, int y, string data) => WriteRawLine($"VCG {width} {height} {x} {y} {data}"); 114 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.QrCode.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 二维条码指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// 二维条码命令 PDF417(横向) 11 | /// 12 | /// 横向起始位置 13 | /// 纵向起始位置 14 | /// 窄元素的单位宽度。范围介于 1 至 32 之间,默认值为 2。 15 | /// 窄元素的单位高度。范围介于 1 至 32 之间,默认值为 6。 16 | /// 要使用的列数。数据列不包括起始/终止字符和左/右指示符。范围介于 1 至 30 之间,默认值为 3 17 | /// 安全级别,指示要检测和/或纠正的大错误量。范围介于 0 至 8 之间,默认值为 1。 18 | /// 条码数据 19 | /// 20 | /// PDF417 条码是一种二维条码,这种条码可以在狭小的空间里包含数量巨大的数据。 21 | /// 仔细观察 PDF417 条码,您会 发现其实它是由较小的条码堆叠而成。 22 | /// 堆叠的数量和高度由用户控制。这类条码可以包含整个 ASCII 255 字符集,并能使用不同的编码方案和不同的纠错安全级别。大数据编码量为 2725 个字符 23 | /// 24 | public CPCLPrintCommand Pdf417(int x, int y, int width, int height, int col, int safeLevel, params string[] data) 25 | { 26 | WriteRawLine($"B PDF-417 {x} {y} XD {width} YD {height} C {col} S {safeLevel}"); 27 | foreach (var item in data) 28 | WriteRawLine(item); 29 | WriteRawLine("ENDPDF"); 30 | return this; 31 | } 32 | 33 | /// 34 | /// 二维条码命令 PDF417(纵向) 35 | /// 36 | /// 横向起始位置 37 | /// 纵向起始位置 38 | /// 窄元素的单位宽度。范围介于 1 至 32 之间,默认值为 2。 39 | /// 窄元素的单位高度。范围介于 1 至 32 之间,默认值为 6。 40 | /// 要使用的列数。数据列不包括起始/终止字符和左/右指示符。范围介于 1 至 30 之间,默认值为 3 41 | /// 安全级别,指示要检测和/或纠正的大错误量。范围介于 0 至 8 之间,默认值为 1。 42 | /// 条码数据 43 | /// 44 | /// PDF417 条码是一种二维条码,这种条码可以在狭小的空间里包含数量巨大的数据。 45 | /// 仔细观察 PDF417 条码,您会 发现其实它是由较小的条码堆叠而成。 46 | /// 堆叠的数量和高度由用户控制。这类条码可以包含整个 ASCII 255 字符集,并能使用不同的编码方案和不同的纠错安全级别。大数据编码量为 2725 个字符 47 | /// 48 | public CPCLPrintCommand VPdf417(int x, int y, int width, int height, int col, int safeLevel, params string[] data) 49 | { 50 | WriteRawLine($"VB PDF-417 {x} {y} XD {width} YD {height} C {col} S {safeLevel}"); 51 | foreach (var item in data) 52 | WriteRawLine(item); 53 | WriteRawLine("ENDPDF"); 54 | return this; 55 | } 56 | 57 | /// 58 | /// 二维条码命令 MAXICODE 59 | /// 60 | /// 横向起始位置 61 | /// 纵向起始位置 62 | /// 参数:标签-数据 63 | /// Maxicode 条码现在可以处理 UPS 定义的所有符号以及标准代码支持的基本字段。Maxicode 支持所有标准的可 打印字符,并能够自动将次级消息中的所有小写字母转换为大写字母。本修订版手册仅介绍了 Mode 2 条码。 64 | public CPCLPrintCommand Maxicode(int x, int y, params (string tag, string data)[] param) 65 | { 66 | WriteRawLine($"B MAXICODE {x} {y}"); 67 | foreach (var item in param) 68 | WriteRawLine($"{item.tag} {item.data}"); 69 | WriteRawLine("ENDMAXICODE"); 70 | return this; 71 | } 72 | 73 | /// 74 | /// 二维条码命令 QRCode(横向) 75 | /// 76 | /// 横向起始位置 77 | /// 纵向起始位置 78 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 79 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 80 | /// 提供生成 QR Code 所需的信息。需要录入二维自定义信息 81 | // ReSharper disable once InconsistentNaming 82 | public CPCLPrintCommand QRCodeRaw(int x, int y, int model, int widthWithHeight, params string[] data) 83 | { 84 | WriteRawLine($"B QR {x} {y} M {model} U {widthWithHeight}"); 85 | foreach (var item in data) 86 | WriteRawLine(item); 87 | WriteRawLine("ENDQR"); 88 | return this; 89 | } 90 | 91 | /// 92 | /// 二维条码命令 QRCode(纵向) 93 | /// 94 | /// 横向起始位置 95 | /// 纵向起始位置 96 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 97 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 98 | /// 提供生成 QR Code 所需的信息。需要录入二维自定义信息 99 | // ReSharper disable once InconsistentNaming 100 | public CPCLPrintCommand VQRCodeRaw(int x, int y, int model, int widthWithHeight, params string[] data) 101 | { 102 | WriteRawLine($"VB QR {x} {y} M {model} U {widthWithHeight}"); 103 | foreach (var item in data) 104 | WriteRawLine(item); 105 | WriteRawLine("ENDQR"); 106 | return this; 107 | } 108 | 109 | /// 110 | /// 二维条码命令 QRCode(横向) 111 | /// 112 | /// 横向起始位置 113 | /// 纵向起始位置 114 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 115 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 116 | /// 纠错级别。如:H、Q、M、L 117 | /// 掩码号。可能会省略,也可能具有一个值(介于 0 至 8 之间) 118 | /// 二维码信息 119 | // ReSharper disable once InconsistentNaming 120 | public CPCLPrintCommand QRCode(int x, int y, int model, int widthWithHeight, string errorCorrectionLevel, int? maskNo, string data) 121 | { 122 | WriteRawLine($"B QR {x} {y} M {model} U {widthWithHeight}"); 123 | WriteRawLine($"{errorCorrectionLevel}{(maskNo == null ? string.Empty : maskNo.ToString())}A,{data}"); 124 | WriteRawLine("ENDQR"); 125 | return this; 126 | } 127 | 128 | /// 129 | /// 二维条码命令 QRCode(纵向) 130 | /// 131 | /// 横向起始位置 132 | /// 纵向起始位置 133 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 134 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 135 | /// 纠错级别。如:H、Q、M、L 136 | /// 掩码号。可能会省略,也可能具有一个值(介于 0 至 8 之间) 137 | /// 二维码信息 138 | // ReSharper disable once InconsistentNaming 139 | public CPCLPrintCommand VQRCode(int x, int y, int model, int widthWithHeight, string errorCorrectionLevel, int? maskNo, string data) 140 | { 141 | WriteRawLine($"VB QR {x} {y} M {model} U {widthWithHeight}"); 142 | WriteRawLine($"{errorCorrectionLevel}{(maskNo == null ? string.Empty : maskNo.ToString())}A,{data}"); 143 | WriteRawLine("ENDQR"); 144 | return this; 145 | } 146 | 147 | /// 148 | /// 二维条码命令 QRCode(横向)手动 149 | /// 150 | /// 横向起始位置 151 | /// 纵向起始位置 152 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 153 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 154 | /// 纠错级别。如:H、Q、M、L 155 | /// 掩码号。可能会省略,也可能具有一个值(介于 0 至 8 之间) 156 | /// 参数:字符模式符(N、A、Bxxxx、K))-数据 157 | // ReSharper disable once InconsistentNaming 158 | public CPCLPrintCommand QRCodeManual(int x, int y, int model, int widthWithHeight, string errorCorrectionLevel, int? maskNo, params (string charMode, string data)[] param) 159 | { 160 | WriteRawLine($"B QR {x} {y} M {model} U {widthWithHeight}"); 161 | WriteRaw($"{errorCorrectionLevel}{(maskNo == null ? string.Empty : maskNo.ToString())}M"); 162 | foreach (var item in param) 163 | WriteRaw($",{item.charMode}{item.data}"); 164 | WriteRawLine(""); 165 | WriteRawLine("ENDQR"); 166 | return this; 167 | } 168 | 169 | /// 170 | /// 二维条码命令 QRCode(纵向)手动 171 | /// 172 | /// 横向起始位置 173 | /// 纵向起始位置 174 | /// QR Code规范编号。选项是 1 或 2。QR Code Model 1 是原始规范,而 QR Code Model 2 则是该符号 的经过增强后的形式。Model 2 提供了附加功能,而且可以自动与 Model 1 进行区分。Model 2 为推荐规范,是 默认值。 175 | /// 模块的单位宽度/单位高度。范围是 1 至 32。默认值为 6。 176 | /// 纠错级别。如:H、Q、M、L 177 | /// 掩码号。可能会省略,也可能具有一个值(介于 0 至 8 之间) 178 | /// 参数:字符模式符(N、A、Bxxxx、K))-数据 179 | // ReSharper disable once InconsistentNaming 180 | public CPCLPrintCommand VQRCodeManual(int x, int y, int model, int widthWithHeight, string errorCorrectionLevel, int? maskNo, params (string charMode, string data)[] param) 181 | { 182 | WriteRawLine($"VB QR {x} {y} M {model} U {widthWithHeight}"); 183 | WriteRaw($"{errorCorrectionLevel}{(maskNo == null ? string.Empty : maskNo.ToString())}M"); 184 | foreach (var item in param) 185 | WriteRaw($",{item.charMode}{item.data}"); 186 | WriteRawLine(""); 187 | WriteRawLine("ENDQR"); 188 | return this; 189 | } 190 | 191 | /// 192 | /// 二维条码命令 Aztec(横向) 193 | /// 194 | /// 横向起始位置 195 | /// 纵向起始位置 196 | /// 最窄元素的单位宽度(以点位单位)。默认值为 6。 197 | /// 纠错参数(0-99)。默认值为 0(默认纠错百分比)。 198 | /// 条码数据 199 | /// 200 | public CPCLPrintCommand Aztec(int x, int y, int width, int errorCorrectionPercentage, params string[] data) 201 | { 202 | WriteRawLine($"B AZTEC {x} {y} XD {width} EC {errorCorrectionPercentage}"); 203 | foreach (var item in data) 204 | WriteRawLine(item); 205 | WriteRawLine("ENDAZTEC"); 206 | return this; 207 | } 208 | 209 | /// 210 | /// 二维条码命令 Aztec(纵向) 211 | /// 212 | /// 横向起始位置 213 | /// 纵向起始位置 214 | /// 最窄元素的单位宽度(以点位单位)。默认值为 6。 215 | /// 纠错参数(0-99)。默认值为 0(默认纠错百分比)。 216 | /// 条码数据 217 | /// 218 | public CPCLPrintCommand VAztec(int x, int y, int width, int errorCorrectionPercentage, params string[] data) 219 | { 220 | WriteRawLine($"VB AZTEC {x} {y} XD {width} EC {errorCorrectionPercentage}"); 221 | foreach (var item in data) 222 | WriteRawLine(item); 223 | WriteRawLine("ENDAZTEC"); 224 | return this; 225 | } 226 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.Text.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.CPCL; 2 | 3 | /// 4 | /// CPCL 打印命令 - 文本指令 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | partial class CPCLPrintCommand 8 | { 9 | /// 10 | /// TEXT 命令 11 | /// 12 | /// 字体名称/编号 13 | /// 字体的大小标识 14 | /// 横向起始位置 15 | /// 纵向起始位置 16 | /// 要打印的文本 17 | /// 横向打印文本。 18 | public CPCLPrintCommand Text(int font, int size, int x, int y, string data) => WriteRawLine($"T {font} {size} {x} {y} {data}"); 19 | 20 | /// 21 | /// TEXT 命令 22 | /// 23 | /// 字体名称/编号 24 | /// 字体的大小标识 25 | /// 横向起始位置 26 | /// 纵向起始位置 27 | /// 要打印的文本 28 | /// 横向打印文本。 29 | public CPCLPrintCommand Text(string font, int size, int x, int y, string data) => WriteRawLine($"T {font} {size} {x} {y} {data}"); 30 | 31 | /// 32 | /// TEXT90 命令 33 | /// 34 | /// 字体名称/编号 35 | /// 字体的大小标识 36 | /// 横向起始位置 37 | /// 纵向起始位置 38 | /// 要打印的文本 39 | /// 逆时针旋转90度,横向打印文本。 40 | public CPCLPrintCommand Text90(int font, int size, int x, int y, string data) => WriteRawLine($"T90 {font} {size} {x} {y} {data}"); 41 | 42 | /// 43 | /// TEXT90 命令 44 | /// 45 | /// 字体名称/编号 46 | /// 字体的大小标识 47 | /// 横向起始位置 48 | /// 纵向起始位置 49 | /// 要打印的文本 50 | /// 逆时针旋转90度,横向打印文本。 51 | public CPCLPrintCommand Text90(string font, int size, int x, int y, string data) => WriteRawLine($"T90 {font} {size} {x} {y} {data}"); 52 | 53 | /// 54 | /// TEXT180 命令 55 | /// 56 | /// 字体名称/编号 57 | /// 字体的大小标识 58 | /// 横向起始位置 59 | /// 纵向起始位置 60 | /// 要打印的文本 61 | /// 逆时针旋转180度,反转打印文本。 62 | public CPCLPrintCommand Text180(int font, int size, int x, int y, string data) => WriteRawLine($"T180 {font} {size} {x} {y} {data}"); 63 | 64 | /// 65 | /// TEXT180 命令 66 | /// 67 | /// 字体名称/编号 68 | /// 字体的大小标识 69 | /// 横向起始位置 70 | /// 纵向起始位置 71 | /// 要打印的文本 72 | /// 逆时针旋转180度,反转打印文本。 73 | public CPCLPrintCommand Text180(string font, int size, int x, int y, string data) => WriteRawLine($"T180 {font} {size} {x} {y} {data}"); 74 | 75 | /// 76 | /// TEXT270 命令 77 | /// 78 | /// 字体名称/编号 79 | /// 字体的大小标识 80 | /// 横向起始位置 81 | /// 纵向起始位置 82 | /// 要打印的文本 83 | /// 逆时针旋转270度,纵向打印文本。 84 | public CPCLPrintCommand Text270(int font, int size, int x, int y, string data) => WriteRawLine($"T270 {font} {size} {x} {y} {data}"); 85 | 86 | /// 87 | /// TEXT270 命令 88 | /// 89 | /// 字体名称/编号 90 | /// 字体的大小标识 91 | /// 横向起始位置 92 | /// 纵向起始位置 93 | /// 要打印的文本 94 | /// 逆时针旋转270度,纵向打印文本。 95 | public CPCLPrintCommand Text270(string font, int size, int x, int y, string data) => WriteRawLine($"T270 {font} {size} {x} {y} {data}"); 96 | 97 | /// 98 | /// VTEXT 命令 99 | /// 100 | /// 字体名称/编号 101 | /// 字体的大小标识 102 | /// 横向起始位置 103 | /// 纵向起始位置 104 | /// 要打印的文本 105 | /// 逆时针旋转90度,纵向打印文本。 106 | public CPCLPrintCommand VText(string font, int size, int x, int y, string data) => WriteRawLine($"VT {font} {size} {x} {y} {data}"); 107 | 108 | /// 109 | /// FONT-GROUP 命令 110 | /// 111 | /// 字体组编号。最多可指定10个字体组。有效字体组范围是0至9. 112 | /// 字体名称/编号-字体的大小标识 113 | /// 字体组。 114 | /// 使用 FG 命令,用户可以将多 10 个预缩放字体文件分至一个组。然后,用户可在 TEXT 命令中指定字体组。如果 文本命令中使用了字体组,则打印机将使用字体组中指定的大字体,这将生成所需的文本数据,并仍保留在文本 标签的可用宽度范围内。在 TEXT 命令中进行指定时,{font} 参数将指定为 FG,而 {size} 参数则指定为 {fg}。请注 意,用户还可以在 CONCAT/ENCONCAT 命令中指定 FG 命令。 115 | /// 116 | public CPCLPrintCommand FontGroup(int fg, params (string fn, int fs)[] param) 117 | { 118 | var sb = string.Empty; 119 | foreach (var item in param) 120 | sb = $"{sb} {item.fn} {item.fs}"; 121 | return WriteRawLine($"FG {fg}{sb}"); 122 | } 123 | 124 | /// 125 | /// CONCAT 文本串联命令(横向) 126 | /// 127 | /// 横向起始位置 128 | /// 纵向起始位置 129 | /// 参数格式:字体名称-字体大小-偏移量-文本 130 | /// 使用文本串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。这项命令可以与可缩 放字体组合使用。请参见可缩放串联命令。 131 | public CPCLPrintCommand Concat(int x, int y, params string[] param) 132 | { 133 | WriteRawLine($"CONCAT {x} {y}"); 134 | foreach (var item in param) 135 | WriteRawLine($"{item}"); 136 | WriteRawLine("ENDCONCAT"); 137 | return this; 138 | } 139 | 140 | /// 141 | /// CONCAT 文本串联命令(横向) 142 | /// 143 | /// 横向起始位置 144 | /// 纵向起始位置 145 | /// 参数格式:字体名称-字体大小-偏移量-文本 146 | /// 使用文本串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。这项命令可以与可缩 放字体组合使用。请参见可缩放串联命令。 147 | public CPCLPrintCommand Concat(int x, int y, params (string font, int size, int offset, string data)[] param) 148 | { 149 | WriteRawLine($"CONCAT {x} {y}"); 150 | foreach (var item in param) 151 | WriteRawLine($"{item.font} {item.size} {item.offset} {item.data}"); 152 | WriteRawLine("ENDCONCAT"); 153 | return this; 154 | } 155 | 156 | /// 157 | /// VCONCAT 文本串联命令(纵向) 158 | /// 159 | /// 横向起始位置 160 | /// 纵向起始位置 161 | /// 参数格式:字体名称-字体大小-偏移量-文本 162 | /// 使用文本串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。这项命令可以与可缩 放字体组合使用。请参见可缩放串联命令。 163 | public CPCLPrintCommand VConcat(int x, int y, params string[] param) 164 | { 165 | WriteRawLine($"VCONCAT {x} {y}"); 166 | foreach (var item in param) 167 | WriteRawLine($"{item}"); 168 | WriteRawLine("ENDCONCAT"); 169 | return this; 170 | } 171 | 172 | /// 173 | /// VCONCAT 文本串联命令(纵向) 174 | /// 175 | /// 横向起始位置 176 | /// 纵向起始位置 177 | /// 参数格式:字体名称-字体大小-偏移量-文本 178 | /// 使用文本串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。这项命令可以与可缩 放字体组合使用。请参见可缩放串联命令。 179 | public CPCLPrintCommand VConcat(int x, int y, params (string font, int size, int offset, string data)[] param) 180 | { 181 | WriteRawLine($"VCONCAT {x} {y}"); 182 | foreach (var item in param) 183 | WriteRawLine($"{item.font} {item.size} {item.offset} {item.data}"); 184 | WriteRawLine("ENDCONCAT"); 185 | return this; 186 | } 187 | 188 | /// 189 | /// MULTILINE 命令 190 | /// 191 | /// 每行文本的单位高度 192 | /// 文本命令,TEXT、VTEXT 193 | /// 字体名称/编号 194 | /// 字体的大小标识 195 | /// 横向起始位置 196 | /// 纵向起始位置 197 | /// 要打印的文本 198 | /// 使用 MULTILINE (ML),可以以相同字体和行高打印多行文本。 199 | public CPCLPrintCommand MultiLine(int height, string textCmd, string font, int size, int x, int y, 200 | params string[] data) 201 | { 202 | WriteRawLine($"ML {height}"); 203 | WriteRawLine($"{textCmd} {font} {size} {x} {y}"); 204 | foreach (var item in data) 205 | WriteRawLine(item); 206 | WriteRawLine("ENDML"); 207 | return this; 208 | } 209 | 210 | /// 211 | /// COUNT 命令 212 | /// 213 | /// 递增值。任何整数值都不能超过20个字符。如果希望减小 TEXT/BARCODE 值,则可以在值前添加“-”符号。输出结果中将保值前导零。 214 | /// 215 | /// COUNT 命令可以用于打印多个标签,其中条码中编码的数字文本域或数字数据将针对每个标签依次递增或者递减。TEXT/BARCODE 命令字符串必须包含此数字数据,将其作为字符串的后若干字符。数字数据部分多可以包 含 20 个字符,且可以以‘-’符号作为前缀。增加或减少数字数据时不能以‘0’为增量或减量。前导零将予以保留。一个标签文件中多可使用三个 COUNT 命令。 递增/递减的数字数据包含在 TEXT 或 BARCODE 命令中,后面紧跟 COUNT 命令。 216 | /// 217 | public CPCLPrintCommand Count(int count) => WriteRawLine($"COUNT {count}"); 218 | 219 | /// 220 | /// SETMAG 命令。设置字体放大倍数 221 | /// 222 | /// 字体的宽度放大倍数。有效放大倍数为1到16。 223 | /// 字体的高度放大倍数。有效放大倍数为1到16。 224 | /// 225 | /// SETMAG 命令可将常驻字体放大指定的放大倍数。
226 | /// SETMAG 命令在标签打印后仍保持有效。这意味着要打印的下一标签将使用近设置的 SETMAG 值。要取消 SETMAG 值并使打印机可以 使用默认字体大小,请使用 SETMAG 命令,且放大倍数为 0,0。 227 | ///
228 | public CPCLPrintCommand SetMag(int w, int h) => WriteRawLine($"SETMAG {w} {h}"); 229 | 230 | /// 231 | /// SCALABLE-TEXT 命令(横向) 232 | /// 233 | /// 字体名称。缩放字体 234 | /// 字体宽度(点大小) 235 | /// 字体高度(点大小) 236 | /// 横向起始位置 237 | /// 纵向起始位置 238 | /// 要打印的文本 239 | /// 使用可缩放文本,用户可以打印任何字体大小的文本。通过指定 X 和 Y 两个方向上的字体大小,可以生成宽度或 高度经过“缩放”的字符。指定的字体大小和生成的文本将以 72 点,即 1 英寸(25.4 毫米)打印出来 240 | public CPCLPrintCommand ScalableText(string name, int width, int height, int x, int y, string data) => WriteRawLine($"ST {name} {width} {height} {x} {y} {data}"); 241 | 242 | /// 243 | /// VSCALABLE-TEXT 命令(纵向) 244 | /// 245 | /// 字体名称。缩放字体 246 | /// 字体宽度(点大小) 247 | /// 字体高度(点大小) 248 | /// 横向起始位置 249 | /// 纵向起始位置 250 | /// 要打印的文本 251 | /// 使用可缩放文本,用户可以打印任何字体大小的文本。通过指定 X 和 Y 两个方向上的字体大小,可以生成宽度或 高度经过“缩放”的字符。指定的字体大小和生成的文本将以 72 点,即 1 英寸(25.4 毫米)打印出来 252 | public CPCLPrintCommand VScalableText(string name, int width, int height, int x, int y, string data) => WriteRawLine($"VST {name} {width} {height} {x} {y} {data}"); 253 | 254 | /// 255 | /// SCALE-TO-FIT 命令(横向) 256 | /// 257 | /// 字体名称。缩放字体 258 | /// 窗口的单位宽度 259 | /// 窗口的单位高度 260 | /// 横向起始位置 261 | /// 纵向起始位置 262 | /// 要打印的文本 263 | /// SCALE-TO-FIT 命令可自动计算文本的比例,确保文本不超出窗口范围。 264 | public CPCLPrintCommand ScaleToFit(string name, int width, int height, int x, int y, string data) => WriteRawLine($"STF {name} {width} {height} {x} {y} {data}"); 265 | 266 | /// 267 | /// SCALE-TO-FIT 命令(纵向) 268 | /// 269 | /// 字体名称。缩放字体 270 | /// 窗口的单位宽度 271 | /// 窗口的单位高度 272 | /// 横向起始位置 273 | /// 纵向起始位置 274 | /// 要打印的文本 275 | /// SCALE-TO-FIT 命令可自动计算文本的比例,确保文本不超出窗口范围。 276 | public CPCLPrintCommand VScaleToFit(string name, int width, int height, int x, int y, string data) => WriteRawLine($"VSTF {name} {width} {height} {x} {y} {data}"); 277 | 278 | /// 279 | /// SCALABLE-CONCATENATION 命令(横向) 280 | /// 281 | /// 横向起始位置 282 | /// 纵向起始位置 283 | /// 参数:字体名称-字体宽度-字体高度-偏移量-文本 284 | /// 使用可缩放串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。可缩放和位图文本 组合到 CONCAT/ENCONCAT 命令中 285 | public CPCLPrintCommand ScalableConcat(int x, int y, params (string name, int width, int height, int offset, string data)[] param) 286 | { 287 | WriteRawLine($"CONCAT {x} {y}"); 288 | foreach (var item in param) 289 | WriteRawLine($"ST {item.name} {item.width} {item.height} {item.offset} {item.data}"); 290 | WriteRawLine("ENDCONCAT"); 291 | return this; 292 | } 293 | 294 | /// 295 | /// SCALABLE-CONCATENATION 命令(纵向) 296 | /// 297 | /// 横向起始位置 298 | /// 纵向起始位置 299 | /// 参数:字体名称-字体宽度-字体高度-偏移量-文本 300 | /// 使用可缩放串联,可以为字符串分配不同的字符样式,在同一文本行上使用统一间距进行打印。可缩放和位图文本 组合到 CONCAT/ENCONCAT 命令中 301 | public CPCLPrintCommand VScalableConcat(int x, int y, params (string name, int width, int height, int offset, string data)[] param) 302 | { 303 | WriteRawLine($"VCONCAT {x} {y}"); 304 | foreach (var item in param) 305 | WriteRawLine($"ST {item.name} {item.width} {item.height} {item.offset} {item.data}"); 306 | WriteRawLine("ENDCONCAT"); 307 | return this; 308 | } 309 | 310 | /// 311 | /// ROTATE 命令 312 | /// 313 | /// 旋转角度 314 | /// ROTATE 命令用于以指定角度旋转所有后续可缩放文本域。旋转方向为以文本中心点为中心逆时针。在发出下一个 ROTATE 命令前,前一个旋转一直有效。默认角度为零度。 315 | public CPCLPrintCommand Rotate(int angle) => WriteRawLine($"R {angle}"); 316 | 317 | /// 318 | /// SETBOLD 命令 319 | /// 320 | /// 值。介于 0 到 5 之间的偏移量。 321 | /// SETBOLD 命令可使文本加粗并且稍微加宽。SETBOLD 命令会采用一个操作数来设置文本变黑的程度。 322 | public CPCLPrintCommand SetBold(int value) => WriteRawLine($"SETBOLD {value}"); 323 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/CPCLPrintCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Bing.EasyPrint.Core; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace Bing.EasyPrint.CPCL; 6 | 7 | /// 8 | /// CPCL 打印命令 9 | /// 10 | // ReSharper disable once InconsistentNaming 11 | public partial class CPCLPrintCommand : IPrintCommand, IPrintComponent 12 | { 13 | /// 14 | /// 缓冲区写入器 15 | /// 16 | internal IBufferWriter Writer { get; private set; } 17 | 18 | /// 19 | /// 命令内容 20 | /// 21 | internal PrintCommandStruct Content { get; } 22 | 23 | /// 24 | /// CPCL命令信息 25 | /// 26 | public CPCLCommandInfo CommandInfo { get; internal set; } 27 | 28 | /// 29 | /// 初始化一个类型的实例 30 | /// 31 | public CPCLPrintCommand() : this(System.Text.Encoding.GetEncoding("gbk")) { } 32 | 33 | /// 34 | /// 初始化一个类型的实例 35 | /// 36 | /// 编码方式 37 | public CPCLPrintCommand(Encoding encoding) 38 | { 39 | Writer = new BufferWriter(encoding); 40 | CommandInfo = new CPCLCommandInfo(); 41 | Content = new PrintCommandStruct(); 42 | } 43 | 44 | /// 45 | /// 初始化 46 | /// 47 | /// 宽度 48 | /// 高度 49 | internal CPCLPrintCommand Init(int width, int height) 50 | { 51 | CommandInfo = new CPCLCommandInfo {Width = width, Height = height}; 52 | Writer.Clear(); 53 | Content.Clear(); 54 | return this; 55 | } 56 | 57 | /// 58 | /// 写入命令 59 | /// 60 | /// 命令 61 | public CPCLPrintCommand WriteRaw(string raw) 62 | { 63 | Content.AddRaw(raw); 64 | return this; 65 | } 66 | 67 | /// 68 | /// 写入命令并换行 69 | /// 70 | /// 命令 71 | public CPCLPrintCommand WriteRawLine(string raw) 72 | { 73 | Content.AddRawLine(raw); 74 | return this; 75 | } 76 | 77 | /// 78 | /// 构建命令 79 | /// 80 | public IBufferWriter Build() 81 | { 82 | Content.SafeInit(CommandInfo); 83 | Content.Build(this); 84 | return Writer; 85 | } 86 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/Barcode1DComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint.CPCL; 4 | 5 | /// 6 | /// 一维条码组件 7 | /// 8 | internal class Barcode1DComponent : ComponentMetadata 9 | { 10 | /// 11 | /// 高度 12 | /// 13 | public int Height { get; set; } 14 | 15 | /// 16 | /// 窄条的单位宽度 17 | /// 18 | public int LineWidth { get; set; } 19 | 20 | /// 21 | /// 宽条与窄条的比率 22 | /// 23 | public int Ratio { get; set; } = 1; 24 | 25 | /// 26 | /// 旋转角度 27 | /// 28 | public int Rotate { get; set; } 29 | 30 | /// 31 | /// 条码内容 32 | /// 33 | public string Text { get; set; } 34 | 35 | /// 36 | /// 条码类型 37 | /// 38 | public string Type { get; set; } 39 | 40 | /// 41 | /// 条码起始x坐标 42 | /// 43 | public int X { get; set; } 44 | 45 | /// 46 | /// 条码起始y坐标 47 | /// 48 | public int Y { get; set; } 49 | 50 | /// 51 | /// 构建 52 | /// 53 | /// 打印命令 54 | public override void Build(CPCLPrintCommand command) 55 | { 56 | var coordinate = Helper.GetBarcodeCoordinate(this); 57 | var cmd = Helper.GetBarcodeRotateCommand(Rotate); 58 | command.Writer.WriteLine($"{cmd} {Type} {LineWidth} {Ratio} {Height} {coordinate.x} {coordinate.y} {Text}"); 59 | } 60 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/BoxComponent.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 矩形组件 6 | /// 7 | internal class BoxComponent : ComponentMetadata 8 | { 9 | /// 10 | /// 线条宽度 11 | /// 12 | public int Width { get; set; } 13 | 14 | /// 15 | /// 矩形框左上角x坐标 16 | /// 17 | public int X0 { get; set; } 18 | 19 | /// 20 | /// 矩形框右下角x坐标 21 | /// 22 | public int X1 { get; set; } 23 | 24 | /// 25 | /// 矩形框左上角y坐标 26 | /// 27 | public int Y0 { get; set; } 28 | 29 | /// 30 | /// 矩形框右下角y坐标 31 | /// 32 | public int Y1 { get; set; } 33 | 34 | /// 35 | /// 构建 36 | /// 37 | /// 打印命令 38 | public override void Build(CPCLPrintCommand command) => command.Writer.WriteLine($"BOX {X0} {Y0} {X1} {Y1} {Width}"); 39 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/DashLineComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint.CPCL; 4 | 5 | /// 6 | /// 虚线组件 7 | /// 8 | internal class DashLineComponent : LineComponent 9 | { 10 | /// 11 | /// 构建 12 | /// 13 | /// 打印命令 14 | public override void Build(CPCLPrintCommand command) 15 | { 16 | command.Writer.WriteLine("SETMAG 1 1"); 17 | for (var i = 0; i < X1; i = ((i + 16) - 1) + 1) 18 | command.Writer.WriteLine($"T 24 0 {X0 + i} {Y0 - 10} -"); 19 | command.Writer.WriteLine("SETMAG 0 0"); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/ImageComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Numerics; 4 | using SixLabors.ImageSharp; 5 | using SixLabors.ImageSharp.Drawing.Processing; 6 | using SixLabors.ImageSharp.Formats.Bmp; 7 | using SixLabors.ImageSharp.PixelFormats; 8 | using SixLabors.ImageSharp.Processing; 9 | using SixLabors.ImageSharp.Processing.Processors.Dithering; 10 | using SixLabors.ImageSharp.Processing.Processors.Quantization; 11 | 12 | // ReSharper disable once CheckNamespace 13 | namespace Bing.EasyPrint.CPCL; 14 | 15 | /// 16 | /// 图片组件 17 | /// 18 | internal class ImageComponent : ComponentMetadata 19 | { 20 | /// 21 | /// 旋转角度 22 | /// 23 | public int Rotate { get; set; } 24 | 25 | /// 26 | /// 图片起始x坐标 27 | /// 28 | public int X { get; set; } 29 | 30 | /// 31 | /// 图片起始y坐标 32 | /// 33 | public int Y { get; set; } 34 | 35 | /// 36 | /// 图片数据 37 | /// 38 | public byte[] Data { get; private set; } 39 | 40 | /// 41 | /// 宽度 42 | /// 43 | public int Width { get; private set; } 44 | 45 | /// 46 | /// 高度 47 | /// 48 | public int Height { get; private set; } 49 | 50 | /// 51 | /// 初始化一个类型的实例 52 | /// 53 | private ImageComponent() { } 54 | 55 | /// 56 | /// 构建 57 | /// 58 | /// 打印命令 59 | public override void Build(CPCLPrintCommand command) 60 | { 61 | var byteCountW = (Width + 7) / 8; 62 | var data = ToHex(Data); 63 | var cmd = Helper.GetImageRotateCommand(Rotate); 64 | command.Writer.WriteLine($"{cmd} {byteCountW} {Height} {X} {Y} {data}"); 65 | } 66 | 67 | /// 68 | /// 初始化位置 69 | /// 70 | /// 图片起始x坐标 71 | /// 图片起始y坐标 72 | public ImageComponent InitPosition(int x, int y) 73 | { 74 | X = x; 75 | Y = y; 76 | return this; 77 | } 78 | 79 | /// 80 | /// 通过文件路径创建图片组件 81 | /// 82 | /// 文件地址 83 | public static ImageComponent CreateFromFile(string fileUrl) 84 | { 85 | using (var image = Image.Load(fileUrl)) 86 | { 87 | return new ImageComponent 88 | { 89 | Width = image.Width, 90 | Height = image.Height, 91 | Data = GetImageData(image) 92 | }; 93 | } 94 | } 95 | 96 | /// 97 | /// 通过流创建图片组件 98 | /// 99 | /// 流 100 | public static ImageComponent CreateFromStream(Stream stream) 101 | { 102 | using (var image = Image.Load(stream)) 103 | { 104 | return new ImageComponent 105 | { 106 | Width = image.Width, 107 | Height = image.Height, 108 | Data = GetImageData(image) 109 | }; 110 | } 111 | } 112 | 113 | /// 114 | /// 通过字节数组创建图片组件 115 | /// 116 | /// 字节数组 117 | public static ImageComponent CreateFromBytes(byte[] bytes) 118 | { 119 | using (var ms = new MemoryStream(bytes)) 120 | return CreateFromStream(ms); 121 | } 122 | 123 | /// 124 | /// 通过图片创建图片组件 125 | /// 126 | /// 图片 127 | public static ImageComponent CreateFromImage(Image image) 128 | { 129 | return new ImageComponent 130 | { 131 | Width = image.Width, 132 | Height = image.Height, 133 | Data = GetImageData(image) 134 | }; 135 | } 136 | 137 | /// 138 | /// 获取图片数据 139 | /// 140 | /// 图片 141 | private static byte[] GetImageData(Image image) 142 | { 143 | var encoder = new BmpEncoder 144 | { 145 | BitsPerPixel = BmpBitsPerPixel.Pixel1, 146 | Quantizer = new OctreeQuantizer(new QuantizerOptions 147 | { 148 | MaxColors = 2, 149 | }) 150 | }; 151 | var width = image.Width; 152 | var height = image.Height; 153 | var rowRealBytesCount = width % 8 > 0 ? width / 8 + 1 : width / 8; 154 | var rowSize = ((width + 31) >> 5) << 2; 155 | var dstStream = new MemoryStream(); 156 | byte[] result = null; 157 | 158 | try 159 | { 160 | image.Mutate(x => 161 | { 162 | x.Grayscale(GrayscaleMode.Bt601); 163 | x.BinaryDither(ErrorDither.FloydSteinberg); 164 | }); 165 | image.SaveAsBmp(dstStream, encoder); 166 | var dstBuffer = dstStream.ToArray(); 167 | 168 | var bfOffBits = BitConverter.ToInt32(dstBuffer, 10); 169 | result = new byte[height * rowRealBytesCount]; 170 | 171 | // 读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。 172 | for (var i = 0; i < height; i++) 173 | Array.Copy(dstBuffer, bfOffBits + (height - 1 - i) * rowSize, result, i * rowRealBytesCount, 174 | rowRealBytesCount); 175 | // 结果数据处理 176 | for (var i = 0; i < result.Length; i++) 177 | result[i] ^= 0xFF; 178 | } 179 | finally 180 | { 181 | dstStream?.Dispose(); 182 | } 183 | return result; 184 | } 185 | 186 | /// 187 | /// 转换为16进制 188 | /// 189 | /// 数 190 | private static string ToHex(byte[] data) => BitConverter.ToString(data).Replace("-", string.Empty); 191 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/LineComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint.CPCL; 4 | 5 | /// 6 | /// 线条组件 7 | /// 8 | internal class LineComponent : ComponentMetadata 9 | { 10 | /// 11 | /// 线条宽度 12 | /// 13 | public int Width { get; set; } 14 | 15 | /// 16 | /// 线条起始点x坐标 17 | /// 18 | public int X0 { get; set; } 19 | 20 | /// 21 | /// 线条结束点x坐标 22 | /// 23 | public int X1 { get; set; } 24 | 25 | /// 26 | /// 线条起始点y坐标 27 | /// 28 | public int Y0 { get; set; } 29 | 30 | /// 31 | /// 线条结束点y坐标 32 | /// 33 | public int Y1 { get; set; } 34 | 35 | /// 36 | /// 构建 37 | /// 38 | /// 打印命令 39 | public override void Build(CPCLPrintCommand command) => command.Writer.WriteLine($"LINE {X0} {Y0} {X1} {Y1} {Width}"); 40 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/QRCodeComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint.CPCL; 4 | 5 | /// 6 | /// 二维码组件 7 | /// 8 | // ReSharper disable once InconsistentNaming 9 | internal class QRCodeComponent : ComponentMetadata 10 | { 11 | /// 12 | /// 二维码纠错级别 13 | /// 14 | public string ErrorLevel { get; set; } 15 | 16 | /// 17 | /// 旋转角度 18 | /// 19 | public int Rotate { get; set; } 20 | 21 | /// 22 | /// 尺寸 23 | /// 24 | public int Size { get; set; } 25 | 26 | /// 27 | /// 二维码起始x坐标 28 | /// 29 | public int X { get; set; } 30 | 31 | /// 32 | /// 二维码起始y坐标 33 | /// 34 | public int Y { get; set; } 35 | 36 | /// 37 | /// 二维码内容 38 | /// 39 | public string Text { get; set; } 40 | 41 | /// 42 | /// 构建 43 | /// 44 | /// 打印命令 45 | public override void Build(CPCLPrintCommand command) 46 | { 47 | var coordinate = Helper.GetBarcodeCoordinate(this); 48 | var cmd = Helper.GetBarcodeRotateCommand(Rotate); 49 | command.Writer.WriteLine($"{cmd} QR {coordinate.x} {coordinate.y} M 2 U {Size}"); 50 | command.Writer.WriteLine($"{ErrorLevel}A,{Text}"); 51 | command.Writer.WriteLine("ENDQR"); 52 | } 53 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/SplitLineComponent.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 分割线组件 6 | /// 7 | internal class SplitLineComponent : ComponentMetadata 8 | { 9 | /// 10 | /// 线条起始x坐标 11 | /// 12 | public int X { get; set; } 13 | 14 | /// 15 | /// 线条起始y坐标 16 | /// 17 | public int Y { get; set; } 18 | 19 | /// 20 | /// 分割符 21 | /// 22 | public char Symbol { get; set; } = '-'; 23 | 24 | /// 25 | /// 构建 26 | /// 27 | /// 打印命令 28 | public override void Build(CPCLPrintCommand command) 29 | { 30 | var lineMaxLength = Helper.GetLineMaxLength(command.CommandInfo.Width - X, Symbol > 127 ? 24 : 12); 31 | var line = new string(Symbol, lineMaxLength); 32 | command.Writer.WriteLine("SETMAG 1 1"); 33 | command.Writer.WriteLine($"T 24 0 {X} {Y} {line}"); 34 | command.Writer.WriteLine("SETMAG 0 0"); 35 | } 36 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Components/TextComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint.CPCL; 4 | 5 | /// 6 | /// 文本组件 7 | /// 8 | internal class TextComponent : ComponentMetadata 9 | { 10 | /// 11 | /// 是否加粗 12 | /// 13 | public bool Bold { get; set; } 14 | 15 | /// 16 | /// 字体大小 17 | /// 18 | public int FontSize { get; set; } 19 | 20 | /// 21 | /// 字体缩放 22 | /// 23 | public int FontZoom { get; set; } 24 | 25 | /// 26 | /// 是否反显 27 | /// 28 | public bool Reverse { get; set; } 29 | 30 | /// 31 | /// 旋转角度 32 | /// 33 | public int Rotate { get; set; } 34 | 35 | /// 36 | /// 内容 37 | /// 38 | public string Text { get; set; } 39 | 40 | /// 41 | /// 文字起始x坐标 42 | /// 43 | public int X { get; set; } 44 | 45 | /// 46 | /// 文字起始y坐标 47 | /// 48 | public int Y { get; set; } 49 | 50 | /// 51 | /// 是否下划线 52 | /// 53 | public bool Underline { get; set; } 54 | 55 | /// 56 | /// 构建 57 | /// 58 | /// 打印命令 59 | public override void Build(CPCLPrintCommand command) 60 | { 61 | AddUnderline(command, true); 62 | AddBold(command, true); 63 | 64 | var computeFontSizeResult = Helper.ComputeFontSize(FontSize); 65 | command.Writer.WriteLine($"SETMAG {computeFontSizeResult.scale} {computeFontSizeResult.scale}"); 66 | 67 | AddText(command, computeFontSizeResult.font, computeFontSizeResult.size); 68 | AddInverseLine(command, computeFontSizeResult.size); 69 | AddBold(command, false); 70 | AddUnderline(command, false); 71 | command.Writer.WriteLine($"SETMAG 0 0"); 72 | } 73 | 74 | /// 75 | /// 添加下划线 76 | /// 77 | /// 打印命令 78 | /// 是否开标签 79 | private void AddUnderline(CPCLPrintCommand command, bool isOpen) 80 | { 81 | if (!Underline) 82 | return; 83 | if (isOpen) 84 | { 85 | command.Writer.WriteLine("UNDERLINE ON"); 86 | return; 87 | } 88 | command.Writer.WriteLine("UNDERLINE OFF"); 89 | } 90 | 91 | /// 92 | /// 添加粗体 93 | /// 94 | /// 打印命令 95 | /// 是否开标签 96 | private void AddBold(CPCLPrintCommand command, bool isOpen) 97 | { 98 | if (!Bold) 99 | return; 100 | if (isOpen) 101 | { 102 | command.Writer.WriteLine("SETBOLD 1"); 103 | return; 104 | } 105 | command.Writer.WriteLine("SETBOLD 0"); 106 | } 107 | 108 | /// 109 | /// 添加文本 110 | /// 111 | /// 打印命令 112 | /// 字体 113 | /// 字体大小 114 | private void AddText(CPCLPrintCommand command, int font, int size) 115 | { 116 | var cmd = Helper.GetTextRotateCommand(Rotate); 117 | command.Writer.WriteLine($"{cmd} {font} {size} {X} {Y} {Text}"); 118 | } 119 | 120 | /// 121 | /// 添加黑白反显 122 | /// 123 | /// 打印命令 124 | /// 大小 125 | private void AddInverseLine(CPCLPrintCommand command, int size) 126 | { 127 | if (!Reverse) 128 | return; 129 | command.Writer.WriteLine($"IL {X} {Y} {X + size / 2 * Text.Length} {Y} {size}"); 130 | } 131 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Helper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Bing.EasyPrint.CPCL; 5 | 6 | /// 7 | /// 命令生成辅助操作 8 | /// 9 | internal static class Helper 10 | { 11 | /// 12 | /// 获取文本旋转命令 13 | /// 14 | /// 旋转角度 15 | public static string GetTextRotateCommand(int rotate) 16 | { 17 | switch (rotate) 18 | { 19 | case 0: 20 | return "T"; 21 | case 90: 22 | return "T90"; 23 | case 180: 24 | return "T180"; 25 | case 270: 26 | return "T270"; 27 | default: 28 | return "T"; 29 | } 30 | } 31 | 32 | /// 33 | /// 计算字体大小 34 | /// 35 | /// 字体大小 36 | public static (int font, int size, int scale) ComputeFontSize(int fontSize) 37 | { 38 | switch (fontSize) 39 | { 40 | case 16: 41 | return (55, 0, 1); 42 | case 24: 43 | return (24, 0, 1); 44 | case 32: 45 | return (55, 0, 2); 46 | case 48: 47 | return (24, 0, 2); 48 | case 64: 49 | return (55, 0, 4); 50 | case 72: 51 | return (24, 0, 3); 52 | case 80: 53 | return (55, 0, 5); 54 | case 96: 55 | return (24, 0, 4); 56 | case 112: 57 | return (55, 0, 7); 58 | case 120: 59 | return (24, 0, 5); 60 | case 128: 61 | return (55, 0, 8); 62 | case 144: 63 | return (24, 0, 6); 64 | case 160: 65 | return (55, 0, 10); 66 | case 168: 67 | return (24, 0, 7); 68 | case 176: 69 | return (55, 0, 11); 70 | case 192: 71 | return (24, 0, 8); 72 | case 208: 73 | return (55, 0, 13); 74 | case 216: 75 | return (24, 0, 9); 76 | case 224: 77 | return (55, 0, 14); 78 | case 240: 79 | return (24, 0, 10); 80 | case 256: 81 | return (55, 0, 16); 82 | case 264: 83 | return (24, 0, 11); 84 | case 288: 85 | return (24, 0, 12); 86 | case 312: 87 | return (24, 0, 13); 88 | case 336: 89 | return (24, 0, 14); 90 | case 360: 91 | return (24, 0, 15); 92 | case 384: 93 | return (24, 0, 16); 94 | default: 95 | return (55, 0, 1); 96 | } 97 | } 98 | 99 | /// 100 | /// 转换样式 101 | /// 102 | /// 样式 103 | public static (bool bold, bool underline) ConvertStyle(int style) 104 | { 105 | switch (style) 106 | { 107 | case 1: 108 | case 3: 109 | return (true, false); 110 | case 4: 111 | case 6: 112 | return (false, true); 113 | case 5: 114 | case 7: 115 | return (true, true); 116 | default: 117 | return (false, false); 118 | } 119 | } 120 | 121 | /// 122 | /// 获取条码旋转命令 123 | /// 124 | /// 旋转角度 125 | public static string GetBarcodeRotateCommand(int rotate) 126 | { 127 | switch (rotate) 128 | { 129 | case 0: 130 | case 180: 131 | return "B"; 132 | case 90: 133 | case 270: 134 | return "VB"; 135 | default: 136 | return "B"; 137 | } 138 | } 139 | 140 | /// 141 | /// 获取条码起始坐标 142 | /// 143 | /// 条码明细 144 | public static (int x, int y) GetBarcodeCoordinate(Barcode1DComponent item) => GetBarcodeCoordinate(item.Rotate, item.X, item.Y, 0, item.Height); 145 | 146 | /// 147 | /// 获取条码起始坐标 148 | /// 149 | /// 二维码明细 150 | public static (int x, int y) GetBarcodeCoordinate(QRCodeComponent item) => GetBarcodeCoordinate(item.Rotate, item.X, item.Y, 0, 0); 151 | 152 | /// 153 | /// 获取条码起始坐标 154 | /// 155 | /// 旋转角度 156 | /// x轴起始坐标 157 | /// y轴起始坐标 158 | /// 宽度 159 | /// 高度 160 | public static (int x, int y) GetBarcodeCoordinate(int rotate, int x, int y, int width, int height) 161 | { 162 | switch (rotate) 163 | { 164 | case 180: 165 | x -= width; 166 | y -= height; 167 | break; 168 | case 270: 169 | x -= height; 170 | y += width; 171 | break; 172 | } 173 | return (x, y); 174 | } 175 | 176 | /// 177 | /// 转换二维码纠错级别 178 | /// 179 | /// 二维码纠错级别 180 | public static string ConvertErrorLevel(int level) 181 | { 182 | switch (level) 183 | { 184 | case 0: 185 | return "L"; 186 | case 1: 187 | return "M"; 188 | case 2: 189 | return "Q"; 190 | default: 191 | return "H"; 192 | } 193 | } 194 | 195 | /// 196 | /// 是否中文字符串 197 | /// 198 | /// 值 199 | public static bool IsChinese(char value) => Regex.IsMatch(value.ToString(), "^[一-龥]$"); 200 | 201 | /// 202 | /// 转换条码类型 203 | /// 204 | /// 条码类型 205 | public static string ConvertBarcodeType(BarcodeType type) 206 | { 207 | switch (type) 208 | { 209 | case BarcodeType.Code128: 210 | return "128"; 211 | case BarcodeType.Code39: 212 | return "39"; 213 | case BarcodeType.Code93: 214 | return "93"; 215 | case BarcodeType.Codabar: 216 | return "CODABAR"; 217 | case BarcodeType.Ean8: 218 | return "EAN8"; 219 | case BarcodeType.Ean13: 220 | return "EAN13"; 221 | case BarcodeType.UpcA: 222 | return "UPCA"; 223 | case BarcodeType.UpcE: 224 | return "UPCE"; 225 | case BarcodeType.I2OF5: 226 | return "I2OF5"; 227 | case BarcodeType.I2OF5C: 228 | return "I2OF5C"; 229 | case BarcodeType.I2OF5G: 230 | return "I20F5G"; 231 | case BarcodeType.UccEan128: 232 | return "UCCEAN128"; 233 | case BarcodeType.Msi: 234 | return "MSI"; 235 | case BarcodeType.Postnet: 236 | return "POSTNET"; 237 | case BarcodeType.Fim: 238 | return "FIM"; 239 | } 240 | throw new NotImplementedException($"未实现条码类型 {type.ToString()} "); 241 | } 242 | 243 | /// 244 | /// 获取图片旋转命令 245 | /// 246 | /// 旋转角度 247 | public static string GetImageRotateCommand(int rotate) 248 | { 249 | switch (rotate) 250 | { 251 | case 0: 252 | case 180: 253 | return "EG"; 254 | case 90: 255 | case 270: 256 | return "VEG"; 257 | default: 258 | return "EG"; 259 | } 260 | } 261 | 262 | /// 263 | /// 获取一行最大字符数。 264 | /// 58mm票据打印机:一行可打印16个汉字,32个字符;80mm票据打印机,一行可打印24个汉字,48个字符;421D标签打印机,一行可打印34个汉字,69个字符。 265 | /// 266 | /// 宽度 267 | /// 字体大小 268 | public static int GetLineMaxLength(int width, int fontSize) => width / fontSize; 269 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Metadata/ComponentMetadata.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 组件 - 元数据 6 | /// 7 | internal abstract class ComponentMetadata : MetadataBase 8 | { 9 | /// 10 | /// 元数据类型 11 | /// 12 | public override MetadataType MetadataType => MetadataType.Component; 13 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Metadata/MetadataBase.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 元数据基类 6 | /// 7 | internal abstract class MetadataBase 8 | { 9 | /// 10 | /// 元数据类型 11 | /// 12 | public abstract MetadataType MetadataType { get; } 13 | 14 | /// 15 | /// 构建 16 | /// 17 | /// 打印命令 18 | public abstract void Build(CPCLPrintCommand command); 19 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Metadata/MetadataType.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 元数据类型 6 | /// 7 | internal enum MetadataType 8 | { 9 | /// 10 | /// 命令 11 | /// 12 | Raw = 0, 13 | /// 14 | /// 组件 15 | /// 16 | Component = 1 17 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/CPCL/Metadata/RawMetadata.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint.CPCL; 3 | 4 | /// 5 | /// 命令 - 元数据 6 | /// 7 | internal class RawMetadata : MetadataBase 8 | { 9 | /// 10 | /// 元数据类型 11 | /// 12 | public override MetadataType MetadataType => MetadataType.Raw; 13 | 14 | /// 15 | /// 命令 16 | /// 17 | public string Raw { get; } 18 | 19 | /// 20 | /// 是否换行 21 | /// 22 | public bool NewLine { get; } 23 | 24 | /// 25 | /// 初始化一个类型的实例 26 | /// 27 | /// 原始命令 28 | public RawMetadata(string raw) : this(raw, false) { } 29 | 30 | /// 31 | /// 初始化一个类型的实例 32 | /// 33 | /// 命令 34 | /// 是否换行 35 | public RawMetadata(string raw, bool newLine) 36 | { 37 | Raw = raw; 38 | NewLine = newLine; 39 | } 40 | 41 | /// 42 | /// 构建 43 | /// 44 | /// 打印命令 45 | public override void Build(CPCLPrintCommand command) 46 | { 47 | if (NewLine) 48 | command.Writer.WriteLine(Raw); 49 | else 50 | command.Writer.Write(Raw); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Core/BufferWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Bing.EasyPrint.Core; 6 | 7 | /// 8 | /// 缓冲区写入器 9 | /// 10 | internal class BufferWriter : IBufferWriter 11 | { 12 | /// 13 | /// 字节缓冲区 14 | /// 15 | private readonly List _buffer; 16 | 17 | /// 18 | /// 原始命令 19 | /// 20 | private readonly List _sources; 21 | 22 | /// 23 | /// 字符编码 24 | /// 25 | private readonly Encoding _encoding; 26 | 27 | /// 28 | /// 初始化一个类型的实例 29 | /// 30 | /// 字符编码 31 | public BufferWriter(Encoding encoding) 32 | { 33 | _encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); 34 | _buffer = new List(); 35 | _sources = new List(); 36 | } 37 | 38 | /// 39 | /// 写入 40 | /// 41 | /// 字节数组 42 | public IBufferWriter Write(byte[] value) 43 | { 44 | if (value == null) 45 | return this; 46 | _buffer.AddRange(value); 47 | return this; 48 | } 49 | 50 | /// 51 | /// 写入 52 | /// 53 | /// 字符串 54 | public IBufferWriter Write(string value) 55 | { 56 | if (string.IsNullOrEmpty(value)) 57 | return this; 58 | var bytes = _encoding.GetBytes(value); 59 | _buffer.AddRange(bytes); 60 | _sources.Add(value); 61 | return this; 62 | } 63 | 64 | /// 65 | /// 清空内容 66 | /// 67 | public IBufferWriter Clear() 68 | { 69 | _buffer.Clear(); 70 | _sources.Clear(); 71 | return this; 72 | } 73 | 74 | /// 75 | /// 获取二进制数组 76 | /// 77 | public byte[] GetBytes() => _buffer.ToArray(); 78 | 79 | /// 80 | /// 输出字符串 81 | /// 82 | public override string ToString() 83 | { 84 | if (_sources.Count == 0) 85 | return string.Empty; 86 | var result = new StringBuilder(); 87 | foreach (var command in _sources) 88 | result.Append(command); 89 | return result.ToString(); 90 | } 91 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/DefaultEasyPrint.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint; 2 | 3 | /// 4 | /// 默认简单打印 5 | /// 6 | public class DefaultEasyPrint : IEasyPrint 7 | { 8 | /// 9 | /// 创建打印命令 10 | /// 11 | /// 打印命令类型 12 | public T CreateCommand() where T : IPrintCommand, new() => new T(); 13 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/BarcodeType.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 条码类型 6 | /// 7 | public enum BarcodeType 8 | { 9 | /// 10 | /// CODE 128 11 | /// 12 | Code128 = 0, 13 | /// 14 | /// CODE 39 15 | /// 16 | Code39 = 1, 17 | /// 18 | /// CODE 93 19 | /// 20 | Code93 = 2, 21 | /// 22 | /// Codabar 23 | /// 24 | Codabar = 3, 25 | /// 26 | /// EAN-8 27 | /// 28 | Ean8 = 4, 29 | /// 30 | /// EAN-13 31 | /// 32 | Ean13 = 5, 33 | /// 34 | /// UPC-A 35 | /// 36 | UpcA = 6, 37 | /// 38 | /// UPC-E 39 | /// 40 | UpcE = 7, 41 | /// 42 | /// I2OF5 43 | /// 44 | // ReSharper disable once InconsistentNaming 45 | I2OF5 = 8, 46 | /// 47 | /// I2OF5C 48 | /// 49 | // ReSharper disable once InconsistentNaming 50 | I2OF5C = 9, 51 | /// 52 | /// I2OF5G 53 | /// 54 | // ReSharper disable once InconsistentNaming 55 | I2OF5G = 10, 56 | /// 57 | /// UCCEAN128 58 | /// 59 | UccEan128 = 11, 60 | /// 61 | /// MSI 62 | /// 63 | Msi = 12, 64 | /// 65 | /// POSTNET 66 | /// 67 | Postnet = 13, 68 | /// 69 | /// FIM 70 | /// 71 | Fim = 14 72 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/FontSize.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 字体大小 6 | /// 7 | public enum FontSize 8 | { 9 | /// 10 | /// 16号字体 11 | /// 12 | Size16 = 16, 13 | /// 14 | /// 24号字体 15 | /// 16 | Size24 = 24, 17 | /// 18 | /// 32号字体 19 | /// 20 | Size32 = 32, 21 | /// 22 | /// 48号字体 23 | /// 24 | Size48 = 48, 25 | /// 26 | /// 64号字体 27 | /// 28 | Size64 = 64, 29 | /// 30 | /// 72号字体 31 | /// 32 | Size72 = 72, 33 | /// 34 | /// 80号字体 35 | /// 36 | Size80 = 80, 37 | /// 38 | /// 96号字体 39 | /// 40 | Size96 = 96, 41 | /// 42 | /// 112号字体 43 | /// 44 | Size112 = 112, 45 | /// 46 | /// 120号字体 47 | /// 48 | Size120 = 120, 49 | /// 50 | /// 128号字体 51 | /// 52 | Size128 = 128, 53 | /// 54 | /// 144号字体 55 | /// 56 | Size144 = 144, 57 | /// 58 | /// 160号字体 59 | /// 60 | Size160 = 160, 61 | /// 62 | /// 168号字体 63 | /// 64 | Size168 = 168, 65 | /// 66 | /// 176号字体 67 | /// 68 | Size176 = 176, 69 | /// 70 | /// 192号字体 71 | /// 72 | Size192 = 192, 73 | /// 74 | /// 208号字体 75 | /// 76 | Size208 = 208, 77 | /// 78 | /// 216号字体 79 | /// 80 | Size216 = 216, 81 | /// 82 | /// 224号字体 83 | /// 84 | Size224 = 224, 85 | /// 86 | /// 240号字体 87 | /// 88 | Size240 = 240, 89 | /// 90 | /// 256号字体 91 | /// 92 | Size256 = 256, 93 | /// 94 | /// 264号字体 95 | /// 96 | Size264 = 264, 97 | /// 98 | /// 288号字体 99 | /// 100 | Size288 = 288, 101 | /// 102 | /// 312号字体 103 | /// 104 | Size312 = 312, 105 | /// 106 | /// 336号字体 107 | /// 108 | Size336 = 336, 109 | /// 110 | /// 360号字体 111 | /// 112 | Size360 = 360, 113 | /// 114 | /// 384号字体 115 | /// 116 | Size384 = 384, 117 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/LineStyle.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 线条样式 6 | /// 7 | public enum LineStyle 8 | { 9 | /// 10 | /// 实线 11 | /// 12 | Full = 0, 13 | /// 14 | /// 虚线 15 | /// 16 | Dotted = 1 17 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/PrintColor.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 打印颜色 6 | /// 7 | public enum PrintColor 8 | { 9 | /// 10 | /// 黑字白底 11 | /// 12 | Black = 0, 13 | /// 14 | /// 白字黑底 15 | /// 16 | White = 1 17 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/PrintOrientation.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 打印方向 6 | /// 7 | public enum PrintOrientation 8 | { 9 | /// 10 | /// 正常 11 | /// 12 | None = 0, 13 | /// 14 | /// 下 15 | /// 16 | Down = 1, 17 | /// 18 | /// 左 19 | /// 20 | Left = 2, 21 | /// 22 | /// 右 23 | /// 24 | Right = 3 25 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/QrCodeCorrectionLevel.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 二维码纠错级别 6 | /// 7 | public enum QrCodeCorrectionLevel 8 | { 9 | /// 10 | /// 7%的字码可被修正 11 | /// 12 | L = 0, 13 | /// 14 | /// 15%的字码可被修正 15 | /// 16 | M = 1, 17 | /// 18 | /// 25%的字码可被修正 19 | /// 20 | Q = 2, 21 | /// 22 | /// 30%的字码可被修正 23 | /// 24 | H = 3, 25 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/QrCodeUnitSize.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 二维码单位尺寸 6 | /// 7 | public enum QrCodeUnitSize 8 | { 9 | /// 10 | /// 尺寸(1 x 1) 11 | /// 12 | Size1 = 1, 13 | /// 14 | /// 尺寸(2 x 2) 15 | /// 16 | Size2 = 2, 17 | /// 18 | /// 尺寸(3 x 3) 19 | /// 20 | Size3 = 3, 21 | /// 22 | /// 尺寸(4 x 4) 23 | /// 24 | Size4 = 4, 25 | /// 26 | /// 尺寸(5 x 5) 27 | /// 28 | Size5 = 5, 29 | /// 30 | /// 尺寸(6 x 6) 31 | /// 32 | Size6 = 6, 33 | /// 34 | /// 尺寸(7 x 7) 35 | /// 36 | Size7 = 7, 37 | /// 38 | /// 尺寸(8 x 8) 39 | /// 40 | Size8 = 8, 41 | /// 42 | /// 尺寸(9 x 9) 43 | /// 44 | Size9 = 9, 45 | /// 46 | /// 尺寸(10 x 10) 47 | /// 48 | Size10 = 10, 49 | /// 50 | /// 尺寸(11 x 11) 51 | /// 52 | Size11 = 11, 53 | /// 54 | /// 尺寸(12 x 12) 55 | /// 56 | Size12 = 12, 57 | /// 58 | /// 尺寸(13 x 13) 59 | /// 60 | Size13 = 13, 61 | /// 62 | /// 尺寸(14 x 14) 63 | /// 64 | Size14 = 14, 65 | /// 66 | /// 尺寸(15 x 15) 67 | /// 68 | Size15 = 15, 69 | /// 70 | /// 尺寸(16 x 16) 71 | /// 72 | Size16 = 16, 73 | /// 74 | /// 尺寸(17 x 17) 75 | /// 76 | Size17 = 17, 77 | /// 78 | /// 尺寸(18 x 18) 79 | /// 80 | Size18 = 18, 81 | /// 82 | /// 尺寸(19 x 19) 83 | /// 84 | Size19 = 19, 85 | /// 86 | /// 尺寸(20 x 20) 87 | /// 88 | Size20 = 20, 89 | /// 90 | /// 尺寸(21 x 21) 91 | /// 92 | Size21 = 21, 93 | /// 94 | /// 尺寸(22 x 22) 95 | /// 96 | Size22 = 22, 97 | /// 98 | /// 尺寸(23 x 23) 99 | /// 100 | Size23 = 23, 101 | /// 102 | /// 尺寸(24 x 24) 103 | /// 104 | Size24 = 24, 105 | /// 106 | /// 尺寸(25 x 25) 107 | /// 108 | Size25 = 25, 109 | /// 110 | /// 尺寸(26 x 26) 111 | /// 112 | Size26 = 26, 113 | /// 114 | /// 尺寸(27 x 27) 115 | /// 116 | Size27 = 27, 117 | /// 118 | /// 尺寸(28 x 28) 119 | /// 120 | Size28 = 28, 121 | /// 122 | /// 尺寸(29 x 29) 123 | /// 124 | Size29 = 29, 125 | /// 126 | /// 尺寸(30 x 30) 127 | /// 128 | Size30 = 30, 129 | /// 130 | /// 尺寸(31 x 31) 131 | /// 132 | Size31 = 31, 133 | /// 134 | /// 尺寸(32 x 32) 135 | /// 136 | Size32 = 32, 137 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/RotationAngle.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 旋转角度 6 | /// 7 | public enum RotationAngle 8 | { 9 | /// 10 | /// 正常 11 | /// 12 | None = 0, 13 | /// 14 | /// 旋转90° 15 | /// 16 | Rotate90 = 90, 17 | /// 18 | /// 旋转180° 19 | /// 20 | Rotate180 = 180, 21 | /// 22 | /// 旋转270° 23 | /// 24 | Rotate270 = 270, 25 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Enums/TextStyle.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace Bing.EasyPrint; 3 | 4 | /// 5 | /// 文字样式 6 | /// 7 | public enum TextStyle 8 | { 9 | /// 10 | /// 正常 11 | /// 12 | None = 0, 13 | /// 14 | /// 粗体 15 | /// 16 | Bold = 1, 17 | /// 18 | /// 斜体 19 | /// 20 | Italic = 2, 21 | /// 22 | /// 下划线 23 | /// 24 | Underline = 4 25 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Extensions/Extensions.IBufferWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace Bing.EasyPrint; 6 | 7 | /// 8 | /// 缓冲区写入器() 扩展 9 | /// 10 | public static class BufferWriterExtensions 11 | { 12 | /// 13 | /// 转换为16进制 14 | /// 15 | /// 类型 16 | /// 缓冲区写入器 17 | public static string ToHex(this IBufferWriter writer) 18 | { 19 | var bytes = writer.GetBytes(); 20 | if (!bytes.Any()) 21 | return string.Empty; 22 | var result = new StringBuilder(); 23 | foreach (var b in bytes) 24 | result.AppendFormat("{0:x2}", b); 25 | return result.Replace("-", "").ToString(); 26 | } 27 | 28 | /// 29 | /// 写入并换行 30 | /// 31 | /// 类型 32 | /// 缓冲区写入器 33 | /// 字符串 34 | public static T WriteLine(this IBufferWriter writer, string value) => writer.Write($"{value}\r\n"); 35 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Extensions/Extensions.IEasyPrint.cs: -------------------------------------------------------------------------------- 1 | using Bing.EasyPrint.CPCL; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace Bing.EasyPrint; 5 | 6 | /// 7 | /// 简单打印() 扩展 8 | /// 9 | public static class EasyPrintExtensions 10 | { 11 | /// 12 | /// 创建CPCL打印命令 13 | /// 14 | /// 15 | // ReSharper disable once InconsistentNaming 16 | public static CPCLPrintCommand CreateCPCLCommand(this IEasyPrint print) 17 | { 18 | var result = print.CreateCommand(); 19 | return result; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Extensions/Extensions.IPrintComponent.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable once CheckNamespace 3 | namespace Bing.EasyPrint; 4 | 5 | /// 6 | /// 打印组件() 扩展 7 | /// 8 | public static class PrintComponentExtensions 9 | { 10 | /// 11 | /// 画文本 12 | /// 13 | /// 类型 14 | /// 打印组件 15 | /// 文字起始x坐标 16 | /// 文字起始y坐标 17 | /// 内容 18 | public static T DrawText(this IPrintComponent component, int x, int y, string text) where T : IPrintCommand => component.DrawText(x, y, text, FontSize.Size16, RotationAngle.None, TextStyle.None); 19 | 20 | /// 21 | /// 画文本 22 | /// 23 | /// 类型 24 | /// 打印组件 25 | /// 文字起始x坐标 26 | /// 文字起始y坐标 27 | /// 内容 28 | /// 字体大小 29 | public static T DrawText(this IPrintComponent component, int x, int y, string text, FontSize fontSize) where T : IPrintCommand => component.DrawText(x, y, text, fontSize, RotationAngle.None, TextStyle.None); 30 | 31 | /// 32 | /// 画文本 33 | /// 34 | /// 类型 35 | /// 打印组件 36 | /// 文字起始x坐标 37 | /// 文字起始y坐标 38 | /// 内容 39 | /// 字体大小 40 | /// 字体样式 41 | public static T DrawText(this IPrintComponent component, int x, int y, string text, FontSize fontSize, TextStyle textStyle) where T : IPrintCommand => component.DrawText(x, y, text, fontSize, RotationAngle.None, textStyle); 42 | 43 | /// 44 | /// 画文本区域 45 | /// 46 | /// 类型 47 | /// 打印组件 48 | /// 文字起始x坐标 49 | /// 文字起始y坐标 50 | /// 文字绘制区域宽度(可以为0,不为0的时候文字需要根据宽度自动换行) 51 | /// 文字绘制区域高度(可以为0) 52 | /// 内容 53 | public static T DrawTextArea(this IPrintComponent component, int x, int y, int width, int height, string text) where T : IPrintCommand => component.DrawTextArea(x, y, width, height, text, FontSize.Size16, RotationAngle.None, TextStyle.None); 54 | 55 | /// 56 | /// 画条码。默认:CODE 128 57 | /// 58 | /// 类型 59 | /// 打印组件 60 | /// 条码起始x坐标 61 | /// 条码起始y坐标 62 | /// 条码内容 63 | /// 线宽 64 | /// 高度 65 | public static T DrawBarcode(this IPrintComponent component, int x, int y, string text, int lineWidth, 66 | int height) where T : IPrintCommand => component.DrawBarcode1D(BarcodeType.Code128, x, y, text, 67 | lineWidth, height, 1, RotationAngle.None); 68 | 69 | /// 70 | /// 画条码。默认:CODE 128 71 | /// 72 | /// 类型 73 | /// 打印组件 74 | /// 条码起始x坐标 75 | /// 条码起始y坐标 76 | /// 条码内容 77 | /// 线宽 78 | /// 高度 79 | /// 宽条与窄条的比率 80 | public static T DrawBarcode(this IPrintComponent component, int x, int y, string text, int lineWidth, 81 | int height, int ratio) where T : IPrintCommand => component.DrawBarcode1D(BarcodeType.Code128, x, y, text, 82 | lineWidth, height, ratio, RotationAngle.None); 83 | 84 | /// 85 | /// 画条码。默认:CODE 128 86 | /// 87 | /// 类型 88 | /// 打印组件 89 | /// 条码起始x坐标 90 | /// 条码起始y坐标 91 | /// 条码内容 92 | /// 线宽 93 | /// 高度 94 | /// 宽条与窄条的比率 95 | /// 旋转角度 96 | public static T DrawBarcode(this IPrintComponent component, int x, int y, string text, int lineWidth, 97 | int height, int ratio, RotationAngle rotation) where T : IPrintCommand => component.DrawBarcode1D(BarcodeType.Code128, x, y, text, 98 | lineWidth, height, ratio, rotation); 99 | 100 | /// 101 | /// 画线 102 | /// 103 | /// 类型 104 | /// 打印组件 105 | /// 线条起始点x坐标 106 | /// 线条起始点y坐标 107 | /// 线条结束点x坐标 108 | /// 线条结束点y坐标 109 | public static T DrawLine(this IPrintComponent component, int x0, int y0, int x1, int y1) where T : IPrintCommand => component.DrawLine(x0, y0, x1, y1, 1, LineStyle.Full); 110 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/Extensions/Extensions.Service.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace Bing.EasyPrint; 5 | 6 | public static partial class Extensions 7 | { 8 | /// 9 | /// 注册EasyPrint 10 | /// 11 | /// 服务集合 12 | public static void AddEasyPrint(this IServiceCollection services) 13 | { 14 | services.AddScoped(); 15 | } 16 | 17 | /// 18 | /// 注册EasyPrint 19 | /// 20 | /// 简单打印实现类型 21 | /// 服务集合 22 | public static void AddEasyPrint(this IServiceCollection services) where TEasyPrint : class, IEasyPrint 23 | { 24 | services.AddScoped(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/IBufferWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint; 2 | 3 | /// 4 | /// 缓冲区写入器 5 | /// 6 | /// 类型 7 | public interface IBufferWriter 8 | { 9 | /// 10 | /// 写入 11 | /// 12 | /// 字节数组 13 | T Write(byte[] value); 14 | 15 | /// 16 | /// 写入 17 | /// 18 | /// 字符串 19 | T Write(string value); 20 | 21 | /// 22 | /// 清空内容 23 | /// 24 | T Clear(); 25 | 26 | /// 27 | /// 获取二进制数组 28 | /// 29 | byte[] GetBytes(); 30 | } 31 | 32 | /// 33 | /// 缓冲区写入器 34 | /// 35 | public interface IBufferWriter : IBufferWriter 36 | { 37 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/IEasyPrint.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint; 2 | 3 | /// 4 | /// 简单打印 5 | /// 6 | public interface IEasyPrint 7 | { 8 | /// 9 | /// 创建打印命令 10 | /// 11 | /// 打印命令类型 12 | T CreateCommand() where T : IPrintCommand, new(); 13 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/IPrintCommand.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint; 2 | 3 | /// 4 | /// 打印命令 5 | /// 6 | public interface IPrintCommand 7 | { 8 | /// 9 | /// 写入命令 10 | /// 11 | /// 命令 12 | TCommand WriteRaw(string raw); 13 | 14 | /// 15 | /// 写入命令并换行 16 | /// 17 | /// 命令 18 | TCommand WriteRawLine(string raw); 19 | 20 | /// 21 | /// 构建命令 22 | /// 23 | IBufferWriter Build(); 24 | } -------------------------------------------------------------------------------- /src/Bing.EasyPrint/IPrintComponent.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using SixLabors.ImageSharp; 3 | 4 | namespace Bing.EasyPrint; 5 | 6 | /// 7 | /// 打印组件 8 | /// 9 | /// 打印组件 10 | public interface IPrintComponent where T : IPrintCommand 11 | { 12 | /// 13 | /// 设置纸张 14 | /// 15 | /// 宽度 16 | /// 高度 17 | /// 旋转角度 18 | T SetPage(int width, int height, PrintOrientation orientation = PrintOrientation.None); 19 | 20 | /// 21 | /// 设置纸张 22 | /// 23 | /// 宽度 24 | /// 高度 25 | /// 旋转角度 26 | T SetPage(int width, int height, int orientation = 0); 27 | 28 | /// 29 | /// 设置打印标签数 30 | /// 31 | /// 打印标签数量 32 | T SetQty(int qty); 33 | 34 | /// 35 | /// 设置标签横向偏移量 36 | /// 37 | /// 偏移量 38 | T SetOffset(int offset); 39 | 40 | /// 41 | /// 画线 42 | /// 43 | /// 线条起始点x坐标 44 | /// 线条起始点y坐标 45 | /// 线条结束点x坐标 46 | /// 线条结束点y坐标 47 | /// 线条宽度 48 | T DrawLine(int x0, int y0, int x1, int y1, int lineWidth); 49 | 50 | /// 51 | /// 画线 52 | /// 53 | /// 线条起始点x坐标 54 | /// 线条起始点y坐标 55 | /// 线条结束点x坐标 56 | /// 线条结束点y坐标 57 | /// 线条宽度 58 | /// 线条样式 59 | T DrawLine(int x0, int y0, int x1, int y1, int lineWidth, LineStyle lineStyle); 60 | 61 | /// 62 | /// 画虚线 63 | /// 64 | /// 线条起始点x坐标 65 | /// 线条起始点y坐标 66 | /// 线条结束点x坐标 67 | /// 线条结束点y坐标 68 | T DrawDashLine(int x0, int y0, int x1, int y1); 69 | 70 | /// 71 | /// 画虚线 72 | /// 73 | /// 线条点x坐标 74 | /// 线条点y坐标 75 | /// 线条长度 76 | T DrawDashLine(int x, int y, int length); 77 | 78 | /// 79 | /// 画矩形 80 | /// 81 | /// 矩形框左上角x坐标 82 | /// 矩形框左上角y坐标 83 | /// 矩形框右下角x坐标 84 | /// 矩形框右下角y坐标 85 | /// 线条宽度 86 | T DrawRect(int x0, int y0, int x1, int y1, int lineWidth); 87 | 88 | /// 89 | /// 画矩形 90 | /// 91 | /// 矩形框左上角x坐标 92 | /// 矩形框左上角y坐标 93 | /// 矩形框右下角x坐标 94 | /// 矩形框右下角y坐标 95 | /// 线条宽度 96 | /// 线条样式 97 | T DrawRect(int x0, int y0, int x1, int y1, int lineWidth, LineStyle lineStyle); 98 | 99 | /// 100 | /// 画矩形(填充) 101 | /// 102 | /// 矩形框左上角x坐标 103 | /// 矩形框左上角y坐标 104 | /// 矩形框右下角x坐标 105 | /// 矩形框右下角y坐标 106 | T DrawRectFill(int x0, int y0, int x1, int y1); 107 | 108 | /// 109 | /// 画一维条码 110 | /// 111 | /// 条码类型 112 | /// 条码起始x坐标 113 | /// 条码起始y坐标 114 | /// 条码内容 115 | /// 条码线条宽度 116 | /// 条码高度 117 | /// 宽条与窄条的比率 118 | /// 旋转角度 119 | T DrawBarcode1D(string type, int x, int y, string text, int lineWidth, int height, int ratio, int rotation); 120 | 121 | /// 122 | /// 画一维条码 123 | /// 124 | /// 条码类型 125 | /// 条码起始x坐标 126 | /// 条码起始y坐标 127 | /// 条码内容 128 | /// 条码线条宽度 129 | /// 条码高度 130 | /// 宽条与窄条的比率 131 | /// 旋转角度 132 | T DrawBarcode1D(int type, int x, int y, string text, int lineWidth, int height, int ratio, int rotation); 133 | 134 | /// 135 | /// 画一维条码 136 | /// 137 | /// 条码类型 138 | /// 条码起始x坐标 139 | /// 条码起始y坐标 140 | /// 条码内容 141 | /// 条码线条宽度 142 | /// 条码高度 143 | /// 宽条与窄条的比率 144 | /// 旋转角度 145 | T DrawBarcode1D(BarcodeType type, int x, int y, string text, int lineWidth, int height, int ratio, RotationAngle rotation); 146 | 147 | /// 148 | /// 画二维码 149 | /// 150 | /// 二维码起始x坐标 151 | /// 二维码起始y坐标 152 | /// 二维码内容 153 | /// 模块的单位宽度。(1-32) 154 | /// 二维码纠错级别 155 | /// 旋转角度 156 | T DrawQrCode(int x, int y, string text, int unitWidth, int errorLevel, int rotation); 157 | 158 | /// 159 | /// 画二维码 160 | /// 161 | /// 二维码起始x坐标 162 | /// 二维码起始y坐标 163 | /// 二维码内容 164 | /// 模块的单位宽度。(1-32) 165 | /// 二维码纠错级别 166 | /// 旋转角度 167 | T DrawQrCode(int x, int y, string text, int unitWidth, string errorLevel, int rotation); 168 | 169 | /// 170 | /// 画二维码 171 | /// 172 | /// 二维码起始x坐标 173 | /// 二维码起始y坐标 174 | /// 二维码内容 175 | /// 模块的单位宽度。(1-32) 176 | /// 二维码纠错级别 177 | /// 旋转角度 178 | T DrawQrCode(int x, int y, string text, QrCodeUnitSize unitWidth, QrCodeCorrectionLevel errorLevel, RotationAngle rotation); 179 | 180 | /// 181 | /// 画图片 182 | /// 183 | /// 图片起始x坐标 184 | /// 图片起始y坐标 185 | /// 图片数据 186 | T DrawImage(int startX, int startY, Image bitmap); 187 | 188 | /// 189 | /// 画图片 190 | /// 191 | /// 图片起始x坐标 192 | /// 图片起始y坐标 193 | /// 图片地址 194 | T DrawImage(int startX, int startY, string imageUrl); 195 | 196 | /// 197 | /// 画图片 198 | /// 199 | /// 图片起始x坐标 200 | /// 图片起始y坐标 201 | /// 图片数据 202 | T DrawImage(int startX, int startY, byte[] bytes); 203 | 204 | /// 205 | /// 画图片 206 | /// 207 | /// 图片起始x坐标 208 | /// 图片起始y坐标 209 | /// 图片流 210 | T DrawImage(int startX, int startY, Stream stream); 211 | 212 | /// 213 | /// 画文字 214 | /// 215 | /// 文字起始x坐标 216 | /// 文字起始y坐标 217 | /// 内容 218 | /// 字体大小 219 | /// 旋转角度 220 | /// 是否加粗 221 | /// 是否颠倒 222 | /// 是否下划线 223 | T DrawText(int x, int y, string text, int fontSize, int rotation, bool bold, bool reverse, bool underline); 224 | 225 | /// 226 | /// 画文字 227 | /// 228 | /// 文字起始x坐标 229 | /// 文字起始y坐标 230 | /// 内容 231 | /// 字体大小 232 | /// 旋转角度 233 | /// 样式 234 | T DrawText(int x, int y, string text, int fontSize, int rotation, int style); 235 | 236 | /// 237 | /// 画文本区域 238 | /// 239 | /// 文字起始x坐标 240 | /// 文字起始y坐标 241 | /// 内容 242 | /// 字体大小 243 | /// 旋转角度 244 | /// 字体样式 245 | T DrawText(int x, int y,string text, FontSize fontSize, RotationAngle rotation, TextStyle textStyle); 246 | 247 | /// 248 | /// 画文本区域 249 | /// 250 | /// 文字起始x坐标 251 | /// 文字起始y坐标 252 | /// 文字绘制区域宽度(可以为0,不为0的时候文字需要根据宽度自动换行) 253 | /// 文字绘制区域高度(可以为0) 254 | /// 内容 255 | /// 字体大小 256 | /// 旋转角度 257 | /// 字体样式 258 | T DrawTextArea(int x, int y, int width, int height, string text, int fontSize, int rotation, int textStyle); 259 | 260 | /// 261 | /// 画文本区域 262 | /// 263 | /// 文字起始x坐标 264 | /// 文字起始y坐标 265 | /// 文字绘制区域宽度(可以为0,不为0的时候文字需要根据宽度自动换行) 266 | /// 文字绘制区域高度(可以为0) 267 | /// 内容 268 | /// 字体大小 269 | /// 旋转角度 270 | /// 字体样式 271 | T DrawTextArea(int x, int y, int width, int height, string text, FontSize fontSize, RotationAngle rotation, TextStyle textStyle); 272 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Bing.EasyPrint.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net7.0;net6.0;net5.0;netcoreapp3.1;netcoreapp2.2; 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Always 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/Images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bing-framework/Bing.EasyPrint/4edfb2ed74d875f221cefaf8ec11f6a26c2c2fca/tests/Bing.EasyPrint.Tests/Biz/Images/logo.jpg -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/Label/PrintPriceLabelBase.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Tests.Biz.Label; 2 | 3 | /// 4 | /// 打印价格标签基类 5 | /// 6 | public abstract class PrintPriceLabelBase 7 | { 8 | /// 9 | /// 简单打印 10 | /// 11 | protected IEasyPrint EasyPrint { get; set; } 12 | 13 | /// 14 | /// 初始化一个类型的实例 15 | /// 16 | protected PrintPriceLabelBase(IEasyPrint easyPrint) => EasyPrint = easyPrint; 17 | 18 | /// 19 | /// 构建 20 | /// 21 | /// 价格标签 22 | public abstract IBufferWriter Build(PriceLabel label); 23 | 24 | /// 25 | /// 创建 26 | /// 27 | /// 简单打印 28 | /// 打印纸类型 29 | public static PrintPriceLabelBase Create(IEasyPrint easyPrint, PrintPageType pageType) 30 | { 31 | switch (pageType) 32 | { 33 | case PrintPageType.Page90mm: 34 | return new PrintPriceLabelBy90mm(easyPrint); 35 | case PrintPageType.Page70mm: 36 | return new PrintPriceLabelBy70mm(easyPrint); 37 | case PrintPageType.Page15mm: 38 | return new PrintPriceLabelBy15mm(easyPrint); 39 | default: 40 | return new PrintPriceLabelBy70mm(easyPrint); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/Label/PrintPriceLabelBy15mm.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Tests.Biz.Label; 2 | 3 | /// 4 | /// 打印价格标签(15mm) 5 | /// 6 | public class PrintPriceLabelBy15mm : PrintPriceLabelBase 7 | { 8 | /// 9 | /// 初始化一个类型的实例 10 | /// 11 | public PrintPriceLabelBy15mm(IEasyPrint easyPrint) : base(easyPrint) 12 | { 13 | } 14 | 15 | /// 16 | /// 构建 17 | /// 18 | /// 价格标签 19 | public override IBufferWriter Build(PriceLabel label) 20 | { 21 | //宽 8px=1mm 22 | var command = EasyPrint.CreateCPCLCommand(); 23 | 24 | #region 设置页面定位信息 25 | 26 | const int xMargin = 0, yMargin = 0; 27 | const int pageWidth = 142, pageHeight = 142; 28 | // 设置打印页 29 | command.SetPage(pageWidth, pageHeight); 30 | 31 | // 抬头 32 | command.DrawTextArea(xMargin + 2, yMargin, 120, 24, "扫码购买", FontSize.Size24, RotationAngle.None, TextStyle.None); 33 | // 二维码 34 | var qrCodeUnitSize = label.QrCode.Length > 52 ? QrCodeUnitSize.Size3 : QrCodeUnitSize.Size4; 35 | command.DrawQrCode(xMargin, yMargin + 28, label.QrCode, qrCodeUnitSize, QrCodeCorrectionLevel.L, RotationAngle.None); 36 | 37 | #endregion 38 | 39 | return command.Build(); 40 | } 41 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/Label/PrintPriceLabelBy70mm.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Tests.Biz.Label; 2 | 3 | /// 4 | /// 打印价格标签(70mm) 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | public class PrintPriceLabelBy70mm : PrintPriceLabelBase 8 | { 9 | /// 10 | /// 初始化一个类型的实例 11 | /// 12 | public PrintPriceLabelBy70mm(IEasyPrint easyPrint) : base(easyPrint) 13 | { 14 | } 15 | 16 | /// 17 | /// 构建 18 | /// 19 | /// 价格标签 20 | public override IBufferWriter Build(PriceLabel label) 21 | { 22 | var printer = EasyPrint.CreateCPCLCommand(); 23 | 24 | #region 设置页面定位信息 25 | 26 | const int xMargin = 30, yMargin = 30; 27 | const int pageWidth = 540, pageHeight = 300; 28 | // 设置打印页 29 | printer.SetPage(pageWidth, pageHeight); 30 | 31 | #endregion 32 | 33 | var name = label.Name.Length > 40 ? $"{label.Name.Substring(0, 38)}..." : label.Name; 34 | // 打印商品名称 35 | printer.DrawTextArea(30 - xMargin, 49 - yMargin, 480, 66, name, FontSize.Size24, RotationAngle.None, TextStyle.None); 36 | 37 | // 打印价格 38 | if (label.OriginPrice == label.Price) 39 | { 40 | // 打印正价 41 | printer.BilingualLabel(30 - xMargin, 112 - yMargin, "零售价:", "Price", 5, zhCnFontSize: FontSize.Size16); 42 | printer.GoodsPriceLabel(78 - xMargin, 186 - yMargin, label.Price, label.Unit); 43 | } 44 | else 45 | { 46 | // 打印促销价 47 | var originalPriceStr = $"零售价:{label.OriginPrice:F2}"; 48 | var width = ((originalPriceStr.Length + 3) * 16) / 2; 49 | printer.DrawLine(30 - xMargin, 106 - yMargin + 8, 30 - xMargin + width, 106 - yMargin + 8); 50 | printer.BilingualLabel(30 - xMargin, 106 - yMargin, originalPriceStr, "Price", 5, zhCnFontSize: FontSize.Size16); 51 | printer.BilingualLabel(30 - xMargin, 150 - yMargin, $"促销价:", "Sale", 5, zhCnFontSize: FontSize.Size16); 52 | printer.GoodsPriceLabel(98 - xMargin, 195 - yMargin, label.Price, label.Unit); 53 | } 54 | 55 | // 辅助属性 56 | printer.BilingualLabel(30 - xMargin, 194 - yMargin, $"规格属性:{label.AttributeName}", "SPEC", 4); 57 | 58 | ////条码 59 | //Printer.BilingualLabel(30 - xMargin, 244 - yMargin, $"条码:{label.Barcode}", "Barcode", 4); 60 | 61 | // 监管电话 62 | printer.BilingualLabel(30 - xMargin, 244 - yMargin, $"商品条码:{label.Barcode}", "监管电话:12358", 4); 63 | 64 | // 二维码 65 | printer.DrawQrCode(390 - xMargin, 109 - yMargin, label.QrCode, QrCodeUnitSize.Size6, QrCodeCorrectionLevel.L, RotationAngle.None); 66 | 67 | //// 监管电话 68 | //Printer.BilingualLabel(358 - xMargin, 243 - yMargin, $"监管电话:12358", "Complaints Hotline", 4); 69 | 70 | return printer.Build(); 71 | } 72 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/Label/PrintPriceLabelBy90mm.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Tests.Biz.Label; 2 | 3 | /// 4 | /// 打印价格标签(90mm) 5 | /// 6 | // ReSharper disable once InconsistentNaming 7 | public class PrintPriceLabelBy90mm : PrintPriceLabelBase 8 | { 9 | /// 10 | /// 初始化一个类型的实例 11 | /// 12 | public PrintPriceLabelBy90mm(IEasyPrint easyPrint) : base(easyPrint) 13 | { 14 | } 15 | 16 | /// 17 | /// 构建 18 | /// 19 | /// 价格标签 20 | public override IBufferWriter Build(PriceLabel label) 21 | { 22 | var printer = EasyPrint.CreateCPCLCommand(); 23 | // 203 dpi 24 | // width: 90mm, height: 37mm 25 | // width: 719px, height: 296px 26 | #region 设置页面定位信息 27 | 28 | const int xStartMargin = 0; 29 | const int xStartMarginColumn2 = 230; 30 | const int xMargin = 30, yMargin = 30; 31 | const int pageWidth = 671, pageHeight = 320; 32 | // 设置打印页 33 | printer.SetPage(pageWidth, pageHeight); 34 | 35 | #endregion 36 | 37 | var name = label.Name.Length > 40 ? $"{label.Name.Substring(0, 38)}..." : label.Name; 38 | // 打印商品名称 39 | printer.DrawTextArea(xStartMargin, 49 - yMargin, 623, 92, name, FontSize.Size32, RotationAngle.None, TextStyle.Bold); 40 | 41 | // 打印价格 42 | if (label.OriginPrice == label.Price) 43 | { 44 | // 打印正价 45 | printer.DrawText(xStartMargin, 132 - yMargin, "零售价/Price", FontSize.Size24); 46 | printer.GoodsPriceLabelV2(xStartMargin, 280 - yMargin, label.Price, label.Unit); 47 | } 48 | else 49 | { 50 | // 打印促销价 51 | var originalPriceStr = $"零售价/Price:{label.OriginPrice:F2}"; 52 | var width = ((originalPriceStr.Length + 3) * 24) / 2; 53 | printer.DrawLine(xStartMargin, 122 - yMargin + 8, 30 - xMargin + width, 122 - yMargin + 8); 54 | printer.DrawText(xStartMargin, 122 - yMargin, originalPriceStr, FontSize.Size24); 55 | printer.DrawText(xStartMargin, 150 - yMargin, "促销价/Sale", FontSize.Size24); 56 | printer.GoodsPriceLabelV2(xStartMargin, 280 - yMargin, label.Price, label.Unit); 57 | } 58 | 59 | // 监管电话 60 | printer.DrawText(xStartMarginColumn2, 270 - yMargin, "监管电话:12358", FontSize.Size24); 61 | 62 | // 规格属性 63 | if (label.OriginPrice == label.Price) 64 | { 65 | printer.DrawText(xStartMarginColumn2, 132 - yMargin, "规格属性/SPEC", FontSize.Size24); 66 | printer.DrawTextArea(xStartMarginColumn2 + 5, 165 - yMargin, 270, 130, label.AttributeName, FontSize.Size24, RotationAngle.None, TextStyle.None); 67 | } 68 | else 69 | { 70 | printer.DrawText(xStartMarginColumn2, 146 - yMargin, "规格属性/SPEC", FontSize.Size24); 71 | printer.DrawTextArea(xStartMarginColumn2 + 5, 179 - yMargin, 270, 130, label.AttributeName, FontSize.Size24,RotationAngle.None, TextStyle.None); 72 | } 73 | 74 | // 商品条码 75 | printer.DrawText(xStartMarginColumn2, 235 - yMargin, $"商品条码:{label.Barcode}", FontSize.Size24); 76 | 77 | // 二维码 78 | printer.DrawQrCode(555 - xMargin, 135 - yMargin, label.QrCode, QrCodeUnitSize.Size5, QrCodeCorrectionLevel.L, RotationAngle.None); 79 | 80 | return printer.Build(); 81 | } 82 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/PriceLabel.cs: -------------------------------------------------------------------------------- 1 | namespace Bing.EasyPrint.Tests.Biz; 2 | 3 | /// 4 | /// 价格标签 5 | /// 6 | public class PriceLabel 7 | { 8 | /// 9 | /// 商品条码 10 | /// 11 | public string Barcode { get; set; } 12 | 13 | /// 14 | /// 二维码 15 | /// 16 | public string QrCode { get; set; } 17 | 18 | /// 19 | /// 商家自定义商品编码 20 | /// 21 | public string CustomProductCode { get; set; } 22 | 23 | /// 24 | /// 商家自定义sku编码 25 | /// 26 | public string CustomSkuCode { get; set; } 27 | 28 | /// 29 | /// 商品名称 30 | /// 31 | public string Name { get; set; } 32 | 33 | /// 34 | /// SKU原价 35 | /// 36 | public decimal OriginPrice { get; set; } 37 | 38 | /// 39 | /// SKU价格 40 | /// 41 | public decimal Price { get; set; } 42 | 43 | /// 44 | /// 商品编码 45 | /// 46 | public string ProductCode { get; set; } 47 | 48 | /// 49 | /// sku编码 50 | /// 51 | public string SkuCode { get; set; } 52 | 53 | /// 54 | /// 店铺编码 55 | /// 56 | public string StoreCode { get; set; } 57 | 58 | /// 59 | /// 单位 60 | /// 61 | public string Unit { get; set; } 62 | 63 | /// 64 | /// 辅助属性 65 | /// 66 | public string AttributeName { get; set; } 67 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/PrintPageType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Bing.EasyPrint.Tests.Biz; 4 | 5 | /// 6 | /// 打印纸类型 7 | /// 8 | public enum PrintPageType 9 | { 10 | /// 11 | /// 15mm 打印纸 12 | /// 13 | [Description("15mm")] 14 | // ReSharper disable once InconsistentNaming 15 | Page15mm = 15, 16 | /// 17 | /// 70mm 打印纸 18 | /// 19 | [Description("70mm")] 20 | // ReSharper disable once InconsistentNaming 21 | Page70mm = 70, 22 | /// 23 | /// 90mm 打印纸 24 | /// 25 | [Description("90mm")] 26 | // ReSharper disable once InconsistentNaming 27 | Page90mm = 90, 28 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/Biz/ShippingLabel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Bing.EasyPrint.Tests.Biz; 6 | 7 | /// 8 | /// 配送面单 9 | /// 10 | public class ShippingLabel 11 | { 12 | /// 13 | /// 单号 14 | /// 15 | public string Sheet { get; set; } 16 | 17 | /// 18 | /// 订单号 19 | /// 20 | public string SourceSheet { get; set; } 21 | 22 | /// 23 | /// 配送中心名称 24 | /// 25 | public string ShippingPointName { get; set; } 26 | 27 | /// 28 | /// 配送中心划区名称 29 | /// 30 | public string ShippingZoningName { get; set; } 31 | 32 | /// 33 | /// 配送起时间 34 | /// 35 | public DateTime DeliveryTimeBegin { get; set; } 36 | 37 | /// 38 | /// 配送止时间 39 | /// 40 | public DateTime DeliveryTimeEnd { get; set; } 41 | 42 | /// 43 | /// 收货人 44 | /// 45 | public string ConsigneeName { get; set; } 46 | 47 | /// 48 | /// 收货人电话 49 | /// 50 | public string ConsigneePhone { get; set; } 51 | 52 | /// 53 | /// 收货人地址 54 | /// 55 | public string ConsigneeStreet { get; set; } 56 | 57 | /// 58 | /// 包裹数 59 | /// 60 | public int BagQty { get; set; } 61 | 62 | /// 63 | /// 商品明细 64 | /// 65 | public List CargoList { get; set; } 66 | } 67 | 68 | 69 | /// 70 | /// 商品明细 71 | /// 72 | public class Cargo 73 | { 74 | /// 75 | /// 商品编码 76 | /// 77 | public string CargoCode { get; set; } 78 | /// 79 | /// 商品名称 80 | /// 81 | public string CargoName { get; set; } 82 | 83 | /// 84 | /// 商品单价 85 | /// 86 | public decimal CargoPrice { get; set; } 87 | 88 | /// 89 | /// 商品数量 90 | /// 91 | public int CargoQty { get; set; } 92 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/BufferWriterTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Text; 3 | using Bing.EasyPrint.Core; 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Bing.EasyPrint.Tests; 8 | 9 | /// 10 | /// 缓冲区写入器 测试 11 | /// 12 | public class BufferWriterTest : TestBase 13 | { 14 | /// 15 | /// 字符编码 16 | /// 17 | private readonly Encoding _encoding; 18 | 19 | /// 20 | /// 缓冲区写入器 21 | /// 22 | private readonly IBufferWriter _writer; 23 | 24 | /// 25 | /// 初始化一个类型的实例 26 | /// 27 | /// 输出 28 | public BufferWriterTest(ITestOutputHelper output) : base(output) 29 | { 30 | _encoding = Encoding.GetEncoding("gbk"); 31 | _writer = new BufferWriter(_encoding); 32 | } 33 | 34 | /// 35 | /// 测试 - 字符串是否匹配字节数组 36 | /// 37 | [Fact] 38 | public void Test_StringEqualBytes() 39 | { 40 | var input = "! 0 200 200 210 1"; 41 | _writer.Write(input); 42 | var original = _writer.GetBytes(); 43 | var target = GetBytes(input); 44 | Assert.True(original.SequenceEqual(target)); 45 | } 46 | 47 | /// 48 | /// 获取字节数组 49 | /// 50 | /// 值 51 | private byte[] GetBytes(string value) => _encoding.GetBytes(value); 52 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.Advanced.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Bing.EasyPrint.Tests.CPCL; 4 | 5 | // ReSharper disable once InconsistentNaming 6 | partial class CPCLPrintCommandTest 7 | { 8 | [Fact] 9 | public void Test_HorizontalAlignment() 10 | { 11 | Command.WriteRawLine("! 0 200 200 210 1") 12 | .PageWidth(600) 13 | .Center() 14 | .Text(4, 0, 0, 75, "C") 15 | .Left() 16 | .Text(4, 0, 0, 75, "L") 17 | .Right() 18 | .Text(4, 0, 0, 75, "R") 19 | .Print(); 20 | Build(); 21 | } 22 | 23 | [Fact] 24 | public void Test_Pace() 25 | { 26 | Command.WriteRawLine("! 0 200 200 210 3") 27 | .Pace() 28 | .Journal() 29 | .Text(4, 1, 0, 10, "Print 3 labels") 30 | .Text(4, 1, 0, 90, "Using PACE") 31 | .Print(); 32 | Build(); 33 | } 34 | 35 | [Fact] 36 | public void Test_AutoPace() 37 | { 38 | Command.WriteRawLine("! 0 200 200 250 10") 39 | .Center() 40 | .Text(7, 0, 0, 10, "AUTO-PACE EXAMPLE") 41 | .PaceAuto() 42 | .Form() 43 | .Print(); 44 | Build(); 45 | } 46 | 47 | [Fact] 48 | public void Test_NoPace() 49 | { 50 | Command.WriteRawLine("! 0 200 200 250 10") 51 | .Text(7, 0, 0, 10, "AUTO-PACE EXAMPLE") 52 | .PaceAuto() 53 | .Form() 54 | .Print() 55 | .WriteRawLine("! 0 200 200 250 10") 56 | .Text(7, 0, 0, 10, "NO-PACE EXAMPLE") 57 | .PaceNo() 58 | .Form() 59 | .Print(); 60 | Build(); 61 | } 62 | 63 | [Fact] 64 | public void Test_Wait() 65 | { 66 | Command.WriteRawLine("! 0 200 200 150 5") 67 | .Wait(80) 68 | .Text(5, 0, 0, 20, "DELAY 10 SECONDS") 69 | .Form() 70 | .Print(); 71 | Build(); 72 | } 73 | 74 | [Fact] 75 | public void Test_Tension() 76 | { 77 | Command.WriteRawLine("! 0 200 200 150 1") 78 | .TensionPre(30) 79 | .Text(5, 0, 0, 20, "ADJUSTS TENSION") 80 | .Print(); 81 | Build(); 82 | } 83 | 84 | [Fact] 85 | public void Test_SetSp() 86 | { 87 | Command.WriteRawLine("! 0 200 200 250 1") 88 | .Text(4, 0, 0, 10, "Normal Spacing") 89 | .SetSp(5) 90 | .Text(4, 0, 0, 50, "Spread Spacing") 91 | .SetSp(0) 92 | .Text(4, 0, 0, 90, "Normal Spacing") 93 | .Form() 94 | .Print(); 95 | Build(); 96 | } 97 | 98 | [Fact] 99 | public void Test_PostFeed() 100 | { 101 | Command.WriteRawLine("! 0 200 200 250 1") 102 | .Text(7, 0, 0, 10, "POSTFEED EXAMPLE") 103 | .Form() 104 | .PostFeed(40) 105 | .Print(); 106 | Build(); 107 | } 108 | 109 | [Fact] 110 | public void Test_PreSendAt() 111 | { 112 | Command.WriteRawLine("! 0 200 200 250 1") 113 | .Text(7, 0, 0, 10, "PRESENT-AT EXAMPLE") 114 | .PreSentAt(80, 2) 115 | .Form() 116 | .Print(); 117 | Build(); 118 | } 119 | 120 | [Fact] 121 | public void Test_DefineFormat() 122 | { 123 | Command.DefineFormat("SHELF.FMT", "! 0 200 200 210 1", "CENTER", "TEXT 4 3 0 15 \\\\", "TEXT 4 0 0 95 \\\\", 124 | "BARCODE UPCA 1 1 40 0 145 \\\\", "TEXT 7 0 0 185 \\\\", "FORM", "PRINT"); 125 | Build(); 126 | } 127 | 128 | [Fact] 129 | public void Test_UseFormat() 130 | { 131 | Command.UseFormat("SHELF.FMT", "$22.99", "SWEATSHIRT", "40123456784", "40123456784"); 132 | Build(); 133 | } 134 | 135 | [Fact] 136 | public void Test_Beep() 137 | { 138 | Command.WriteRawLine("! 0 200 200 210 1") 139 | .Center() 140 | .Text("5", 0, 0, 10, "beeps for two seconds") 141 | .Beep(16) 142 | .Form() 143 | .Print(); 144 | Build(); 145 | } 146 | 147 | [Fact] 148 | public void Test_Cut() 149 | { 150 | Command.WriteRawLine("! 0 200 200 210 1") 151 | .Center() 152 | .Text("4", 0, 0, 1, ".15 CUT COMMAND") 153 | .Cut() 154 | .Print(); 155 | Build(); 156 | } 157 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.Component.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Bing.EasyPrint.Tests.CPCL; 4 | 5 | // ReSharper disable once InconsistentNaming 6 | partial class CPCLPrintCommandTest 7 | { 8 | /// 9 | /// 测试 - 画文本 10 | /// 11 | [Fact] 12 | public void Test_DrawText_1() 13 | { 14 | Command.SetPage(400, 240) 15 | .DrawText(0, 0, "隔壁老王的战斗 with lao wang de zhan dou", 16, 0, false, false, false); 16 | Build(); 17 | } 18 | 19 | /// 20 | /// 测试 - 画线条 21 | /// 22 | [Fact] 23 | public void Test_DrawLine_1() 24 | { 25 | Command.SetPage(200, 210) 26 | .DrawLine(0, 0, 200, 0, 1) 27 | .DrawLine(0, 0, 200, 200, 2) 28 | .DrawLine(0, 0, 0, 200, 3); 29 | Build(); 30 | } 31 | 32 | /// 33 | /// 测试 - 画虚线 34 | /// 35 | [Fact] 36 | public void Test_DrawDashLine_1() 37 | { 38 | Command.SetPage(600, 200) 39 | .DrawDashLine(0, 10, 595, 5); 40 | Build(); 41 | } 42 | 43 | /// 44 | /// 测试 - 画虚线 45 | /// 46 | [Fact] 47 | public void Test_DrawDashLine_2() 48 | { 49 | Command.SetPage(600, 200) 50 | .DrawDashLine(50, 10, 595, 5); 51 | Build(); 52 | } 53 | 54 | /// 55 | /// 测试 - 画分割线 56 | /// 57 | [Fact] 58 | public void Test_DrawSplitLine_1() 59 | { 60 | Command.SetPage(76 * 8, 200) 61 | .DrawSplitLine(0, 10); 62 | Build(); 63 | } 64 | 65 | /// 66 | /// 测试 - 画分割线 67 | /// 68 | [Fact] 69 | public void Test_DrawSplitLine_2() 70 | { 71 | Command.SetPage(76 * 8, 200) 72 | .DrawSplitLine(0, 10, '.'); 73 | Build(); 74 | } 75 | 76 | /// 77 | /// 测试 - 画分割线 78 | /// 79 | [Fact] 80 | public void Test_DrawSplitLine_3() 81 | { 82 | Command.SetPage(76 * 8, 200) 83 | .DrawSplitLine(0, 10, '★'); 84 | Build(); 85 | } 86 | 87 | /// 88 | /// 测试 - 画分割线 89 | /// 90 | [Fact] 91 | public void Test_DrawSplitLine_4() 92 | { 93 | Command.SetPage(76 * 8, 200) 94 | .DrawSplitLine(0, 10, '糟'); 95 | Build(); 96 | } 97 | 98 | /// 99 | /// 测试 - 画矩形 100 | /// 101 | [Fact] 102 | public void Test_DrawRect_1() 103 | { 104 | Command.SetPage(400, 210) 105 | .DrawRect(0, 0, 200, 200, 1) 106 | .DrawRect(200, 0, 400, 200, 1); 107 | Build(); 108 | } 109 | 110 | /// 111 | /// 测试 - 画条码 112 | /// 113 | [Fact] 114 | public void Test_DrawBarcode_1() 115 | { 116 | Command.SetPage(400, 210) 117 | .DrawBarcode1D("128", 150, 10, "HORIZ.", 1, 50, 0, 1) 118 | .DrawText(210, 60, "HORIZ.", 16, 0, false, false, false) 119 | .DrawBarcode1D("128", 10, 200, "VERT.", 1, 50, 90, 1) 120 | .DrawText(60, 140, "VERT.", 16, 90, false, false, false); 121 | Build(); 122 | } 123 | 124 | /// 125 | /// 测试 - 画条码 126 | /// 127 | [Fact] 128 | public void Test_DrawBarcode_2() 129 | { 130 | Command.SetPage(600, 350) 131 | .DrawBarcode(0, 0, "10000000256", 1, 100) 132 | .DrawBarcode(0, 150, "10000000257", 2, 100); 133 | Build(); 134 | } 135 | 136 | /// 137 | /// 测试 - 画二维码 138 | /// 139 | [Fact] 140 | public void Test_DrawQrCode_1() 141 | { 142 | Command.SetPage(400, 500) 143 | .DrawQrCode(10, 100, "ABC123", 10, "M", 0); 144 | Build(); 145 | } 146 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.Graphics.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Bing.EasyPrint.Tests.CPCL; 4 | 5 | // ReSharper disable once InconsistentNaming 6 | partial class CPCLPrintCommandTest 7 | { 8 | [Fact] 9 | public void Test_Box() 10 | { 11 | Command.WriteRawLine("! 0 200 200 210 1") 12 | .PageWidth(500) 13 | .Box(0, 0, 200, 200, 1) 14 | .Form() 15 | .Print(); 16 | Build(); 17 | } 18 | 19 | [Fact] 20 | public void Test_Line() 21 | { 22 | Command.WriteRawLine("! 0 200 200 210 1") 23 | .Line(0, 0, 200, 0, 1) 24 | .Line(0, 0, 200, 200, 2) 25 | .Line(0, 0, 0, 200, 3) 26 | .Form() 27 | .Print(); 28 | Build(); 29 | } 30 | 31 | [Fact] 32 | public void Test_InverseLine_1() 33 | { 34 | Command.WriteRawLine("! 0 200 200 210 1") 35 | .Center() 36 | .Text(4, 0, 0, 45, "SAVE") 37 | .Text(4, 0, 0, 95, "MORE") 38 | .InverseLine(0, 45, 145, 45, 45) 39 | .InverseLine(0, 95, 145, 95, 45) 40 | .Form() 41 | .Print(); 42 | Build(); 43 | } 44 | 45 | [Fact] 46 | public void Test_InverseLine_2() 47 | { 48 | Command.WriteRawLine("! 0 200 200 210 1") 49 | .Center() 50 | .Text(4, 2, 30, 20, "$123.45") 51 | .Text(4, 2, 30, 70, "$678.90") 52 | .InverseLine(25, 40, 350, 40, 90) 53 | .Text(4, 2, 30, 120, "$432.10") 54 | .Form() 55 | .Print(); 56 | Build(); 57 | } 58 | 59 | [Fact] 60 | public void Test_Pattern() 61 | { 62 | Command.WriteRawLine("! 0 200 200 700 1") 63 | .Pattern(101) 64 | .Line(10, 10, 160, 10, 42) 65 | .Pattern(102) 66 | .Line(170, 10, 350, 10, 42) 67 | .Pattern(103) 68 | .Line(10, 65, 160, 65, 40) 69 | .Pattern(104) 70 | .Line(170, 65, 350, 65, 40) 71 | .Pattern(105) 72 | .Line(10, 115, 160, 115, 40) 73 | .Pattern(106) 74 | .Line(170, 115, 350, 115, 40) 75 | .Form() 76 | .Print(); 77 | Build(); 78 | } 79 | 80 | [Fact] 81 | public void Test_ExpandedGraphics() 82 | { 83 | Command.WriteRawLine("! 0 200 200 210 1") 84 | .ExpandedGraphics(2, 16, 90, 45, "F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0FF0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F") 85 | .Form() 86 | .Print(); 87 | Build(); 88 | } 89 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.Other.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace Bing.EasyPrint.Tests.CPCL; 7 | 8 | // ReSharper disable once InconsistentNaming 9 | partial class CPCLPrintCommandTest 10 | { 11 | [Fact] 12 | public void Test_GetLineMaxLength() 13 | { 14 | var cLength = GetLineMaxLength(77 * 8, 12); 15 | var sb = new StringBuilder(); 16 | for (var i = 0; i < cLength; i++) 17 | sb.Append("-"); 18 | 19 | Command 20 | .InitCommand(0, 78*8, 200, 1) 21 | //.WriteRawLine("SETMAG 1 1") 22 | .WriteRawLine($"T 03 0 0 20 {sb.ToString()}") 23 | //.WriteRawLine("SETMAG 0 0") 24 | .Print(); 25 | Build(); 26 | } 27 | 28 | private static int GetLineMaxLength(int width, int fontSize) => width / fontSize; 29 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.QrCode.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Bing.EasyPrint.Tests.CPCL; 4 | 5 | // ReSharper disable once InconsistentNaming 6 | partial class CPCLPrintCommandTest 7 | { 8 | [Fact] 9 | public void Test_QrCode_1() 10 | { 11 | Command.WriteRawLine("! 0 200 200 500 1") 12 | .QRCode(10, 100, 2, 10, "M", null, "QR code ABC123") 13 | .Text(4, 0, 10, 400, "QR code ABC123") 14 | .Form() 15 | .Print(); 16 | Build(); 17 | } 18 | 19 | [Fact] 20 | public void Test_Aztec() 21 | { 22 | Command.WriteRawLine("! 0 200 200 600 1") 23 | .Text(7, 0, 50, 0, "Aztec Code - Label Spec 5-1 EC=47") 24 | .Aztec(50, 100, 7, 47, "123456789012") 25 | .Print(); 26 | Build(); 27 | } 28 | 29 | [Fact] 30 | public void Test_BarcodeRss() 31 | { 32 | Command.WriteRawLine("! 0 200 200 300 1") 33 | .Text("5", 0, 10, 40, "RSS14 Composite") 34 | .BarcodeRss(10, 110, 2, 25, 3, 22, 5, "1234567890123", "1234567890") 35 | .Print(); 36 | Build(); 37 | } 38 | 39 | [Fact] 40 | public void Test_Pdf417() 41 | { 42 | Command.WriteRawLine("! 0 200 200 300 1") 43 | .Text("5", 0, 10, 40, "RSS14 Composite") 44 | .Pdf417(10, 20, 3, 12, 3, 2, "PDF Data", "ABCDE12345") 45 | .Print(); 46 | Build(); 47 | } 48 | 49 | [Fact] 50 | public void Test_Maxicode() 51 | { 52 | Command.WriteRawLine("! 0 200 200 600 1") 53 | .WriteRawLine("JOURNAL") 54 | .Maxicode(20, 20, ("CC", "12345"), ("MSG", "This is a MAXICODE low priority message."), ("SC", "12345"), ("POST", "02886")) 55 | .Print(); 56 | Build(); 57 | } 58 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/CPCL/CPCLPrintCommandTest.cs: -------------------------------------------------------------------------------- 1 | using Bing.EasyPrint.CPCL; 2 | using Xunit.Abstractions; 3 | 4 | namespace Bing.EasyPrint.Tests.CPCL; 5 | 6 | /// 7 | /// CPCL 打印命令测试 8 | /// 9 | // ReSharper disable once InconsistentNaming 10 | public partial class CPCLPrintCommandTest : TestBase 11 | { 12 | /// 13 | /// CPCL 打印命令 14 | /// 15 | protected CPCLPrintCommand Command { get; set; } 16 | 17 | /// 18 | /// 初始化一个类型的实例 19 | /// 20 | /// 输出 21 | public CPCLPrintCommandTest(ITestOutputHelper output) : base(output) 22 | { 23 | IEasyPrint print = new DefaultEasyPrint(); 24 | Command = print.CreateCPCLCommand(); 25 | } 26 | 27 | /// 28 | /// 构建 29 | /// 30 | private void Build() 31 | { 32 | var result = Command.Build(); 33 | Output.WriteLine("----------------------------- 调试命令 ---------------------------------------"); 34 | Output.WriteLine(result.ToString()); 35 | Output.WriteLine("----------------------------- 调试命令-十六进制 ---------------------------------------"); 36 | Output.WriteLine(result.ToHex()); 37 | Output.WriteLine("----------------------------- 执行命令 ---------------------------------------"); 38 | Print(result.GetBytes()); 39 | } 40 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/RawPrinterHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace Bing.EasyPrint.Tests; 7 | 8 | /// 9 | /// 命令打印帮助类 10 | /// 11 | public class RawPrinterHelper 12 | { 13 | // Structure and API declarions: 14 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 15 | public class DOCINFOA 16 | { 17 | [MarshalAs(UnmanagedType.LPStr)] 18 | public string pDocName; 19 | [MarshalAs(UnmanagedType.LPStr)] 20 | public string pOutputFile; 21 | [MarshalAs(UnmanagedType.LPStr)] 22 | public string pDataType; 23 | } 24 | [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 25 | public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); 26 | 27 | [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 28 | public static extern bool ClosePrinter(IntPtr hPrinter); 29 | 30 | [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 31 | public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di); 32 | 33 | [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 34 | public static extern bool EndDocPrinter(IntPtr hPrinter); 35 | 36 | [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 37 | public static extern bool StartPagePrinter(IntPtr hPrinter); 38 | 39 | [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 40 | public static extern bool EndPagePrinter(IntPtr hPrinter); 41 | 42 | [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 43 | public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten); 44 | 45 | // SendBytesToPrinter() 46 | // When the function is given a printer name and an unmanaged array 47 | // of bytes, the function sends those bytes to the print queue. 48 | // Returns true on success, false on failure. 49 | public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) 50 | { 51 | Int32 dwError = 0, dwWritten = 0; 52 | IntPtr hPrinter = new IntPtr(0); 53 | DOCINFOA di = new DOCINFOA(); 54 | bool bSuccess = false; // Assume failure unless you specifically succeed. 55 | 56 | di.pDocName = "RAW Document"; 57 | // Win7 58 | di.pDataType = "RAW"; 59 | 60 | // Win8+ 61 | // di.pDataType = "XPS_PASS"; 62 | 63 | // Open the printer. 64 | if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 65 | { 66 | // Start a document. 67 | if (StartDocPrinter(hPrinter, 1, di)) 68 | { 69 | // Start a page. 70 | if (StartPagePrinter(hPrinter)) 71 | { 72 | // Write your bytes. 73 | bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 74 | EndPagePrinter(hPrinter); 75 | } 76 | EndDocPrinter(hPrinter); 77 | } 78 | ClosePrinter(hPrinter); 79 | } 80 | // If you did not succeed, GetLastError may give more information 81 | // about why not. 82 | if (bSuccess == false) 83 | { 84 | dwError = Marshal.GetLastWin32Error(); 85 | } 86 | return bSuccess; 87 | } 88 | 89 | public static bool SendBytesToPrinter(string szPrinterName, byte[] data) 90 | { 91 | var pUnmanagedBytes = Marshal.AllocCoTaskMem(data.Length); // Allocate unmanaged memory 92 | Marshal.Copy(data, 0, pUnmanagedBytes, data.Length); // copy bytes into unmanaged memory 93 | var retval = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, data.Length); 94 | Marshal.FreeCoTaskMem(pUnmanagedBytes); // Free the allocated unmanaged memory 95 | 96 | return retval; 97 | } 98 | 99 | public static bool SendFileToPrinter(string szPrinterName, string szFileName) 100 | { 101 | // Open the file. 102 | FileStream fs = new FileStream(szFileName, FileMode.Open); 103 | // Create a BinaryReader on the file. 104 | BinaryReader br = new BinaryReader(fs); 105 | // Dim an array of bytes big enough to hold the file's contents. 106 | Byte[] bytes = new Byte[fs.Length]; 107 | bool bSuccess = false; 108 | // Your unmanaged pointer. 109 | IntPtr pUnmanagedBytes = new IntPtr(0); 110 | int nLength; 111 | 112 | nLength = Convert.ToInt32(fs.Length); 113 | // Read the contents of the file into the array. 114 | bytes = br.ReadBytes(nLength); 115 | // Allocate some unmanaged memory for those bytes. 116 | pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); 117 | // Copy the managed byte array into the unmanaged array. 118 | Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength); 119 | // Send the unmanaged bytes to the printer. 120 | bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); 121 | // Free the unmanaged memory that you allocated earlier. 122 | Marshal.FreeCoTaskMem(pUnmanagedBytes); 123 | fs.Close(); 124 | fs.Dispose(); 125 | fs = null; 126 | return bSuccess; 127 | } 128 | public static bool SendStringToPrinter(string szPrinterName, string szString) 129 | { 130 | IntPtr pBytes; 131 | Int32 dwCount; 132 | // How many characters are in the string? 133 | dwCount = szString.Length; 134 | // Assume that the printer is expecting ANSI text, and then convert 135 | // the string to ANSI text. 136 | pBytes = Marshal.StringToCoTaskMemAnsi(szString); 137 | // Send the converted ANSI string to the printer. 138 | SendBytesToPrinter(szPrinterName, pBytes, dwCount); 139 | Marshal.FreeCoTaskMem(pBytes); 140 | return true; 141 | } 142 | 143 | //if you want a wrapper function for you strings : 144 | public static bool SendAsciiToPrinter(string szPrinterName, string data) 145 | { 146 | var retval = false; 147 | 148 | //if you are using UTF-8 and get wrong values in qrcode printing, you must use ASCII instead. 149 | //retval = SendBytesToPrinter(szPrinterName, Encoding.UTF8.GetBytes(data)); 150 | retval = SendBytesToPrinter(szPrinterName, Encoding.ASCII.GetBytes(data)); 151 | 152 | return retval; 153 | } 154 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/SimpleTest.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Xunit; 3 | 4 | namespace Bing.EasyPrint.Tests; 5 | 6 | /// 7 | /// 简单测试 8 | /// 9 | public class SimpleTest 10 | { 11 | /// 12 | /// 测试 - 初始化命令 13 | /// 14 | [Theory] 15 | [InlineData("! 0 200 200 210 1\r\n", true)] 16 | [InlineData("! 0 200 200 210 1", true)] 17 | [InlineData("! 0 200 200 210 1 AAA", false)] 18 | [InlineData("! 0 200 200 210 1\r\nAAA", false)] 19 | public void Test_InitCommand(string input, bool target) 20 | { 21 | var pattern = "^!\\s[0-9]\\s[0-9]+\\s[0-9]+\\s[0-9]+\\s[0-9]+\\s{0,1}$"; 22 | var result = Regex.IsMatch(input, pattern); 23 | Assert.Equal(target, result); 24 | } 25 | 26 | /// 27 | /// 测试 - 打印命令 28 | /// 29 | [Theory] 30 | [InlineData("PRINT\r\n", true)] 31 | [InlineData("PRINT", true)] 32 | [InlineData("PRINT AAA", false)] 33 | [InlineData("PRINT\r\nAAA", false)] 34 | public void Test_PrintCommand(string input, bool target) 35 | { 36 | var pattern = "^PRINT\\s{0,1}$"; 37 | var result = Regex.IsMatch(input, pattern); 38 | Assert.Equal(target, result); 39 | } 40 | 41 | /// 42 | /// 测试 - 页宽命令 43 | /// 44 | [Theory] 45 | [InlineData("PAGE-WIDTH 500\r\n", true)] 46 | [InlineData("PAGE-WIDTH 500", true)] 47 | [InlineData("PAGE-WIDTH 500 AAA", false)] 48 | [InlineData("PAGE-WIDTH 500\r\nAAA", false)] 49 | [InlineData("PW 500\r\n", true)] 50 | [InlineData("PW 500", true)] 51 | [InlineData("PW 500 AAA", false)] 52 | [InlineData("PW 500\r\nAAA", false)] 53 | public void Test_PageWidthCommand(string input, bool target) 54 | { 55 | var pattern = "^(PAGE-WIDTH|PW)\\s[0-9]+\\s{0,1}$"; 56 | var result = Regex.IsMatch(input, pattern); 57 | Assert.Equal(target, result); 58 | } 59 | } -------------------------------------------------------------------------------- /tests/Bing.EasyPrint.Tests/TestBase.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Xunit.Abstractions; 3 | 4 | namespace Bing.EasyPrint.Tests; 5 | 6 | /// 7 | /// 测试基类 8 | /// 9 | public abstract class TestBase 10 | { 11 | /// 12 | /// 输出 13 | /// 14 | protected ITestOutputHelper Output { get; } 15 | 16 | /// 17 | /// 初始化一个类型的实例 18 | /// 19 | /// 输出 20 | protected TestBase(ITestOutputHelper output) 21 | { 22 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 23 | Output = output; 24 | } 25 | 26 | /// 27 | /// 打印 28 | /// 29 | /// 字节数组 30 | protected bool Print(byte[] bytes) => RawPrinterHelper.SendBytesToPrinter("Zicox CS4", bytes); 31 | 32 | /// 33 | /// 打印 34 | /// 35 | /// 字符串 36 | protected bool Print(string str) => RawPrinterHelper.SendStringToPrinter("Zicox CS4", str); 37 | } -------------------------------------------------------------------------------- /version.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 0 5 | 0 6 | 20231115-1 7 | $(VersionMajor).$(VersionMinor).$(VersionPatch) 8 | 9 | 10 | --------------------------------------------------------------------------------