
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
294 lines
8.1 KiB
C
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);
|
|
}
|