From 72f445c4263475caa86cb1cbce6beaf7fc28a0e9 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Wed, 16 Mar 2011 23:22:11 +0000 Subject: [PATCH] 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; };