NSIS/Contrib/AdvSplash/advsplash.c
anders_k 7cc150c464 MakeNSIS can now generate Unicode or Ansi installers based on a script attribute. SCons generates both Ansi and Unicode stubs and plugins.
The official plugins are now stored in architecture specific subdirectories under NSIS\Plugins. !AddPluginDir also gained a new (optional) architecture flag because MakeNSIS now stores separate plugin information for each target architecture. Storing plugins in the root of the Plugins directory is no longer supported.

MinGW does not implement the unicode CRT startup functions so the entry point functions and linker parameters had to be changed. The unicode tools use the ansi entry point and a small helper function that calls into the real code: _tmain has full argc+argv emulation while wWinMain does not pass the command line parameters. The stubs do not use any CRT functions and have no CRT or unicode helper code, they call our entry point directly.



git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6269 212acab6-be3b-0410-9dea-997c60f758d6
2012-10-13 01:47:50 +00:00

294 lines
8.1 KiB
C

// Unicode support by Jim Park -- 08/22/2007
// For layered windows
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <windowsx.h>
#include <nsis/pluginapi.h> // nsis plugin
#ifndef LWA_COLORKEY
# define LWA_COLORKEY 1
# define LWA_ALPHA 2
#endif
HINSTANCE g_hInstance;
#define RESOLUTION 32 // 30 fps ;) (32? I like SHR more than iDIV ;)
BITMAP bm;
HBITMAP g_hbm;
int g_rv;
int resolution;
int sleep_val, fadein_val, fadeout_val, state, timeleft, keycolor, nt50,
alphaparam;
const TCHAR classname[4] = _T("_sp");
typedef BOOL(_stdcall * _tSetLayeredWindowAttributesProc) (HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
);
_tSetLayeredWindowAttributesProc SetLayeredWindowAttributesProc;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
PAINTSTRUCT ps;
RECT r;
HDC curdc = NULL;
HDC hdc;
HBITMAP oldbm;
switch (uMsg) {
case WM_CREATE:
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
SetWindowLongPtr(hwnd, GWL_STYLE, 0);
SetWindowPos(hwnd, NULL,
r.left + (r.right - r.left - bm.bmWidth) / 2,
r.top + (r.bottom - r.top - bm.bmHeight) / 2,
bm.bmWidth, bm.bmHeight, SWP_NOZORDER | SWP_SHOWWINDOW);
return 0;
case WM_PAINT:
curdc = BeginPaint(hwnd, &ps);
hdc = CreateCompatibleDC(curdc);
GetClientRect(hwnd, &r);
oldbm = SelectObject(hdc, g_hbm);
BitBlt(curdc, r.left, r.top, r.right - r.left, r.bottom - r.top, hdc,
0, 0, SRCCOPY);
SelectObject(hdc, oldbm);
DeleteDC(hdc);
EndPaint(hwnd, &ps);
case WM_CLOSE:
return 0;
case WM_TIMER:
case WM_LBUTTONDOWN:
g_rv = (uMsg == WM_LBUTTONDOWN);
DestroyWindow(hwnd);
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void SetTransparentRegion(HWND myWnd)
{
HDC dc;
int x, y;
HRGN region, cutrgn;
BITMAPINFO bmi;
int size = bm.bmWidth * bm.bmHeight * 4;
int *bmp = GlobalAlloc(GPTR, size);
int *bmp_orig = bmp;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biHeight = bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
dc = CreateCompatibleDC(NULL);
SelectObject(dc, g_hbm);
x = GetDIBits(dc, g_hbm, 0, bm.bmHeight, bmp, &bmi, DIB_RGB_COLORS);
region = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight);
// Search for transparent pixels
for (y = bm.bmHeight - 1; y >= 0; y--) {
for (x = 0; x < bm.bmWidth;) {
if ((*bmp & 0xFFFFFF) == keycolor) {
int j = x;
while ((x < bm.bmWidth) && ((*bmp & 0xFFFFFF) == keycolor)) {
bmp++, x++;
}
// Cut transparent pixels from the original region
cutrgn = CreateRectRgn(j, y, x, y + 1);
CombineRgn(region, region, cutrgn, RGN_XOR);
DeleteObject(cutrgn);
} else {
bmp++, x++;
}
}
}
// Set resulting region.
SetWindowRgn(myWnd, region, TRUE);
DeleteObject(region);
DeleteObject(dc);
GlobalFree(bmp_orig);
}
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ul_reason_for_call,
LPVOID lpReserved)
{
g_hInstance = hInst;
return TRUE;
}
void CALLBACK TimeProc(UINT uID,
UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
int call = -1;
switch (state) {
// FadeIN
case 0:
if (timeleft == 0) {
timeleft = sleep_val;
state++;
if (nt50)
call = 255;
} else {
call = ((fadein_val - timeleft) * 255) / fadein_val;
break;
}
// Sleep
case 1:
if (timeleft == 0) {
timeleft = fadeout_val;
state++;
// fadeout
} else
break;
// FadeOUT
case 2:
if (timeleft == 0) {
PostMessage((HWND) dwUser, WM_TIMER, 0, 0);
return;
} else {
call = ((timeleft) * 255) / fadeout_val;
break;
}
}
// Transparency value aquired, and could be set...
if ((call >= 0) && nt50)
SetLayeredWindowAttributesProc((HWND) dwUser, keycolor,
(BYTE) call, alphaparam);
// Time is running out...
timeleft--;
}
void __declspec(dllexport) show(HWND hwndParent, int string_size,
TCHAR *variables, stack_t ** stacktop)
{
DEVMODE dm;
TCHAR fn[MAX_PATH];
TCHAR temp[64];
g_rv = -1;
resolution = RESOLUTION;
EXDLL_INIT();
popstring(temp);
sleep_val = myatoi(temp);
popstring(temp);
fadein_val = myatoi(temp);
popstring(temp);
fadeout_val = myatoi(temp);
popstring(temp);
keycolor = myatoi(temp);
popstring(fn);
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
// Check for winXP/2k at 32 bpp transparency
nt50 = (LOBYTE(LOWORD(GetVersion())) >= 5) && !((dm.dmBitsPerPel < 32)
&& (keycolor != -1));
if (!nt50) {
// Fading+transparency is unsupported at old windows versions...
resolution = sleep_val + fadein_val + fadeout_val;
fadeout_val = fadein_val = 0;
sleep_val = 1;
state = 1; // skip fade in
} else {
// div them by resolution
sleep_val >>= 5;
fadein_val >>= 5;
fadeout_val >>= 5;
state = 0;
alphaparam = LWA_ALPHA | ((keycolor == -1) ? (0) : (LWA_COLORKEY));
keycolor =
((keycolor & 0xFF) << 16) + (keycolor & 0xFF00) +
((keycolor & 0xFF0000) >> 16);
}
if (fn[0] && ((sleep_val + fadein_val + fadeout_val) > 0)) {
MSG msg;
static WNDCLASS wc;
wc.lpfnWndProc = WndProc;
wc.hInstance = g_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = classname;
if (RegisterClass(&wc)) {
TCHAR fn2[MAX_PATH];
lstrcpy(fn2, fn);
lstrcat(fn, _T(".bmp"));
lstrcat(fn2, _T(".wav"));
g_hbm =
LoadImage(NULL, fn, IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (g_hbm) {
HWND myWnd;
UINT timerEvent;
// Get Bitmap Information
GetObject(g_hbm, sizeof(bm), & bm);
myWnd =
CreateWindowEx(WS_EX_TOOLWINDOW |
((nt50) ? (WS_EX_LAYERED) : (0)), classname,
classname, 0, 0, 0, 0, 0, (HWND) hwndParent,
NULL, g_hInstance, NULL);
// Set transparency / key color
if (nt50) {
// Get blending proc address
HANDLE user32 = GetModuleHandle(_T("user32"));
SetLayeredWindowAttributesProc =
(_tSetLayeredWindowAttributesProc) GetProcAddress(user32,
"SetLayeredWindowAttributes");
// Use win2k method
SetLayeredWindowAttributesProc(myWnd, keycolor,
(BYTE) ((fadein_val > 0) ? (0) : (255)),
alphaparam);
} else if (keycolor != -1) {
// transparency mode
SetTransparentRegion(myWnd);
}
PlaySound(fn2, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT);
// Start up timer...
timeleft = fadein_val;
timerEvent =
timeSetEvent(resolution, RESOLUTION / 4, TimeProc,
(DWORD_PTR) myWnd, TIME_PERIODIC);
while (IsWindow(myWnd) && GetMessage(&msg, myWnd, 0, 0)) {
DispatchMessage(&msg);
}
// Kill the timer...
timeKillEvent(timerEvent);
// Stop currently playing wave, we want to exit
PlaySound(0, 0, 0);
DeleteObject(g_hbm);
}
// We should UnRegister class, since Windows NT series never does this by itself
UnregisterClass(wc.lpszClassName, g_hInstance);
}
}
wsprintf(temp, _T("%d"), g_rv);
pushstring(temp);
}