Fix SplashScreen closing after https://codereview.scilab.org/#/c/14056/
[scilab.git] / scilab / modules / windows_tools / src / c / scilab_windows / splashScreen.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA - Allan CORNET
4 * Copyright (C) DIGITEO - 2012 - Allan CORNET
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11 *
12 */
13 /*--------------------------------------------------------------------------*/
14 #pragma comment (lib, "gdiplus.lib")
15 /*--------------------------------------------------------------------------*/
16 #include <Windows.h>
17 #include <stdio.h>
18 #include <string>
19 #include <CommCtrl.h>
20 #include <GdiPlus.h>
21 extern "C"
22 {
23 #include "splashScreen.h"
24 #include "localization.h"
25 #include "resource.h"
26 #include "version.h"
27 #include "WndThread.h"
28 #include "charEncoding.h"
29 #include "getScilabDirectory.h"
30 #include "InnosetupMutex.h"
31 #include "MALLOC.h"
32 };
33 /*--------------------------------------------------------------------------*/
34 #define SPLASH_WINDOW_CLASSNAME "Scilab splashscreen"
35 #define FORMAT_FULLPATH_SPLASH_IMAGE "%s/modules/gui/images/icons/aboutScilab.png"
36 /*--------------------------------------------------------------------------*/
37 static DWORD WINAPI ThreadSplashScreen(LPVOID lpParam);
38 static BOOL stopSplashScreen(UINT _time, UINT _timeMax);
39 static BOOL haveConsoleWindow(void);
40 /*--------------------------------------------------------------------------*/
41 static UINT timeSplashScreen = 0;
42 static Gdiplus::Image* pImage = NULL;
43 /*--------------------------------------------------------------------------*/
44 void splashScreen(void)
45 {
46     DWORD dwThreadId, dwThrdParam = 0;
47
48     if (!haveConsoleWindow() && !haveInnosetupMutex())
49     {
50         HANDLE hThreadSplashScreen = CreateThread(NULL, 0, ThreadSplashScreen, &dwThrdParam, 0, &dwThreadId);
51     }
52 }
53 /*--------------------------------------------------------------------------*/
54 LRESULT CALLBACK SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
55 {
56     switch (uMsg)
57     {
58         case WM_PAINT:
59         {
60             if (pImage)
61             {
62                 Gdiplus::Graphics gdip(hwnd);
63                 gdip.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
64             }
65             ValidateRect(hwnd, NULL);
66             return 0;
67         }
68         break;
69         case WM_DESTROY:
70         {
71             if (pImage)
72             {
73                 delete pImage;
74                 pImage = NULL;
75             }
76         }
77     }
78
79     return DefWindowProc(hwnd, uMsg, wParam, lParam);
80 }
81 /*--------------------------------------------------------------------------*/
82 static DWORD WINAPI ThreadSplashScreen(LPVOID lpParam)
83 {
84     char *ScilabDirectory = NULL;
85     char *ImageFilename = NULL;
86     wchar_t *wImageFilename = NULL;
87
88     size_t len = 0;
89     Gdiplus::GdiplusStartupInput gdiplusStartupInput;
90
91     ULONG_PTR gdiplusToken = NULL;
92     Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
93
94     HINSTANCE hInstanceThisDll = (HINSTANCE)GetModuleHandle("scilab_windows");
95
96     ScilabDirectory = getScilabDirectory(TRUE);
97     if (ScilabDirectory == NULL)
98     {
99         return 0;
100     }
101
102     len = strlen(FORMAT_FULLPATH_SPLASH_IMAGE) + strlen(ScilabDirectory) + 1;
103     ImageFilename = (char*)MALLOC(sizeof(char) * len);
104     if (ImageFilename == NULL)
105     {
106         return 0;
107     }
108
109     sprintf(ImageFilename, FORMAT_FULLPATH_SPLASH_IMAGE, ScilabDirectory);
110     FREE(ScilabDirectory);
111     ScilabDirectory = NULL;
112
113     wImageFilename = to_wide_string(ImageFilename);
114     FREE(ImageFilename);
115     ImageFilename = NULL;
116     if (wImageFilename == NULL)
117     {
118         return 0;
119     }
120
121     pImage = Gdiplus::Image::FromFile((const WCHAR *)wImageFilename);
122     FREE(wImageFilename);
123     wImageFilename = NULL;
124     if (pImage == NULL)
125     {
126         return 0;
127     }
128
129     WNDCLASS wndcls = {0};
130
131     wndcls.style = CS_HREDRAW | CS_VREDRAW;
132     wndcls.lpfnWndProc = SplashWndProc;
133     wndcls.hInstance = GetModuleHandle(NULL);
134     wndcls.hCursor = LoadCursor(NULL, IDC_APPSTARTING);
135     wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
136     wndcls.lpszClassName = SPLASH_WINDOW_CLASSNAME;
137     wndcls.hIcon = LoadIcon(wndcls.hInstance, (char*)MAKEINTRESOURCE(IDI_APPLICATION));
138
139     if (!RegisterClass(&wndcls))
140     {
141         if (GetLastError() != 0x00000582) // already registered
142         {
143             return 0;
144         }
145     }
146
147     // try to find monitor where mouse was last time
148     POINT point = {0};
149     MONITORINFO mi = {sizeof(MONITORINFO), 0};
150     HMONITOR hMonitor = 0;
151     RECT rcArea = {0};
152
153     ::GetCursorPos(&point);
154     hMonitor = ::MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST);
155     if (::GetMonitorInfo(hMonitor, &mi))
156     {
157         rcArea.left = (mi.rcMonitor.right + mi.rcMonitor.left - pImage->GetWidth()) / 2;
158         rcArea.top = (mi.rcMonitor.top + mi.rcMonitor.bottom - pImage->GetHeight()) / 2;
159     }
160     else
161     {
162         SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
163         rcArea.left = (rcArea.right + rcArea.left - pImage->GetWidth()) / 2;
164         rcArea.top = (rcArea.top + rcArea.bottom - pImage->GetHeight()) / 2;
165     }
166
167     HWND hdlg = CreateWindowEx(WS_EX_TOOLWINDOW,
168                                SPLASH_WINDOW_CLASSNAME,
169                                SPLASH_WINDOW_CLASSNAME,
170                                WS_CLIPCHILDREN | WS_POPUP,
171                                rcArea.left,
172                                rcArea.top,
173                                pImage->GetWidth(),
174                                pImage->GetHeight(),
175                                NULL,
176                                NULL,
177                                wndcls.hInstance,
178                                NULL);
179
180     if (hdlg == NULL)
181     {
182         return 0;
183     }
184
185     ShowWindow(hdlg, SW_SHOWNORMAL);
186     UpdateWindow(hdlg);
187     SetWindowPos(hdlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
188
189     while (!stopSplashScreen(20, 1000))
190     {
191         Sleep(20);
192     }
193
194     DestroyWindow(hdlg);
195     return 0;
196 }
197 /*--------------------------------------------------------------------------*/
198 static BOOL stopSplashScreen(UINT _time, UINT _timeMax)
199 {
200     if (haveConsoleWindow() || (timeSplashScreen >= _timeMax))
201     {
202         return TRUE;
203     }
204     else
205     {
206         if (timeSplashScreen < _timeMax)
207         {
208             timeSplashScreen = timeSplashScreen + _time;
209         }
210     }
211     return FALSE;
212 }
213 /*--------------------------------------------------------------------------*/
214 static BOOL haveConsoleWindow(void)
215 {
216     HWND hWndMainScilab = NULL;
217     char titleMainWindow[MAX_PATH];
218     int id = getCurrentScilabId();
219
220     wsprintf(titleMainWindow, "%s (%d)", SCI_VERSION_STRING, id);
221     hWndMainScilab = FindWindow(NULL, titleMainWindow);
222
223     if (hWndMainScilab == NULL)
224     {
225         wsprintf(titleMainWindow, _("Scilab %s Console"),  std::string(SCI_VERSION_STRING).substr(strlen("scilab-"), std::string::npos).c_str());
226         hWndMainScilab = FindWindow(NULL, titleMainWindow);
227     }
228
229     return (hWndMainScilab == NULL) ? FALSE : TRUE;
230 }
231 /*--------------------------------------------------------------------------*/