1. Supports any bpp for transparent images

2. Windows XP at bpp < 32 possible bug fixed
3. Removed transparency by pallete color index (always use RGB value)
4. shrinked a bit (0.5 kb)


git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2903 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
joostverburg 2003-09-12 14:01:29 +00:00
parent de5c3d3561
commit 73870f0e8e
4 changed files with 272 additions and 285 deletions

View file

@ -7,25 +7,28 @@ XPStyle on
Function .onInit
# the plugins dir is automatically deleted when the installer exits
InitPluginsDir
File /oname=$PLUGINSDIR\splash.bmp "${NSISDIR}\Contrib\Makensisw\logo.bmp"
File /oname=$PLUGINSDIR\splash.bmp "${NSISDIR}\Contrib\Icons\modern-header.bmp"
#optional
#File /oname=$PLUGINSDIR\splash.wav "C:\myprog\sound.wav"
MessageBox MB_OK "Fading"
advsplash::show 1000 600 400 -1 $PLUGINSDIR\splash
Pop $0 ; $0 has '1' if the user closed the splash screen early,
Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normal, and '-1' if some error occured.
MessageBox MB_OK "Now with transparency"
MessageBox MB_OK "Transparency"
File /oname=$PLUGINSDIR\splash.bmp "${NSISDIR}\Contrib\Makensisw\logo.bmp"
advsplash::show 2000 0 0 0x1856B1 $PLUGINSDIR\splash
Pop $0
File /oname=$PLUGINSDIR\splash.bmp "${NSISDIR}\Contrib\Icons\modern.bmp"
advsplash::show 1000 600 400 0xFF00FF $PLUGINSDIR\splash
Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normal, and '-1' if some error occured.
MessageBox MB_OK "$0"
MessageBox MB_OK "Transparency/Fading"
File /oname=$PLUGINSDIR\splash.bmp "${NSISDIR}\Contrib\Icons\modern-wizard llama.bmp"
advsplash::show 1000 600 400 0x00005B $PLUGINSDIR\splash
Pop $0
Delete $PLUGINSDIR\splash.bmp
FunctionEnd
Section

View file

@ -2,80 +2,284 @@
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include "../exdll/exdll.h"
#include <windowsx.h>
#include "..\exdll\exdll.h"
HINSTANCE g_hInstance;
#define RESOLUTION 20 // 50 fps ;)
#define KEYCOLOR_8BIT_RGBSUPPORT 1 // Includes (1) code for
// specifing key color for 8bit images as RGB
#define RESOLUTION 32 // 30 fps ;) (32? I like SHR more than iDIV ;)
BITMAP bm;
HBITMAP g_hbm;
int g_rv=-1;
int resolution = RESOLUTION;
int g_rv;
int resolution;
int sleep_val, fadein_val, fadeout_val, state, timeleft, keycolor, nt50, alphaparam;
int call = -1;
const char classname[4]="_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)
{
if (uMsg == WM_CREATE)
{
RECT vp;
SystemParametersInfo(SPI_GETWORKAREA, 0, &vp, 0);
SetWindowLong(hwnd,GWL_STYLE,0);
SetWindowPos(hwnd,NULL,
vp.left+(vp.right-vp.left-bm.bmWidth)/2,
vp.top+(vp.bottom-vp.top-bm.bmHeight)/2,
bm.bmWidth,bm.bmHeight,
SWP_NOZORDER);
ShowWindow(hwnd,SW_SHOW);
return 0;
}
if (uMsg == WM_PAINT)
{
PAINTSTRUCT ps;
RECT r;
HDC curdc=BeginPaint(hwnd,&ps);
HDC hdc=CreateCompatibleDC(curdc);
HDC curdc = NULL;
HDC hdc;
HBITMAP oldbm;
oldbm=(HBITMAP)SelectObject(hdc,g_hbm);
GetClientRect(hwnd,&r);
BitBlt(curdc,r.left,r.top,r.right-r.left,r.bottom-r.top,hdc,0,0,SRCCOPY);
switch (uMsg)
{
case WM_CREATE:
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
SetWindowLong(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);
return 0;
}
if (uMsg == WM_CLOSE) return 0;
if (uMsg == WM_TIMER || uMsg == WM_LBUTTONDOWN)
{
g_rv=(uMsg == WM_LBUTTONDOWN);
DestroyWindow(hwnd);
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
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);
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);
}
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance=hInst;
return TRUE;
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,
call,
alphaparam);
// Time is running out...
timeleft--;
}
int myatoi(char *s);
void __declspec(dllexport) show(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
{
DEVMODE dm;
char fn[MAX_PATH];
char 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;
} else
{
// div them by resolution
sleep_val >>= 5;
fadein_val >>= 5;
fadeout_val >>= 5;
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))
{
char fn2[MAX_PATH];
lstrcpy(fn2,fn);
lstrcat(fn,".bmp");
lstrcat(fn2,".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), (LPSTR)&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("user32");
SetLayeredWindowAttributesProc = (_tSetLayeredWindowAttributesProc) GetProcAddress(user32, "SetLayeredWindowAttributes");
// Use win2k method
SetLayeredWindowAttributesProc(myWnd, keycolor,
(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...
state = 0; 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,"%d",g_rv);
pushstring(temp);
}
#ifdef _DEBUG
void main()
{
}
#endif
int myatoi(char *s)
{
unsigned int v=0;
@ -120,219 +324,3 @@ int myatoi(char *s)
}
return (int)v;
}
void CALLBACK TimeProc(
UINT uID,
UINT uMsg,
DWORD dwUser,
DWORD dw1,
DWORD dw2)
{
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++;
} 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,
call,
alphaparam);
call = -1;
// Time is running out...
timeleft--;
}
void __declspec(dllexport) show(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
{
char fn[MAX_PATH];
char temp[64];
char *sleep=temp;
EXDLL_INIT();
popstring(temp);
sleep_val = myatoi(temp) / RESOLUTION;
popstring(temp);
fadein_val = myatoi(temp) / RESOLUTION;
popstring(temp);
fadeout_val = myatoi(temp) / RESOLUTION;
popstring(temp);
keycolor = myatoi(temp);
popstring(fn);
// Check for winXP/2k
nt50 = (LOBYTE(LOWORD(GetVersion())) >= 5);
if (!nt50)
{
// Fading is unsupported at old windows versions...
resolution = (sleep_val + fadein_val + fadeout_val) * RESOLUTION;
fadeout_val = fadein_val = 0;
sleep_val = 1;
} else alphaparam = LWA_ALPHA | ((keycolor == -1)?(0):(LWA_COLORKEY));
if (fn[0] && sleep_val>0)
{
MSG msg;
char classname[4]="_sp";
static WNDCLASS wc;
wc.lpfnWndProc = WndProc;
wc.hInstance = g_hInstance;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.lpszClassName = classname;
if (RegisterClass(&wc))
{
char fn2[MAX_PATH];
lstrcpy(fn2,fn);
lstrcat(fn,".bmp");
lstrcat(fn2,".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), (LPSTR)&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("user32");
SetLayeredWindowAttributesProc = (_tSetLayeredWindowAttributesProc) GetProcAddress(user32, "SetLayeredWindowAttributes");
// Use win2k method
SetLayeredWindowAttributesProc(myWnd, keycolor,
(fadein_val > 0)?(0):(255),
alphaparam);
} else
if (keycolor != -1)
{
// Use simpliest region method
int x, y, wdelta;
HRGN region, cutrgn;
BYTE *bmp = bm.bmBits;
region = CreateRectRgn(0,0,bm.bmWidth,bm.bmHeight);
//region = CreateRectRgn(0,0,0,0);
if (bm.bmBitsPixel == 8)
{
#if (KEYCOLOR_8BIT_RGBSUPPORT == 1)
HDC hMemDC;
HBITMAP hOldBitmap;
int rgb[256];
int nColors;
// Find out how many colors are in the color table
nColors = 1 << bm.bmBitsPixel;
// Create a memory DC and select the DIBSection into it
hMemDC = CreateCompatibleDC(NULL);
hOldBitmap = SelectObject(hMemDC,g_hbm);
// Get the DIBSection's color table
GetDIBColorTable(hMemDC,0,nColors,(RGBQUAD*)rgb);
// Find our keycolor at palette
if (keycolor < 0x1000000)
{
for (x = 0; x < nColors; x++)
if (rgb[x] == keycolor) { keycolor = x; break; }
} else keycolor &= 0xff;
// Free used objects
SelectObject(hMemDC,hOldBitmap);
DeleteDC(hMemDC);
#endif
// Bitmap is DWORD aligned by width
//wdelta = (( bm.bmWidth + 3 ) & ~3) - bm.bmWidth;
wdelta = ((bm.bmWidth + 3) & 3) ^ 3;
// Search for transparent pixels
for (y = bm.bmHeight-1; y >= 0; y--, bmp += wdelta)
for (x = 0; x < bm.bmWidth; )
if (*bmp == (BYTE) keycolor)
{
int j = x;
while ((x < bm.bmWidth) && (*bmp == (BYTE) keycolor)) x++, bmp++;
// 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++;
} else if (bm.bmBitsPixel == 24)
{
// Bitmap is DWORD aligned by width
wdelta = ((bm.bmWidth*3 + 3 ) & 3) ^ 3;
// Search for transparent pixels
for (y = bm.bmHeight-1; y >= 0; y--, bmp += wdelta)
for (x = 0; x < bm.bmWidth; )
if ((*(int*)bmp & 0xFFFFFF) == keycolor)
{
int j = x;
while ((x < bm.bmWidth) && ((*(int*)bmp & 0xFFFFFF) == keycolor)) bmp+=3, 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 += 3, x++;
}
// Set resulting region.
SetWindowRgn(myWnd, region, TRUE);
}
PlaySound(fn2,NULL,SND_ASYNC|SND_FILENAME|SND_NODEFAULT);
// Start up timer...
state = 0; 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,"%d",g_rv);
pushstring(temp);
}
#ifdef _DEBUG
void main()
{
}
#endif

View file

@ -1,6 +1,6 @@
AdvSplash.exe - small (6.0k), simple plugin that lets you throw
AdvSplash.exe - small (5.5k), simple plugin that lets you throw
up a splash screen in NSIS installers with cool fading effects (win2k/xp)
and transparency (24bit/8bit bitmaps).
and transparency.
To use:
@ -31,13 +31,9 @@ Calling format
Delay - length to show the screen for (in milliseconds)
FadeIn - length to show the fadein scene (in ms) (not included in Delay)
FadeOut - length to show the fadeout scene (in ms) (not included in Delay)
KeyColor - color used for transparency. For 24 bit bitmaps could be any RGB
value (for ex. R=255 G=100 B=16 -> KeyColor=0xFF6410), for 8 bit bitmaps
could be either RGB value or index of the color at bitmap palette
(if such RGB color present in your image and you'd like to use palette
index, use (0x1000000+index) as KeyColor [you should calculate
this value by yourself]). Use KeyColor=-1 if there is now transparent
color at your image.
KeyColor - color used for transparency, could be any RGB value
(for ex. R=255 G=100 B=16 -> KeyColor=0xFF6410),
use KeyColor=-1 if there is no transparent color at your image.
FileName - splash bitmap filename (without the .bmp). The BMP file used will be
this parameter.bmp, and the wave file used (if present) will be this
parameter.wav.
@ -45,11 +41,11 @@ FileName - splash bitmap filename (without the .bmp). The BMP file used will be
(If you already have an .onInit function, put that in it)
Note 1: fadein/fadeout supported only on win2k/winxp systems, all other systems
will show simple splash screen with Delay = Delay + FadeIn + FadeOut.
will show simple splash screen with Delay = Delay + FadeIn + FadeOut. Also, I've
noted my winXP uses no transparent color at 16 bpp, so at bpps lower than 32
for images with transparent color no fading effect will occur.
Note 2: transparency supported only for 24bit and 8bit bitmaps.
Note 3: the return value of splash is 1 if the user closed the splash
Note 2: the return value of splash is 1 if the user closed the splash
screen early (pop it from the stack)
-Justin

Binary file not shown.