// alpha.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text ULONG_PTR m_gdiplustoken; // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HBITMAP GetAlphaChannelBitmap(const WCHAR *, bool); void UpdateWindow(HWND, const WCHAR *, BYTE); char szFileName[MAX_PATH]; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; if (lpCmdLine) strcpy(szFileName, lpCmdLine); else szFileName[0] = 0; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_ALPHA, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Initialize GDI+ Gdiplus::Status result; Gdiplus::GdiplusStartupInput gdiplusstartupinput; result = Gdiplus::GdiplusStartup(&m_gdiplustoken, &gdiplusstartupinput, NULL); if (result != Gdiplus::Ok) { return FALSE; } // Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_ALPHA); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } Gdiplus::GdiplusShutdown(m_gdiplustoken); return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_ALPHA); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_ALPHA; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, szWindowClass, szTitle, WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd, L"background.png", 255); return TRUE; } HBITMAP GetAlphaChannelBitmap(const WCHAR *pFileName, bool bPreMultiply) { HBITMAP hBmp = NULL; // Configure the background color Gdiplus::Color backColor(GetSysColor(CTLCOLOR_DLG)); Gdiplus::SolidBrush brushBackColor(backColor); // Get the bitmap Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(pFileName); //bitmap->GetHBITMAP(backColor, &hBmp); //return hBmp; Gdiplus::BitmapData bmp_data; Gdiplus::Rect bitmapRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); bitmap->LockBits(&bitmapRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, &bmp_data); BYTE *bmpPtr = (BYTE *)(bmp_data.Scan0); if (bPreMultiply) { for (int y = 0; y < bmp_data.Height; y++) { BYTE *pPixel = (BYTE *)bmpPtr + bmp_data.Width * 4 * y; for (int x = 0; x < bmp_data.Width; x++) { pPixel[0] = pPixel[0] * pPixel[3] / 255; pPixel[1] = pPixel[1] * pPixel[3] / 255; pPixel[2] = pPixel[2] * pPixel[3] / 255; pPixel += 4; } } } Gdiplus::Bitmap *bmp = new Gdiplus::Bitmap(bmp_data.Width, bmp_data.Height, bmp_data.Stride, bmp_data.PixelFormat, (BYTE *)bmpPtr); //bmp->GetHBITMAP(backColor, &hBmp); BITMAPINFO bmi; // Initialize header to 0s. ZeroMemory(&bmi, sizeof(bmi)); // Fill out the fields you care about. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = bmp_data.Width; bmi.bmiHeader.biHeight = -bmp_data.Height; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; HDC hDC = GetDC(NULL); hBmp = CreateDIBitmap(hDC, &bmi.bmiHeader, CBM_INIT, (void *)bmpPtr, &bmi, DIB_RGB_COLORS); ReleaseDC(NULL, hDC); bitmap->UnlockBits(&bmp_data); delete bmp; delete bitmap; return hBmp; } void AlphaDraw(HDC hDC, int x, int y, int width, int height, HBITMAP hBmp) { HDC hMemDC = CreateCompatibleDC(hDC); HGDIOBJ hOld = SelectObject(hMemDC, hBmp); HBRUSH hBrush = CreateSolidBrush(RGB(0xFF, 0xFF, 0)); SelectObject(hDC, hBrush); SelectObject(hDC, GetStockObject(NULL_PEN)); Rectangle(hDC, x, y, x+width+1, y+height+1); //SelectObject(hDC, GetStockObject(WHITE_BRUSH)); DeleteObject(hBrush); //BitBlt(hDC, x, y, width, height, hMemDC, 0, 0, SRCCOPY); //BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; //AlphaBlend(hDC, x, y + height, width, height, hMemDC, 0, 0, width, height, pixelblend); BLENDFUNCTION blend50 = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; AlphaBlend(hDC, x, y, width, height, hMemDC, 0, 0, width, height, blend50); SelectObject(hMemDC, hOld); DeleteObject(hMemDC); } void UpdateWindow(HWND hWnd, const WCHAR *lpFileName, BYTE SourceConstantAlpha) { if (!(::GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_LAYERED)) return; HBITMAP hBmp = GetAlphaChannelBitmap(lpFileName, false); HDC hScreenDC = GetDC(hWnd); HDC hMemDC = CreateCompatibleDC(hScreenDC); HGDIOBJ hOld = SelectObject(hMemDC, hBmp); BLENDFUNCTION bf; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; UpdateLayeredWindow(hWnd, hScreenDC, NULL, NULL, hMemDC, NULL, 0, &bf, ULW_ALPHA); SelectObject(hMemDC, hOld); DeleteObject(hMemDC); } void OnDraw(HDC hDC, const WCHAR *pFileName) { static HBITMAP hBmp = NULL; if ( hBmp==NULL ) hBmp = GetAlphaChannelBitmap(pFileName, true); BITMAP bmp; GetObject(hBmp, sizeof(BITMAP), & bmp); AlphaDraw(hDC, 0, 0, bmp.bmWidth, bmp.bmHeight, hBmp); } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; switch (message) { case WM_COMMAND: // Parse the menu selections: switch ( LOWORD(wParam) ) { case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: OnDraw(BeginPaint(hWnd, &ps), L"background.png"); // szFileName); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }