jjzjj

c# - 在 C# WPF 中编写漂亮的收据以在热敏打印机 POS 上打印

coder 2024-05-18 原文

我正在尝试在我的一个项目中实现打印功能,但我不太擅长这种工作。

我已经连接到我的热敏打印机并写入/打印相同的样本。 现在我正在尝试找到一些方法来设计我的收据,使其看起来像来自附加图像的收据。

我有一些想法,但我不确定它们是否适用于这种工作,其中之一是尝试将我的收据格式化为 html 并将它们渲染为 html,如位图(图像),然后打印它,我已经试过了,但看起来我的质量有所下降。

如果有人对我如何使收据看起来像图片有任何其他想法,请与我分享此信息,我将非常感激。

这是我已经为打印一些示例所做的,我使用 graphics.DrawString 进行格式化,但我认为使用它我无法完成太多工作。

public void Print()
{
    var doc = new PrintDocument();
    doc.PrintPage += new PrintPageEventHandler(ProvideContent);
    doc.Print();
}

public void ProvideContent(object sender, PrintPageEventArgs e)
{
    Graphics graphics = e.Graphics;
    Font font = new Font("Courier New", 10);

    float fontHeight = font.GetHeight();

    int startX = 0;
    int startY = 0;
    int Offset = 20;

    e.PageSettings.PaperSize.Width = 50;
    graphics.DrawString("Welcome to MSST", new Font("Courier New", 8),
                        new SolidBrush(Color.Black), startX, startY + Offset);
    Offset = Offset + 20;

    graphics.DrawString("Ticket No:" + "4525554654545",
                new Font("Courier New", 14),
                new SolidBrush(Color.Black), startX, startY + Offset);
    Offset = Offset + 20;


    graphics.DrawString("Ticket Date :" + "21/12/215",
                new Font("Courier New", 14),
                new SolidBrush(Color.Black), startX, startY + Offset);

    Offset = Offset + 20;
    String underLine = "------------------------------------------";

    graphics.DrawString(underLine, new Font("Courier New", 14),
                new SolidBrush(Color.Black), startX, startY + Offset);

    Offset = Offset + 20;
    String Grosstotal = "Total Amount to Pay = " + "2566";

    Offset = Offset + 20;
    underLine = "------------------------------------------";
    graphics.DrawString(underLine, new Font("Courier New", 14),
                new SolidBrush(Color.Black), startX, startY + Offset);
    Offset = Offset + 20;

    graphics.DrawString(Grosstotal, new Font("Courier New", 14),
                new SolidBrush(Color.Black), startX, startY + Offset);

}

最佳答案

在过去这样做时,我将收据分成单独的部分,使用不同的字体或对齐方式,例如页眉、正文、页脚。

我使用以下类布局来封装我的打印文本定义。 (你从哪里获得字体以及如何管理它的生命周期取决于你)

public class PrintText
{
    public PrintText(string text, Font font) : this(text, font, new StringFormat()) {}

    public PrintText(string text, Font font, StringFormat stringFormat)
    {
        Text = text;
        Font = font;
        StringFormat = stringFormat;
    }

    public string Text { get; set; }

    public Font Font { get; set; }

    /// <summary> Default is horizontal string formatting </summary>
    public StringFormat StringFormat { get; set; }
}

当有较长的文本列表使用相同的字体和填充时,使用 stringbuilder 来构建您的文本会让生活变得轻松,因此您只需检查代码就可以直观地了解它的外观。

如果你有静态文本,你可以把它们放在一起:

var sb = new StringBuilder();
sb.AppendLine("Start of receipt");
sb.AppendLine("================");
sb.AppendLine("Item 1");
sb.AppendLine("Item 2");
sb.AppendLine("================");

或者如果数据有点动态传递给一些对象,你可以遍历并附加你的格式化文本:

private class ReceiptItem
{
    public string Name { get; set; }

    public decimal Cost { get; set; }

    public int Amount { get; set; }

    public int Discount { get; set; }

    public decimal Total { get { return Cost * Amount; } }
}
const int FIRST_COL_PAD = 20;
const int SECOND_COL_PAD = 7;
const int THIRD_COL_PAD = 20;

var sb = new StringBuilder();
sb.AppendLine("Start of receipt");
sb.AppendLine("================");

foreach (var item in receiptItems)
{
    sb.Append(item.Name.PadRight(FIRST_COL_PAD));

    var breakDown = item.Amount > 0 ? item.Amount + "x" + item.Cost : string.Empty;
    sb.Append(breakDown.PadRight(SECOND_COL_PAD));

    sb.AppendLine(string.Format("{0:0.00} A", item.Total).PadLeft(THIRD_COL_PAD));

    if (item.Discount > 0)
    {
        sb.Append(string.Format("DISCOUNT {0:D2}%", item.Discount).PadRight(FIRST_COL_PAD + SECOND_COL_PAD));
        sb.Append(string.Format("{0:0.00} A", -(item.Total / 100 * item.Discount)).PadLeft(THIRD_COL_PAD));
        sb.AppendLine();
    }
}

sb.AppendLine("================");

输出如下:

Start of receipt
================
Joes Food           1x10      10.00 A
DISCOUNT 10%                  -1.00 A
Fun Facts           1x20      20.00 A
DISCOUNT 15%                  -3.00 A
Bag of Sand         7x40     280.00 A
================

使用前面的 PrintText 类,我们可以存储格式良好的字符串构建器输出

var printText = new PrintText(sb.ToString(), new Font("Monospace Please...", 8));

最后在尝试绘制字符串时使用它

var layoutArea = new SizeF(AvailableWidth, 0);
SizeF stringSize = g.MeasureString(printText.Text, printText.Font, layoutArea, printText.StringFormat);

RectangleF rectf = new RectangleF(new PointF(), new SizeF(AvailableWidth, stringSize.Height));

g.DrawString(printText.Text, printText.Font, Brushes.Black, rectf, printText.StringFormat);

如果文本打印不正确,您还可以尝试一些不同的图形调整,例如:

g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;

关于c# - 在 C# WPF 中编写漂亮的收据以在热敏打印机 POS 上打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28096578/

有关c# - 在 C# WPF 中编写漂亮的收据以在热敏打印机 POS 上打印的更多相关文章

  1. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  2. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  4. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. ruby-on-rails - 如何为空白字段编写 rspec? [Rails3.1] - 2

    我使用rails3.1+rspec和factorygirl。我对必填字段(validates_presence_of)的验证工作正常。我如何让测试将该事实用作“成功”而不是“失败”规范是:describe"Addanindustrywithnoname"docontext"Unabletocreatearecordwhenthenameisblank"dosubjectdoind=Factory.create(:industry_name_blank)endit{shouldbe_invalid}endend但是我失败了:Failures:1)Addanindustrywithnona

  8. ruby - 是否有用于复杂比较的漂亮语法? - 2

    方法应返回-1,0或1分别表示“小于”、“等于”和“大于”。对于某些类型的可排序对象,通常将排序顺序基于多个属性。以下是可行的,但我认为它看起来很笨拙:classLeagueStatsattr_accessor:points,:goal_diffdefinitializepts,gd@points=pts@goal_diff=gdenddefothercompare_pts=pointsother.pointsreturncompare_ptsunlesscompare_pts==0goal_diffother.goal_diffendend尝试一下:[LeagueStats.new(

  9. ruby - 如何打印 ruby​​ 对象的实例变量 - 2

    classPacketdefinitialize(name,age,number,array)@name=name@age=age@number=number@neighbors=arrayendendp1=Packet.new("n1",5,2,[1,2,3,4])putsp1.name我有上面的代码,但是每当我执行puts语句时,我都会收到nameisnotamethod的错误。我不知道任何其他方式来打印p1的名称。如何打印姓名? 最佳答案 这里的问题是,虽然您拥有实例变量,但您并未使它们可访问。attr_reader:vari

  10. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

随机推荐