how to create a virtual printer

eryksun () eryksun at gmail.com
Tue Mar 29 20:03:05 EDT 2011


On Monday, March 28, 2011 7:12:23 AM UTC-4, kalo... at gmail.com wrote:
> 
> Does anybody know how to create a virtual
> printer with python (on both windows and linux)?

Here's some code I just put together showing how to use Python to create a PostScript file printer on Windows, output raw text to a file, and also output text with fonts and simple line graphics. You'll need the pywin32 extensions. 

This code is only minimally tested, and it does little if any error checking. However, this is just to demonstrate the gist of using pywin32 for printing PostScript to a file. If you get an error about finding the driver for "MS Publisher Imagesetter', you may need to add the printer manually to make the driver available (it's under the 'generic' manufacturer). No doubt there's a way to install this driver automatically using the Win32 API, but I haven't looked into it.

The generated PostScript file can be viewed on Windows using the evince viewer:

http://live.gnome.org/Evince/Downloads

#

import win32print, win32ui, win32gui
import win32con, pywintypes

def create_printer(printer_name='MyPSPrinter'):
    printer_info = {
        'pPrinterName': printer_name,
        'pDevMode': pywintypes.DEVMODEType(),        
        'pDriverName': 'MS Publisher Imagesetter',
        'pPortName': 'FILE:',
        'pPrintProcessor': 'WinPrint',
        'Attributes': 0,
        'AveragePPM': 0,
        'cJobs': 0,
        'DefaultPriority': 0,
        'Priority': 0,
        'StartTime': 0,
        'Status': 0,
        'UntilTime': 0,
        'pComment': '',
        'pLocation': '',
        'pDatatype': None,
        'pParameters': None,
        'pSecurityDescriptor': None,
        'pSepFile': None,
        'pServerName': None,
        'pShareName': None}

    h_printer = win32print.AddPrinter(None, 2, printer_info)
    return h_printer


def test_raw(printer='MyPSPrinter',
             filename=r'D:\test.txt',
             text=None):
    '''send plain text to a file'''
    if text is None:
        text_data = "This is a test. This is only a test."
    else:
        text_data = text
    job_info = ("Raw File Print", filename, 'RAW')
    h_printer = win32print.OpenPrinter(printer)
    try:
        h_job = win32print.StartDocPrinter(h_printer, 1, job_info)
        try:
            win32print.StartPagePrinter(h_printer)
            win32print.WritePrinter(h_printer, text_data)
            win32print.EndPagePrinter(h_printer)
        finally:
            win32print.EndDocPrinter(h_printer)
    finally:
        win32print.ClosePrinter(h_printer)


def test_ps(printer='MyPSPrinter',
            filename=r'D:\test.ps',
            margin=(0.25,1.5,0.25,1.0),
            font_size=24,
            text=None):
    '''render postscript text and graphics to a file'''
    if text is None:
        text_data = "This is a test.\nThis is only a test."
    else:
        text_data = str(text)

    # Get the printer's DEVMODE structure
    h_printer = win32print.OpenPrinter(printer)
    devmode = win32print.GetPrinter(h_printer, 2)['pDevMode']
    win32print.ClosePrinter(h_printer)

    # set up the device context
    # see MSDN: ff552837, aa452943, dd319099, dd145045
    devmode.FormName = 'Letter'  # or 'A4'
    devmode.PaperSize = win32con.DMPAPER_LETTER  # or DMPAPER_A4
    devmode.Orientation = win32con.DMORIENT_PORTRAIT 
    devmode.PrintQuality = win32con.DMRES_HIGH
    devmode.Color = win32con.DMCOLOR_MONOCHROME
    devmode.TTOption = win32con.DMTT_SUBDEV
    devmode.Scale = 100
    devmode.Fields |= (win32con.DM_FORMNAME | 
                       win32con.DM_PAPERSIZE | 
                       win32con.DM_ORIENTATION | 
                       win32con.DM_PRINTQUALITY | 
                       win32con.DM_COLOR | 
                       win32con.DM_TTOPTION | 
                       win32con.DM_SCALE)    
    h_dc = win32gui.CreateDC('WINSPOOL', printer, devmode)
    dc = win32ui.CreateDCFromHandle(h_dc)
    dc.SetMapMode(win32con.MM_TWIPS) # or MM_HIMETRIC (0.01 mm)

    # begin writing the document
    dc.StartDoc('Postscript File Print', filename)
    dc.StartPage()

    # we need a pen and a font
    scale = 20  # 72 pt/inch * 20 twip/pt = 1440
    inch = 72*scale
    pen = win32ui.CreatePen(win32con.PS_SOLID,
                            scale, # 1 pt
                            0)     # black
    dc.SelectObject(pen)
    font = win32ui.CreateFont({
        'name': 'Times New Roman',
        'height': font_size * scale,
        'weight': win32con.FW_NORMAL})
    dc.SelectObject(font)

    # output the text
    x = int(margin[0] * inch)
    y = -int(margin[1] * inch)
    width = int((8.5 - margin[0] - margin[2]) * inch)
    height = int((11.0 - margin[1] - margin[3]) * inch)
    rect = (x, y, x + width, y - height)
    dc.DrawText(text_data, rect, win32con.DT_LEFT)
    
    if text is None:
        # draw 8 steps starting at x = 0.25", y = 3"
        width = inch
        height = inch
        for n in range(8):
            x = n * width + 18*scale
            y = -n * height - 3*inch
            dc.MoveTo((x, y))
            dc.LineTo((x + width, y))
            dc.MoveTo((x + width, y))
            dc.LineTo((x + width, y - height))

    dc.EndPage()
    dc.EndDoc()

#end



More information about the Python-list mailing list