Show slideshow while installing files master
authorAndre Heinecke <aheinecke@intevation.de>
Tue, 28 Jun 2016 14:46:40 +0000 (16:46 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Tue, 28 Jun 2016 14:50:25 +0000 (16:50 +0200)
* README: Add note about slideshow
* src/inst-final.nsi: Stop slideshow.
* src/inst-gpg4win.nsi: Start slideshow.
* src/installer.nsi: Hide Show Details button.
* src/Makefile.am: Add slideshow.cpp to g4wihelp.
* src/slideshow/01.png: Placeholder image (logo).
* src/slideshow/slides.data: Placeholder file.

--
The plan is to show some hints e.g. that you can now use
the file explorer for encryption or GpgOL for Mailencryption
and that the Installed Applications are available not as Gpg4win
but under the names "Kleopatra" or "GPA".

README
src/Makefile.am
src/inst-final.nsi
src/inst-gpg4win.nsi
src/installer.nsi
src/slideshow.cpp [new file with mode: 0644]
src/slideshow/01.png [new file with mode: 0644]
src/slideshow/slides.dat [new file with mode: 0644]

diff --git a/README b/README
index ef42273..286f6ce 100644 (file)
--- a/README
+++ b/README
@@ -114,20 +114,22 @@ The tarballs and the nsis scripts are located in the temp directory
 kde-l10n prints as output.
 
 
+Installer Slideshow
+===================
+
+During installation we are showing a slide show. If you want to
+change the contents shown add / modify files in the src/slideshow
+subfolder. Install them in inst-gpg4win.nsi (Add them to the list
+of files before g4wihelp::slide_show) and modify
+src/slideshow/slides.dat accordingly.
+
 Version numbers
 ===============
 
 We use a specific order of version numbers.  This is best shown by an
 example:
 
-  1.0.0             - The final 1.0.0 release.
-  1.0.1-svn1234     - A snapshot based on SVN revision 1234
-  1.0.1-svn1235     - A newer snapshot
-  1.0.1rc1-svn1236  - A snapshot while preparing for a release candidate
-  1.0.1rc1          - The first release candidate for 1.0.1
-  1.0.1-svn1240     - yet another snapshot
-  1.0.1             - The final 1.0.1 release
-  2.1.1             - The final 2.1.1 release
+  2.1.1             - The final 2.1.1 release.
   2.1.1-beta88      - A snapshot before the 2.1.1 release.
                       (The 88 in this example is the number of
                        commits since the last release).
index 6e6ddda..fbec3b9 100644 (file)
@@ -21,7 +21,7 @@ EXTRA_DIST = pkg-config gpg4win.nsi gpg4win-src.nsi \
        config.site config.nsi.in \
         libiconv.def libintl.def loreley.mid \
         gpg4win-splash.wav exdll.h g4wihelp.c desktopshellrun.cpp \
-        g4wihelp.nsi \
+        g4wihelp.nsi slideshow.cpp \
         inst-sections.nsi installer.nsi installer-finish.nsi  \
        zlib.pc sha1sum.c mkportable.c     \
        mkportable-vanilla.h mkportable-light.h mkportable-full.h \
@@ -101,7 +101,7 @@ foosum_exe = sha1sum.exe md5sum.exe sha256sum.exe mkportable.exe
 # Need to clean the dll because we bypassed automake.
 CLEANFILES = g4wihelp.dll desktopshellrun.o versioninfo.txt $(README_files) \
                         $(HOWTO_files) NEWS.tmp COMPONENTS-list.tmp \
-                        license.blurb cdversioninfo.tmp \
+                        license.blurb cdversioninfo.tmp slideshow.o \
                         $(foosum_exe)
 
 # Supported source packages.
@@ -618,11 +618,12 @@ installers/gpg4win-src-$(VERSION).exe: gpg4win-src.nsi $(common_nsii) \
 license.blurb: $(top_srcdir)/doc/license-page $(top_srcdir)/doc/GPLv3
        cat $(top_srcdir)/doc/license-page $(top_srcdir)/doc/GPLv3 >$@
 
-g4wihelp.dll: desktopshellrun.cpp g4wihelp.c exdll.h
+g4wihelp.dll: slideshow.cpp desktopshellrun.cpp g4wihelp.c exdll.h
        $(CC) -I. -O2 -c -o desktopshellrun.o $(srcdir)/desktopshellrun.cpp
+       $(CC) -I. -O2 -c -o slideshow.o $(srcdir)/slideshow.cpp
        $(CC) -I. -shared -O2 -o g4wihelp.dll $(srcdir)/g4wihelp.c \
-         desktopshellrun.o -lwinmm -lgdi32 -luserenv -lshell32 \
-         -lole32 -loleaut32
+         desktopshellrun.o slideshow.o -lwinmm -lgdi32 -luserenv -lshell32 \
+         -lole32 -loleaut32 -lshlwapi -lmsimg32
        $(STRIP) g4wihelp.dll
 
 sha1sum.exe: sha1sum.c
index abfc7db..191bc95 100644 (file)
@@ -24,4 +24,7 @@ Section "-final" SEC_final
   # Set outpath back so that the Finish page gets what it expects.
   SetOutPath "$INSTDIR"
 
+  # Stop the slideshow
+  g4wihelp::slide_stop
+
 SectionEnd
index 6b530a9..cc151d5 100644 (file)
@@ -24,6 +24,17 @@ Section "-gpg4win" SEC_gpg4win
   SetOutPath "$INSTDIR"
   File "${BUILD_DIR}/../gpg4win-${VERSION}.tar.bz2"
 !else
+# Start the slideshow.
+  SetDetailsPrint none
+
+  SetOutPath "$PLUGINSDIR\Slides"
+  File "${BUILD_DIR}/slideshow/01.png"
+#  File "${BUILD_DIR}/slideshow/02.png"
+#  File "${BUILD_DIR}/slideshow/03.png"
+  File "${BUILD_DIR}/slideshow/slides.dat"
+  g4wihelp::slide_show /NOUNLOAD /CCOLOR=0x0000FF "/auto=$PLUGINSDIR\Slides\slides.dat"
+  SetDetailsPrint both
+  SetOutPath "$INSTDIR"
 
 # Uninstall an old version if found.
   ClearErrors
index cc9b798..20b6e34 100644 (file)
@@ -67,6 +67,8 @@ BrandingText "${PRETTY_PACKAGE}-${VERSION}"
 !endif
 !endif
 
+# Details button conflicts with splashscreen
+ShowInstDetails nevershow
 
 # Set the installation directory.
 !ifndef INSTALL_DIR
diff --git a/src/slideshow.cpp b/src/slideshow.cpp
new file mode 100644 (file)
index 0000000..0c0bfe5
--- /dev/null
@@ -0,0 +1,459 @@
+/* slideshow.cpp - NSIS Helper DLL for a slideshow. -*- coding: latin-1; -*-
+ * Copyright (C) 2016 Intevation GmbH
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose, including commercial applications, and to alter it and
+ * redistribute it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must
+ *    not claim that you wrote the original software. If you use this
+ *    software in a product, an acknowledgment in the product
+ *    documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must
+ *    not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ *    distribution.
+ ************************************************************
+ * The code is heavily based on the Slideshow
+ * plugin from http://wiz0u.free.fr/prog/nsisSlideshow
+ *
+ * It was slightly modified and adapted by:
+ * 2016 Andre Heinecke <aheinecke@intevation.de>
+ *
+ * Version 1.7 was Licensed at the time of copying (28.6.2016) as:
+ * Copyright (c) 2009-2011 Olivier Marcoux
+ *
+ * This software is provided 'as-is', without any express or implied warranty. In no
+ * event will the authors be held liable for any damages arising from the use of this
+ * software.
+ *
+ * Permission is granted to anyone to use this software for any purpose, including
+ * commercial applications, and to alter it and redistribute it freely, subject to the
+ * following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not claim
+ * that you wrote the original software. If you use this software in a product, an
+ * acknowledgment in the product documentation would be appreciated but is not
+ * required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ ************************************************************
+ */
+
+#include <windows.h>
+#include <shlwapi.h>
+#include <iimgctx.h>
+#include <stdio.h>
+#include "exdll.h"
+#include <initguid.h>
+
+#ifndef _countof
+#define _countof(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#ifndef INITGUID
+#define INITGUID
+#endif
+
+__CRT_UUID_DECL(IImgCtx,
+                0x3050f3d7, 0x98b5, 0x11cf,
+                0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b);
+
+DEFINE_GUID(IID_IImgCtx,
+            0x3050f3d7, 0x98b5, 0x11cf,
+            0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b);
+
+DEFINE_GUID(CLSID_IImgCtx,
+            0x3050f3d6, 0x98b5, 0x11cf,
+            0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b);
+
+#undef INITGUID
+
+/* array of precalculated alpha values for a linear crossfade in 15 steps */
+const BYTE SCA_Steps[15] = { 17, 18, 20, 21, 23, 26, 28, 32, 36, 43, 51, 64, 85, 127, 255 };
+int     g_step = 0;
+HWND    g_hWnd = NULL;
+HDC     g_hdcMem = NULL;
+HBITMAP g_hbmMem = NULL;
+TCHAR   g_autoPath[MAX_PATH];
+LPTSTR  g_autoBuffer = NULL;
+LPTSTR  g_autoNext = NULL;
+int     g_autoDelay = 0;
+RECT    rDest;
+int     wDest, hDest;
+WNDPROC lpPrevWndFunc = NULL;
+enum HAlign {
+    HALIGN_CENTER = 0,
+    HALIGN_LEFT,
+    HALIGN_RIGHT
+} iHAlign;
+enum VAlign {
+    VALIGN_CENTER = 0,
+    VALIGN_TOP,
+    VALIGN_BOTTOM
+} iVAlign;
+enum Fit {
+    FIT_STRETCH = 0,
+    FIT_WIDTH,
+    FIT_HEIGHT,
+    FIT_BOTH
+} iFit;
+COLORREF captionColor;
+
+static LRESULT CALLBACK slide_WndProc(HWND, UINT, WPARAM, LPARAM);
+
+/*****************************************************
+ * Abort: stops current processing, detach from slide_WndProc and release resources
+ *****************************************************/
+static void
+slide_abort(bool stayAuto = false)
+{
+  KillTimer(g_hWnd, 'XFBN');
+  if (!stayAuto)
+    {
+      if (lpPrevWndFunc != NULL && IsWindow(g_hWnd))
+        {
+          if ((WNDPROC) GetWindowLong(g_hWnd, GWL_WNDPROC) == slide_WndProc)
+            SetWindowLongPtr(g_hWnd, GWL_WNDPROC, (long)lpPrevWndFunc);
+        }
+      lpPrevWndFunc = NULL;
+      GlobalFree(g_autoBuffer);
+      g_autoBuffer = NULL;
+      g_autoNext = NULL;
+      g_autoDelay = false;
+    }
+  DeleteDC(g_hdcMem);
+  g_hdcMem = NULL;
+  DeleteObject(g_hbmMem);
+  g_hbmMem = NULL;
+}
+
+static void
+slide_NewImage(LPCTSTR imgPath, LPCTSTR caption, int duration)
+{
+#ifdef _UNICODE
+  LPCWSTR imgPathW = imgPath;
+#else
+  WCHAR imgPathW[MAX_PATH];
+  MultiByteToWideChar(CP_ACP, 0, imgPath, -1, imgPathW, _countof(imgPathW));
+#endif
+  IImgCtx *pImage = NULL;
+  SIZE imgSize = {0, 0};
+  if (SUCCEEDED(CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_ALL, IID_IImgCtx, (void**)&pImage)))
+    {
+      if (SUCCEEDED(pImage->Load(imgPathW, 0)))
+        {
+          DWORD dwState;
+          while (SUCCEEDED(pImage->GetStateInfo(&dwState, NULL, true)) && (dwState & (IMGLOAD_COMPLETE|IMGLOAD_ERROR)) == 0)
+            Sleep(20);
+          pImage->GetStateInfo(&dwState, &imgSize, true);
+        }
+      if (imgSize.cx == 0 || imgSize.cy == 0) // error path or format (IMGLOAD_ERROR)
+        {
+          pImage->Release();
+          pImage = NULL;
+        }
+    }
+  if (pImage == NULL)
+    return;
+
+  // fit image
+  wDest = rDest.right - rDest.left;
+  hDest = rDest.bottom - rDest.top;
+  if (iFit == FIT_BOTH)
+    iFit = (wDest*imgSize.cy > imgSize.cx*hDest) ? FIT_HEIGHT : FIT_WIDTH;
+  if (iFit == FIT_HEIGHT)
+    wDest = (imgSize.cx * hDest) / imgSize.cy;
+  else if (iFit == FIT_WIDTH)
+    hDest = (imgSize.cy * wDest) / imgSize.cx;
+
+  // align image
+  if (iHAlign == HALIGN_CENTER) rDest.left = (rDest.left + rDest.right - wDest) / 2;
+  else if (iHAlign == HALIGN_RIGHT) rDest.left = rDest.right - wDest;
+  if (iVAlign == VALIGN_CENTER) rDest.top  = (rDest.top + rDest.bottom - hDest) / 2;
+  else if (iVAlign == VALIGN_BOTTOM) rDest.top = rDest.bottom - hDest;
+  rDest.right = rDest.left + wDest;
+  rDest.bottom = rDest.top + hDest;
+
+  // create memory DC & Bitmap compatible with window's DC
+  HDC hWndDC = GetDC(g_hWnd);
+  g_hdcMem = CreateCompatibleDC(hWndDC);
+  g_hbmMem = CreateCompatibleBitmap(hWndDC, wDest, hDest);
+  ReleaseDC(g_hWnd, hWndDC);
+  SelectObject(g_hdcMem, g_hbmMem);
+
+  // paint image in memory DC
+  RECT bounds = { 0, 0, wDest, hDest };
+  pImage->Draw(g_hdcMem, &bounds);
+  pImage->Release(); // we don't need the image anymore
+
+  if (caption[0] != '\0')
+    {
+      LOGFONT lf;
+      GetObject((HFONT) ::SendMessage(g_hWnd, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+      lf.lfHeight += lf.lfHeight/2;
+      HFONT hFont = CreateFontIndirect(&lf);
+      HGDIOBJ hOldFont = SelectObject(g_hdcMem, hFont);
+      SetTextColor(g_hdcMem, captionColor);
+      SetBkMode(g_hdcMem, TRANSPARENT);
+      SetTextAlign(g_hdcMem, TA_BOTTOM|TA_CENTER|TA_NOUPDATECP);
+      TextOut(g_hdcMem, wDest/2, hDest-10, caption, lstrlen(caption));
+      DeleteObject(SelectObject(g_hdcMem, hOldFont));
+    }
+
+  // replace windows procedure, start time and initiate first step
+  if (lpPrevWndFunc == NULL)
+    lpPrevWndFunc = (WNDPROC) SetWindowLongPtr(g_hWnd, GWL_WNDPROC, (long) slide_WndProc);
+  if (duration == 0)
+    {
+      g_step = _countof(SCA_Steps);
+      InvalidateRect(g_hWnd, NULL, FALSE); // no duration => force a WM_PAINT for immediate draw of picture
+      if (g_autoNext && g_autoDelay)
+        SetTimer(g_hWnd, 'XFBN', g_autoDelay, NULL);
+    }
+  else
+    {
+      g_step = 0;
+      slide_WndProc(g_hWnd, WM_TIMER, 'XFBN', 0); // first iteration right now
+      SetTimer(g_hWnd, 'XFBN', duration/_countof(SCA_Steps), NULL);
+    }
+}
+
+static bool
+slide_NextAuto()
+{
+  LPTSTR scan;
+  if (g_autoNext == NULL)
+    return false;
+  if (*g_autoNext == '.')
+    {
+      g_autoNext = g_autoBuffer;
+      return false;
+    }
+  bool result = false;
+  if (*g_autoNext == '=')
+    g_autoNext++;
+  for (scan = g_autoNext; *scan; scan++)
+    if (*scan == ',') break;
+  if (*scan)
+    {
+      TCHAR imgPath[MAX_PATH];
+      *scan = '\0';
+      PathCombine(imgPath, g_autoPath, g_autoNext);
+      *scan = ',';
+      g_autoNext = scan+1;
+
+      int duration = StrToInt(g_autoNext);
+      for (scan = g_autoNext; *scan; scan++)
+        if (*scan == ',') break;
+      if (*scan)
+        {
+          g_autoNext = scan+1;
+          g_autoDelay = StrToInt(g_autoNext);
+          for (scan = g_autoNext; *scan; scan++)
+            if (*scan == ',') break;
+          if (*scan && (scan[1] == '"'))
+            {
+              g_autoNext = scan+2;
+              for (scan = g_autoNext; *scan; scan++)
+                if (*scan == '"') break;
+              if (*scan)
+                {
+                  TCHAR caption[MAX_PATH];
+                  lstrcpyn(caption, g_autoNext, scan-g_autoNext+1);
+                  g_autoNext = scan+1;
+                  slide_NewImage(imgPath, caption, duration);
+                  result = true;
+                }
+            }
+        }
+    }
+  g_autoNext += lstrlen(g_autoNext);
+  g_autoNext++;
+  if (*g_autoNext == '\0')
+    g_autoNext = g_autoBuffer;
+  return result;
+}
+
+/*****************************************************
+ * overriden WndProc for NSIS wizard pane
+ *****************************************************/
+static LRESULT CALLBACK slide_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+  switch (uMsg)
+    {
+    case WM_TIMER:
+      if (wParam == 'XFBN')
+        {
+          if (g_step == _countof(SCA_Steps))
+            {
+              slide_abort(true);
+              if (!slide_NextAuto())
+                {
+                  slide_abort();
+                }
+              return 0;
+            }
+          HDC hDC = GetDC(hWnd);
+          const BLENDFUNCTION ftn = { AC_SRC_OVER, 0, SCA_Steps[g_step++], 0 };
+          AlphaBlend(hDC, rDest.left, rDest.top, wDest, hDest, g_hdcMem, 0, 0, wDest, hDest, ftn);
+          ReleaseDC(hWnd, hDC);
+          if (g_step == _countof(SCA_Steps))
+            {
+              if (g_autoNext && g_autoDelay)
+                SetTimer(hWnd, 'XFBN', g_autoDelay, NULL);
+              else
+                KillTimer(hWnd, 'XFBN');
+            }
+          return 0;
+        }
+    case WM_PAINT:
+      if (g_hdcMem)
+        {
+          PAINTSTRUCT ps;
+          HDC hDC = BeginPaint(hWnd, &ps);
+          CallWindowProc(lpPrevWndFunc, hWnd, uMsg, wParam, lParam);
+          BitBlt(hDC, rDest.left, rDest.top, wDest, hDest, g_hdcMem, 0, 0, SRCCOPY);
+          EndPaint(hWnd, &ps);
+          return 0;
+        }
+      break;
+
+    case WM_CLOSE:
+      slide_abort();
+      break;
+    case WM_COMMAND:
+      if(LOWORD(wParam) == IDCANCEL || LOWORD(wParam) == IDOK || LOWORD(wParam) == IDABORT)
+        slide_abort();
+      break;
+
+    default:
+      break;
+    }
+  return CallWindowProc(lpPrevWndFunc, hWnd, uMsg, wParam, lParam);
+}
+
+/*****************************************************
+ * NSIS Plugin "stop" entrypoint
+ *****************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __declspec(dllexport)
+slide_stop(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop)
+{
+  slide_abort();
+}
+
+/*****************************************************
+ * NSIS Plugin "show" entrypoint
+ *****************************************************/
+void __declspec(dllexport)
+slide_show(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop)
+{
+  EXDLL_INIT();
+  slide_abort();
+
+  // argument default values
+  iHAlign = HALIGN_CENTER;
+  iVAlign = VALIGN_CENTER;
+  iFit    = FIT_BOTH;
+  g_hWnd = NULL;
+  captionColor = RGB(255,255,255);
+  int duration = 1000; // transition duration in ms (default = 1s)
+  TCHAR caption[MAX_PATH];
+  caption[0] = '\0';
+
+  // parse arguments
+  TCHAR arg[MAX_PATH];
+  LPTSTR argValue;
+  while(!popstring(arg, sizeof arg) && *arg == '/' && (argValue = StrChr(arg, '=')) != NULL)
+    {
+      *argValue++ = '\0';     // replace '=' by '\0'
+      if(lstrcmpi(arg, TEXT("/hwnd")) == 0)
+        StrToIntEx(argValue, STIF_SUPPORT_HEX, (int*) &g_hWnd);
+      else if(lstrcmpi(arg, TEXT("/fit")) == 0)
+        {
+          if(lstrcmpi(argValue, TEXT("height")) == 0)          iFit = FIT_HEIGHT;
+          else if(lstrcmpi(argValue, TEXT("width")) == 0)      iFit = FIT_WIDTH;
+          else if(lstrcmpi(argValue, TEXT("stretch")) == 0)    iFit = FIT_STRETCH;
+        }
+      else if(lstrcmpi(arg, TEXT("/halign")) == 0)
+        {
+          if(lstrcmpi(argValue, TEXT("left")) == 0) iHAlign = HALIGN_LEFT;
+          else if(lstrcmpi(argValue, TEXT("right")) == 0) iHAlign = HALIGN_RIGHT;
+        }
+      else if(lstrcmpi(arg, TEXT("/valign")) == 0)
+        {
+          if(lstrcmpi(argValue, TEXT("top")) == 0) iVAlign = VALIGN_TOP;
+          else if(lstrcmpi(argValue, TEXT("bottom")) == 0) iVAlign = VALIGN_BOTTOM;
+        }
+      else if(lstrcmpi(arg, TEXT("/duration")) == 0)
+        StrToIntEx(argValue, STIF_SUPPORT_HEX, &duration);
+      else if(lstrcmpi(arg, TEXT("/caption")) == 0)
+        lstrcpy(caption, argValue);
+      else if(lstrcmpi(arg, TEXT("/ccolor")) == 0)
+        StrToIntEx(argValue, STIF_SUPPORT_HEX, (int*) &captionColor);
+      else if(lstrcmpi(arg, TEXT("/auto")) == 0)
+        {
+          lstrcpy(g_autoPath, argValue);
+          PathRemoveFileSpec(g_autoPath);
+          HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, 32767*sizeof(TCHAR));
+          DWORD count = GetPrivateProfileSection(getuservariable(INST_LANG), LPTSTR(hMem), 32767, argValue);
+          if (count == 0)
+            {
+              count = GetPrivateProfileSection(TEXT("1033"), LPTSTR(hMem), 32767, argValue);
+              if (count == 0)
+                count = GetPrivateProfileSection(TEXT("0"), LPTSTR(hMem), 32767, argValue);
+            }
+          if (count)
+            {
+              g_autoBuffer = LPTSTR(GlobalReAlloc(hMem, (count+1)*sizeof(TCHAR), 0));
+              g_autoNext = g_autoBuffer;
+            }
+          else
+            GlobalFree(hMem);
+        }
+    }
+
+  // if target window not defined we'll search for default (the details listview)
+  if (g_hWnd == NULL)
+    {
+      g_hWnd = FindWindowEx(hwndParent, NULL, TEXT("#32770"), NULL);
+      if (g_hWnd == NULL)
+        return;
+      hwndParent = FindWindowEx(hwndParent, g_hWnd, TEXT("#32770"), NULL);
+      if (hwndParent != NULL && !IsWindowVisible(hwndParent))
+        g_hWnd = hwndParent;
+      if (g_hWnd == NULL)
+        return;
+      HWND hWnd = GetDlgItem(g_hWnd, 1016);
+      GetWindowRect(hWnd, &rDest);
+      ScreenToClient(g_hWnd, (LPPOINT) &rDest.left);
+      ScreenToClient(g_hWnd, (LPPOINT) &rDest.right);
+    }
+  else
+    GetClientRect(g_hWnd, &rDest);
+
+  // load new image
+  if (arg[0] == '\0')
+    return; // stop here if no filename
+
+  if (g_autoNext != NULL)
+    slide_NextAuto();
+  else
+    slide_NewImage(arg, caption, duration);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/slideshow/01.png b/src/slideshow/01.png
new file mode 100644 (file)
index 0000000..18cf060
Binary files /dev/null and b/src/slideshow/01.png differ
diff --git a/src/slideshow/slides.dat b/src/slideshow/slides.dat
new file mode 100644 (file)
index 0000000..d2ebcd4
--- /dev/null
@@ -0,0 +1,13 @@
+; Add slideshow definition for each language here
+; Remember to use the 8bit encoding of the language until
+; Gpg4win switches to unicode nsis.
+; Ending with a period will cause the slideshow not to loop.
+
+; For more info see: http://wiz0u.free.fr/prog/nsisSlideshow/
+
+[1033]
+=01.png,1000,2000,"We will show"
+=01.png,500,3000,"some hints that the app is called Kleopatra"
+=01.png,500,500,"or GPA,.."
+=01.png,2000,2000,"and how to access GpgOL and GpgEx Here!"
+=01.png,2000,2000,"Awesome!"