#include LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HBITMAP CreateLayeredWindowBitmap(void); BOOL UpdateLayeredWindowByBitmapWithPerPixelAlpha(HWND hWnd, HBITMAP hBmp); HINSTANCE hInstance; const char szWindowClass[] = "LayeredWindowSampleClass"; const char szWindowName[] = "LayeredWindowSample"; #define WINDOW_WIDTH 512 #define WINDOW_HEIGHT 384 INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, INT nCmdShow) { WNDCLASSEX wcex; HWND hWnd; MSG msg; ::hInstance = hInstance; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = 0; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = NULL; RegisterClassEx(&wcex); hWnd = CreateWindowEx( WS_EX_LAYERED, szWindowClass, szWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch (message) { case WM_CREATE: { HBITMAP hBmp; HRGN hRgnWnd; hRgnWnd = CreateRectRgn(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); SetWindowRgn(hWnd, hRgnWnd, FALSE); hBmp = CreateLayeredWindowBitmap(); UpdateLayeredWindowByBitmapWithPerPixelAlpha(hWnd, hBmp); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } // レイヤードウィンドウを描画するためのビットマップを作成する HBITMAP CreateLayeredWindowBitmap(void) { DWORD *pdwBmp; BITMAPINFO bmi; HDC hdcScreen; HBITMAP hBmp; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = WINDOW_WIDTH; bmi.bmiHeader.biHeight = WINDOW_HEIGHT; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; hdcScreen = GetDC(NULL); hBmp = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void **)&pdwBmp, 0, 0); ReleaseDC(NULL, hdcScreen); for (int y = 0; y < WINDOW_HEIGHT; y++) { // 縦方向に色が変化する DWORD r = (y * 255) / WINDOW_HEIGHT; DWORD b = ((WINDOW_HEIGHT - y - 1) * 255) / WINDOW_HEIGHT; for (int x = 0; x < WINDOW_WIDTH; x++) { // 横方向にアルファ値が変化する DWORD a = (x * 255) / WINDOW_WIDTH; // 乗算済みアルファに変換する DWORD rr = r * a / 255; DWORD bb = b * a / 255; pdwBmp[x + y*WINDOW_WIDTH] = (a << 24) | (rr << 16) | bb; } } return hBmp; } // ビットマップをもとにレイヤードウィンドウを更新する BOOL UpdateLayeredWindowByBitmapWithPerPixelAlpha(HWND hWnd, HBITMAP hBmp) { HDC hdcScreen, hdcBmp; HGDIOBJ hBmpPrev; RECT rc; POINT ptDst, ptSrc; SIZE size; BLENDFUNCTION bf; BOOL ret; hdcScreen = GetDC(NULL); hdcBmp = CreateCompatibleDC(hdcScreen); hBmpPrev = SelectObject(hdcBmp, hBmp); GetWindowRect(hWnd, &rc); ptDst.x = rc.left; ptDst.y = rc.top; ptSrc.x = 0; ptSrc.y = 0; size.cx = WINDOW_WIDTH; size.cy = WINDOW_HEIGHT; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.AlphaFormat = AC_SRC_ALPHA; bf.SourceConstantAlpha = 255; ret = UpdateLayeredWindow(hWnd, hdcScreen, &ptDst, &size, hdcBmp, &ptSrc, 0, &bf, ULW_ALPHA); ReleaseDC(NULL, hdcScreen); SelectObject(hdcBmp, hBmpPrev); DeleteDC(hdcBmp); return ret; }