// Unicode support by Jim Park -- 08/22/2007 // For layered windows #define _WIN32_WINNT 0x0500 #include #include #include // nsis plugin 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); 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); 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(HANDLE 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); }