#------------------------------------------------------------------------------ # # PyGUI - Printing - Win32 # #------------------------------------------------------------------------------ import WinPageSetup as wps, WinPrint as wp import win32print as wp2 from GUI.GPrinting import PageSetup as GPageSetup, Printable as GPrintable, \ Paginator from GUI import Canvas #------------------------------------------------------------------------------ win_paper_names = { 1: "Letter", # Letter 8 1/2 x 11 in 2: "Letter Small", # Letter Small 8 1/2 x 11 in 3: "Tabloid", # Tabloid 11 x 17 in 4: "Ledger", # Ledger 17 x 11 in 5: "Legal", # Legal 8 1/2 x 14 in 6: "Statement", # Statement 5 1/2 x 8 1/2 in 7: "Executive", # Executive 7 1/4 x 10 1/2 in 8: "A3", # A3 297 x 420 mm 9: "A4", # A4 210 x 297 mm 10: "A4 Small", # A4 Small 210 x 297 mm 11: "A5", # A5 148 x 210 mm 12: "B4 (JIS)", # B4 (JIS) 250 x 354 13: "B5 (JIS)", # B5 (JIS) 182 x 257 mm 14: "Folio", # Folio 8 1/2 x 13 in 15: "Quarto", # Quarto 215 x 275 mm 16: "10x14", # 10x14 in 17: "11x17", # 11x17 in 18: "Note", # Note 8 1/2 x 11 in 19: "Envelope #9", # Envelope #9 3 7/8 x 8 7/8 20: "Envelope #10", # Envelope #10 4 1/8 x 9 1/2 21: "Envelope #11", # Envelope #11 4 1/2 x 10 3/8 22: "Envelope #12", # Envelope #12 4 \276 x 11 23: "Envelope #14", # Envelope #14 5 x 11 1/2 24: "C Sheet", # C size sheet 25: "D Sheet", # D size sheet 26: "E Sheet", # E size sheet 27: "Envelope DL", # Envelope DL 110 x 220mm 28: "Envelope C5", # Envelope C5 162 x 229 mm 29: "Envelope C3", # Envelope C3 324 x 458 mm 30: "Envelope C4", # Envelope C4 229 x 324 mm 31: "Envelope C6", # Envelope C6 114 x 162 mm 32: "Envelope C65", # Envelope C65 114 x 229 mm 33: "Envelope B4", # Envelope B4 250 x 353 mm 34: "Envelope B5", # Envelope B5 176 x 250 mm 35: "Envelope B6", # Envelope B6 176 x 125 mm 36: "Envelope", # Envelope 110 x 230 mm 37: "Envelope Monarch", # Envelope Monarch 3.875 x 7.5 in 38: "6 3/4 Envelope", # 6 3/4 Envelope 3 5/8 x 6 1/2 in 39: "US Std Fanfold", # US Std Fanfold 14 7/8 x 11 in 40: "German Std Fanfold", # German Std Fanfold 8 1/2 x 12 in 41: "German Legal Fanfold", # German Legal Fanfold 8 1/2 x 13 in 42: "B4", # B4 (ISO) 250 x 353 mm 43: "Japanese Postcard", # Japanese Postcard 100 x 148 mm 44: "9x11", # 9 x 11 in 45: "10x11", # 10 x 11 in 46: "15x11", # 15 x 11 in 47: "Envelope Invite", # Envelope Invite 220 x 220 mm #48: "", # RESERVED--DO NOT USE #49: "", # RESERVED--DO NOT USE 50: "Letter Extra", # Letter Extra 9 \275 x 12 in 51: "Legal Extra", # Legal Extra 9 \275 x 15 in 52: "Tabloid Extra", # Tabloid Extra 11.69 x 18 in 53: "A4 Extra", # A4 Extra 9.27 x 12.69 in 54: "Letter Transverse", # Letter Transverse 8 \275 x 11 in 55: "A4 Transverse", # A4 Transverse 210 x 297 mm 56: "Letter Extra Transverse", # Letter Extra Transverse 9\275 x 12 in 57: "SuperA", # SuperA/SuperA/A4 227 x 356 mm 58: "SuperB", # SuperB/SuperB/A3 305 x 487 mm 59: "Letter Plus", # Letter Plus 8.5 x 12.69 in 60: "A4 Plus", # A4 Plus 210 x 330 mm 61: "A5 Transverse", # A5 Transverse 148 x 210 mm 62: "B5 (JIS) Transverse", # B5 (JIS) Transverse 182 x 257 mm 63: "A3 Extra", # A3 Extra 322 x 445 mm 64: "A5 Extra", # A5 Extra 174 x 235 mm 65: "B5 (ISO) Extra", # B5 (ISO) Extra 201 x 276 mm 66: "A2", # A2 420 x 594 mm 67: "A3 Transverse", # A3 Transverse 297 x 420 mm 68: "A3 Extra Transverse", # A3 Extra Transverse 322 x 445 mm } win_paper_codes = dict([(name, code) for (code, name) in win_paper_names.iteritems()]) def ti_to_pts(x): return x * 0.072 def pts_to_ti(x): return int(round(x / 0.072)) #------------------------------------------------------------------------------ class PageSetup(GPageSetup): def __new__(cls): self = GPageSetup.__new__(cls) self._win_psd = wps.get_defaults() return self def __init__(self): self.margins = (36, 36, 36, 36) def __getstate__(self): psd = self._win_psd state = GPageSetup.__getstate__(self) state['_win_devmode'] = wps.get_handle_contents(psd.hDevMode) state['_win_devnames'] = wps.get_handle_contents(psd.hDevNames) return state def __setstate__(self, state): psd = self._win_psd dm = state.pop('_win_devmode', None) dn = state.pop('_win_devnames', None) GPageSetup.__setstate__(self, state) if dm: wps.GlobalFree(psd.hDevMode) psd.hDevMode = handle_with_contents(dm) if dn: wps.GlobalFree(psd.hDevNames) psd.hDevNames = handle_with_contents(dn) def _win_lock_devmode(self): return wps.lock_devmode_handle(self._win_psd.hDevMode) def _win_unlock_devmode(self): wps.GlobalUnlock(self._win_psd.hDevMode) def get_printable_rect(self): psd = self._win_psd pw, ph = self.paper_size mm = psd.rtMinMargin ml = ti_to_pts(mm.left) mt = ti_to_pts(mm.top) mr = ti_to_pts(mm.right) mb = ti_to_pts(mm.bottom) return (ml, mt, pw - mr, ph - mb) def get_paper_name(self): dm = self._win_lock_devmode() result = win_paper_names.get(dm.dmPaperSize, "Custom") self._win_unlock_devmode() return result def set_paper_name(self, name): dm = self._win_lock_devmode() dm.dmPaperSize = win_paper_codes.get(name, 0) self._win_unlock_devmode() def get_paper_width(self): return ti_to_pts(self._win_psd.ptPaperSize.x) def get_paper_height(self): return ti_to_pts(self._win_psd.ptPaperSize.y) def set_paper_width(self, v): self._win_psd.ptPaperSize.x = pts_to_ti(v) def set_paper_height(self, v): self._win_psd.ptPaperSize.y = pts_to_ti(v) def get_left_margin(self): return ti_to_pts(self._win_psd.rtMargin.left) def get_top_margin(self): return ti_to_pts(self._win_psd.rtMargin.top) def get_right_margin(self): return ti_to_pts(self._win_psd.rtMargin.right) def get_bottom_margin(self): return ti_to_pts(self._win_psd.rtMargin.bottom) def set_left_margin(self, v): self._win_psd.rtMargin.left = pts_to_ti(v) def set_top_margin(self, v): self._win_psd.rtMargin.top = pts_to_ti(v) def set_right_margin(self, v): self._win_psd.rtMargin.right = pts_to_ti(v) def set_bottom_margin(self, v): self._win_psd.rtMargin.bottom = pts_to_ti(v) def get_orientation(self): dm = self._win_lock_devmode() result = win_orientation_names.get(dm.dmOrientation, 'portrait') self._win_unlock_devmode() return result def set_orientation(self, v): dm = self._win_lock_devmode() dm.dmOrientation = win_orientation_codes.get(v, 1) self._win_unlock_devmode() def get_printer_name(self): dm = self._win_lock_devmode() result = dm.dmDeviceName self._win_unlock_devmode() return result def set_printer_name(self, v): dm = self._win_lock_devmode() dm.dmDeviceName = v self._win_unlock_devmode() #------------------------------------------------------------------------------ class Printable(GPrintable): def print_view(self, page_setup, prompt = True): paginator = Paginator(self, page_setup) psd = page_setup._win_psd pd = wp.PRINTDLG() pd.hDevMode = psd.hDevMode pd.hDevNames = psd.hDevNames pd.nMinPage = 1 pd.nMaxPage = paginator.num_pages pd.nCopies = 1 if wp.PrintDlg(pd): title = self.print_title di = wp.DOCINFO() di.lpszDocName = title devnames = wps.DevNames(psd.hDevNames) if devnames.output == "FILE:": from FileDialogs import request_new_file f = request_new_file("Print '%s' to file:" % title) if not f: return output_path = f.path di.lpszOutput = output_path try: hdc = pd.hDC dx, dy = wp.GetPrintingOffset(hdc) print "TODO: Printable: Implement a Cancel dialog" ### #wp.install_abort_proc(hdc) wp.StartDoc(hdc, di) for page_num in xrange(pd.nFromPage - 1, pd.nToPage): wp.StartPage(hdc) canvas = Canvas._from_win_hdc(hdc, for_printing = True) canvas.translate(-dx, -dy) paginator.draw_page(canvas, page_num) wp.EndPage(hdc) wp.EndDoc(hdc) finally: wp.DeleteDC(hdc) #------------------------------------------------------------------------------ def present_page_setup_dialog(page_setup): return wps.PageSetupDlg(page_setup._win_psd)