zoukankan      html  css  js  c++  java
  • Python win32print

    python 调用win32print

    背景

    POS机打印小票含有中文, 英文, 高棉语、图片等信息,高棉语的无法正常输出。原因是大多嵌入式打印小票打印机只提供了英文字库,国产的做了中文字库的装载。而类似小国家的非常的库没有厂商愿做。

    解决办法(Windows 平台)

    • 适配字库, 然后调用DLL;
    • 生成word docx、txt、rtf文件, 调用print 命令打印;
    • win32 api把打印合成图片, 使用win32print以图片bmp格式打印;

    前提是已配置好打印机,可以在word或记事本里能正常打印

    
    HORZRES = 8
    VERTRES = 10
    LOGPIXELSX = 88
    LOGPIXELSY = 90
    PHYSICALWIDTH = 110
    PHYSICALHEIGHT = 111
    
    from PIL import ImageWin
    import win32gui, win32ui, win32print, win32con, win32api
    
    scale_factor = 20
    
    pr_dict = dict()
    
    paper_sizes = {
        "letter": 1,
        "lettersmall": 2,
        "tabloid": 3,
        "ledger": 4,
        "legal": 5,
        "statement": 6,
        "executive": 7,
        "a3": 8,
        "a4": 9,
        "envelope9": 19,
        "envelope10": 20,
        "envelope11": 21,
        "envelope12": 22,
        "envelope14": 23,
        "fanfold": 39,
    }
    
    orientations = {
        "portrait": 1,
        "landscape": 2,
    }
    
    duplexes = {
        "normal": 1,
        "none": 1,
        "long": 2,
        "short": 3,
    }
    
    
    class Document:
    
        def __init__(self, printer=None, paper_size=None, orientation=None, duplex=None):
            self.dc = None
            self.font = None
            self.printer = printer
            self.paper_size = paper_size
            self.orientation = orientation
            self.page = 0
            self.duplex = duplex
            self.pen = None
            self.hdc = None
            self.h_printer = None
    
        def scale_pos(self, pos):
            rc, _ = list(), self
            for i in range(len(pos)):
                p = pos[i]
                if i % 2:
                    p *= -1
                rc.append(int(p * scale_factor))
            return tuple(rc)
    
        def begin_document(self, name="DMallPOS print job"):
            # open the printer
            if self.printer is None:
                self.printer = win32print.GetDefaultPrinter()
            self.h_printer = win32print.OpenPrinter(self.printer)
    
            # load default settings
            dev_mode = win32print.GetPrinter(self.h_printer, 8)["pDevMode"]
    
            # change paper size and orientation
            if self.paper_size is not None:
                if type(self.paper_size) is int:
                    dev_mode.PaperSize = self.paper_size
                else:
                    dev_mode.PaperSize = paper_sizes[self.paper_size]
            if self.orientation is not None:
                dev_mode.Orientation = orientations[self.orientation]
            if self.duplex is not None:
                dev_mode.Duplex = duplexes[self.duplex]
    
            # create dc using new settings
            self.hdc = win32gui.CreateDC("WINSPOOL", self.printer, dev_mode)
            self.dc = win32ui.CreateDCFromHandle(self.hdc)
    
            # self.dc = win32ui.CreateDC()
            # if self.printer is not None:
            #     self.dc.CreatePrinterDC(self.printer)
            # else:
            #     self.dc.CreatePrinterDC()
    
            self.dc.SetMapMode(win32con.MM_TWIPS)  # hundredths of inches
            self.dc.StartDoc(name)
            self.dc.SetBkMode(win32con.TRANSPARENT)
            self.pen = win32ui.CreatePen(0, int(scale_factor), 0)
            self.dc.SelectObject(self.pen)
            win32gui.SetBkMode(self.hdc, 1)  # transparent
            self.page = 1
    
        def end_document(self):
            if self.page == 0:
                return  # document was never started
            self.dc.EndDoc()
            del self.dc
    
        def end_page(self):
            if self.page == 0:
                return  # nothing on the page
            # end page gets stupid if the page is completely blank
            self.text((1, 1), " ")
            self.dc.EndPage()
            self.page += 1
    
        def getsize(self):
            if not self.page:
                self.begin_document()
            # returns printable (width, height) in points
            width = float(self.dc.GetDeviceCaps(HORZRES)) * (72.0 / self.dc.GetDeviceCaps(LOGPIXELSX))
            height = float(self.dc.GetDeviceCaps(VERTRES)) * (72.0 / self.dc.GetDeviceCaps(LOGPIXELSY))
            return width, height
    
        def line(self, from_, to):
            if not self.page:
                self.begin_document()
            self.dc.MoveTo(self.scale_pos(from_))
            self.dc.LineTo(self.scale_pos(to))
    
        def rectangle(self, box):
            if not self.page:
                self.begin_document()
            self.dc.MoveTo(self.scale_pos((box[0], box[1])))
            self.dc.LineTo(self.scale_pos((box[2], box[1])))
            self.dc.LineTo(self.scale_pos((box[2], box[3])))
            self.dc.LineTo(self.scale_pos((box[0], box[3])))
            self.dc.LineTo(self.scale_pos((box[0], box[1])))
    
        def text(self, position, text):
            if self.page == 0:
                self.begin_document()
            self.dc.TextOut(int(scale_factor * position[0]),
                            int(-1 * scale_factor * position[1]), text)
    
        def set_font(self, name, size, bold=None, italic=None):
            if not self.page:
                self.begin_document()
            wt = 400
            if bold:
                wt = 700
            if italic:
                italic = 1
            else:
                italic = 0
            self.font = get_font(name, size, wt, italic)
            self.dc.SelectObject(self.font)
    
        def image(self, position, image, size):
            """print PIL image at position with given size"""
            if ImageWin is None:
                raise Exception()
            if self.page == 0:
                self.begin_document()
            dib = ImageWin.Dib(image)
            end_pos = (position[0] + size[0], position[1] + size[1])
            dst = (position[0] * scale_factor, -1 * position[1] * scale_factor,
                   end_pos[0] * scale_factor, -1 * end_pos[1] * scale_factor)
            dib.draw(self.hdc, dst)
    
        def set_ink(self, ink):
            win32gui.SetTextColor(self.hdc, win32api.RGB(*ink))
    
        def set_fill(self, on_off):
            pass
    
    
    def build_dict():
        global pr_dict
        lst = win32print.EnumPrinters(
            win32print.PRINTER_ENUM_CONNECTIONS
            + win32print.PRINTER_ENUM_LOCAL)
        pr_dict = {}
        for flags, description, name, comment in lst:
            pr_dict[name] = {}
            pr_dict[name]["flags"] = flags
            pr_dict[name]["description"] = description
            pr_dict[name]["comment"] = comment
    
    
    def list_printers():
        dft = win32print.GetDefaultPrinter()
        if pr_dict is None:
            build_dict()
        keys = pr_dict.keys()
        keys.sort()
        rc = [dft]
        for k in keys:
            if k != dft:
                rc.append(k)
        return rc
    
    
    def desc(name):
        not pr_dict and list_printers()
        return pr_dict[name]
    
    
    def get_font(name, size, weight=400, italic=0):
        if italic:
            return win32ui.CreateFont({"name": name, "height": scale_factor * size, "weight": weight, "italic": italic,})
        else:
            return win32ui.CreateFont({"name": name, "height": scale_factor * size, "weight": weight, })
    
    
    if __name__ == "__main__":
        doc = Document(orientation="portrait")
        doc.begin_document()
        doc.set_font("Khmer UI", 12, bold=True)
        doc.text((0, 0), "ញ្ចូលមាតិកាជាភាសាខ្មែរដែលអ្នកចង់បកប្រែខាងក្រោម")
        doc.set_font("Khmer UI", 12, bold=False)
        doc.text((0, 48), "ញ្ចូលមាតិកាជាភាសាខ្មែរដែលអ្នកចង់បកប្រែខាងក្រោម")
    
        doc.set_font("宋体", 12)
        doc.text((0, 48 + 48), "羅拔臣什味啫喱粉")
        # doc.rectangle((72, 72, 72*6, 72*3))
        # doc.line((72, 72), (72*6, 72*3))
        from PIL import Image
    
        img = Image.open("a.bmp", )
        doc.image((0, 100), img, img.size)
        doc.end_document()
    
        from win32com import client
        c = client.Dispatch("OPOS.CashDrawer")
        c.Open("StanderU")
        c.ClaimDevice(1000)
        c.DeviceEnabled = True
        c.OpenDrawer()
        c.DeviceEnabled = False
        c.Release()
        c.Close()
    
    

    参考

    代码
    字体

  • 相关阅读:
    ALV 填值返回更新屏幕
    alv 的几种形式 和 函数
    JS 截取字符串的空格
    codeigniter 轻量级架构知识初习
    之前的博客挂掉了
    在服务器上运行php文件来执行操作
    浏览器判断
    php 汉字判断
    web 套打方法实现打印机功能
    WIN8
  • 原文地址:https://www.cnblogs.com/onsunsl/p/python_call_win32print_print_unicode.html
Copyright © 2011-2022 走看看