1
#----------------------------------------------------------------------
3
# Purpose: A class that allows the use of the Acrobat PDF reader
8
# Created: 22-March-2004
9
# RCS-ID: $Id: pdfwin.py 49208 2007-10-18 00:40:21Z RD $
10
# Copyright: (c) 2004 by Total Control Software
11
# Licence: wxWindows license
12
#----------------------------------------------------------------------
16
#----------------------------------------------------------------------
20
def get_acroversion():
21
" Return version of Adobe Acrobat executable or None"
23
if _acroversion == None and wx.PlatformInfo[1] == 'wxMSW':
25
regKey = _winreg.HKEY_LOCAL_MACHINE
26
acrokeys, acroversions = [], []
28
adobesoft = _winreg.OpenKey(regKey, r'Software\Adobe')
30
regKey = _winreg.HKEY_CURRENT_USER
31
adobesoft = _winreg.OpenKey(regKey, r'Software\Adobe')
33
for index in range(_winreg.QueryInfoKey(adobesoft)[0]):
34
key = _winreg.EnumKey(adobesoft, index)
35
if "acrobat" in key.lower():
36
acrokeys.append(_winreg.OpenKey(regKey, 'Software\\Adobe\\%s' % key))
37
for acrokey in acrokeys:
38
for index in range(_winreg.QueryInfoKey(acrokey)[0]):
39
key = _winreg.EnumKey(acrokey, index)
41
acroversions.append(float(key))
44
acroversions.sort(reverse=True)
46
_acroversion = acroversions[0]
50
#----------------------------------------------------------------------
52
# The ActiveX module from Acrobat 7.0 has changed and it seems to now
53
# require much more from the container than what our wx.activex module
54
# provides. If we try to use it via wx.activex then Acrobat crashes.
55
# So instead we will use Internet Explorer (via the win32com modules
56
# so we can use better dynamic dispatch) and embed the Acrobat control
57
# within that. Acrobat provides the IAcroAXDocShim COM class that is
58
# accessible via the IE window's Document property after a PDF file
61
# Details of the Acrobat reader methods can be found in
62
# http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACOverview.pdf
63
# http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf
65
# Co-ordinates passed as parameters are in points (1/72 inch).
68
if get_acroversion() >= 7.0:
70
from wx.lib.activexwrapper import MakeActiveXClass
71
import win32com.client.gencache
72
_browserModule = win32com.client.gencache.EnsureModule(
73
"{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
75
class PDFWindowError(RuntimeError):
77
RuntimeError.__init__(self, "A PDF must be loaded before calling this method.")
80
class PDFWindow(wx.Panel):
81
def __init__(self, *args, **kw):
82
wx.Panel.__init__(self, *args, **kw)
84
# Make a new class that derives from the WebBrowser class
85
# in the COM module imported above. This class also
86
# derives from wxWindow and implements the machinery
87
# needed to integrate the two worlds.
88
_WebBrowserClass = MakeActiveXClass(_browserModule.WebBrowser)
89
self.ie = _WebBrowserClass(self, -1)
91
sizer.Add(self.ie, 1, wx.EXPAND)
95
def LoadFile(self, fileName):
97
Opens and displays the specified document within the browser.
100
return self.ie.Document.LoadFile(fileName)
102
self.ie.Navigate2(fileName)
103
return True # can we sense failure at this point?
105
def GetVersions(self):
107
Deprecated: No longer available - do not use.
110
return self.ie.Document.GetVersions()
112
raise PDFWindowError()
116
Prints the document according to the specified options in a user dialog box.
119
return self.ie.Document.Print()
121
raise PDFWindowError()
123
def goBackwardStack(self):
125
Goes to the previous view on the view stack, if it exists.
128
return self.ie.Document.goBackwardStack()
130
raise PDFWindowError()
132
def goForwardStack(self):
134
Goes to the next view on the view stack, if it exists.
137
return self.ie.Document.goForwardStack()
139
raise PDFWindowError()
141
def gotoFirstPage(self):
143
Goes to the first page in the document.
146
return self.ie.Document.gotoFirstPage()
148
raise PDFWindowError()
150
def gotoLastPage(self):
152
Goes to the last page in the document.
155
return self.ie.Document.gotoLastPage()
157
raise PDFWindowError()
159
def gotoNextPage(self):
161
Goes to the next page in the document, if it exists
164
return self.ie.Document.gotoNextPage()
166
raise PDFWindowError()
168
def gotoPreviousPage(self):
170
Goes to the previous page in the document, if it exists.
173
return self.ie.Document.gotoPreviousPage()
175
raise PDFWindowError()
179
Prints the entire document without displaying a user
180
dialog box. The current printer, page settings, and job
181
settings are used. This method returns immediately, even
182
if the printing has not completed.
185
return self.ie.Document.printAll()
187
raise PDFWindowError()
189
def printAllFit(self, shrinkToFit):
191
Prints the entire document without a user dialog box, and
192
(if shrinkToFit) shrinks pages as needed to fit the
193
imageable area of a page in the printer.
196
return self.ie.Document.printAllFit(shrinkToFit)
198
raise PDFWindowError()
200
def printPages(self, from_, to):
202
Prints the specified pages without displaying a user dialog box.
205
return self.ie.Document.printPages(from_, to)
207
raise PDFWindowError()
209
def printPagesFit(self, from_, to, shrinkToFit):
211
Prints the specified pages without displaying a user
212
dialog box, and (if shrinkToFit) shrinks pages as needed
213
to fit the imageable area of a page in the printer.
216
return self.ie.Document.printPagesFit( from_, to, shrinkToFit)
218
raise PDFWindowError()
220
def printWithDialog(self):
222
Prints the document according to the specified options in
223
a user dialog box. These options may include embedded
224
printing and specifying which printer is to be used.
226
NB. The page range in the dialog defaults to
227
'From Page 1 to 1' - Use Print() above instead. (dfh)
230
return self.ie.Document.printWithDialog()
232
raise PDFWindowError()
234
def setCurrentHighlight(self, a, b, c, d):
236
return self.ie.Document.setCurrentHighlight(a, b, c, d)
238
raise PDFWindowError()
240
def setCurrentPage(self, npage):
242
Goes to the specified page in the document. Maintains the
243
current location within the page and zoom level. npage is
244
the page number of the destination page. The first page
245
in a document is page 0.
247
## Oh no it isn't! The first page is 1 (dfh)
250
return self.ie.Document.setCurrentPage(npage)
252
raise PDFWindowError()
254
def setLayoutMode(self, layoutMode):
256
LayoutMode possible values:
258
================= ====================================
259
'DontCare' use the current user preference
260
'SinglePage' use single page mode (as in pre-Acrobat
262
'OneColumn' use one-column continuous mode
263
'TwoColumnLeft' use two-column continuous mode, first
265
'TwoColumnRight' use two-column continuous mode, first
267
================= ====================================
270
return self.ie.Document.setLayoutMode(layoutMode)
272
raise PDFWindowError()
274
def setNamedDest(self, namedDest):
276
Changes the page view to the named destination in the specified string.
279
return self.ie.Document.setNamedDest(namedDest)
281
raise PDFWindowError()
283
def setPageMode(self, pageMode):
285
Sets the page mode to display the document only, or to
286
additionally display bookmarks or thumbnails. pageMode =
287
'none' or 'bookmarks' or 'thumbs'.
289
## NB.'thumbs' is case-sensitive, the other are not (dfh)
292
return self.ie.Document.setPageMode(pageMode)
294
raise PDFWindowError()
296
def setShowScrollbars(self, On):
298
Determines whether scrollbars will appear in the document
301
## NB. If scrollbars are off, the navigation tools disappear as well (dfh)
304
return self.ie.Document.setShowScrollbars(On)
306
raise PDFWindowError()
308
def setShowToolbar(self, On):
310
Determines whether a toolbar will appear in the application.
313
return self.ie.Document.setShowToolbar(On)
315
raise PDFWindowError()
317
def setView(self, viewMode):
319
Determines how the page will fit in the current view.
320
viewMode possible values:
322
======== ==============================================
323
'Fit' fits whole page within the window both vertically
325
'FitH' fits the width of the page within the window.
326
'FitV' fits the height of the page within the window.
327
'FitB' fits bounding box within the window both vertically
329
'FitBH' fits the width of the bounding box within the window.
330
'FitBV' fits the height of the bounding box within the window.
331
======== ==============================================
334
return self.ie.Document.setView(viewMode)
336
raise PDFWindowError()
338
def setViewRect(self, left, top, width, height):
340
Sets the view rectangle according to the specified coordinates.
342
:param left: The upper left horizontal coordinate.
343
:param top: The vertical coordinate in the upper left corner.
344
:param width: The horizontal width of the rectangle.
345
:param height: The vertical height of the rectangle.
348
return self.ie.Document.setViewRect(left, top, width, height)
350
raise PDFWindowError()
352
def setViewScroll(self, viewMode, offset):
354
Sets the view of a page according to the specified string.
355
Depending on the view mode, the page is either scrolled to
356
the right or scrolled down by the amount specified in
357
offset. Possible values of viewMode are as in setView
358
above. offset is the horizontal or vertical coordinate
359
positioned either at the left or top edge.
362
return self.ie.Document.setViewScroll(viewMode, offset)
364
raise PDFWindowError()
366
def setZoom(self, percent):
368
Sets the magnification according to the specified value
369
expressed as a percentage (float)
372
return self.ie.Document.setZoom(percent)
374
raise PDFWindowError()
376
def setZoomScroll(self, percent, left, top):
378
Sets the magnification according to the specified value,
379
and scrolls the page view both horizontally and vertically
380
according to the specified amounts.
382
:param left: the horizontal coordinate positioned at the left edge.
383
:param top: the vertical coordinate positioned at the top edge.
386
return self.ie.Document.setZoomScroll(percent, left, top)
388
raise PDFWindowError()
392
elif get_acroversion() is not None:
395
clsID = '{CA8A9780-280D-11CF-A24D-444553540000}'
396
progID = 'AcroPDF.PDF.1'
399
# Create eventTypes and event binders
400
wxEVT_Error = wx.activex.RegisterActiveXEvent('OnError')
401
wxEVT_Message = wx.activex.RegisterActiveXEvent('OnMessage')
403
EVT_Error = wx.PyEventBinder(wxEVT_Error, 1)
404
EVT_Message = wx.PyEventBinder(wxEVT_Message, 1)
407
# Derive a new class from ActiveXWindow
408
class PDFWindow(wx.activex.ActiveXWindow):
409
def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
410
size=wx.DefaultSize, style=0, name='PDFWindow'):
411
wx.activex.ActiveXWindow.__init__(self, parent,
412
wx.activex.CLSID('{CA8A9780-280D-11CF-A24D-444553540000}'),
413
ID, pos, size, style, name)
415
# Methods exported by the ActiveX object
416
def QueryInterface(self, riid):
417
return self.CallAXMethod('QueryInterface', riid)
420
return self.CallAXMethod('AddRef')
423
return self.CallAXMethod('Release')
425
def GetTypeInfoCount(self):
426
return self.CallAXMethod('GetTypeInfoCount')
428
def GetTypeInfo(self, itinfo, lcid):
429
return self.CallAXMethod('GetTypeInfo', itinfo, lcid)
431
def GetIDsOfNames(self, riid, rgszNames, cNames, lcid):
432
return self.CallAXMethod('GetIDsOfNames', riid, rgszNames, cNames, lcid)
434
def Invoke(self, dispidMember, riid, lcid, wFlags, pdispparams):
435
return self.CallAXMethod('Invoke', dispidMember, riid, lcid, wFlags, pdispparams)
437
def LoadFile(self, fileName):
438
return self.CallAXMethod('LoadFile', fileName)
440
def setShowToolbar(self, On):
441
return self.CallAXMethod('setShowToolbar', On)
443
def gotoFirstPage(self):
444
return self.CallAXMethod('gotoFirstPage')
446
def gotoLastPage(self):
447
return self.CallAXMethod('gotoLastPage')
449
def gotoNextPage(self):
450
return self.CallAXMethod('gotoNextPage')
452
def gotoPreviousPage(self):
453
return self.CallAXMethod('gotoPreviousPage')
455
def setCurrentPage(self, n):
456
return self.CallAXMethod('setCurrentPage', n)
458
def goForwardStack(self):
459
return self.CallAXMethod('goForwardStack')
461
def goBackwardStack(self):
462
return self.CallAXMethod('goBackwardStack')
464
def setPageMode(self, pageMode):
465
return self.CallAXMethod('setPageMode', pageMode)
467
def setLayoutMode(self, layoutMode):
468
return self.CallAXMethod('setLayoutMode', layoutMode)
470
def setNamedDest(self, namedDest):
471
return self.CallAXMethod('setNamedDest', namedDest)
474
return self.CallAXMethod('Print')
476
def printWithDialog(self):
477
return self.CallAXMethod('printWithDialog')
479
def setZoom(self, percent):
480
return self.CallAXMethod('setZoom', percent)
482
def setZoomScroll(self, percent, left, top):
483
return self.CallAXMethod('setZoomScroll', percent, left, top)
485
def setView(self, viewMode):
486
return self.CallAXMethod('setView', viewMode)
488
def setViewScroll(self, viewMode, offset):
489
return self.CallAXMethod('setViewScroll', viewMode, offset)
491
def setViewRect(self, left, top, width, height):
492
return self.CallAXMethod('setViewRect', left, top, width, height)
494
def printPages(self, from_, to):
495
return self.CallAXMethod('printPages', from_, to)
497
def printPagesFit(self, from_, to, shrinkToFit):
498
return self.CallAXMethod('printPagesFit', from_, to, shrinkToFit)
501
return self.CallAXMethod('printAll')
503
def printAllFit(self, shrinkToFit):
504
return self.CallAXMethod('printAllFit', shrinkToFit)
506
def setShowScrollbars(self, On):
507
return self.CallAXMethod('setShowScrollbars', On)
509
def GetVersions(self):
510
return self.CallAXMethod('GetVersions')
512
def setCurrentHighlight(self, a, b, c, d):
513
return self.CallAXMethod('setCurrentHighlight', a, b, c, d)
515
def postMessage(self, strArray):
516
return self.CallAXMethod('postMessage', strArray)
518
# Getters, Setters and properties
520
return self.GetAXProp('src')
521
def _set_src(self, src):
522
self.SetAXProp('src', src)
523
src = property(_get_src, _set_src)
525
def _get_messageHandler(self):
526
return self.GetAXProp('messageHandler')
527
def _set_messageHandler(self, messageHandler):
528
self.SetAXProp('messageHandler', messageHandler)
529
messagehandler = property(_get_messageHandler, _set_messageHandler)
533
# --------------------
535
# type:string arg:string canGet:True canSet:True
538
# type:VT_VARIANT arg:VT_VARIANT canGet:True canSet:True
544
# --------------------
549
# in:True out:False optional:False type:unsupported type 29
551
# in:False out:True optional:False type:unsupported type 26
563
# in:False out:True optional:False type:int
569
# in:True out:False optional:False type:int
571
# in:True out:False optional:False type:int
573
# in:False out:True optional:False type:unsupported type 26
579
# in:True out:False optional:False type:unsupported type 29
581
# in:True out:False optional:False type:unsupported type 26
583
# in:True out:False optional:False type:int
585
# in:True out:False optional:False type:int
587
# in:False out:True optional:False type:int
593
# in:True out:False optional:False type:int
595
# in:True out:False optional:False type:unsupported type 29
597
# in:True out:False optional:False type:int
599
# in:True out:False optional:False type:int
601
# in:True out:False optional:False type:unsupported type 29
603
# in:False out:True optional:False type:VT_VARIANT
605
# in:False out:True optional:False type:unsupported type 29
607
# in:False out:True optional:False type:int
613
# in:True out:False optional:False type:string
619
# in:True out:False optional:False type:bool
637
# in:True out:False optional:False type:int
649
# in:True out:False optional:False type:string
655
# in:True out:False optional:False type:string
661
# in:True out:False optional:False type:string
673
# in:True out:False optional:False type:double
679
# in:True out:False optional:False type:double
681
# in:True out:False optional:False type:double
683
# in:True out:False optional:False type:double
689
# in:True out:False optional:False type:string
695
# in:True out:False optional:False type:string
697
# in:True out:False optional:False type:double
703
# in:True out:False optional:False type:double
705
# in:True out:False optional:False type:double
707
# in:True out:False optional:False type:double
709
# in:True out:False optional:False type:double
715
# in:True out:False optional:False type:int
717
# in:True out:False optional:False type:int
723
# in:True out:False optional:False type:int
725
# in:True out:False optional:False type:int
727
# in:True out:False optional:False type:bool
736
# in:True out:False optional:False type:bool
742
# in:True out:False optional:False type:bool
745
# retType: VT_VARIANT
747
# setCurrentHightlight
751
# in:True out:False optional:False type:int
753
# in:True out:False optional:False type:int
755
# in:True out:False optional:False type:int
757
# in:True out:False optional:False type:int
759
# setCurrentHighlight
763
# in:True out:False optional:False type:int
765
# in:True out:False optional:False type:int
767
# in:True out:False optional:False type:int
769
# in:True out:False optional:False type:int
775
# in:True out:False optional:False type:VT_VARIANT
781
# --------------------