Python:使用Windows API创建日文/中文文本的Unicode呈现

时间:2012-06-28 02:39:24

标签: python winapi unicode fonts render

我正在尝试使用Python程序从Excel .xls文件中读取一系列非西方(日文/中文)Unicode字符串,并为每个字符串创建一个图像文件。 xlrd模块为我提供了Excel文件中的Unicode字符串,它们可以正确显示。

previous question的回答提供了一些在Python中使用Windows API将普通西方文本呈现为图像文件的基本元素。但是,如果我更改为基本调用以从Unicode文本字符串中呈现2个日语字符:

f = Win32Font("MS Gothic", 24)
im = f.renderText(u'\u30bb\u30c3')
im.save("hope.png")

代码失败:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

使用Windows API正确呈现Unicode字符串的任何帮助都将非常感激。

3 个答案:

答案 0 :(得分:0)

您需要使用Win32Api的Unicode版本。通过快速浏览其他问题的链接,您在win32gui.DrawTextW实施中至少需要win32ui.DrawText而不是Win32Font。注意win32 g ui是本机API而不是win32ui包含的MFC API。我在pywin32文档的快速浏览中没有看到使用Unicode版本的MFC调用的方法,因此您需要使用{{1}从PyCDC中获取本机句柄将它与原生API一起使用。

如果您需要更多帮助,请发布完整示例。

答案 1 :(得分:0)

我花了几十个小时寻找一个unicode ... W win32 ...函数,直到Mark Tolonen的答案,我已经立即将其实现为一个工作示例,其代码如下所示。如果一切正常,你的打印机应该输出一个字符串“汉字,にほんご,עברית,عربي我都会刷出。”。

# -*- coding: utf-8 -*-

import win32ui, win32con, win32gui, win32print, traceback

# init, bla bla bla
printername = win32print.GetDefaultPrinter()
hprinter = win32print.OpenPrinter(printername)
# load default settings
devmode = win32print.GetPrinter(hprinter, 8)["pDevMode"]
# this is where it gets INTERESTING:
# after the following two lines, use:
# dc for win32ui calls like LineTo, SelectObject, ...
# hdc for DrawTextW, your *MAGIC* function that supports unicode output
hdc = win32gui.CreateDC("WINSPOOL", printername, devmode)
dc = win32ui.CreateDCFromHandle(hdc)

# 1440 twips = 1 inch
dc.SetMapMode(win32con.MM_TWIPS)
# 20 twips = 1 pt
scale_factor = 20

# start the document, description as unicode
description = u'Test1'
dc.StartDoc(description)

# when working with the printer, enclose any potentially failing calls within a try block,
# because if you do not properly end the print job (see bottom), after a couple of such failures,
# you might need to restart windows as it runs out of handles or something and starts
# behaving in an unpredictable way, some documents fail to print, you cannot open windows, etc.

try :

    # Use a font
    font = win32ui.CreateFont({
        "name": "Arial Unicode MS", # a font name
        "height": int(scale_factor * 10), # 10 pt
        "weight": 400, # 400 = normal
    })

    # use dc -- SelectObject is a win32ui call
    dc.SelectObject(font)

    # this is the miracle where the unicode text gets to be printed; notice hdc,
    # not dc, for DrawTextW uses a different handle, i have found this in other posts
    win32gui.DrawTextW (hdc, u"\u6C49\u5B57\u3001\u306B\u307B\u3093\u3054\u3001\u05E2\u05D1\u05E8\u05D9\u05EA\u3001\u0639\u0631\u0628\u064A\u6211\u90FD\u4F1A\u5237\u51FA\u3002", -1, (0, -2000, 4000, -4000), win32con.DT_CENTER)

except :
    traceback.print_exc()

# must not forget to tell Windows we're done. This line must get called if StartDoc 
# was called, if you fail to do so, your sys might start behaving unexpectedly
dc.EndDoc()

答案 2 :(得分:0)

# -*- coding: utf-8 -*-

import win32ui, win32con, win32gui, win32print, traceback

# init, bla bla bla
printername = win32print.GetDefaultPrinter()
hprinter = win32print.OpenPrinter(printername)
# load default settings
devmode = win32print.GetPrinter(hprinter, 8)["pDevMode"]
# this is where it gets INTERESTING:
# after the following two lines, use:
# dc for win32ui calls like LineTo, SelectObject, ...
# hdc for DrawTextW, your *MAGIC* function that supports unicode output
hdc = win32gui.CreateDC("WINSPOOL", printername, devmode)
dc = win32ui.CreateDCFromHandle(hdc)

# 1440 twips = 1 inch
dc.SetMapMode(win32con.MM_TWIPS)
# 20 twips = 1 pt
scale_factor = 20

# start the document, description as unicode
description = u'Test1'
dc.StartDoc(description)

# when working with the printer, enclose any potentially failing calls within a try block,
# because if you do not properly end the print job (see bottom), after a couple of such failures,
# you might need to restart windows as it runs out of handles or something and starts
# behaving in an unpredictable way, some documents fail to print, you cannot open windows, etc.

try :

    # Use a font
    font = win32ui.CreateFont({
        "name": "Arial Unicode MS", # a font name
        "height": int(scale_factor * 10), # 10 pt
        "weight": 400, # 400 = normal
    })

    # use dc -- SelectObject is a win32ui call
    dc.SelectObject(font)

    # this is the miracle where the unicode text gets to be printed; notice hdc,
    # not dc, for DrawTextW uses a different handle, i have found this in other posts
    win32gui.DrawTextW (hdc, u"\u6C49\u5B57\u3001\u306B\u307B\u3093\u3054\u3001\u05E2\u05D1\u05E8\u05D9\u05EA\u3001\u0639\u0631\u0628\u064A\u6211\u90FD\u4F1A\u5237\u51FA\u3002", -1, (0, -2000, 4000, -4000), win32con.DT_CENTER)

except :
    traceback.print_exc()

# must not forget to tell Windows we're done. This line must get called if StartDoc 
# was called, if you fail to do so, your sys might start behaving unexpectedly
dc.EndDoc()


如何使用这段代码打印bmp文件?我需要打印二维码 我有 bmp 文件 我收到此错误 - ( win32gui.DrawTextW(hdc, img, -1, (0, -2100, 4000, -4000), win32con.DT_CENTER) 类型错误:“PilImage”类型的对象无法转换为 Unicode。)