From ec9fa355990acfbd5121177f9e60b3a0d966136d Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 16 Mar 2011 13:15:12 +0100 Subject: [PATCH 01/11] fixed loading the wrong values --- openlp/core/ui/generaltab.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index e705d5ec3..3ba3afb20 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -267,8 +267,7 @@ class GeneralTab(SettingsTab): 'Automatically preview next item in service')) self.timeoutLabel.setText(translate('OpenLP.GeneralTab', 'Slide loop delay:')) - self.timeoutSpinBox.setSuffix( - translate('OpenLP.GeneralTab', ' sec')) + self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec')) self.ccliGroupBox.setTitle( translate('OpenLP.GeneralTab', 'CCLI Details')) self.numberLabel.setText(UiStrings.CCLINumberLabel) @@ -286,15 +285,13 @@ class GeneralTab(SettingsTab): self.currentHeightLabel.setText( translate('OpenLP.GeneralTab', 'Height')) self.currentHeightValueLabel.setText(u'0') - self.currentWidthLabel.setText( - translate('OpenLP.GeneralTab', 'Width')) + self.currentWidthLabel.setText(translate('OpenLP.GeneralTab', 'Width')) self.currentWidthValueLabel.setText(u'0') self.overrideCheckBox.setText(translate('OpenLP.GeneralTab', 'Override display position')) self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X')) self.customYLabel.setText(translate('OpenLP.GeneralTab', 'Y')) - self.customHeightLabel.setText( - translate('OpenLP.GeneralTab', 'Height')) + self.customHeightLabel.setText(translate('OpenLP.GeneralTab', 'Height')) self.customWidthLabel.setText(translate('OpenLP.GeneralTab', 'Width')) def load(self): @@ -304,8 +301,7 @@ class GeneralTab(SettingsTab): settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) self.monitorComboBox.clear() - for screen in self.screens.get_screen_list(): - self.monitorComboBox.addItem(screen) + self.monitorComboBox.addItems(self.screens.get_screen_list()) self.numberEdit.setText(unicode(settings.value( u'ccli number', QtCore.QVariant(u'')).toString())) self.usernameEdit.setText(unicode(settings.value( @@ -328,14 +324,13 @@ class GeneralTab(SettingsTab): QtCore.QVariant(False)).toBool()) self.timeoutSpinBox.setValue(settings.value(u'loop delay', QtCore.QVariant(5)).toInt()[0]) - self.currentXValueLabel.setText( - unicode(self.screens.current[u'size'].x())) - self.currentYValueLabel.setText( - unicode(self.screens.current[u'size'].y())) - self.currentHeightValueLabel.setText( - unicode(self.screens.current[u'size'].height())) - self.currentWidthValueLabel.setText( - unicode(self.screens.current[u'size'].width())) + for screen in self.screens.screen_list: + if screen[u'number'] == self.monitorNumber: + size = screen[u'size'] + self.currentXValueLabel.setText(unicode(size.x())) + self.currentYValueLabel.setText(unicode(size.y())) + self.currentHeightValueLabel.setText(unicode(size.height())) + self.currentWidthValueLabel.setText(unicode(size.width())) self.overrideCheckBox.setChecked(settings.value(u'override position', QtCore.QVariant(False)).toBool()) self.customXValueEdit.setText(settings.value(u'x position', From 30e5cee13a723649797391d06f59c71452c5f99a Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 16 Mar 2011 18:30:02 +0100 Subject: [PATCH 02/11] --- openlp/core/ui/generaltab.py | 129 +++++++++++------------------------ 1 file changed, 38 insertions(+), 91 deletions(-) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 3ba3afb20..277a93bc3 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -32,27 +32,6 @@ from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) -class ValidEdit(QtGui.QLineEdit): - """ - Only allow numeric characters to be edited - """ - def __init__(self, parent): - """ - Set up Override and Validator - """ - QtGui.QLineEdit.__init__(self, parent) - self.setValidator(QtGui.QIntValidator(0, 9999, self)) - - def validText(self): - """ - Only return Integers. Space is 0 - """ - if self.text().isEmpty(): - return QtCore.QString(u'0') - else: - return self.text() - - class GeneralTab(SettingsTab): """ GeneralTab is the general settings tab in the settings dialog. @@ -164,30 +143,6 @@ class GeneralTab(SettingsTab): self.displayGroupBox.setObjectName(u'displayGroupBox') self.displayLayout = QtGui.QGridLayout(self.displayGroupBox) self.displayLayout.setObjectName(u'displayLayout') - self.currentXLabel = QtGui.QLabel(self.displayGroupBox) - self.currentXLabel.setObjectName(u'currentXLabel') - self.displayLayout.addWidget(self.currentXLabel, 0, 0) - self.currentXValueLabel = QtGui.QLabel(self.displayGroupBox) - self.currentXValueLabel.setObjectName(u'currentXValueLabel') - self.displayLayout.addWidget(self.currentXValueLabel, 1, 0) - self.currentYLabel = QtGui.QLabel(self.displayGroupBox) - self.currentYLabel.setObjectName(u'currentYLabel') - self.displayLayout.addWidget(self.currentYLabel, 0, 1) - self.currentYValueLabel = QtGui.QLabel(self.displayGroupBox) - self.currentYValueLabel.setObjectName(u'currentYValueLabel') - self.displayLayout.addWidget(self.currentYValueLabel, 1, 1) - self.currentWidthLabel = QtGui.QLabel(self.displayGroupBox) - self.currentWidthLabel.setObjectName(u'currentWidthLabel') - self.displayLayout.addWidget(self.currentWidthLabel, 0, 2) - self.currentWidthValueLabel = QtGui.QLabel(self.displayGroupBox) - self.currentWidthValueLabel.setObjectName(u'currentWidthValueLabel') - self.displayLayout.addWidget(self.currentWidthValueLabel, 1, 2) - self.currentHeightLabel = QtGui.QLabel(self.displayGroupBox) - self.currentHeightLabel.setObjectName(u'currentHeightLabel') - self.displayLayout.addWidget(self.currentHeightLabel, 0, 3) - self.currentHeightValueLabel = QtGui.QLabel(self.displayGroupBox) - self.currentHeightValueLabel.setObjectName(u'Height') - self.displayLayout.addWidget(self.currentHeightValueLabel, 1, 3) self.overrideCheckBox = QtGui.QCheckBox(self.displayGroupBox) self.overrideCheckBox.setObjectName(u'overrideCheckBox') self.displayLayout.addWidget(self.overrideCheckBox, 2, 0, 1, 4) @@ -196,26 +151,30 @@ class GeneralTab(SettingsTab): self.customXLabel = QtGui.QLabel(self.displayGroupBox) self.customXLabel.setObjectName(u'customXLabel') self.displayLayout.addWidget(self.customXLabel, 3, 0) - self.customXValueEdit = ValidEdit(self.displayGroupBox) + self.customXValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customXValueEdit.setObjectName(u'customXValueEdit') + self.customXValueEdit.setMaximum(9999) self.displayLayout.addWidget(self.customXValueEdit, 4, 0) self.customYLabel = QtGui.QLabel(self.displayGroupBox) self.customYLabel.setObjectName(u'customYLabel') self.displayLayout.addWidget(self.customYLabel, 3, 1) - self.customYValueEdit = ValidEdit(self.displayGroupBox) + self.customYValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customYValueEdit.setObjectName(u'customYValueEdit') + self.customYValueEdit.setMaximum(9999) self.displayLayout.addWidget(self.customYValueEdit, 4, 1) self.customWidthLabel = QtGui.QLabel(self.displayGroupBox) self.customWidthLabel.setObjectName(u'customWidthLabel') self.displayLayout.addWidget(self.customWidthLabel, 3, 2) - self.customWidthValueEdit = ValidEdit(self.displayGroupBox) + self.customWidthValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customWidthValueEdit.setObjectName(u'customWidthValueEdit') + self.customWidthValueEdit.setMaximum(9999) self.displayLayout.addWidget(self.customWidthValueEdit, 4, 2) self.customHeightLabel = QtGui.QLabel(self.displayGroupBox) self.customHeightLabel.setObjectName(u'customHeightLabel') self.displayLayout.addWidget(self.customHeightLabel, 3, 3) - self.customHeightValueEdit = ValidEdit(self.displayGroupBox) + self.customHeightValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customHeightValueEdit.setObjectName(u'customHeightValueEdit') + self.customHeightValueEdit.setMaximum(9999) self.displayLayout.addWidget(self.customHeightValueEdit, 4, 3) self.rightLayout.addWidget(self.displayGroupBox) self.rightLayout.addStretch() @@ -223,17 +182,13 @@ class GeneralTab(SettingsTab): QtCore.QObject.connect(self.overrideCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideCheckBoxToggled) QtCore.QObject.connect(self.customHeightValueEdit, - QtCore.SIGNAL(u'textEdited(const QString&)'), - self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) QtCore.QObject.connect(self.customWidthValueEdit, - QtCore.SIGNAL(u'textEdited(const QString&)'), - self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) QtCore.QObject.connect(self.customYValueEdit, - QtCore.SIGNAL(u'textEdited(const QString&)'), - self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) QtCore.QObject.connect(self.customXValueEdit, - QtCore.SIGNAL(u'textEdited(const QString&)'), - self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) # Reload the tab, as the screen resolution/count may have changed. QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.load) @@ -278,15 +233,6 @@ class GeneralTab(SettingsTab): # Moved from display tab self.displayGroupBox.setTitle( translate('OpenLP.GeneralTab', 'Display Position')) - self.currentXLabel.setText(translate('OpenLP.GeneralTab', 'X')) - self.currentXValueLabel.setText(u'0') - self.currentYLabel.setText(translate('OpenLP.GeneralTab', 'Y')) - self.currentYValueLabel.setText(u'0') - self.currentHeightLabel.setText( - translate('OpenLP.GeneralTab', 'Height')) - self.currentHeightValueLabel.setText(u'0') - self.currentWidthLabel.setText(translate('OpenLP.GeneralTab', 'Width')) - self.currentWidthValueLabel.setText(u'0') self.overrideCheckBox.setText(translate('OpenLP.GeneralTab', 'Override display position')) self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X')) @@ -324,25 +270,26 @@ class GeneralTab(SettingsTab): QtCore.QVariant(False)).toBool()) self.timeoutSpinBox.setValue(settings.value(u'loop delay', QtCore.QVariant(5)).toInt()[0]) - for screen in self.screens.screen_list: - if screen[u'number'] == self.monitorNumber: - size = screen[u'size'] - self.currentXValueLabel.setText(unicode(size.x())) - self.currentYValueLabel.setText(unicode(size.y())) - self.currentHeightValueLabel.setText(unicode(size.height())) - self.currentWidthValueLabel.setText(unicode(size.width())) self.overrideCheckBox.setChecked(settings.value(u'override position', QtCore.QVariant(False)).toBool()) - self.customXValueEdit.setText(settings.value(u'x position', - QtCore.QVariant(self.screens.current[u'size'].x())).toString()) - self.customYValueEdit.setText(settings.value(u'y position', - QtCore.QVariant(self.screens.current[u'size'].y())).toString()) - self.customHeightValueEdit.setText( - settings.value(u'height', QtCore.QVariant( - self.screens.current[u'size'].height())).toString()) - self.customWidthValueEdit.setText( - settings.value(u'width', QtCore.QVariant( - self.screens.current[u'size'].width())).toString()) + if self.overrideCheckBox.isChecked(): + self.customXValueEdit.setValue(settings.value(u'x position', + QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0]) + self.customYValueEdit.setValue(settings.value(u'y position', + QtCore.QVariant(self.screens.current[u'size'].y())).toInt()[0]) + self.customHeightValueEdit.setValue( + settings.value(u'height', QtCore.QVariant( + self.screens.current[u'size'].height())).toInt()[0]) + self.customWidthValueEdit.setValue( + settings.value(u'width', QtCore.QVariant( + self.screens.current[u'size'].width())).toInt()[0]) + else: + self.customXValueEdit.setValue(self.screens.current[u'size'].x()) + self.customYValueEdit.setValue(self.screens.current[u'size'].y()) + self.customHeightValueEdit.setValue( + self.screens.current[u'size'].height()) + self.customWidthValueEdit.setValue( + self.screens.current[u'size'].width()) settings.endGroup() self.customXValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked()) @@ -380,13 +327,13 @@ class GeneralTab(SettingsTab): settings.setValue(u'songselect password', QtCore.QVariant(self.passwordEdit.displayText())) settings.setValue(u'x position', - QtCore.QVariant(self.customXValueEdit.text())) + QtCore.QVariant(self.customXValueEdit.value())) settings.setValue(u'y position', - QtCore.QVariant(self.customYValueEdit.text())) + QtCore.QVariant(self.customYValueEdit.value())) settings.setValue(u'height', - QtCore.QVariant(self.customHeightValueEdit.text())) + QtCore.QVariant(self.customHeightValueEdit.value())) settings.setValue(u'width', - QtCore.QVariant(self.customWidthValueEdit.text())) + QtCore.QVariant(self.customWidthValueEdit.value())) settings.setValue(u'override position', QtCore.QVariant(self.overrideCheckBox.isChecked())) settings.endGroup() @@ -410,10 +357,10 @@ class GeneralTab(SettingsTab): # Reset screens after initial definition if self.overrideChanged: self.screens.override[u'size'] = QtCore.QRect( - int(self.customXValueEdit.validText()), - int(self.customYValueEdit.validText()), - int(self.customWidthValueEdit.validText()), - int(self.customHeightValueEdit.validText())) + self.customXValueEdit.value(), + self.customYValueEdit.value(), + self.customWidthValueEdit.value(), + self.customHeightValueEdit.value()) if self.overrideCheckBox.isChecked(): self.screens.set_override_display() else: From 72f445c4263475caa86cb1cbce6beaf7fc28a0e9 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Wed, 16 Mar 2011 23:22:11 +0000 Subject: [PATCH 03/11] pptviewer fixes and tidyups --- .../presentations/lib/powerpointcontroller.py | 2 - .../presentations/lib/pptviewlib/ppttest.py | 220 ++--- .../lib/pptviewlib/pptviewlib.cpp | 757 ++++++++++-------- .../lib/pptviewlib/pptviewlib.dll | Bin 47104 -> 78848 bytes .../presentations/lib/pptviewlib/pptviewlib.h | 55 +- 5 files changed, 601 insertions(+), 433 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index f220f558a..4dd57c5e1 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -80,8 +80,6 @@ class PowerpointController(PresentationController): log.debug(u'start_process') if not self.process: self.process = Dispatch(u'PowerPoint.Application') - if float(self.process.Version) < 13: - self.process.Visible = True self.process.WindowState = 2 def kill(self): diff --git a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py index f8d0fabd9..9730659c3 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py +++ b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py @@ -30,19 +30,32 @@ from ctypes import * from ctypes.wintypes import RECT class PPTViewer(QtGui.QWidget): + """ + Standalone Test Harness for the pptviewlib library + """ def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.pptid = -1 self.setWindowTitle(u'PowerPoint Viewer Test') - PPTLabel = QtGui.QLabel(u'Open PowerPoint file') - slideLabel = QtGui.QLabel(u'Go to slide #') - self.PPTEdit = QtGui.QLineEdit() + ppt_label = QtGui.QLabel(u'Open PowerPoint file') + slide_label = QtGui.QLabel(u'Go to slide #') + self.pptEdit = QtGui.QLineEdit() self.slideEdit = QtGui.QLineEdit() + x_label = QtGui.QLabel(u'X pos') + y_label = QtGui.QLabel(u'Y pos') + width_label = QtGui.QLabel(u'Width') + height_label = QtGui.QLabel(u'Height') + self.xEdit = QtGui.QLineEdit(u'100') + self.yEdit = QtGui.QLineEdit(u'100') + self.widthEdit = QtGui.QLineEdit(u'900') + self.heightEdit = QtGui.QLineEdit(u'700') self.total = QtGui.QLabel() - PPTBtn = QtGui.QPushButton(u'Open') - PPTDlgBtn = QtGui.QPushButton(u'...') - slideBtn = QtGui.QPushButton(u'Go') + ppt_btn = QtGui.QPushButton(u'Open') + ppt_dlg_btn = QtGui.QPushButton(u'...') + folder_label = QtGui.QLabel(u'Slide .bmp path') + self.folderEdit = QtGui.QLineEdit(u'slide') + slide_btn = QtGui.QPushButton(u'Go') prev = QtGui.QPushButton(u'Prev') next = QtGui.QPushButton(u'Next') blank = QtGui.QPushButton(u'Blank') @@ -51,122 +64,149 @@ class PPTViewer(QtGui.QWidget): close = QtGui.QPushButton(u'Close') resume = QtGui.QPushButton(u'Resume') stop = QtGui.QPushButton(u'Stop') - pptwindow = QtGui.QWidget() - grid = QtGui.QGridLayout() - grid.addWidget(PPTLabel, 0, 0) - grid.addWidget(self.PPTEdit, 0, 1) - grid.addWidget(PPTDlgBtn, 0, 2) - grid.addWidget(PPTBtn, 0, 3) - grid.addWidget(slideLabel, 1, 0) - grid.addWidget(self.slideEdit, 1, 1) - grid.addWidget(slideBtn, 1, 3) - grid.addWidget(prev, 2, 0) - grid.addWidget(next, 2, 1) - grid.addWidget(blank, 3, 0) - grid.addWidget(unblank, 3, 1) - grid.addWidget(restart, 4, 0) - grid.addWidget(close, 4, 1) - grid.addWidget(stop, 5, 0) - grid.addWidget(resume, 5, 1) - grid.addWidget(pptwindow, 6, 0, 10, 3) - self.connect(PPTBtn, QtCore.SIGNAL(u'clicked()'), self.OpenClick) - self.connect(PPTDlgBtn, QtCore.SIGNAL(u'clicked()'), self.OpenDialog) - self.connect(slideBtn, QtCore.SIGNAL(u'clicked()'), self.GotoClick) - self.connect(prev, QtCore.SIGNAL(u'clicked()'), self.PrevClick) - self.connect(next, QtCore.SIGNAL(u'clicked()'), self.NextClick) - self.connect(blank, QtCore.SIGNAL(u'clicked()'), self.BlankClick) - self.connect(unblank, QtCore.SIGNAL(u'clicked()'), self.UnblankClick) - self.connect(restart, QtCore.SIGNAL(u'clicked()'), self.RestartClick) - self.connect(close, QtCore.SIGNAL(u'clicked()'), self.CloseClick) - self.connect(stop, QtCore.SIGNAL(u'clicked()'), self.StopClick) - self.connect(resume, QtCore.SIGNAL(u'clicked()'), self.ResumeClick) - + row = 0 + grid.addWidget(folder_label, 0, 0) + grid.addWidget(self.folderEdit, 0, 1) + row = row + 1 + grid.addWidget(x_label, row, 0) + grid.addWidget(self.xEdit, row, 1) + grid.addWidget(y_label, row, 2) + grid.addWidget(self.yEdit, row, 3) + row = row + 1 + grid.addWidget(width_label, row, 0) + grid.addWidget(self.widthEdit, row, 1) + grid.addWidget(height_label, row, 2) + grid.addWidget(self.heightEdit, row, 3) + row = row + 1 + grid.addWidget(ppt_label, row, 0) + grid.addWidget(self.pptEdit, row, 1) + grid.addWidget(ppt_dlg_btn, row, 2) + grid.addWidget(ppt_btn, row, 3) + row = row + 1 + grid.addWidget(slide_label, row, 0) + grid.addWidget(self.slideEdit, row, 1) + grid.addWidget(slide_btn, row, 2) + row = row + 1 + grid.addWidget(prev, row, 0) + grid.addWidget(next, row, 1) + row = row + 1 + grid.addWidget(blank, row, 0) + grid.addWidget(unblank, row, 1) + row = row + 1 + grid.addWidget(restart, row, 0) + grid.addWidget(close, row, 1) + row = row + 1 + grid.addWidget(stop, row, 0) + grid.addWidget(resume, row, 1) + self.connect(ppt_btn, QtCore.SIGNAL(u'clicked()'), self.openClick) + self.connect(ppt_dlg_btn, QtCore.SIGNAL(u'clicked()'), self.openDialog) + self.connect(slide_btn, QtCore.SIGNAL(u'clicked()'), self.gotoClick) + self.connect(prev, QtCore.SIGNAL(u'clicked()'), self.prevClick) + self.connect(next, QtCore.SIGNAL(u'clicked()'), self.nextClick) + self.connect(blank, QtCore.SIGNAL(u'clicked()'), self.blankClick) + self.connect(unblank, QtCore.SIGNAL(u'clicked()'), self.unblankClick) + self.connect(restart, QtCore.SIGNAL(u'clicked()'), self.restartClick) + self.connect(close, QtCore.SIGNAL(u'clicked()'), self.closeClick) + self.connect(stop, QtCore.SIGNAL(u'clicked()'), self.stopClick) + self.connect(resume, QtCore.SIGNAL(u'clicked()'), self.resumeClick) self.setLayout(grid) - self.resize(300, 150) - def PrevClick(self): - if self.pptid<0: return - pptdll.PrevStep(self.pptid) - self.UpdateCurrSlide() + def prevClick(self): + if self.pptid < 0: + return + self.pptdll.PrevStep(self.pptid) + self.updateCurrSlide() app.processEvents() - def NextClick(self): - if(self.pptid<0): return - pptdll.NextStep(self.pptid) - self.UpdateCurrSlide() + def nextClick(self): + if self.pptid < 0: + return + self.pptdll.NextStep(self.pptid) + self.updateCurrSlide() app.processEvents() - def BlankClick(self): - if(self.pptid<0): return - pptdll.Blank(self.pptid) + def blankClick(self): + if self.pptid < 0: + return + self.pptdll.Blank(self.pptid) app.processEvents() - def UnblankClick(self): - if(self.pptid<0): return - pptdll.Unblank(self.pptid) + def unblankClick(self): + if self.pptid < 0: + return + self.pptdll.Unblank(self.pptid) app.processEvents() - def RestartClick(self): - if(self.pptid<0): return - pptdll.RestartShow(self.pptid) - self.UpdateCurrSlide() + def restartClick(self): + if self.pptid < 0: + return + self.pptdll.RestartShow(self.pptid) + self.updateCurrSlide() app.processEvents() - def StopClick(self): - if(self.pptid<0): return - pptdll.Stop(self.pptid) + def stopClick(self): + if self.pptid < 0: + return + self.pptdll.Stop(self.pptid) app.processEvents() - def ResumeClick(self): - if(self.pptid<0): return - pptdll.Resume(self.pptid) + def resumeClick(self): + if self.pptid < 0: + return + self.pptdll.Resume(self.pptid) app.processEvents() - def CloseClick(self): - if(self.pptid<0): return - pptdll.ClosePPT(self.pptid) + def closeClick(self): + if self.pptid < 0: + return + self.pptdll.ClosePPT(self.pptid) self.pptid = -1 app.processEvents() - def OpenClick(self): + def openClick(self): oldid = self.pptid; - rect = RECT(100,100,900,700) - filename = str(self.PPTEdit.text().replace(u'/', u'\\')) - print filename - self.pptid = pptdll.OpenPPT(filename, None, rect, 'c:\\temp\\slide') - print "id: " + unicode(self.pptid) - if oldid>=0: - pptdll.ClosePPT(oldid); - slides = pptdll.GetSlideCount(self.pptid) - print "slidecount: " + unicode(slides) - self.total.setNum(pptdll.GetSlideCount(self.pptid)) - self.UpdateCurrSlide() + rect = RECT(int(self.xEdit.text()), int(self.yEdit.text()), + int(self.widthEdit.text()), int(self.heightEdit.text())) + filename = str(self.pptEdit.text().replace(u'/', u'\\')) + folder = str(self.folderEdit.text().replace(u'/', u'\\')) + print filename, folder + self.pptid = self.pptdll.OpenPPT(filename, None, rect, folder) + print u'id: ' + unicode(self.pptid) + if oldid >= 0: + self.pptdll.ClosePPT(oldid); + slides = self.pptdll.GetSlideCount(self.pptid) + print u'slidecount: ' + unicode(slides) + self.total.setNum(self.pptdll.GetSlideCount(self.pptid)) + self.updateCurrSlide() - def UpdateCurrSlide(self): - if(self.pptid<0): return - slide = unicode(pptdll.GetCurrentSlide(self.pptid)) - print "currslide: " + slide + def updateCurrSlide(self): + if self.pptid < 0: + return + slide = unicode(self.pptdll.GetCurrentSlide(self.pptid)) + print u'currslide: ' + slide self.slideEdit.setText(slide) app.processEvents() - def GotoClick(self): - if(self.pptid<0): return + def gotoClick(self): + if self.pptid < 0: + return print self.slideEdit.text() - pptdll.GotoSlide(self.pptid, int(self.slideEdit.text())) - self.UpdateCurrSlide() + self.pptdll.GotoSlide(self.pptid, int(self.slideEdit.text())) + self.updateCurrSlide() app.processEvents() - def OpenDialog(self): - self.PPTEdit.setText(QtGui.QFileDialog.getOpenFileName(self, 'Open file')) + def openDialog(self): + self.pptEdit.setText(QtGui.QFileDialog.getOpenFileName(self, + u'Open file')) if __name__ == '__main__': - #pptdll = cdll.LoadLibrary(r'C:\Documents and Settings\jonathan\Desktop\pptviewlib.dll') pptdll = cdll.LoadLibrary(r'pptviewlib.dll') pptdll.SetDebug(1) - print "Begin..." + print u'Begin...' app = QtGui.QApplication(sys.argv) - qb = PPTViewer() - qb.show() + window = PPTViewer() + window.pptdll = pptdll + window.show() sys.exit(app.exec_()) diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index 86876a836..4a3b1c399 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -1,21 +1,26 @@ -/* - * PPTVIEWLIB - Control PowerPoint Viewer 2003/2007 (for openlp.org) - * Copyright (C) 2008 Jonathan Corwin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - +/****************************************************************************** +* PptViewLib - PowerPoint Viewer 2003/2007 Controller * +* OpenLP - Open Source Lyrics Projection * +* --------------------------------------------------------------------------- * +* Copyright (c) 2008-2011 Raoul Snyman * +* Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael * +* Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, * +* Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon * +* Tibble, Carsten Tinggaard, Frode Woldsund * +* --------------------------------------------------------------------------- * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation; version 2 of the License. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, write to the Free Software Foundation, Inc., 59 * +* Temple Place, Suite 330, Boston, MA 02111-1307 USA * +******************************************************************************/ #define WIN32_LEAN_AND_MEAN #include @@ -27,67 +32,63 @@ #include #include "pptviewlib.h" - -// Because of the callbacks used by SetWindowsHookEx, the memory used needs to be -// sharable across processes (the callbacks are done from a different process) -// Therefore use data_seg with RWS memory. +// Because of the callbacks used by SetWindowsHookEx, the memory used needs to +// be sharable across processes (the callbacks are done from a different +// process) Therefore use data_seg with RWS memory. // -// See http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx for alternative -// method of holding memory, removing fixed limits which would allow dynamic number -// of items, rather than a fixed number. Use a Local\ mapping, since global has UAC -// issues in Vista. +// See http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx for +// alternative method of holding memory, removing fixed limits which would allow +// dynamic number of items, rather than a fixed number. Use a Local\ mapping, +// since global has UAC issues in Vista. + #pragma data_seg(".PPTVIEWLIB") -PPTVIEWOBJ pptviewobj[MAX_PPTOBJS] = {NULL}; -HHOOK globalhook = NULL; +PPTVIEW pptView[MAX_PPTS] = {NULL}; +HHOOK globalHook = NULL; BOOL debug = FALSE; #pragma data_seg() #pragma comment(linker, "/SECTION:.PPTVIEWLIB,RWS") -#define DEBUG(...) if(debug) printf(__VA_ARGS__) - - HINSTANCE hInstance = NULL; -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, + LPVOID lpReserved) { hInstance = (HINSTANCE)hModule; - switch (ul_reason_for_call) + switch(ulReasonForCall) { - case DLL_PROCESS_ATTACH: - DEBUG("PROCESS_ATTACH\n"); - break; - case DLL_THREAD_ATTACH: - DEBUG("THREAD_ATTACH\n"); - break; - case DLL_THREAD_DETACH: - DEBUG("THREAD_DETACH\n"); - break; - case DLL_PROCESS_DETACH: - // Clean up... hopefully there is only the one process attached? - // We'll find out soon enough during tests! - DEBUG("PROCESS_DETACH\n"); - for(int i = 0; i.bmp" will be appended to complete the path. E.g. "c:\temp\slide" would // create "c:\temp\slide1.bmp" slide2.bmp, slide3.bmp etc. // It will also create a *info.txt containing information about the ppt -DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewpath) +DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, + char *previewPath) { STARTUPINFO si; PROCESS_INFORMATION pi; - char cmdline[MAX_PATH * 2]; + char cmdLine[MAX_PATH * 2]; int id; - DEBUG("OpenPPT start: %s; %s\n", filename, previewpath); - DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, rect.left, rect.bottom, rect.right); - if(GetPPTViewerPath(cmdline, sizeof(cmdline))==FALSE) + DEBUG("OpenPPT start: %s; %s\n", filename, previewPath); + DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, + rect.left, rect.bottom, rect.right); + if (GetPPTViewerPath(cmdLine, sizeof(cmdLine)) == FALSE) { DEBUG("OpenPPT: GetPPTViewerPath failed\n"); return -1; } id = -1; - for(int i = 0; ibottom-wndrect->top; - pptviewobj[id].rect.right = wndrect->right-wndrect->left; + LPRECT windowRect = NULL; + GetWindowRect(hParentWnd, windowRect); + pptView[id].rect.top = 0; + pptView[id].rect.left = 0; + pptView[id].rect.bottom = windowRect->bottom - windowRect->top; + pptView[id].rect.right = windowRect->right - windowRect->left; } else { - pptviewobj[id].rect.top = rect.top; - pptviewobj[id].rect.left = rect.left; - pptviewobj[id].rect.bottom = rect.bottom; - pptviewobj[id].rect.right = rect.right; + pptView[id].rect.top = rect.top; + pptView[id].rect.left = rect.left; + pptView[id].rect.bottom = rect.bottom; + pptView[id].rect.right = rect.right; } - strcat_s(cmdline, MAX_PATH * 2, "/F /S \""); - strcat_s(cmdline, MAX_PATH * 2, filename); - strcat_s(cmdline, MAX_PATH * 2, "\""); + strcat_s(cmdLine, MAX_PATH * 2, "/F /S \""); + strcat_s(cmdLine, MAX_PATH * 2, filename); + strcat_s(cmdLine, MAX_PATH * 2, "\""); memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); - BOOL gotinfo = GetPPTInfo(id); + BOOL gotInfo = GetPPTInfo(id); /* - * I'd really like to just hook on the new threadid. However this always gives - * error 87. Perhaps I'm hooking to soon? No idea... however can't wait - * since I need to ensure I pick up the WM_CREATE as this is the only + * I'd really like to just hook on the new threadid. However this always + * gives error 87. Perhaps I'm hooking to soon? No idea... however can't + * wait since I need to ensure I pick up the WM_CREATE as this is the only * time the window can be resized in such away the content scales correctly * * hook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,pi.dwThreadId); */ - if(globalhook!=NULL) - UnhookWindowsHookEx(globalhook); - globalhook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,NULL); - if(globalhook==0) + if (globalHook != NULL) + { + UnhookWindowsHookEx(globalHook); + } + globalHook = SetWindowsHookEx(WH_CBT, CbtProc, hInstance, NULL); + if (globalHook == 0) { DEBUG("OpenPPT: SetWindowsHookEx failed\n"); ClosePPT(id); return -1; } - pptviewobj[id].state = PPT_STARTED; + pptView[id].state = PPT_STARTED; Sleep(10); - if(!CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi)) + if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi)) { DEBUG("OpenPPT: CreateProcess failed\n"); ClosePPT(id); return -1; } - pptviewobj[id].dwProcessId = pi.dwProcessId; - pptviewobj[id].dwThreadId = pi.dwThreadId; - pptviewobj[id].hThread = pi.hThread; - pptviewobj[id].hProcess = pi.hProcess; - while(pptviewobj[id].state==PPT_STARTED) + pptView[id].dwProcessId = pi.dwProcessId; + pptView[id].dwThreadId = pi.dwThreadId; + pptView[id].hThread = pi.hThread; + pptView[id].hProcess = pi.hProcess; + while (pptView[id].state == PPT_STARTED) Sleep(10); - if(gotinfo) + if (gotInfo) { DEBUG("OpenPPT: Info loaded, no refresh\n"); - pptviewobj[id].state = PPT_LOADED; + pptView[id].state = PPT_LOADED; Resume(id); } else { DEBUG("OpenPPT: Get info\n"); - pptviewobj[id].steps = 0; + pptView[id].steps = 0; int steps = 0; - while(pptviewobj[id].state==PPT_OPENED) + while (pptView[id].state == PPT_OPENED) { - if(steps<=pptviewobj[id].steps) + if (steps <= pptView[id].steps) { Sleep(20); - DEBUG("OpenPPT: Step %d/%d\n",steps,pptviewobj[id].steps); + DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps); steps++; NextStep(id); } Sleep(10); } - DEBUG("OpenPPT: Steps %d, first slide steps %d\n",pptviewobj[id].steps,pptviewobj[id].firstSlideSteps); + DEBUG("OpenPPT: Slides %d, Steps %d, first slide steps %d\n", + pptView[id].slideCount, pptView[id].steps, + pptView[id].firstSlideSteps); + for(int i = 1; i <= pptView[id].slideCount; i++) + { + DEBUG("OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]); + } SavePPTInfo(id); - if(pptviewobj[id].state==PPT_CLOSING||pptviewobj[id].slideCount<=0){ + if (pptView[id].state == PPT_CLOSING + || pptView[id].slideCount <= 0) + { ClosePPT(id); id=-1; } - else + else + { RestartShow(id); + } } - if(id>=0) + if (id >= 0) { - if(pptviewobj[id].mhook!=NULL) - UnhookWindowsHookEx(pptviewobj[id].mhook); - pptviewobj[id].mhook = NULL; + if (pptView[id].msgHook != NULL) + { + UnhookWindowsHookEx(pptView[id].msgHook); + } + pptView[id].msgHook = NULL; } DEBUG("OpenPPT: Exit: id=%i\n", id); return id; @@ -236,100 +260,119 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewp // first slide steps BOOL GetPPTInfo(int id) { - struct _stat filestats; + struct _stat fileStats; char info[MAX_PATH]; FILE* pFile; char buf[100]; DEBUG("GetPPTInfo: start\n"); - if(_stat(pptviewobj[id].filename, &filestats)!=0) + if (_stat(pptView[id].filename, &fileStats) != 0) + { return FALSE; - sprintf_s(info, MAX_PATH, "%sinfo.txt", pptviewobj[id].previewpath); + } + sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); int err = fopen_s(&pFile, info, "r"); - if(err!=0) + if (err != 0) { DEBUG("GetPPTInfo: file open failed - %d\n", err); return FALSE; } fgets(buf, 100, pFile); // version == 1 fgets(buf, 100, pFile); - if(filestats.st_mtime!=atoi(buf)) + if (fileStats.st_mtime != atoi(buf)) { + DEBUG("GetPPTInfo: date changed\n"); fclose (pFile); return FALSE; } fgets(buf, 100, pFile); - if(filestats.st_size!=atoi(buf)) + if (fileStats.st_size != atoi(buf)) { + DEBUG("GetPPTInfo: size changed\n"); fclose (pFile); return FALSE; } fgets(buf, 100, pFile); // slidecount - int slidecount = atoi(buf); + int slideCount = atoi(buf); fgets(buf, 100, pFile); // first slide steps - int firstslidesteps = atoi(buf); + int firstSlideSteps = atoi(buf); // check all the preview images still exist - for(int i = 1; i<=slidecount; i++) + for (int i = 1; i <= slideCount; i++) { - sprintf_s(info, MAX_PATH, "%s%i.bmp", pptviewobj[id].previewpath, i); - if(GetFileAttributes(info)==INVALID_FILE_ATTRIBUTES) + sprintf_s(info, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, i); + if (GetFileAttributes(info) == INVALID_FILE_ATTRIBUTES) + { + DEBUG("GetPPTInfo: bmp not found\n"); return FALSE; + } } fclose(pFile); - pptviewobj[id].slideCount = slidecount; - pptviewobj[id].firstSlideSteps = firstslidesteps; + pptView[id].slideCount = slideCount; + pptView[id].firstSlideSteps = firstSlideSteps; DEBUG("GetPPTInfo: exit ok\n"); return TRUE; } BOOL SavePPTInfo(int id) { - struct _stat filestats; + struct _stat fileStats; char info[MAX_PATH]; FILE* pFile; DEBUG("SavePPTInfo: start\n"); - if(_stat(pptviewobj[id].filename, &filestats)!=0) + if (_stat(pptView[id].filename, &fileStats) != 0) { - DEBUG("SavePPTInfo: stat of %s failed\n", pptviewobj[id].filename); + DEBUG("SavePPTInfo: stat of %s failed\n", pptView[id].filename); return FALSE; } - sprintf_s(info, MAX_PATH, "%sinfo.txt", pptviewobj[id].previewpath); + sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); int err = fopen_s(&pFile, info, "w"); - if(err!=0) + if (err != 0) { DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err); return FALSE; } fprintf(pFile, "1\n"); - fprintf(pFile, "%u\n", filestats.st_mtime); - fprintf(pFile, "%u\n", filestats.st_size); - fprintf(pFile, "%u\n", pptviewobj[id].slideCount); - fprintf(pFile, "%u\n", pptviewobj[id].firstSlideSteps); - fclose (pFile); + fprintf(pFile, "%u\n", fileStats.st_mtime); + fprintf(pFile, "%u\n", fileStats.st_size); + fprintf(pFile, "%u\n", pptView[id].slideCount); + fprintf(pFile, "%u\n", pptView[id].firstSlideSteps); + fclose(pFile); DEBUG("SavePPTInfo: exit ok\n"); return TRUE; } // Get the path of the PowerPoint viewer from the registry -BOOL GetPPTViewerPath(char *pptviewerpath, int strsize) +BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize) { - HKEY hkey; - DWORD dwtype, dwsize; - LRESULT lresult; + HKEY hKey; + DWORD dwType, dwSize; + LRESULT lResult; DEBUG("GetPPTViewerPath: start\n"); - if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS) - if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS) - if(RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hkey)!=ERROR_SUCCESS) - return FALSE; - dwtype = REG_SZ; - dwsize = (DWORD)strsize; - lresult = RegQueryValueEx(hkey, NULL, NULL, &dwtype, (LPBYTE)pptviewerpath, &dwsize ); - RegCloseKey(hkey); - if(lresult!=ERROR_SUCCESS) + if ((RegOpenKeyEx(HKEY_CLASSES_ROOT, + "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey) + != ERROR_SUCCESS) + && (RegOpenKeyEx(HKEY_CLASSES_ROOT, + "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey) + != ERROR_SUCCESS) + && (RegOpenKeyEx(HKEY_CLASSES_ROOT, + "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey) + != ERROR_SUCCESS)) + { + return FALSE; + } + dwType = REG_SZ; + dwSize = (DWORD)stringSize; + lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)pptViewerPath, + &dwSize); + RegCloseKey(hKey); + if (lResult != ERROR_SUCCESS) + { return FALSE; - pptviewerpath[strlen(pptviewerpath)-4] = '\0'; // remove "%1" from end of key value + } + // remove "%1" from end of key value + pptViewerPath[strlen(pptViewerPath) - 4] = '\0'; DEBUG("GetPPTViewerPath: exit ok\n"); return TRUE; } @@ -338,12 +381,16 @@ BOOL GetPPTViewerPath(char *pptviewerpath, int strsize) void Unhook(int id) { DEBUG("Unhook: start %d\n", id); - if(pptviewobj[id].hook!=NULL) - UnhookWindowsHookEx(pptviewobj[id].hook); - if(pptviewobj[id].mhook!=NULL) - UnhookWindowsHookEx(pptviewobj[id].mhook); - pptviewobj[id].hook = NULL; - pptviewobj[id].mhook = NULL; + if (pptView[id].hook != NULL) + { + UnhookWindowsHookEx(pptView[id].hook); + } + if (pptView[id].msgHook != NULL) + { + UnhookWindowsHookEx(pptView[id].msgHook); + } + pptView[id].hook = NULL; + pptView[id].msgHook = NULL; DEBUG("Unhook: exit ok\n"); } @@ -351,15 +398,19 @@ void Unhook(int id) DllExport void ClosePPT(int id) { DEBUG("ClosePPT: start%d\n", id); - pptviewobj[id].state = PPT_CLOSED; + pptView[id].state = PPT_CLOSED; Unhook(id); - if(pptviewobj[id].hWnd==0) - TerminateThread(pptviewobj[id].hThread, 0); + if (pptView[id].hWnd == 0) + { + TerminateThread(pptView[id].hThread, 0); + } else - PostMessage(pptviewobj[id].hWnd, WM_CLOSE, 0, 0); - CloseHandle(pptviewobj[id].hThread); - CloseHandle(pptviewobj[id].hProcess); - memset(&pptviewobj[id], 0, sizeof(PPTVIEWOBJ)); + { + PostMessage(pptView[id].hWnd, WM_CLOSE, 0, 0); + } + CloseHandle(pptView[id].hThread); + CloseHandle(pptView[id].hProcess); + memset(&pptView[id], 0, sizeof(PPTVIEW)); DEBUG("ClosePPT: exit ok\n"); return; } @@ -367,54 +418,72 @@ DllExport void ClosePPT(int id) DllExport void Resume(int id) { DEBUG("Resume: %d\n", id); - MoveWindow(pptviewobj[id].hWnd, pptviewobj[id].rect.left, pptviewobj[id].rect.top, - pptviewobj[id].rect.right - pptviewobj[id].rect.left, - pptviewobj[id].rect.bottom - pptviewobj[id].rect.top, TRUE); + MoveWindow(pptView[id].hWnd, pptView[id].rect.left, + pptView[id].rect.top, + pptView[id].rect.right - pptView[id].rect.left, + pptView[id].rect.bottom - pptView[id].rect.top, TRUE); Unblank(id); } // Moves the show off the screen so it can't be seen DllExport void Stop(int id) { DEBUG("Stop:%d\n", id); - MoveWindow(pptviewobj[id].hWnd, -32000, -32000, - pptviewobj[id].rect.right - pptviewobj[id].rect.left, - pptviewobj[id].rect.bottom - pptviewobj[id].rect.top, TRUE); + MoveWindow(pptView[id].hWnd, -32000, -32000, + pptView[id].rect.right - pptView[id].rect.left, + pptView[id].rect.bottom - pptView[id].rect.top, TRUE); } // Return the total number of slides DllExport int GetSlideCount(int id) { DEBUG("GetSlideCount:%d\n", id); - if(pptviewobj[id].state==0) + if (pptView[id].state == 0) + { return -1; + } else - return pptviewobj[id].slideCount; + { + return pptView[id].slideCount; + } } // Return the number of the slide currently viewing DllExport int GetCurrentSlide(int id) { DEBUG("GetCurrentSlide:%d\n", id); - if(pptviewobj[id].state==0) + if (pptView[id].state == 0) + { return -1; + } else - return pptviewobj[id].currentSlide; + { + return pptView[id].currentSlide; + } } // Take a step forwards through the show DllExport void NextStep(int id) { - DEBUG("NextStep:%d\n", id); - if(pptviewobj[id].currentSlide>pptviewobj[id].slideCount) - return; - PostMessage(pptviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), 0); + DEBUG("NextStep:%d (%d)\n", id, pptView[id].currentSlide); + if (pptView[id].currentSlide > pptView[id].slideCount) return; + if (pptView[id].currentSlide < pptView[id].slideCount) + { + pptView[id].guess = pptView[id].currentSlide + 1; + } + PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), + 0); } // Take a step backwards through the show DllExport void PrevStep(int id) { - DEBUG("PrevStep:%d\n", id); - PostMessage(pptviewobj[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0); + DEBUG("PrevStep:%d (%d)\n", id, pptView[id].currentSlide); + if (pptView[id].currentSlide > 1) + { + pptView[id].guess = pptView[id].currentSlide - 1; + } + PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), + 0); } // Blank the show (black screen) @@ -427,18 +496,16 @@ DllExport void Blank(int id) DEBUG("Blank:%d\n", id); HWND h1 = GetForegroundWindow(); HWND h2 = GetFocus(); - SetForegroundWindow(pptviewobj[id].hWnd); - SetFocus(pptviewobj[id].hWnd); - Sleep(50); // slight pause, otherwise event triggering this call may grab focus back! + SetForegroundWindow(pptView[id].hWnd); + SetFocus(pptView[id].hWnd); + // slight pause, otherwise event triggering this call may grab focus back! + Sleep(50); keybd_event((int)'A', 0, 0, 0); keybd_event((int)'A', 0, KEYEVENTF_KEYUP, 0); keybd_event((int)'B', 0, 0, 0); keybd_event((int)'B', 0, KEYEVENTF_KEYUP, 0); SetForegroundWindow(h1); SetFocus(h2); - //PostMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, 'B', 0x00300001); - //PostMessage(pptviewobj[id].hWnd2, WM_CHAR, 'b', 0x00300001); - //PostMessage(pptviewobj[id].hWnd2, WM_KEYUP, 'B', 0xC0300001); } // Unblank the show DllExport void Unblank(int id) @@ -446,39 +513,31 @@ DllExport void Unblank(int id) DEBUG("Unblank:%d\n", id); // Pressing any key resumes. // For some reason SendMessage works for unblanking, but not blanking. -// SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, 'A', 0); - SendMessage(pptviewobj[id].hWnd2, WM_CHAR, 'A', 0); -// SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, 'A', 0); -// HWND h1 = GetForegroundWindow(); -// HWND h2 = GetFocus(); -// Sleep(50); // slight pause, otherwise event triggering this call may grab focus back! -// SetForegroundWindow(pptviewobj[id].hWnd); -// SetFocus(pptviewobj[id].hWnd); -// keybd_event((int)'A', 0, 0, 0); -// SetForegroundWindow(h1); -// SetFocus(h2); + SendMessage(pptView[id].hWnd2, WM_CHAR, 'A', 0); } // Go directly to a slide -DllExport void GotoSlide(int id, int slideno) +DllExport void GotoSlide(int id, int slideNo) { - DEBUG("GotoSlide %i %i:\n", id, slideno); + DEBUG("GotoSlide %i %i:\n", id, slideNo); // Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work // perhaps I was sending to the wrong window? No idea. // Anyway fall back to keybd_event, which is OK as long we makesure // the slideshow has focus first char ch[10]; - if(slideno<0) return; - _itoa_s(slideno, ch, 10, 10); + if (slideNo < 0) return; + pptView[id].guess = slideNo; + _itoa_s(slideNo, ch, 10, 10); HWND h1 = GetForegroundWindow(); HWND h2 = GetFocus(); - SetForegroundWindow(pptviewobj[id].hWnd); - SetFocus(pptviewobj[id].hWnd); - Sleep(50); // slight pause, otherwise event triggering this call may grab focus back! - for(int i=0;i<10;i++) + SetForegroundWindow(pptView[id].hWnd); + SetFocus(pptView[id].hWnd); + // slight pause, otherwise event triggering this call may grab focus back! + Sleep(50); + for (int i=0; i<10; i++) { - if(ch[i]=='\0') break; + if (ch[i] == '\0') break; keybd_event((BYTE)ch[i], 0, 0, 0); keybd_event((BYTE)ch[i], 0, KEYEVENTF_KEYUP, 0); } @@ -486,39 +545,28 @@ DllExport void GotoSlide(int id, int slideno) keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); SetForegroundWindow(h1); SetFocus(h2); - - //for(int i=0;i<10;i++) - //{ - // if(ch[i]=='\0') break; - // SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, ch[i], 0); - // SendMessage(pptviewobj[id].hWnd2, WM_CHAR, ch[i], 0); - // SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, ch[i], 0); - //} - //SendMessage(pptviewobj[id].hWnd2, WM_KEYDOWN, VK_RETURN, 0); - //SendMessage(pptviewobj[id].hWnd2, WM_CHAR, VK_RETURN, 0); - //SendMessage(pptviewobj[id].hWnd2, WM_KEYUP, VK_RETURN, 0); - //keybd_event(VK_RETURN, 0, 0, 0); } // Restart the show from the beginning DllExport void RestartShow(int id) { - // If we just go direct to slide one, then it remembers that all other slides have - // been animated, so ends up just showing the completed slides of those slides that - // have been animated next time we advance. - // Only way I've found to get around this is to step backwards all the way through. - // Lets move the window out of the way first so the audience doesn't see this. + // If we just go direct to slide one, then it remembers that all other + // slides have been animated, so ends up just showing the completed slides + // of those slides that have been animated next time we advance. + // Only way I've found to get around this is to step backwards all the way + // through. Lets move the window out of the way first so the audience + // doesn't see this. DEBUG("RestartShow:%d\n", id); Stop(id); - GotoSlide(id, pptviewobj[id].slideCount); - while(pptviewobj[id].currentSlide>1) + GotoSlide(id, pptView[id].slideCount); + for (int i=0; i <= pptView[id].steps - pptView[id].lastSlideSteps; i++) { PrevStep(id); Sleep(10); } - for(int i=0;i<=pptviewobj[id].firstSlideSteps;i++) + int i = 0; + while ((pptView[id].currentSlide > 1) && (i++ < 30000)) { - PrevStep(id); Sleep(10); } Resume(id); @@ -530,54 +578,62 @@ DllExport void RestartShow(int id) // Release the hook as soon as we're complete to free up resources LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) { - HHOOK hook = globalhook; - if(nCode==HCBT_CREATEWND) + HHOOK hook = globalHook; + if (nCode == HCBT_CREATEWND) { char csClassName[16]; HWND hCurrWnd = (HWND)wParam; DWORD retProcId = NULL; GetClassName(hCurrWnd, csClassName, sizeof(csClassName)); - if((strcmp(csClassName, "paneClassDC")==0) - ||(strcmp(csClassName, "screenClass")==0)) + if ((strcmp(csClassName, "paneClassDC") == 0) + ||(strcmp(csClassName, "screenClass") == 0)) { - int id=-1; - DWORD windowthread = GetWindowThreadProcessId(hCurrWnd,NULL); - for(int i=0; i=0) + if (id >= 0) { - if(strcmp(csClassName, "paneClassDC")==0) - pptviewobj[id].hWnd2=hCurrWnd; + if (strcmp(csClassName, "paneClassDC") == 0) + { + pptView[id].hWnd2 = hCurrWnd; + } else { - pptviewobj[id].hWnd=hCurrWnd; + pptView[id].hWnd = hCurrWnd; CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam; - if(pptviewobj[id].hParentWnd!=NULL) - cw->lpcs->hwndParent = pptviewobj[id].hParentWnd; - cw->lpcs->cy=(pptviewobj[id].rect.bottom-pptviewobj[id].rect.top); - cw->lpcs->cx=(pptviewobj[id].rect.right-pptviewobj[id].rect.left); - cw->lpcs->y=-32000; - cw->lpcs->x=-32000; + if (pptView[id].hParentWnd != NULL) + { + cw->lpcs->hwndParent = pptView[id].hParentWnd; + } + cw->lpcs->cy = pptView[id].rect.bottom + - pptView[id].rect.top; + cw->lpcs->cx = pptView[id].rect.right + - pptView[id].rect.left; + cw->lpcs->y = -32000; + cw->lpcs->x = -32000; } - if((pptviewobj[id].hWnd!=NULL)&&(pptviewobj[id].hWnd2!=NULL)) + if ((pptView[id].hWnd != NULL) && (pptView[id].hWnd2 != NULL)) { - UnhookWindowsHookEx(globalhook); - globalhook=NULL; - pptviewobj[id].hook = SetWindowsHookEx(WH_CALLWNDPROC,CwpProc,hInstance,pptviewobj[id].dwThreadId); - pptviewobj[id].mhook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInstance,pptviewobj[id].dwThreadId); + UnhookWindowsHookEx(globalHook); + globalHook = NULL; + pptView[id].hook = SetWindowsHookEx(WH_CALLWNDPROC, + CwpProc, hInstance, pptView[id].dwThreadId); + pptView[id].msgHook = SetWindowsHookEx(WH_GETMESSAGE, + GetMsgProc, hInstance, pptView[id].dwThreadId); Sleep(10); - pptviewobj[id].state = PPT_OPENED; + pptView[id].state = PPT_OPENED; } } } } - return CallNextHookEx(hook,nCode,wParam,lParam); + return CallNextHookEx(hook, nCode, wParam, lParam); } // This hook exists whilst the slideshow is loading but only listens on the @@ -586,24 +642,28 @@ LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { HHOOK hook = NULL; MSG *pMSG = (MSG *)lParam; - DWORD windowthread = GetWindowThreadProcessId(pMSG->hwnd,NULL); - int id=-1; - for(int i=0; ihwnd, NULL); + int id = -1; + for (int i = 0; i < MAX_PPTS; i++) { - if(pptviewobj[i].dwThreadId==windowthread) + if (pptView[i].dwThreadId == windowThread) { - id=i; - hook = pptviewobj[id].mhook; + id = i; + hook = pptView[id].msgHook; break; } } - if(id>=0&&nCode==HC_ACTION&&wParam==PM_REMOVE&&pMSG->message==WM_MOUSEWHEEL) + if (id >= 0 && nCode == HC_ACTION && wParam == PM_REMOVE + && pMSG->message == WM_MOUSEWHEEL) { - if(pptviewobj[id].state!=PPT_LOADED) + if (pptView[id].state != PPT_LOADED) { - if(pptviewobj[id].currentSlide==1) - pptviewobj[id].firstSlideSteps++; - pptviewobj[id].steps++; + if (pptView[id].currentSlide == 1) + { + pptView[id].firstSlideSteps++; + } + pptView[id].steps++; + pptView[id].lastSlideSteps++; } } return CallNextHookEx(hook, nCode, wParam, lParam); @@ -616,88 +676,125 @@ LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ HHOOK hook = NULL; char filename[MAX_PATH]; - DWORD windowthread = GetWindowThreadProcessId(cwp->hwnd,NULL); - int id=-1; - for(int i=0; ihwnd, NULL); + int id = -1; + for (int i = 0; i < MAX_PPTS; i++) { - if(pptviewobj[i].dwThreadId==windowthread) + if (pptView[i].dwThreadId == windowThread) { - id=i; - hook = pptviewobj[id].hook; + id = i; + hook = pptView[id].hook; break; } } - if((id>=0)&&(nCode==HC_ACTION)) + if ((id >= 0) && (nCode == HC_ACTION)) { - if(cwp->message==WM_USER+22) + if (cwp->message == WM_USER + 22) { - if(pptviewobj[id].state != PPT_LOADED) + if (pptView[id].state != PPT_LOADED) { - if((pptviewobj[id].currentSlide>0) - && (pptviewobj[id].previewpath!=NULL&&strlen(pptviewobj[id].previewpath)>0)) + if ((pptView[id].currentSlide > 0) + && (pptView[id].previewPath != NULL + && strlen(pptView[id].previewPath) > 0)) { - sprintf_s(filename, MAX_PATH, "%s%i.bmp", pptviewobj[id].previewpath, pptviewobj[id].currentSlide); + sprintf_s(filename, MAX_PATH, "%s%i.bmp", + pptView[id].previewPath, + pptView[id].currentSlide); CaptureAndSaveWindow(cwp->hwnd, filename); } - } - if(cwp->wParam==0) - { - if(pptviewobj[id].currentSlide>0) + if (((cwp->wParam == 0) + || (pptView[id].slideNos[1] == cwp->wParam)) + && (pptView[id].currentSlide > 0)) + { + pptView[id].state = PPT_LOADED; + pptView[id].currentSlide = pptView[id].slideCount + 1; + } + else { - pptviewobj[id].state = PPT_LOADED; - pptviewobj[id].currentSlide = pptviewobj[id].slideCount+1; - } - } - else - { - pptviewobj[id].currentSlide = cwp->wParam - 255; - if(pptviewobj[id].currentSlide>pptviewobj[id].slideCount) - pptviewobj[id].slideCount = pptviewobj[id].currentSlide; + if (cwp->wParam > 0) + { + pptView[id].currentSlide = pptView[id].currentSlide + 1; + pptView[id].slideNos[pptView[id].currentSlide] + = cwp->wParam; + pptView[id].slideCount = pptView[id].currentSlide; + pptView[id].lastSlideSteps = 0; + } + } + } + else + { + if (cwp->wParam > 0) + { + if(pptView[id].guess > 0 + && pptView[id].slideNos[pptView[id].guess] == 0) + { + pptView[id].currentSlide = 0; + } + for(int i = 1; i <= pptView[id].slideCount; i++) + { + if(pptView[id].slideNos[i] == cwp->wParam) + { + pptView[id].currentSlide = i; + break; + } + } + if(pptView[id].currentSlide == 0) + { + pptView[id].slideNos[pptView[id].guess] = cwp->wParam; + pptView[id].currentSlide = pptView[id].guess; + } + pptView[id].guess = 0; + } } } - if((pptviewobj[id].state != PPT_CLOSED)&&(cwp->message==WM_CLOSE||cwp->message==WM_QUIT)) - pptviewobj[id].state = PPT_CLOSING; + if ((pptView[id].state != PPT_CLOSED) + + &&(cwp->message == WM_CLOSE || cwp->message == WM_QUIT)) + { + pptView[id].state = PPT_CLOSING; + } } - return CallNextHookEx(hook,nCode,wParam,lParam); + return CallNextHookEx(hook, nCode, wParam, lParam); } VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename) { HBITMAP hBmp; if ((hBmp = CaptureWindow(hWnd)) == NULL) + { return; - + } RECT client; - GetClientRect (hWnd, &client); + GetClientRect(hWnd, &client); UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits UINT uiRemainderForPadding; - if ((uiRemainderForPadding = uiBytesPerRow % sizeof (DWORD)) > 0) - uiBytesPerRow += (sizeof (DWORD) - uiRemainderForPadding); + if ((uiRemainderForPadding = uiBytesPerRow % sizeof(DWORD)) > 0) + uiBytesPerRow += (sizeof(DWORD) - uiRemainderForPadding); UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom; PBYTE pDataBits; - if ((pDataBits = new BYTE [uiBytesPerAllRows]) != NULL) + if ((pDataBits = new BYTE[uiBytesPerAllRows]) != NULL) { BITMAPINFOHEADER bmi = {0}; BITMAPFILEHEADER bmf = {0}; // Prepare to get the data out of HBITMAP: - bmi.biSize = sizeof (bmi); + bmi.biSize = sizeof(bmi); bmi.biPlanes = 1; bmi.biBitCount = 24; bmi.biHeight = client.bottom; bmi.biWidth = client.right; // Get it: - HDC hDC = GetDC (hWnd); - GetDIBits (hDC, hBmp, 0, client.bottom, pDataBits, - (BITMAPINFO*) &bmi, DIB_RGB_COLORS); - ReleaseDC (hWnd, hDC); + HDC hDC = GetDC(hWnd); + GetDIBits(hDC, hBmp, 0, client.bottom, pDataBits, (BITMAPINFO*) &bmi, + DIB_RGB_COLORS); + ReleaseDC(hWnd, hDC); // Fill the file header: - bmf.bfOffBits = sizeof (bmf) + sizeof (bmi); + bmf.bfOffBits = sizeof(bmf) + sizeof(bmi); bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows; bmf.bfType = 0x4D42; @@ -706,56 +803,60 @@ VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename) int err = fopen_s(&pFile, filename, "wb"); if (err == 0) { - fwrite (&bmf, sizeof (bmf), 1, pFile); - fwrite (&bmi, sizeof (bmi), 1, pFile); - fwrite (pDataBits, sizeof (BYTE), uiBytesPerAllRows, pFile); - fclose (pFile); + fwrite(&bmf, sizeof(bmf), 1, pFile); + fwrite(&bmi, sizeof(bmi), 1, pFile); + fwrite(pDataBits, sizeof(BYTE), uiBytesPerAllRows, pFile); + fclose(pFile); } delete [] pDataBits; } - DeleteObject (hBmp); + DeleteObject(hBmp); } -HBITMAP CaptureWindow (HWND hWnd) { +HBITMAP CaptureWindow(HWND hWnd) +{ HDC hDC; BOOL bOk = FALSE; HBITMAP hImage = NULL; - hDC = GetDC (hWnd); + hDC = GetDC(hWnd); RECT rcClient; - GetClientRect (hWnd, &rcClient); - if ((hImage = CreateCompatibleBitmap (hDC, rcClient.right, rcClient.bottom)) != NULL) + GetClientRect(hWnd, &rcClient); + if ((hImage = CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom)) + != NULL) { HDC hMemDC; HBITMAP hDCBmp; - if ((hMemDC = CreateCompatibleDC (hDC)) != NULL) + if ((hMemDC = CreateCompatibleDC(hDC)) != NULL) { - hDCBmp = (HBITMAP) SelectObject (hMemDC, hImage); + hDCBmp = (HBITMAP)SelectObject(hMemDC, hImage); HMODULE hLib = LoadLibrary("User32"); // PrintWindow works for windows outside displayable area - // but was only introduced in WinXP. BitBlt requires the window to be topmost - // and within the viewable area of the display - if(GetProcAddress(hLib, "PrintWindow")==NULL) + // but was only introduced in WinXP. BitBlt requires the window to + // be topmost and within the viewable area of the display + if (GetProcAddress(hLib, "PrintWindow") == NULL) { SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); - BitBlt (hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, 0, SRCCOPY); - SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, SWP_NOSIZE); + BitBlt(hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, + 0, SRCCOPY); + SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, + SWP_NOSIZE); } else { PrintWindow(hWnd, hMemDC, 0); } - SelectObject (hMemDC, hDCBmp); - DeleteDC (hMemDC); + SelectObject(hMemDC, hDCBmp); + DeleteDC(hMemDC); bOk = TRUE; } } - ReleaseDC (hWnd, hDC); - if (! bOk) + ReleaseDC(hWnd, hDC); + if (!bOk) { if (hImage) { - DeleteObject (hImage); + DeleteObject(hImage); hImage = NULL; } } diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.dll b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.dll index f8a0de0d33e562014629fc97d25cc11103695e55..36581e00bb3bde8d7d059b50bf7b0eb51bd92a6e 100644 GIT binary patch literal 78848 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 diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h index 6012b0467..5ef09f47c 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h @@ -1,42 +1,68 @@ +/****************************************************************************** +* PptViewLib - PowerPoint Viewer 2003/2007 Controller * +* OpenLP - Open Source Lyrics Projection * +* --------------------------------------------------------------------------- * +* Copyright (c) 2008-2011 Raoul Snyman * +* Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael * +* Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, * +* Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon * +* Tibble, Carsten Tinggaard, Frode Woldsund * +* --------------------------------------------------------------------------- * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the Free * +* Software Foundation; version 2 of the License. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, write to the Free Software Foundation, Inc., 59 * +* Temple Place, Suite 330, Boston, MA 02111-1307 USA * +******************************************************************************/ #define DllExport extern "C" __declspec( dllexport ) -enum PPTVIEWSTATE { PPT_CLOSED, PPT_STARTED, PPT_OPENED, PPT_LOADED, PPT_CLOSING}; +#define DEBUG(...) if (debug) printf(__VA_ARGS__) -DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewpath); +enum PPTVIEWSTATE {PPT_CLOSED, PPT_STARTED, PPT_OPENED, PPT_LOADED, + PPT_CLOSING}; + +DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, + char *previewPath); DllExport BOOL CheckInstalled(); DllExport void ClosePPT(int id); DllExport int GetCurrentSlide(int id); DllExport int GetSlideCount(int id); DllExport void NextStep(int id); DllExport void PrevStep(int id); -DllExport void GotoSlide(int id, int slideno); +DllExport void GotoSlide(int id, int slide_no); DllExport void RestartShow(int id); DllExport void Blank(int id); DllExport void Unblank(int id); DllExport void Stop(int id); DllExport void Resume(int id); -DllExport void SetDebug(BOOL onoff); +DllExport void SetDebug(BOOL onOff); LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam); -BOOL GetPPTViewerPath(char *pptviewerpath, int strsize); -HBITMAP CaptureWindow (HWND hWnd); -VOID SaveBitmap (CHAR* filename, HBITMAP hBmp) ; +BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize); +HBITMAP CaptureWindow(HWND hWnd); +VOID SaveBitmap(CHAR* filename, HBITMAP hBmp) ; VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename); BOOL GetPPTInfo(int id); BOOL SavePPTInfo(int id); - - void Unhook(int id); -#define MAX_PPTOBJS 50 +#define MAX_PPTS 16 +#define MAX_SLIDES 256 -struct PPTVIEWOBJ +struct PPTVIEW { HHOOK hook; - HHOOK mhook; + HHOOK msgHook; HWND hWnd; HWND hWnd2; HWND hParentWnd; @@ -48,8 +74,11 @@ struct PPTVIEWOBJ int slideCount; int currentSlide; int firstSlideSteps; + int lastSlideSteps; int steps; + int guess; char filename[MAX_PATH]; - char previewpath[MAX_PATH]; + char previewPath[MAX_PATH]; + int slideNos[MAX_SLIDES]; PPTVIEWSTATE state; }; From 23e178846ba7b844e83032f42cd895c43317f618 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Wed, 16 Mar 2011 23:37:16 +0000 Subject: [PATCH 04/11] Fix PPT again! and remove tabs --- .../presentations/lib/powerpointcontroller.py | 1 + .../lib/pptviewlib/pptviewlib.cpp | 1088 ++++++++--------- .../presentations/lib/pptviewlib/pptviewlib.h | 36 +- 3 files changed, 563 insertions(+), 562 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 4dd57c5e1..5b19ac246 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -80,6 +80,7 @@ class PowerpointController(PresentationController): log.debug(u'start_process') if not self.process: self.process = Dispatch(u'PowerPoint.Application') + self.process.Visible = True self.process.WindowState = 2 def kill(self): diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index 4a3b1c399..f8a07d940 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -54,8 +54,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, LPVOID lpReserved) { hInstance = (HINSTANCE)hModule; - switch(ulReasonForCall) - { + switch(ulReasonForCall) + { case DLL_PROCESS_ATTACH: DEBUG("PROCESS_ATTACH\n"); break; @@ -72,23 +72,23 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, for (int i = 0; i < MAX_PPTS; i++) ClosePPT(i); break; - } - return TRUE; + } + return TRUE; } DllExport void SetDebug(BOOL onOff) { - printf("SetDebug\n"); - debug = onOff; - DEBUG("enabled\n"); + printf("SetDebug\n"); + debug = onOff; + DEBUG("enabled\n"); } DllExport BOOL CheckInstalled() { - char cmdLine[MAX_PATH * 2]; + char cmdLine[MAX_PATH * 2]; - DEBUG("CheckInstalled\n"); - return GetPPTViewerPath(cmdLine, sizeof(cmdLine)); + DEBUG("CheckInstalled\n"); + return GetPPTViewerPath(cmdLine, sizeof(cmdLine)); } // Open the PointPoint, count the slides and take a snapshot of each slide @@ -100,156 +100,156 @@ DllExport BOOL CheckInstalled() DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, char *previewPath) { - STARTUPINFO si; - PROCESS_INFORMATION pi; - char cmdLine[MAX_PATH * 2]; - int id; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char cmdLine[MAX_PATH * 2]; + int id; - DEBUG("OpenPPT start: %s; %s\n", filename, previewPath); - DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, + DEBUG("OpenPPT start: %s; %s\n", filename, previewPath); + DEBUG("OpenPPT start: %u; %i, %i, %i, %i\n", hParentWnd, rect.top, rect.left, rect.bottom, rect.right); - if (GetPPTViewerPath(cmdLine, sizeof(cmdLine)) == FALSE) - { - DEBUG("OpenPPT: GetPPTViewerPath failed\n"); - return -1; - } - id = -1; - for (int i = 0; i < MAX_PPTS; i++) - { - if (pptView[i].state == PPT_CLOSED) - { - id = i; - break; - } - } - if (id < 0) - { - DEBUG("OpenPPT: Too many PPTs\n"); - return -1; - } - memset(&pptView[id], 0, sizeof(PPTVIEW)); - strcpy_s(pptView[id].filename, MAX_PATH, filename); - strcpy_s(pptView[id].previewPath, MAX_PATH, previewPath); - pptView[id].state = PPT_CLOSED; - pptView[id].slideCount = 0; - pptView[id].currentSlide = 0; - pptView[id].firstSlideSteps = 0; - pptView[id].lastSlideSteps = 0; + if (GetPPTViewerPath(cmdLine, sizeof(cmdLine)) == FALSE) + { + DEBUG("OpenPPT: GetPPTViewerPath failed\n"); + return -1; + } + id = -1; + for (int i = 0; i < MAX_PPTS; i++) + { + if (pptView[i].state == PPT_CLOSED) + { + id = i; + break; + } + } + if (id < 0) + { + DEBUG("OpenPPT: Too many PPTs\n"); + return -1; + } + memset(&pptView[id], 0, sizeof(PPTVIEW)); + strcpy_s(pptView[id].filename, MAX_PATH, filename); + strcpy_s(pptView[id].previewPath, MAX_PATH, previewPath); + pptView[id].state = PPT_CLOSED; + pptView[id].slideCount = 0; + pptView[id].currentSlide = 0; + pptView[id].firstSlideSteps = 0; + pptView[id].lastSlideSteps = 0; pptView[id].guess = 0; - pptView[id].hParentWnd = hParentWnd; - pptView[id].hWnd = NULL; - pptView[id].hWnd2 = NULL; + pptView[id].hParentWnd = hParentWnd; + pptView[id].hWnd = NULL; + pptView[id].hWnd2 = NULL; for (int i = 0; i < MAX_SLIDES; i++) { pptView[id].slideNos[i] = 0; } - if (hParentWnd != NULL && rect.top == 0 && rect.bottom == 0 + if (hParentWnd != NULL && rect.top == 0 && rect.bottom == 0 && rect.left == 0 && rect.right == 0) - { - LPRECT windowRect = NULL; - GetWindowRect(hParentWnd, windowRect); - pptView[id].rect.top = 0; - pptView[id].rect.left = 0; - pptView[id].rect.bottom = windowRect->bottom - windowRect->top; - pptView[id].rect.right = windowRect->right - windowRect->left; - } - else - { - pptView[id].rect.top = rect.top; - pptView[id].rect.left = rect.left; - pptView[id].rect.bottom = rect.bottom; - pptView[id].rect.right = rect.right; - } - strcat_s(cmdLine, MAX_PATH * 2, "/F /S \""); - strcat_s(cmdLine, MAX_PATH * 2, filename); - strcat_s(cmdLine, MAX_PATH * 2, "\""); - memset(&si, 0, sizeof(si)); - memset(&pi, 0, sizeof(pi)); - BOOL gotInfo = GetPPTInfo(id); - /* - * I'd really like to just hook on the new threadid. However this always - * gives error 87. Perhaps I'm hooking to soon? No idea... however can't - * wait since I need to ensure I pick up the WM_CREATE as this is the only - * time the window can be resized in such away the content scales correctly - * - * hook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,pi.dwThreadId); - */ - if (globalHook != NULL) { - UnhookWindowsHookEx(globalHook); + LPRECT windowRect = NULL; + GetWindowRect(hParentWnd, windowRect); + pptView[id].rect.top = 0; + pptView[id].rect.left = 0; + pptView[id].rect.bottom = windowRect->bottom - windowRect->top; + pptView[id].rect.right = windowRect->right - windowRect->left; } - globalHook = SetWindowsHookEx(WH_CBT, CbtProc, hInstance, NULL); - if (globalHook == 0) - { - DEBUG("OpenPPT: SetWindowsHookEx failed\n"); - ClosePPT(id); - return -1; - } - pptView[id].state = PPT_STARTED; + else + { + pptView[id].rect.top = rect.top; + pptView[id].rect.left = rect.left; + pptView[id].rect.bottom = rect.bottom; + pptView[id].rect.right = rect.right; + } + strcat_s(cmdLine, MAX_PATH * 2, "/F /S \""); + strcat_s(cmdLine, MAX_PATH * 2, filename); + strcat_s(cmdLine, MAX_PATH * 2, "\""); + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + BOOL gotInfo = GetPPTInfo(id); + /* + * I'd really like to just hook on the new threadid. However this always + * gives error 87. Perhaps I'm hooking to soon? No idea... however can't + * wait since I need to ensure I pick up the WM_CREATE as this is the only + * time the window can be resized in such away the content scales correctly + * + * hook = SetWindowsHookEx(WH_CBT,CbtProc,hInstance,pi.dwThreadId); + */ + if (globalHook != NULL) + { + UnhookWindowsHookEx(globalHook); + } + globalHook = SetWindowsHookEx(WH_CBT, CbtProc, hInstance, NULL); + if (globalHook == 0) + { + DEBUG("OpenPPT: SetWindowsHookEx failed\n"); + ClosePPT(id); + return -1; + } + pptView[id].state = PPT_STARTED; Sleep(10); - if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi)) - { - DEBUG("OpenPPT: CreateProcess failed\n"); - ClosePPT(id); - return -1; - } - pptView[id].dwProcessId = pi.dwProcessId; - pptView[id].dwThreadId = pi.dwThreadId; - pptView[id].hThread = pi.hThread; - pptView[id].hProcess = pi.hProcess; - while (pptView[id].state == PPT_STARTED) - Sleep(10); - if (gotInfo) - { - DEBUG("OpenPPT: Info loaded, no refresh\n"); - pptView[id].state = PPT_LOADED; - Resume(id); - } - else - { - DEBUG("OpenPPT: Get info\n"); - pptView[id].steps = 0; - int steps = 0; - while (pptView[id].state == PPT_OPENED) - { - if (steps <= pptView[id].steps) - { - Sleep(20); - DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps); - steps++; - NextStep(id); - } - Sleep(10); - } - DEBUG("OpenPPT: Slides %d, Steps %d, first slide steps %d\n", + if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi)) + { + DEBUG("OpenPPT: CreateProcess failed\n"); + ClosePPT(id); + return -1; + } + pptView[id].dwProcessId = pi.dwProcessId; + pptView[id].dwThreadId = pi.dwThreadId; + pptView[id].hThread = pi.hThread; + pptView[id].hProcess = pi.hProcess; + while (pptView[id].state == PPT_STARTED) + Sleep(10); + if (gotInfo) + { + DEBUG("OpenPPT: Info loaded, no refresh\n"); + pptView[id].state = PPT_LOADED; + Resume(id); + } + else + { + DEBUG("OpenPPT: Get info\n"); + pptView[id].steps = 0; + int steps = 0; + while (pptView[id].state == PPT_OPENED) + { + if (steps <= pptView[id].steps) + { + Sleep(20); + DEBUG("OpenPPT: Step %d/%d\n", steps, pptView[id].steps); + steps++; + NextStep(id); + } + Sleep(10); + } + DEBUG("OpenPPT: Slides %d, Steps %d, first slide steps %d\n", pptView[id].slideCount, pptView[id].steps, - pptView[id].firstSlideSteps); + pptView[id].firstSlideSteps); for(int i = 1; i <= pptView[id].slideCount; i++) { - DEBUG("OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]); + DEBUG("OpenPPT: Slide %d = %d\n", i, pptView[id].slideNos[i]); } - SavePPTInfo(id); - if (pptView[id].state == PPT_CLOSING + SavePPTInfo(id); + if (pptView[id].state == PPT_CLOSING || pptView[id].slideCount <= 0) { - ClosePPT(id); - id=-1; - } - else - { - RestartShow(id); + ClosePPT(id); + id=-1; } - } - if (id >= 0) - { - if (pptView[id].msgHook != NULL) + else { - UnhookWindowsHookEx(pptView[id].msgHook); + RestartShow(id); } - pptView[id].msgHook = NULL; - } - DEBUG("OpenPPT: Exit: id=%i\n", id); - return id; + } + if (id >= 0) + { + if (pptView[id].msgHook != NULL) + { + UnhookWindowsHookEx(pptView[id].msgHook); + } + pptView[id].msgHook = NULL; + } + DEBUG("OpenPPT: Exit: id=%i\n", id); + return id; } // Load information about the ppt from an info.txt file. // Format: @@ -260,175 +260,175 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect, // first slide steps BOOL GetPPTInfo(int id) { - struct _stat fileStats; - char info[MAX_PATH]; - FILE* pFile; - char buf[100]; + struct _stat fileStats; + char info[MAX_PATH]; + FILE* pFile; + char buf[100]; - DEBUG("GetPPTInfo: start\n"); - if (_stat(pptView[id].filename, &fileStats) != 0) + DEBUG("GetPPTInfo: start\n"); + if (_stat(pptView[id].filename, &fileStats) != 0) { - return FALSE; + return FALSE; } - sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); - int err = fopen_s(&pFile, info, "r"); - if (err != 0) - { - DEBUG("GetPPTInfo: file open failed - %d\n", err); - return FALSE; - } - fgets(buf, 100, pFile); // version == 1 - fgets(buf, 100, pFile); - if (fileStats.st_mtime != atoi(buf)) - { - DEBUG("GetPPTInfo: date changed\n"); - fclose (pFile); - return FALSE; - } - fgets(buf, 100, pFile); - if (fileStats.st_size != atoi(buf)) - { - DEBUG("GetPPTInfo: size changed\n"); - fclose (pFile); - return FALSE; - } - fgets(buf, 100, pFile); // slidecount - int slideCount = atoi(buf); - fgets(buf, 100, pFile); // first slide steps - int firstSlideSteps = atoi(buf); - // check all the preview images still exist - for (int i = 1; i <= slideCount; i++) - { - sprintf_s(info, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, i); - if (GetFileAttributes(info) == INVALID_FILE_ATTRIBUTES) + sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); + int err = fopen_s(&pFile, info, "r"); + if (err != 0) + { + DEBUG("GetPPTInfo: file open failed - %d\n", err); + return FALSE; + } + fgets(buf, 100, pFile); // version == 1 + fgets(buf, 100, pFile); + if (fileStats.st_mtime != atoi(buf)) + { + DEBUG("GetPPTInfo: date changed\n"); + fclose (pFile); + return FALSE; + } + fgets(buf, 100, pFile); + if (fileStats.st_size != atoi(buf)) + { + DEBUG("GetPPTInfo: size changed\n"); + fclose (pFile); + return FALSE; + } + fgets(buf, 100, pFile); // slidecount + int slideCount = atoi(buf); + fgets(buf, 100, pFile); // first slide steps + int firstSlideSteps = atoi(buf); + // check all the preview images still exist + for (int i = 1; i <= slideCount; i++) + { + sprintf_s(info, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, i); + if (GetFileAttributes(info) == INVALID_FILE_ATTRIBUTES) { - DEBUG("GetPPTInfo: bmp not found\n"); - return FALSE; + DEBUG("GetPPTInfo: bmp not found\n"); + return FALSE; } - } - fclose(pFile); - pptView[id].slideCount = slideCount; - pptView[id].firstSlideSteps = firstSlideSteps; - DEBUG("GetPPTInfo: exit ok\n"); - return TRUE; + } + fclose(pFile); + pptView[id].slideCount = slideCount; + pptView[id].firstSlideSteps = firstSlideSteps; + DEBUG("GetPPTInfo: exit ok\n"); + return TRUE; } BOOL SavePPTInfo(int id) { - struct _stat fileStats; - char info[MAX_PATH]; - FILE* pFile; + struct _stat fileStats; + char info[MAX_PATH]; + FILE* pFile; - DEBUG("SavePPTInfo: start\n"); - if (_stat(pptView[id].filename, &fileStats) != 0) - { - DEBUG("SavePPTInfo: stat of %s failed\n", pptView[id].filename); - return FALSE; - } - sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); - int err = fopen_s(&pFile, info, "w"); - if (err != 0) - { - DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err); - return FALSE; - } - fprintf(pFile, "1\n"); - fprintf(pFile, "%u\n", fileStats.st_mtime); - fprintf(pFile, "%u\n", fileStats.st_size); - fprintf(pFile, "%u\n", pptView[id].slideCount); - fprintf(pFile, "%u\n", pptView[id].firstSlideSteps); - fclose(pFile); - DEBUG("SavePPTInfo: exit ok\n"); - return TRUE; + DEBUG("SavePPTInfo: start\n"); + if (_stat(pptView[id].filename, &fileStats) != 0) + { + DEBUG("SavePPTInfo: stat of %s failed\n", pptView[id].filename); + return FALSE; + } + sprintf_s(info, MAX_PATH, "%sinfo.txt", pptView[id].previewPath); + int err = fopen_s(&pFile, info, "w"); + if (err != 0) + { + DEBUG("SavePPTInfo: fopen of %s failed%i\n", info, err); + return FALSE; + } + fprintf(pFile, "1\n"); + fprintf(pFile, "%u\n", fileStats.st_mtime); + fprintf(pFile, "%u\n", fileStats.st_size); + fprintf(pFile, "%u\n", pptView[id].slideCount); + fprintf(pFile, "%u\n", pptView[id].firstSlideSteps); + fclose(pFile); + DEBUG("SavePPTInfo: exit ok\n"); + return TRUE; } // Get the path of the PowerPoint viewer from the registry BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize) { - HKEY hKey; - DWORD dwType, dwSize; - LRESULT lResult; + HKEY hKey; + DWORD dwType, dwSize; + LRESULT lResult; - DEBUG("GetPPTViewerPath: start\n"); - if ((RegOpenKeyEx(HKEY_CLASSES_ROOT, + DEBUG("GetPPTViewerPath: start\n"); + if ((RegOpenKeyEx(HKEY_CLASSES_ROOT, "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey) != ERROR_SUCCESS) && (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey) != ERROR_SUCCESS) - && (RegOpenKeyEx(HKEY_CLASSES_ROOT, + && (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Applications\\PPTVIEW.EXE\\shell\\Show\\command", 0, KEY_READ, &hKey) != ERROR_SUCCESS)) { return FALSE; } - dwType = REG_SZ; - dwSize = (DWORD)stringSize; - lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)pptViewerPath, + dwType = REG_SZ; + dwSize = (DWORD)stringSize; + lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)pptViewerPath, &dwSize); - RegCloseKey(hKey); - if (lResult != ERROR_SUCCESS) + RegCloseKey(hKey); + if (lResult != ERROR_SUCCESS) { - return FALSE; + return FALSE; } // remove "%1" from end of key value - pptViewerPath[strlen(pptViewerPath) - 4] = '\0'; - DEBUG("GetPPTViewerPath: exit ok\n"); - return TRUE; + pptViewerPath[strlen(pptViewerPath) - 4] = '\0'; + DEBUG("GetPPTViewerPath: exit ok\n"); + return TRUE; } // Unhook the Windows hook void Unhook(int id) { - DEBUG("Unhook: start %d\n", id); - if (pptView[id].hook != NULL) + DEBUG("Unhook: start %d\n", id); + if (pptView[id].hook != NULL) { - UnhookWindowsHookEx(pptView[id].hook); + UnhookWindowsHookEx(pptView[id].hook); } - if (pptView[id].msgHook != NULL) + if (pptView[id].msgHook != NULL) { - UnhookWindowsHookEx(pptView[id].msgHook); + UnhookWindowsHookEx(pptView[id].msgHook); } - pptView[id].hook = NULL; - pptView[id].msgHook = NULL; - DEBUG("Unhook: exit ok\n"); + pptView[id].hook = NULL; + pptView[id].msgHook = NULL; + DEBUG("Unhook: exit ok\n"); } // Close the PowerPoint viewer, release resources DllExport void ClosePPT(int id) { - DEBUG("ClosePPT: start%d\n", id); - pptView[id].state = PPT_CLOSED; - Unhook(id); - if (pptView[id].hWnd == 0) + DEBUG("ClosePPT: start%d\n", id); + pptView[id].state = PPT_CLOSED; + Unhook(id); + if (pptView[id].hWnd == 0) { - TerminateThread(pptView[id].hThread, 0); + TerminateThread(pptView[id].hThread, 0); } - else + else { - PostMessage(pptView[id].hWnd, WM_CLOSE, 0, 0); + PostMessage(pptView[id].hWnd, WM_CLOSE, 0, 0); } - CloseHandle(pptView[id].hThread); - CloseHandle(pptView[id].hProcess); - memset(&pptView[id], 0, sizeof(PPTVIEW)); - DEBUG("ClosePPT: exit ok\n"); - return; + CloseHandle(pptView[id].hThread); + CloseHandle(pptView[id].hProcess); + memset(&pptView[id], 0, sizeof(PPTVIEW)); + DEBUG("ClosePPT: exit ok\n"); + return; } // Moves the show back onto the display DllExport void Resume(int id) { - DEBUG("Resume: %d\n", id); - MoveWindow(pptView[id].hWnd, pptView[id].rect.left, + DEBUG("Resume: %d\n", id); + MoveWindow(pptView[id].hWnd, pptView[id].rect.left, pptView[id].rect.top, pptView[id].rect.right - pptView[id].rect.left, pptView[id].rect.bottom - pptView[id].rect.top, TRUE); - Unblank(id); + Unblank(id); } // Moves the show off the screen so it can't be seen DllExport void Stop(int id) { - DEBUG("Stop:%d\n", id); - MoveWindow(pptView[id].hWnd, -32000, -32000, + DEBUG("Stop:%d\n", id); + MoveWindow(pptView[id].hWnd, -32000, -32000, pptView[id].rect.right - pptView[id].rect.left, pptView[id].rect.bottom - pptView[id].rect.top, TRUE); } @@ -436,140 +436,140 @@ DllExport void Stop(int id) // Return the total number of slides DllExport int GetSlideCount(int id) { - DEBUG("GetSlideCount:%d\n", id); - if (pptView[id].state == 0) + DEBUG("GetSlideCount:%d\n", id); + if (pptView[id].state == 0) { - return -1; + return -1; } - else + else { - return pptView[id].slideCount; + return pptView[id].slideCount; } } // Return the number of the slide currently viewing DllExport int GetCurrentSlide(int id) { - DEBUG("GetCurrentSlide:%d\n", id); - if (pptView[id].state == 0) + DEBUG("GetCurrentSlide:%d\n", id); + if (pptView[id].state == 0) { - return -1; + return -1; } - else + else { - return pptView[id].currentSlide; + return pptView[id].currentSlide; } } // Take a step forwards through the show DllExport void NextStep(int id) { - DEBUG("NextStep:%d (%d)\n", id, pptView[id].currentSlide); - if (pptView[id].currentSlide > pptView[id].slideCount) return; + DEBUG("NextStep:%d (%d)\n", id, pptView[id].currentSlide); + if (pptView[id].currentSlide > pptView[id].slideCount) return; if (pptView[id].currentSlide < pptView[id].slideCount) { pptView[id].guess = pptView[id].currentSlide + 1; } - PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), + PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, -WHEEL_DELTA), 0); } // Take a step backwards through the show DllExport void PrevStep(int id) { - DEBUG("PrevStep:%d (%d)\n", id, pptView[id].currentSlide); + DEBUG("PrevStep:%d (%d)\n", id, pptView[id].currentSlide); if (pptView[id].currentSlide > 1) { pptView[id].guess = pptView[id].currentSlide - 1; } - PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), + PostMessage(pptView[id].hWnd2, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0); } // Blank the show (black screen) DllExport void Blank(int id) -{ - // B just toggles blank on/off. However pressing any key unblanks. - // So send random unmapped letter first (say 'A'), then we can - // better guarantee B will blank instead of trying to guess - // whether it was already blank or not. - DEBUG("Blank:%d\n", id); - HWND h1 = GetForegroundWindow(); - HWND h2 = GetFocus(); - SetForegroundWindow(pptView[id].hWnd); - SetFocus(pptView[id].hWnd); +{ + // B just toggles blank on/off. However pressing any key unblanks. + // So send random unmapped letter first (say 'A'), then we can + // better guarantee B will blank instead of trying to guess + // whether it was already blank or not. + DEBUG("Blank:%d\n", id); + HWND h1 = GetForegroundWindow(); + HWND h2 = GetFocus(); + SetForegroundWindow(pptView[id].hWnd); + SetFocus(pptView[id].hWnd); // slight pause, otherwise event triggering this call may grab focus back! - Sleep(50); - keybd_event((int)'A', 0, 0, 0); - keybd_event((int)'A', 0, KEYEVENTF_KEYUP, 0); - keybd_event((int)'B', 0, 0, 0); - keybd_event((int)'B', 0, KEYEVENTF_KEYUP, 0); - SetForegroundWindow(h1); - SetFocus(h2); + Sleep(50); + keybd_event((int)'A', 0, 0, 0); + keybd_event((int)'A', 0, KEYEVENTF_KEYUP, 0); + keybd_event((int)'B', 0, 0, 0); + keybd_event((int)'B', 0, KEYEVENTF_KEYUP, 0); + SetForegroundWindow(h1); + SetFocus(h2); } // Unblank the show DllExport void Unblank(int id) -{ - DEBUG("Unblank:%d\n", id); - // Pressing any key resumes. - // For some reason SendMessage works for unblanking, but not blanking. - SendMessage(pptView[id].hWnd2, WM_CHAR, 'A', 0); +{ + DEBUG("Unblank:%d\n", id); + // Pressing any key resumes. + // For some reason SendMessage works for unblanking, but not blanking. + SendMessage(pptView[id].hWnd2, WM_CHAR, 'A', 0); } // Go directly to a slide DllExport void GotoSlide(int id, int slideNo) -{ - DEBUG("GotoSlide %i %i:\n", id, slideNo); - // Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work - // perhaps I was sending to the wrong window? No idea. - // Anyway fall back to keybd_event, which is OK as long we makesure - // the slideshow has focus first - char ch[10]; +{ + DEBUG("GotoSlide %i %i:\n", id, slideNo); + // Did try WM_KEYDOWN/WM_CHAR/WM_KEYUP with SendMessage but didn't work + // perhaps I was sending to the wrong window? No idea. + // Anyway fall back to keybd_event, which is OK as long we makesure + // the slideshow has focus first + char ch[10]; - if (slideNo < 0) return; + if (slideNo < 0) return; pptView[id].guess = slideNo; - _itoa_s(slideNo, ch, 10, 10); - HWND h1 = GetForegroundWindow(); - HWND h2 = GetFocus(); - SetForegroundWindow(pptView[id].hWnd); - SetFocus(pptView[id].hWnd); + _itoa_s(slideNo, ch, 10, 10); + HWND h1 = GetForegroundWindow(); + HWND h2 = GetFocus(); + SetForegroundWindow(pptView[id].hWnd); + SetFocus(pptView[id].hWnd); // slight pause, otherwise event triggering this call may grab focus back! - Sleep(50); - for (int i=0; i<10; i++) - { - if (ch[i] == '\0') break; - keybd_event((BYTE)ch[i], 0, 0, 0); - keybd_event((BYTE)ch[i], 0, KEYEVENTF_KEYUP, 0); - } - keybd_event(VK_RETURN, 0, 0, 0); - keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); - SetForegroundWindow(h1); - SetFocus(h2); + Sleep(50); + for (int i=0; i<10; i++) + { + if (ch[i] == '\0') break; + keybd_event((BYTE)ch[i], 0, 0, 0); + keybd_event((BYTE)ch[i], 0, KEYEVENTF_KEYUP, 0); + } + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + SetForegroundWindow(h1); + SetFocus(h2); } // Restart the show from the beginning DllExport void RestartShow(int id) { - // If we just go direct to slide one, then it remembers that all other - // slides have been animated, so ends up just showing the completed slides - // of those slides that have been animated next time we advance. - // Only way I've found to get around this is to step backwards all the way - // through. Lets move the window out of the way first so the audience + // If we just go direct to slide one, then it remembers that all other + // slides have been animated, so ends up just showing the completed slides + // of those slides that have been animated next time we advance. + // Only way I've found to get around this is to step backwards all the way + // through. Lets move the window out of the way first so the audience // doesn't see this. - DEBUG("RestartShow:%d\n", id); - Stop(id); - GotoSlide(id, pptView[id].slideCount); - for (int i=0; i <= pptView[id].steps - pptView[id].lastSlideSteps; i++) - { - PrevStep(id); - Sleep(10); - } - int i = 0; - while ((pptView[id].currentSlide > 1) && (i++ < 30000)) - { - Sleep(10); - } - Resume(id); + DEBUG("RestartShow:%d\n", id); + Stop(id); + GotoSlide(id, pptView[id].slideCount); + for (int i=0; i <= pptView[id].steps - pptView[id].lastSlideSteps; i++) + { + PrevStep(id); + Sleep(10); + } + int i = 0; + while ((pptView[id].currentSlide > 1) && (i++ < 30000)) + { + Sleep(10); + } + Resume(id); } // This hook is started with the PPTVIEW.EXE process and waits for the @@ -578,130 +578,130 @@ DllExport void RestartShow(int id) // Release the hook as soon as we're complete to free up resources LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) { - HHOOK hook = globalHook; + HHOOK hook = globalHook; if (nCode == HCBT_CREATEWND) { - char csClassName[16]; + char csClassName[16]; HWND hCurrWnd = (HWND)wParam; - DWORD retProcId = NULL; - GetClassName(hCurrWnd, csClassName, sizeof(csClassName)); - if ((strcmp(csClassName, "paneClassDC") == 0) - ||(strcmp(csClassName, "screenClass") == 0)) - { - int id = -1; - DWORD windowThread = GetWindowThreadProcessId(hCurrWnd, NULL); - for (int i=0; i < MAX_PPTS; i++) - { - if (pptView[i].dwThreadId == windowThread) - { - id = i; - break; - } - } - if (id >= 0) - { - if (strcmp(csClassName, "paneClassDC") == 0) + DWORD retProcId = NULL; + GetClassName(hCurrWnd, csClassName, sizeof(csClassName)); + if ((strcmp(csClassName, "paneClassDC") == 0) + ||(strcmp(csClassName, "screenClass") == 0)) + { + int id = -1; + DWORD windowThread = GetWindowThreadProcessId(hCurrWnd, NULL); + for (int i=0; i < MAX_PPTS; i++) + { + if (pptView[i].dwThreadId == windowThread) { - pptView[id].hWnd2 = hCurrWnd; + id = i; + break; } - else - { - pptView[id].hWnd = hCurrWnd; - CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam; - if (pptView[id].hParentWnd != NULL) + } + if (id >= 0) + { + if (strcmp(csClassName, "paneClassDC") == 0) + { + pptView[id].hWnd2 = hCurrWnd; + } + else + { + pptView[id].hWnd = hCurrWnd; + CBT_CREATEWND* cw = (CBT_CREATEWND*)lParam; + if (pptView[id].hParentWnd != NULL) { - cw->lpcs->hwndParent = pptView[id].hParentWnd; + cw->lpcs->hwndParent = pptView[id].hParentWnd; } - cw->lpcs->cy = pptView[id].rect.bottom + cw->lpcs->cy = pptView[id].rect.bottom - pptView[id].rect.top; - cw->lpcs->cx = pptView[id].rect.right + cw->lpcs->cx = pptView[id].rect.right - pptView[id].rect.left; - cw->lpcs->y = -32000; - cw->lpcs->x = -32000; - } - if ((pptView[id].hWnd != NULL) && (pptView[id].hWnd2 != NULL)) - { - UnhookWindowsHookEx(globalHook); - globalHook = NULL; - pptView[id].hook = SetWindowsHookEx(WH_CALLWNDPROC, + cw->lpcs->y = -32000; + cw->lpcs->x = -32000; + } + if ((pptView[id].hWnd != NULL) && (pptView[id].hWnd2 != NULL)) + { + UnhookWindowsHookEx(globalHook); + globalHook = NULL; + pptView[id].hook = SetWindowsHookEx(WH_CALLWNDPROC, CwpProc, hInstance, pptView[id].dwThreadId); - pptView[id].msgHook = SetWindowsHookEx(WH_GETMESSAGE, + pptView[id].msgHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hInstance, pptView[id].dwThreadId); - Sleep(10); - pptView[id].state = PPT_OPENED; - } - } - } + Sleep(10); + pptView[id].state = PPT_OPENED; + } + } + } } - return CallNextHookEx(hook, nCode, wParam, lParam); + return CallNextHookEx(hook, nCode, wParam, lParam); } // This hook exists whilst the slideshow is loading but only listens on the // slideshows thread. It listens out for mousewheel events LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { - HHOOK hook = NULL; - MSG *pMSG = (MSG *)lParam; - DWORD windowThread = GetWindowThreadProcessId(pMSG->hwnd, NULL); - int id = -1; - for (int i = 0; i < MAX_PPTS; i++) - { - if (pptView[i].dwThreadId == windowThread) - { - id = i; - hook = pptView[id].msgHook; - break; - } - } - if (id >= 0 && nCode == HC_ACTION && wParam == PM_REMOVE + HHOOK hook = NULL; + MSG *pMSG = (MSG *)lParam; + DWORD windowThread = GetWindowThreadProcessId(pMSG->hwnd, NULL); + int id = -1; + for (int i = 0; i < MAX_PPTS; i++) + { + if (pptView[i].dwThreadId == windowThread) + { + id = i; + hook = pptView[id].msgHook; + break; + } + } + if (id >= 0 && nCode == HC_ACTION && wParam == PM_REMOVE && pMSG->message == WM_MOUSEWHEEL) { - if (pptView[id].state != PPT_LOADED) - { - if (pptView[id].currentSlide == 1) + if (pptView[id].state != PPT_LOADED) + { + if (pptView[id].currentSlide == 1) { - pptView[id].firstSlideSteps++; + pptView[id].firstSlideSteps++; } - pptView[id].steps++; - pptView[id].lastSlideSteps++; - } + pptView[id].steps++; + pptView[id].lastSlideSteps++; + } } return CallNextHookEx(hook, nCode, wParam, lParam); } // This hook exists whilst the slideshow is running but only listens on the // slideshows thread. It listens out for slide changes, message WM_USER+22. LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ - CWPSTRUCT *cwp; - cwp = (CWPSTRUCT *)lParam; - HHOOK hook = NULL; - char filename[MAX_PATH]; + CWPSTRUCT *cwp; + cwp = (CWPSTRUCT *)lParam; + HHOOK hook = NULL; + char filename[MAX_PATH]; - DWORD windowThread = GetWindowThreadProcessId(cwp->hwnd, NULL); - int id = -1; - for (int i = 0; i < MAX_PPTS; i++) - { - if (pptView[i].dwThreadId == windowThread) - { - id = i; - hook = pptView[id].hook; - break; - } - } - if ((id >= 0) && (nCode == HC_ACTION)) - { - if (cwp->message == WM_USER + 22) - { - if (pptView[id].state != PPT_LOADED) - { - if ((pptView[id].currentSlide > 0) + DWORD windowThread = GetWindowThreadProcessId(cwp->hwnd, NULL); + int id = -1; + for (int i = 0; i < MAX_PPTS; i++) + { + if (pptView[i].dwThreadId == windowThread) + { + id = i; + hook = pptView[id].hook; + break; + } + } + if ((id >= 0) && (nCode == HC_ACTION)) + { + if (cwp->message == WM_USER + 22) + { + if (pptView[id].state != PPT_LOADED) + { + if ((pptView[id].currentSlide > 0) && (pptView[id].previewPath != NULL && strlen(pptView[id].previewPath) > 0)) - { - sprintf_s(filename, MAX_PATH, "%s%i.bmp", + { + sprintf_s(filename, MAX_PATH, "%s%i.bmp", pptView[id].previewPath, pptView[id].currentSlide); - CaptureAndSaveWindow(cwp->hwnd, filename); - } + CaptureAndSaveWindow(cwp->hwnd, filename); + } if (((cwp->wParam == 0) || (pptView[id].slideNos[1] == cwp->wParam)) && (pptView[id].currentSlide > 0)) @@ -709,156 +709,156 @@ LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam){ pptView[id].state = PPT_LOADED; pptView[id].currentSlide = pptView[id].slideCount + 1; } - else - { - if (cwp->wParam > 0) - { - pptView[id].currentSlide = pptView[id].currentSlide + 1; - pptView[id].slideNos[pptView[id].currentSlide] - = cwp->wParam; - pptView[id].slideCount = pptView[id].currentSlide; - pptView[id].lastSlideSteps = 0; - } + else + { + if (cwp->wParam > 0) + { + pptView[id].currentSlide = pptView[id].currentSlide + 1; + pptView[id].slideNos[pptView[id].currentSlide] + = cwp->wParam; + pptView[id].slideCount = pptView[id].currentSlide; + pptView[id].lastSlideSteps = 0; + } } } else { if (cwp->wParam > 0) { - if(pptView[id].guess > 0 - && pptView[id].slideNos[pptView[id].guess] == 0) - { - pptView[id].currentSlide = 0; - } - for(int i = 1; i <= pptView[id].slideCount; i++) - { - if(pptView[id].slideNos[i] == cwp->wParam) - { - pptView[id].currentSlide = i; - break; - } - } - if(pptView[id].currentSlide == 0) - { - pptView[id].slideNos[pptView[id].guess] = cwp->wParam; - pptView[id].currentSlide = pptView[id].guess; - } - pptView[id].guess = 0; - } - } - } - if ((pptView[id].state != PPT_CLOSED) - - &&(cwp->message == WM_CLOSE || cwp->message == WM_QUIT)) - { - pptView[id].state = PPT_CLOSING; + if(pptView[id].guess > 0 + && pptView[id].slideNos[pptView[id].guess] == 0) + { + pptView[id].currentSlide = 0; + } + for(int i = 1; i <= pptView[id].slideCount; i++) + { + if(pptView[id].slideNos[i] == cwp->wParam) + { + pptView[id].currentSlide = i; + break; + } + } + if(pptView[id].currentSlide == 0) + { + pptView[id].slideNos[pptView[id].guess] = cwp->wParam; + pptView[id].currentSlide = pptView[id].guess; + } + pptView[id].guess = 0; + } + } } - } - return CallNextHookEx(hook, nCode, wParam, lParam); + if ((pptView[id].state != PPT_CLOSED) + + &&(cwp->message == WM_CLOSE || cwp->message == WM_QUIT)) + { + pptView[id].state = PPT_CLOSING; + } + } + return CallNextHookEx(hook, nCode, wParam, lParam); } VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename) { - HBITMAP hBmp; - if ((hBmp = CaptureWindow(hWnd)) == NULL) + HBITMAP hBmp; + if ((hBmp = CaptureWindow(hWnd)) == NULL) { - return; + return; } - RECT client; - GetClientRect(hWnd, &client); - UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits - UINT uiRemainderForPadding; + RECT client; + GetClientRect(hWnd, &client); + UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits + UINT uiRemainderForPadding; - if ((uiRemainderForPadding = uiBytesPerRow % sizeof(DWORD)) > 0) - uiBytesPerRow += (sizeof(DWORD) - uiRemainderForPadding); + if ((uiRemainderForPadding = uiBytesPerRow % sizeof(DWORD)) > 0) + uiBytesPerRow += (sizeof(DWORD) - uiRemainderForPadding); - UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom; - PBYTE pDataBits; + UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom; + PBYTE pDataBits; - if ((pDataBits = new BYTE[uiBytesPerAllRows]) != NULL) - { - BITMAPINFOHEADER bmi = {0}; - BITMAPFILEHEADER bmf = {0}; + if ((pDataBits = new BYTE[uiBytesPerAllRows]) != NULL) + { + BITMAPINFOHEADER bmi = {0}; + BITMAPFILEHEADER bmf = {0}; - // Prepare to get the data out of HBITMAP: - bmi.biSize = sizeof(bmi); - bmi.biPlanes = 1; - bmi.biBitCount = 24; - bmi.biHeight = client.bottom; - bmi.biWidth = client.right; + // Prepare to get the data out of HBITMAP: + bmi.biSize = sizeof(bmi); + bmi.biPlanes = 1; + bmi.biBitCount = 24; + bmi.biHeight = client.bottom; + bmi.biWidth = client.right; - // Get it: - HDC hDC = GetDC(hWnd); - GetDIBits(hDC, hBmp, 0, client.bottom, pDataBits, (BITMAPINFO*) &bmi, + // Get it: + HDC hDC = GetDC(hWnd); + GetDIBits(hDC, hBmp, 0, client.bottom, pDataBits, (BITMAPINFO*) &bmi, DIB_RGB_COLORS); - ReleaseDC(hWnd, hDC); + ReleaseDC(hWnd, hDC); - // Fill the file header: - bmf.bfOffBits = sizeof(bmf) + sizeof(bmi); - bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows; - bmf.bfType = 0x4D42; + // Fill the file header: + bmf.bfOffBits = sizeof(bmf) + sizeof(bmi); + bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows; + bmf.bfType = 0x4D42; - // Writing: - FILE* pFile; - int err = fopen_s(&pFile, filename, "wb"); - if (err == 0) - { - fwrite(&bmf, sizeof(bmf), 1, pFile); - fwrite(&bmi, sizeof(bmi), 1, pFile); - fwrite(pDataBits, sizeof(BYTE), uiBytesPerAllRows, pFile); - fclose(pFile); - } - delete [] pDataBits; - } - DeleteObject(hBmp); + // Writing: + FILE* pFile; + int err = fopen_s(&pFile, filename, "wb"); + if (err == 0) + { + fwrite(&bmf, sizeof(bmf), 1, pFile); + fwrite(&bmi, sizeof(bmi), 1, pFile); + fwrite(pDataBits, sizeof(BYTE), uiBytesPerAllRows, pFile); + fclose(pFile); + } + delete [] pDataBits; + } + DeleteObject(hBmp); } HBITMAP CaptureWindow(HWND hWnd) { - HDC hDC; - BOOL bOk = FALSE; - HBITMAP hImage = NULL; + HDC hDC; + BOOL bOk = FALSE; + HBITMAP hImage = NULL; - hDC = GetDC(hWnd); - RECT rcClient; - GetClientRect(hWnd, &rcClient); - if ((hImage = CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom)) + hDC = GetDC(hWnd); + RECT rcClient; + GetClientRect(hWnd, &rcClient); + if ((hImage = CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom)) != NULL) - { - HDC hMemDC; - HBITMAP hDCBmp; + { + HDC hMemDC; + HBITMAP hDCBmp; - if ((hMemDC = CreateCompatibleDC(hDC)) != NULL) - { - hDCBmp = (HBITMAP)SelectObject(hMemDC, hImage); - HMODULE hLib = LoadLibrary("User32"); - // PrintWindow works for windows outside displayable area - // but was only introduced in WinXP. BitBlt requires the window to - // be topmost and within the viewable area of the display - if (GetProcAddress(hLib, "PrintWindow") == NULL) - { - SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); - BitBlt(hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, + if ((hMemDC = CreateCompatibleDC(hDC)) != NULL) + { + hDCBmp = (HBITMAP)SelectObject(hMemDC, hImage); + HMODULE hLib = LoadLibrary("User32"); + // PrintWindow works for windows outside displayable area + // but was only introduced in WinXP. BitBlt requires the window to + // be topmost and within the viewable area of the display + if (GetProcAddress(hLib, "PrintWindow") == NULL) + { + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); + BitBlt(hMemDC, 0, 0, rcClient.right, rcClient.bottom, hDC, 0, 0, SRCCOPY); - SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, + SetWindowPos(hWnd, HWND_NOTOPMOST, -32000, -32000, 0, 0, SWP_NOSIZE); - } - else - { - PrintWindow(hWnd, hMemDC, 0); - } - SelectObject(hMemDC, hDCBmp); - DeleteDC(hMemDC); - bOk = TRUE; - } - } - ReleaseDC(hWnd, hDC); - if (!bOk) - { - if (hImage) - { - DeleteObject(hImage); - hImage = NULL; - } - } - return hImage; + } + else + { + PrintWindow(hWnd, hMemDC, 0); + } + SelectObject(hMemDC, hDCBmp); + DeleteDC(hMemDC); + bOk = TRUE; + } + } + ReleaseDC(hWnd, hDC); + if (!bOk) + { + if (hImage) + { + DeleteObject(hImage); + hImage = NULL; + } + } + return hImage; } diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h index 5ef09f47c..714376f63 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h @@ -61,24 +61,24 @@ void Unhook(int id); struct PPTVIEW { - HHOOK hook; - HHOOK msgHook; - HWND hWnd; - HWND hWnd2; - HWND hParentWnd; - HANDLE hProcess; - HANDLE hThread; - DWORD dwProcessId; - DWORD dwThreadId; - RECT rect; - int slideCount; - int currentSlide; - int firstSlideSteps; - int lastSlideSteps; - int steps; + HHOOK hook; + HHOOK msgHook; + HWND hWnd; + HWND hWnd2; + HWND hParentWnd; + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId; + RECT rect; + int slideCount; + int currentSlide; + int firstSlideSteps; + int lastSlideSteps; + int steps; int guess; - char filename[MAX_PATH]; - char previewPath[MAX_PATH]; + char filename[MAX_PATH]; + char previewPath[MAX_PATH]; int slideNos[MAX_SLIDES]; - PPTVIEWSTATE state; + PPTVIEWSTATE state; }; From e9bcab13de5024d9c91f6e0e3457361c07aea9c9 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 17 Mar 2011 13:32:45 +0100 Subject: [PATCH 05/11] fixed Verse Tag' column; clean up --- openlp/plugins/songs/forms/editsongform.py | 115 ++++++++++----------- 1 file changed, 54 insertions(+), 61 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index b63d775a0..4c9645834 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -297,7 +297,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.verseOrderEdit.setText(u' '.join(translated)) else: self.verseOrderEdit.setText(u'') - self.verseListWidget.resizeRowsToContents() self.tagRows() # clear the results self.authorsListView.clear() @@ -312,10 +311,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) self.topicsListView.addItem(topic_name) self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason) - # if not preview hide the preview button - self.previewButton.setVisible(False) - if preview: - self.previewButton.setVisible(True) + # Hide or show the preview button. + self.previewButton.setVisible(preview) def tagRows(self): """ @@ -329,6 +326,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): row_def = u'%s%s' % (verse_tag, verse_def[1:]) row_label.append(row_def) self.verseListWidget.setVerticalHeaderLabels(row_label) + self.verseListWidget.setColumnWidth(0, self.width) + self.verseListWidget.resizeRowsToContents() + self.verseListWidget.repaint() def onAuthorAddButtonClicked(self): item = int(self.authorsComboBox.currentIndex()) @@ -453,9 +453,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.verseListWidget.setRowCount( self.verseListWidget.rowCount() + 1) self.verseListWidget.setItem( - int(self.verseListWidget.rowCount() - 1), 0, item) - self.verseListWidget.setColumnWidth(0, self.width) - self.verseListWidget.resizeRowsToContents() + self.verseListWidget.rowCount() - 1, 0, item) self.tagRows() def onVerseEditButtonClicked(self): @@ -482,8 +480,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): item = QtGui.QTableWidgetItem(tempList[row], 0) item.setData(QtCore.Qt.UserRole, tempId[row]) self.verseListWidget.setItem(row, 0, item) - self.verseListWidget.resizeRowsToContents() - self.verseListWidget.repaint() self.tagRows() def onVerseEditAllButtonClicked(self): @@ -500,53 +496,50 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.verse_form.setVerse(verse_list) else: self.verse_form.setVerse(u'') - if self.verse_form.exec_(): - verse_list = self.verse_form.getVerseAll() - verse_list = unicode(verse_list.replace(u'\r\n', u'\n')) - self.verseListWidget.clear() - self.verseListWidget.setRowCount(0) - for row in self.findVerseSplit.split(verse_list): - for match in row.split(u'---['): - for count, parts in enumerate(match.split(u']---\n')): - if len(parts) > 1: - if count == 0: - # handling carefully user inputted versetags - separator = parts.find(u':') - if separator >= 0: - verse_name = parts[0:separator].strip() - verse_num = parts[separator+1:].strip() - else: - verse_name = parts - verse_num = u'1' - verse_index = \ - VerseType.from_loose_input(verse_name) - verse_tag = VerseType.Tags[verse_index] - # Later we need to handle v1a as well. - #regex = re.compile(r'(\d+\w.)') - regex = re.compile(r'\D*(\d+)\D*') - match = regex.match(verse_num) - if match: - verse_num = match.group(1) - else: - verse_num = u'1' - verse_def = u'%s%s' % (verse_tag, verse_num) - else: - if parts.endswith(u'\n'): - parts = parts.rstrip(u'\n') - item = QtGui.QTableWidgetItem(parts) - item.setData(QtCore.Qt.UserRole, - QtCore.QVariant(verse_def)) - self.verseListWidget.setRowCount( - self.verseListWidget.rowCount() + 1) - self.verseListWidget.setItem( - int(self.verseListWidget.rowCount() - 1), - 0, item) - self.verseListWidget.setColumnWidth(0, self.width) - self.verseListWidget.resizeRowsToContents() - self.verseListWidget.repaint() - self.tagRows() - self.verseEditButton.setEnabled(False) - self.verseDeleteButton.setEnabled(False) + if not self.verse_form.exec_(): + return + verse_list = self.verse_form.getVerseAll() + verse_list = unicode(verse_list.replace(u'\r\n', u'\n')) + self.verseListWidget.clear() + self.verseListWidget.setRowCount(0) + for row in self.findVerseSplit.split(verse_list): + for match in row.split(u'---['): + for count, parts in enumerate(match.split(u']---\n')): + if len(parts) <= 1: + continue + if count == 0: + # handling carefully user inputted versetags + separator = parts.find(u':') + if separator >= 0: + verse_name = parts[0:separator].strip() + verse_num = parts[separator+1:].strip() + else: + verse_name = parts + verse_num = u'1' + verse_index = VerseType.from_loose_input(verse_name) + verse_tag = VerseType.Tags[verse_index] + # Later we need to handle v1a as well. + #regex = re.compile(r'(\d+\w.)') + regex = re.compile(r'\D*(\d+)\D*') + match = regex.match(verse_num) + if match: + verse_num = match.group(1) + else: + verse_num = u'1' + verse_def = u'%s%s' % (verse_tag, verse_num) + else: + if parts.endswith(u'\n'): + parts = parts.rstrip(u'\n') + item = QtGui.QTableWidgetItem(parts) + item.setData(QtCore.Qt.UserRole, + QtCore.QVariant(verse_def)) + self.verseListWidget.setRowCount( + self.verseListWidget.rowCount() + 1) + self.verseListWidget.setItem( + self.verseListWidget.rowCount() - 1, 0, item) + self.tagRows() + self.verseEditButton.setEnabled(False) + self.verseDeleteButton.setEnabled(False) def onVerseDeleteButtonClicked(self): self.verseListWidget.removeRow(self.verseListWidget.currentRow()) @@ -728,7 +721,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.title = unicode(self.titleEdit.text()) self.song.alternate_title = unicode(self.alternativeEdit.text()) self.song.copyright = unicode(self.copyrightEdit.text()) - # Values will be set when cleaning the song. + # Values will be set when cleaning the song. self.song.search_title = u'' self.song.search_lyrics = u'' self.song.verse_order = u'' @@ -753,7 +746,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.theme_name = theme_name else: self.song.theme_name = None - self.processLyrics() + self._processLyrics() self.song.authors = [] for row in range(self.authorsListView.count()): item = self.authorsListView.item(row) @@ -769,12 +762,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if not preview: self.song = None - def processLyrics(self): + def _processLyrics(self): """ Process the lyric data entered by the user into the OpenLP XML format. """ # This method must only be run after the self.song = Song() assignment. - log.debug(u'processLyrics') + log.debug(u'_processLyrics') try: sxml = SongXML() multiple = [] From 3fc666d095f3625465a988bd0d818bc9dd0617a6 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 17 Mar 2011 15:03:57 +0200 Subject: [PATCH 06/11] Added download feedback. --- openlp/core/ui/firsttimeform.py | 48 ++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 08e240b5c..af90930db 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -52,7 +52,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): # check to see if we have web access self.web = u'http://openlp.org/files/frw/' self.config = SafeConfigParser() - self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg')) + self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg?99')) if self.webAccess: files = self.webAccess.read() self.config.readfp(io.BytesIO(files)) @@ -160,6 +160,16 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self._performWizard() self._postWizard() + def _getFileSize(self, url): + site = urllib.urlopen(url) + meta = site.info() + return int(meta.getheaders("Content-Length")[0]) + + def _downloadProgress(self, count, block_size, total_size): + increment = (count * block_size) - self.previous_size + self._incrementProgressBar(None, increment) + self.previous_size = count * block_size + def _incrementProgressBar(self, status_text, increment=1): """ Update the wizard progress page. @@ -184,19 +194,27 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): max_progress = 2 # Loop through the songs list and increase for each selected item for i in xrange(self.songsListWidget.count()): - if self.songsListWidget.item(i).checkState() == QtCore.Qt.Checked: - max_progress += 1 + item = self.songsListWidget.item(i) + if item.checkState() == QtCore.Qt.Checked: + filename = item.data(QtCore.Qt.UserRole).toString() + size = self._getFileSize(u'%s%s' % (self.web, filename)) + max_progress += size # Loop through the Bibles list and increase for each selected item iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget) while iterator.value(): item = iterator.value() if item.parent() and item.checkState(0) == QtCore.Qt.Checked: - max_progress += 1 + filename = item.data(0, QtCore.Qt.UserRole).toString() + size = self._getFileSize(u'%s%s' % (self.web, filename)) + max_progress += size iterator += 1 # Loop through the themes list and increase for each selected item for i in xrange(self.themesListWidget.count()): - if self.themesListWidget.item(i).checkState() == QtCore.Qt.Checked: - max_progress += 1 + item = self.themesListWidget.item(i) + if item.checkState() == QtCore.Qt.Checked: + filename, screenshot = item.data(QtCore.Qt.UserRole).toPyObject() + size = self._getFileSize(u'%s%s' % (self.web, filename)) + max_progress += size self.finishButton.setVisible(False) self.progressBar.setValue(0) self.progressBar.setMinimum(0) @@ -241,27 +259,33 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): item = self.songsListWidget.item(i) if item.checkState() == QtCore.Qt.Checked: filename = item.data(QtCore.Qt.UserRole).toString() - self._incrementProgressBar(self.downloading % filename) + self._incrementProgressBar(self.downloading % filename, 0) + self.previous_size = 0 destination = os.path.join(songs_destination, unicode(filename)) - urllib.urlretrieve(u'%s%s' % (self.web, filename), destination) + urllib.urlretrieve(u'%s%s' % (self.web, filename), destination, + self._downloadProgress) # Download Bibles bibles_iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget) while bibles_iterator.value(): item = bibles_iterator.value() if item.parent() and item.checkState(0) == QtCore.Qt.Checked: bible = unicode(item.data(0, QtCore.Qt.UserRole).toString()) - self._incrementProgressBar(self.downloading % bible) + self._incrementProgressBar(self.downloading % bible, 0) + self.previous_size = 0 urllib.urlretrieve(u'%s%s' % (self.web, bible), - os.path.join(bibles_destination, bible)) + os.path.join(bibles_destination, bible), + self._downloadProgress) bibles_iterator += 1 # Download themes for i in xrange(self.themesListWidget.count()): item = self.themesListWidget.item(i) if item.checkState() == QtCore.Qt.Checked: theme = unicode(item.data(QtCore.Qt.UserRole).toString()) - self._incrementProgressBar(self.downloading % theme) + self._incrementProgressBar(self.downloading % theme, 0) + self.previous_size = 0 urllib.urlretrieve(u'%s%s' % (self.web, theme), - os.path.join(themes_destination, theme)) + os.path.join(themes_destination, theme), + self._downloadProgress) # Set Default Display if self.displayComboBox.currentIndex() != -1: QtCore.QSettings().setValue(u'General/monitor', From 8e27f6938284ce82af1d02d95b2c808c8a59d120 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 17 Mar 2011 18:12:59 +0200 Subject: [PATCH 07/11] Fixed up the left-over anti-caching, and fixed a bug with the themes. --- openlp/core/ui/firsttimeform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index af90930db..708571f8d 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -52,7 +52,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): # check to see if we have web access self.web = u'http://openlp.org/files/frw/' self.config = SafeConfigParser() - self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg?99')) + self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg')) if self.webAccess: files = self.webAccess.read() self.config.readfp(io.BytesIO(files)) @@ -212,7 +212,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): for i in xrange(self.themesListWidget.count()): item = self.themesListWidget.item(i) if item.checkState() == QtCore.Qt.Checked: - filename, screenshot = item.data(QtCore.Qt.UserRole).toPyObject() + filename = item.data(QtCore.Qt.UserRole).toString() size = self._getFileSize(u'%s%s' % (self.web, filename)) max_progress += size self.finishButton.setVisible(False) From b057612a5e3aef27fed11552e671475995fa3f78 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 17 Mar 2011 20:01:15 +0100 Subject: [PATCH 08/11] only save custom values, and not default values --- openlp/core/ui/generaltab.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 277a93bc3..b53cf4e90 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -272,24 +272,14 @@ class GeneralTab(SettingsTab): QtCore.QVariant(5)).toInt()[0]) self.overrideCheckBox.setChecked(settings.value(u'override position', QtCore.QVariant(False)).toBool()) - if self.overrideCheckBox.isChecked(): - self.customXValueEdit.setValue(settings.value(u'x position', - QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0]) - self.customYValueEdit.setValue(settings.value(u'y position', - QtCore.QVariant(self.screens.current[u'size'].y())).toInt()[0]) - self.customHeightValueEdit.setValue( - settings.value(u'height', QtCore.QVariant( - self.screens.current[u'size'].height())).toInt()[0]) - self.customWidthValueEdit.setValue( - settings.value(u'width', QtCore.QVariant( - self.screens.current[u'size'].width())).toInt()[0]) - else: - self.customXValueEdit.setValue(self.screens.current[u'size'].x()) - self.customYValueEdit.setValue(self.screens.current[u'size'].y()) - self.customHeightValueEdit.setValue( - self.screens.current[u'size'].height()) - self.customWidthValueEdit.setValue( - self.screens.current[u'size'].width()) + self.customXValueEdit.setValue(settings.value(u'x position', + QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0]) + self.customYValueEdit.setValue(settings.value(u'y position', + QtCore.QVariant(self.screens.current[u'size'].y())).toInt()[0]) + self.customHeightValueEdit.setValue(settings.value(u'height', + QtCore.QVariant(self.screens.current[u'size'].height())).toInt()[0]) + self.customWidthValueEdit.setValue(settings.value(u'width', + QtCore.QVariant(self.screens.current[u'size'].width())).toInt()[0]) settings.endGroup() self.customXValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked()) From 6db4d5247b8a608d4d58b838a4e418b3b633f3e9 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 17 Mar 2011 21:00:19 +0100 Subject: [PATCH 09/11] fixed full version of verse tag --- openlp/plugins/songs/lib/xml.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index ee826af77..45099ef7f 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -89,8 +89,8 @@ class SongXML(object): Add a verse to the ```` tag. ``type`` - A string denoting the type of verse. Possible values are *Verse*, - *Chorus*, *Bridge*, *Pre-Chorus*, *Intro*, *Ending* and *Other*. + A string denoting the type of verse. Possible values are *v*, + *c*, *b*, *p*, *i*, *e* and *o*. Any other type is **not** allowed, this also includes translated types. @@ -128,8 +128,8 @@ class SongXML(object): The returned list has the following format:: - [[{'lang': 'en', 'type': 'Verse', 'label': '1'}, u"English verse"], - [{'lang': 'en', 'type': 'Chorus', 'label': '1'}, u"English chorus"]] + [[{'lang': 'en', 'type': 'v', 'label': '1'}, u"English verse"], + [{'lang': 'en', 'type': 'c', 'label': '1'}, u"English chorus"]] """ self.song_xml = None if xml[:5] == u' Date: Thu, 17 Mar 2011 21:23:26 +0100 Subject: [PATCH 10/11] imporved handling unknown verse tags --- openlp/plugins/songs/lib/xml.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 45099ef7f..215afd65a 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -451,8 +451,12 @@ class OpenLyrics(object): if text: text += u'\n' text += u'\n'.join([unicode(line) for line in lines.line]) - verse_name = self._get(verse, u'name').lower() - verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name) + verse_tag = self._get(verse, u'name').lower() + if verse_tag[0] in VerseType.Tags: + verse_def = verse_tag[0] + else: + verse_def = VerseType.Tags[VerseType.Other] + verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_tag) # OpenLyrics allows e. g. "c", but we need "c1". However, this does # not correct the verse order. if not verse_number: @@ -460,7 +464,7 @@ class OpenLyrics(object): lang = None if self._get(verse, u'lang'): lang = self._get(verse, u'lang') - sxml.add_verse_to_lyrics(verse_name[0], verse_number, text, lang) + sxml.add_verse_to_lyrics(verse_def, verse_number, text, lang) song.lyrics = unicode(sxml.extract_xml(), u'utf-8') # Process verse order if hasattr(properties, u'verseOrder'): From d1542d2c2bb3d94eb88bddce93e929019df49e95 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 17 Mar 2011 21:38:05 +0100 Subject: [PATCH 11/11] now the right way around --- openlp/plugins/songs/lib/xml.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 215afd65a..c1b5ee5c1 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -451,12 +451,12 @@ class OpenLyrics(object): if text: text += u'\n' text += u'\n'.join([unicode(line) for line in lines.line]) - verse_tag = self._get(verse, u'name').lower() - if verse_tag[0] in VerseType.Tags: - verse_def = verse_tag[0] + verse_def = self._get(verse, u'name').lower() + if verse_def[0] in VerseType.Tags: + verse_tag = verse_def[0] else: - verse_def = VerseType.Tags[VerseType.Other] - verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_tag) + verse_tag = VerseType.Tags[VerseType.Other] + verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_def) # OpenLyrics allows e. g. "c", but we need "c1". However, this does # not correct the verse order. if not verse_number: @@ -464,7 +464,7 @@ class OpenLyrics(object): lang = None if self._get(verse, u'lang'): lang = self._get(verse, u'lang') - sxml.add_verse_to_lyrics(verse_def, verse_number, text, lang) + sxml.add_verse_to_lyrics(verse_tag, verse_number, text, lang) song.lyrics = unicode(sxml.extract_xml(), u'utf-8') # Process verse order if hasattr(properties, u'verseOrder'):