I'm trying to start experimenting with OpenGL and Windows GUI stuff. I'm running Windows 7 on my dev box and running Visual Studio 2013. When I run the below code, I don't receive any errors and all the of window information seems correct but nothing is drawn to the screen from OpenGL.
For a first program I was looking to put an overlay on top of Notepad, then draw a line/plus sign somewhere in the screen.
First I create a window:
myWindow = CreateWindowEx(
WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_LAYERED,
WINDOW_NAME,
WINDOW_NAME,
WS_POPUP | WS_VISIBLE | WS_MAXIMIZE,
g_NotepadCoords.left,
g_NotepadCoords.top,
g_width,
g_height,
NULL, NULL, g_me, NULL);
The globals and coordinates for the window are calculated using FindWindowA and GetClientRect. Both of these function calls succeed and return reasonable values. After CreateWindowEx, I use the following function calls to set properties and check support, etc:
SetLayeredWindowAttributes(myWindow, RGB(0, 0, 0), 255, LWA_ALPHA | LWA_COLORKEY);
if (S_OK != DwmIsCompositionEnabled(&bIsEnabled)){...}
Right now HandleWindowMessage has WM_CREATE, WM_CLOSE, WM_DESTROY and WM_PAINT enabled. SetupOpenGL is called in WM_CREATE, and the drawing happens in WM_PAINT.
WM_CREATE and WM_PAINT:
case WM_CREATE:
{
printf("WM_CREATE\n");
g_Hdc = GetDC(hWnd);
SetupGL();
return 0;
}
break;
case WM_PAINT:
{
GLenum err;
const GLubyte *errString;
RGB colorToDraw = { 0 };
drawPlus(g_.middleX, g_.middleY, 12, 12, 4, &colorToDraw);
err = glGetError();
errString = gluErrorString(err);
printf("ERROR DRAWING? %s\n", errString);
}
break;
As far as I can tell I set up OpenGL correctly; no errors are printed:
void SetupOpenGL()
{
__try{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | // Format Must Support Window, OPENGL, Composition
PFD_SUPPORT_OPENGL |
PFD_SUPPORT_COMPOSITION |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA, // RGBA
32,
0, 0, 0, 0, 0, 0,
8, // alpha
0, 0, 0, 0, 0, 0, 0,
8, // stencil Buffer
0,
PFD_MAIN_PLANE, // Main Drawing Layer
0, 0, 0, 0
};
PixelFormat = ChoosePixelFormat(g_Hdc, &pfd);
if (0 == PixelFormat)
{
printf("ChoosePixelFormat failed %d\n", GetLastError());
__leave;
}
if (!SetPixelFormat(g_Hdc, PixelFormat, &pfd))
{
printf("SetPixelFormat failed %d\n", GetLastError());
__leave;
}
if (!DescribePixelFormat(g_Hdc, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
{
printf("DescribePixelFormat failed %d\n", GetLastError());
__leave;
}
g_MainHGLRC = wglCreateContext(g_Hdc);
if (!g_MainHGLRC)
{
printf("wglCreateContext failed %d\n", GetLastError());
__leave;
}
if (!wglMakeCurrent(g_Hdc, g_MainHGLRC))
{
printf("wglMakeCurrent failed %d\n", GetLastError());
__leave;
}
glMatrixMode(GL_PROJECTION);
glClearColor(0.f, 0.f, 0.f, 0.f);
}
__finally{}
}
And then drawPlus is super simple:
void drawPlus(float x, float y, float width, float height, float lineWidth, RGB* RGB)
{
printf("drawPlus(%f,%f,%f,%f,%f,[%d,%d,%d])", x, y, width, height, lineWidth, RGB->red, RGB->green, RGB->blue);
glLineWidth(lineWidth);
glBegin(GL_LINES);
glColor4f(RGB->red, RGB->green, RGB->blue, 1);
glVertex2f(x, y + height/2);
glVertex2f(x, y - height/2);
glVertex2f(x + width/2, y);
glVertex2f(x - width/2, y);
glEnd();
}
When I run it, I don't receive any errors, I can see the executable creating another window and I've confirmed that drawPlus is getting called correctly and with good parameters. However, there's nothing actually drawn to the screen so I'm not sure what I'm missing. I just ran a quick check on the coordinates and for the Notepad windows elements I got:
top: 86
bottom: 916
left: 170
right: 609
And then for where to draw the plus I got
x = 219
y = 412
Which both seem reasonable so it's not my windows being mismatched or etc.
Related
I'm working on a Win32 app with layered windows. The window contents are drawn using Cairo. The transparency is very unpredictable however. Sometimes everything is correct; opaque parts are opaque, transparent parts transparent. Other times what should be opaque becomes transparent or vanishes completely.
This is the most minimal example I could reduce the problem to (based on this answer). It should draw a square in the upper left corner of the screen, with the left half transparent grey and the right half opaque black.
import core.sys.windows.windows;
import std.utf;
import std.stdio;
import cairo;
import cairo_win32;
const UINT WIDTH = 500;
const UINT HEIGHT = 500;
extern(Windows)
LRESULT WndProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) nothrow {
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void main(string[] args) {
WNDCLASS wndclass;
wndclass.lpszClassName = "Test".toUTF16z;
wndclass.lpfnWndProc = &WndProc;
RegisterClass(&wndclass);
HINSTANCE hInstance = GetModuleHandle(NULL);
HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW, wndclass.lpszClassName, "Test".toUTF16z, WS_POPUP, 50, 50, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOWNA);
HDC hdcScreen = GetDC(NULL);
// Offscreen hdc for painting
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hbmMem = CreateCompatibleBitmap(hdcScreen, WIDTH, HEIGHT);
auto hOld = SelectObject(hdcMem, hbmMem);
// Draw using offscreen hdc
auto surface = cairo_win32_surface_create(hdcMem);
auto cr = cairo_create(surface);
// Transparent grey
cairo_rectangle(cr, 0, 0, 250, HEIGHT);
cairo_set_source_rgba(cr, 0.4, 0.4, 0.4, 0.8);
cairo_fill(cr);
// Black
cairo_rectangle(cr, 250, 0, 250, HEIGHT);
cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_fill(cr);
cairo_destroy(cr);
cairo_surface_destroy(surface);
// Show on screen
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
RECT win_rect;
GetWindowRect(hwnd, &win_rect);
POINT ptZero = POINT(0, 0);
POINT win_pos = POINT(win_rect.left, win_rect.top);
SIZE win_dims = SIZE(WIDTH, HEIGHT);
UpdateLayeredWindow(hwnd, hdcScreen, &win_pos, &win_dims, hdcMem, &ptZero, RGB(0, 0, 0), &blend, ULW_ALPHA);
// Reset offscreen hdc to default bitmap
SelectObject(hdcMem, hOld);
// Cleanup
DeleteObject(hbmMem);
DeleteDC (hdcMem);
ReleaseDC(NULL, hdcScreen);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
This works, as you can see here.
However, when I now switch the order of the two Cairo draw calls like this:
// Opaque black
cairo_rectangle(cr, 250, 0, 250, HEIGHT);
cairo_set_source_rgba(cr, 0.01, 0.01, 0.01, 1.0);
cairo_fill(cr);
// Transparent grey
cairo_rectangle(cr, 0, 0, 250, HEIGHT);
cairo_set_source_rgba(cr, 0.4, 0.4, 0.4, 0.8);
cairo_fill(cr);
Then the opaque right half becomes completely transparent.
What's going on here? I assume I must be doing something more fundamentally wrong, probably with the whole HDC and UpdateLayeredWindow business.
Update: I tried to create an image surface with CAIRO_FORMAT_ARGB32, used the exact same drawing operations and wrote it to a PNG file. In that case both images look correct and identical.
It seems like the first operation can't have an alpha of exactly 1.0. If I set the first rectangle's alpha to 1.0, the second (black opaque) rectangle vanishes. If I set the first rectangle's alpha to 0.99 instead, the second rectangle is drawn correctly.
I tried use gdi to capture certain window, it's ok for most window.
But to some window like "visual studio code", it doesn't work.
DX can't support capturing certain window.
How should I do? THANKS
::EnumWindows(EnumWindowsProc, NULL);
if (hCapWnd == NULL)
{
return FALSE;
}
SwitchToThisWindow(hCapWnd, true);
Sleep(1000);
//HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetWindowDC(hCapWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
SetStretchBltMode(hCaptureDC, COLORONCOLOR);
RECT rc;
::GetWindowRect(hCapWnd, &rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, width, height);
SelectObject(hCaptureDC, hCaptureBitmap);
BOOL bRet = BitBlt(hCaptureDC, 0, 0, width, height, hDesktopDC, 0, 0, SRCCOPY);
Init(width, height);
int nRet = GetDIBits(hCaptureDC, hCaptureBitmap, 0, height, buf, (BITMAPINFO*)&m_bitmapInfo, DIB_RGB_COLORS);
static int n = 0;
//if (n++ % 10 == 0)
{
// std::string name = ustd::format_string("%s\\%d.bmp", ustd::get_program_path().c_str(), n);
SaveBitmapToFile(hCaptureBitmap);
}
ReleaseDC(hCapWnd, hDesktopDC);
DeleteDC(hCaptureDC);
DeleteObject(hCaptureBitmap);
On Windows, I'm trying to use CEF (Chromium Embedded Framework) to create a window application with parent window to be transparent and its child window to be opaque (I want to have a rounded corner and an arrow pointing to the status bar in the child window). Something similar to:
I tried to use SetLayeredWindowAttributes to make the parent window transparent but it also makes the child window transparent. Is there a way to make this happen on Windows?
SetLayeredWindowAttributes needs a color for transparency. Make sure the transparency color is not used by the child window. You can pick a random color, for example RGB(255, 0, 254) and assume the child window is not using it.
If you have no control over the child window, and you can't be sure what colors it might use, then SetWindowRgn is another option to create non-rectangular windows.
The example below shows how to set the region such that the corners are round with a triangle on top.
You can use GDI+ to gain more flexibility for drawing the region, and for anti-aliasing effect so that the borders look more smooth.
#include <Windows.h>
int triangle_height = 30;
int corner_size = 20;
int caption_height = 60;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_CREATE:
{
//create a child button for testing
CreateWindowW(L"BUTTON", L"Close", WS_CHILD | WS_VISIBLE,
10, caption_height + 10, 100, 30,
hwnd, HMENU(100), GetModuleHandle(NULL), NULL);
RECT rc;
GetClientRect(hwnd, &rc);
//create a triangle region
int w = rc.right;
int h = rc.bottom;
int z = triangle_height;
POINT pt[3];
pt[0] = { w / 2, 0 };
pt[1] = { w / 2 - z, z };
pt[2] = { w / 2 + z, z };
HRGN htri = CreatePolygonRgn(pt, 3, WINDING);
//create a round rectangle region
HRGN hrgn = CreateRoundRectRgn(0, z, w, h - z, corner_size, corner_size);
//combine the triangle with round rectangle
CombineRgn(hrgn, htri, hrgn, RGN_OR);
//set the new region
SetWindowRgn(hwnd, hrgn, TRUE);
DeleteObject(htri);
DeleteObject(hrgn);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc = ps.rcPaint;
//we don't have a standard title bar, paint one here:
rc.bottom = caption_height;
SetDCBrushColor(hdc, RGB(80, 80, 80));
FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));
//paint the background
rc = ps.rcPaint;
rc.top = caption_height;
SetDCBrushColor(hdc, RGB(240, 240, 240));
FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));
//use FrameRgn to paint a border around the region
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hwnd, hrgn);
SetDCBrushColor(hdc, RGB(128, 128, 128));
FrameRgn(hdc, hrgn, (HBRUSH)GetStockObject(DC_BRUSH), 1, 1);
DeleteObject(hrgn);
EndPaint(hwnd, &ps);
return 0;
}
case WM_NCHITTEST:
{
//we don't have a standard title-bar
//respond to our custome title-bar manually:
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwnd, &pt);
if(pt.y < caption_height)
return HTCAPTION;
break;
}
case WM_COMMAND:
if(HIWORD(wparam) == BN_CLICKED)
if(LOWORD(wparam) == 100)
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
WNDCLASSEXW wcex = { sizeof(wcex) };
wcex.style = CS_DROPSHADOW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszClassName = L"classname";
RegisterClassExW(&wcex);
CreateWindowW(wcex.lpszClassName, L"Test", WS_VISIBLE | WS_POPUP,
200, 200, 600, 400, 0, 0, hInstance, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
I'm trying to use NDK to display a bitmap on a full screen. The requirement force me to develop with completely native code. I use Skia to draw a SkBitmap, then display it by Opengl APIs. When my application first time run on a real android device, it always works well. However, after I keep opening and closing the program for several times, it will show a bad image. Why does this happen?
Function engine_init_display is to initialize OpenGL ES and EGL, create bitmap and load texture.
static int engine_init_display(struct engine* engine){
// initialize OpenGL ES and EGL
/*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_DEPTH_SIZE, 16,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
/* Here, the application chooses the configuration it desires. In this
* sample, we have a very simplified selection process, where we pick
* the first EGLConfig that matches our criteria */
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
engine->display = display;
engine->context = context;
engine->surface = surface;
engine->width = w;
engine->height = h;
engine->state.angle = 0;
engine->format=format;
// Initialize GL state.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
SkBitmap bitmap;
GLvoid* bitmapBuffer;
createBitmap(bitmap,bitmapBuffer,width,height);
drawBitmap(bitmap,width,height);
glEnable(GL_TEXTURE_2D);
glGenTextures(1,&sTexture);
glBindTexture(GL_TEXTURE_2D,sTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)bitmapBuffer);
glDisable(GL_TEXTURE_2D);
glFinish();
clearBitmapBuffer(bitmap,bitmapBuffer);
//engine_draw_frame(engine);
return 0;
}
Function render is to display a bitmap
void render(struct engine* engine, int width, int height){
glViewport((engine->width-width)/2, (engine->height-height)/2, width, height);
glClearColorx((GLfixed)(0.1f * 65536),(GLfixed)(0.2f * 65536),(GLfixed)(0.3f * 65536), 0x10000);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D,sTexture);
glFrontFace(GL_CW);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glFlush();
eglSwapBuffers(engine->display, engine->surface);
}
And when the window is being closed, engine_term_display will be called
static void engine_term_display(struct engine* engine) {
if (engine->display != EGL_NO_DISPLAY) {
eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (engine->context != EGL_NO_CONTEXT) {
eglDestroyContext(engine->display, engine->context);
}
if (engine->surface != EGL_NO_SURFACE) {
eglDestroySurface(engine->display, engine->surface);
}
eglTerminate(engine->display);
}
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
}
update
android_main is the main entry point of my native application. I find that when this main function has returned, the whole application is still running.
void android_main(struct android_app* state) {
struct engine engine;
// Make sure glue isn't stripped.
app_dummy();
memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state;
ANativeActivity_setWindowFlags(engine.app->activity, AWINDOW_FLAG_FULLSCREEN, 0);
if (state->savedState != NULL) {
// We are starting with a previous saved state; restore from it.
engine.state = *(struct saved_state*)state->savedState;
}
while(1){
int ident;
int events;
struct android_poll_source* source;
if((ident=ALooper_pollAll(-1, NULL, &events,(void**)&source))>=0){
// Process this event.
if (source != NULL) {
source->process(state, source);
}
if (state->destroyRequested != 0) {
engine_term_display(&engine);
return;
}
}
}
}
I fix it by myself, use exit(0) instead of return to finish the activity completely.
if (state->destroyRequested != 0) {
engine_term_display(&engine);
exit(0);
}
I attampted to draw a irregular window with the UpdateLayeredWindow(), in msvc2008, xp sp3.
Here is part of my code:
//Add something(CreateWindowEx()):
hwndCyauWnd = CreateWindowEx(
/*WS_EX_TOOLWINDOW |*/ WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_LAYERED,
lpwsCyauClassName,
lpwsCyauWndName,
WS_CLIPSIBLINGS | WS_POPUP,
GetSystemMetrics(SM_CXSCREEN)-320,
GetSystemMetrics(SM_CYSCREEN)-232,
320, 200,
NULL,
NULL,
hInstance,
NULL);
//Skip Lines
HDC hdcCyauWnd = GetDC(hwndCyauWnd);
HDC hdcBuffer = CreateCompatibleDC(hdcCyauWnd);
//HBITMAP hbmCyau = CreateCompatibleBitmap(hdcBuffer,120, 93);
//SelectObject(hdcBuffer, hbmCyau);
POINT ptZero = {0, 0};
POINT ptDrawPos = {0, 0};
RECT rctCyauWnd;
GetWindowRect(hwndCyauWnd, &rctCyauWnd);
SIZE szCyauWnd={rctCyauWnd.right - rctCyauWnd.left, rctCyauWnd.bottom - rctCyauWnd.top};
BLENDFUNCTION blendPixelFunction = { AC_SRC_OVER, 0, 100, AC_SRC_ALPHA};
Graphics gphCyauWnd(hdcBuffer);
Image imgCyau(L"surface0000.png");
gphCyauWnd.DrawImage(&imgCyau, 0, 0, 125, 93);
UpdateLayeredWindow(hwndCyauWnd,
hdcCyauWnd, &ptZero,
&szCyauWnd,
hdcBuffer, &ptZero,
0, //RGB(255, 255, 255),
&blendPixelFunction,
ULW_ALPHA);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
I have tried several method to use this function, but all failed, NOTHING APPEAR on the screen.
Could anybody tell me what happens and how to slove it?
Add:
Whole source file have been upload to my skydrive, anyone can edit, much appreciation! (I have become a poor underdog now...)
You mixed up GDI and GDI+, which is not a good idea. Here is a working example:
hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, 0,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
// Load PNG
CImage img;
img.Load("BACKGR.png");
// Get image sizes
int nWidth = img.GetWidth();
int nHeight = img.GetHeight();
// Create memory DC
HDC hdcScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hdcScreen);
// Create memory bitmap
HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
// Draw image to memory bitmap (currently selected in memory DC)
img.Draw(hDC, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 128;// half transparent
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = {0, 0};
SIZE szWnd = {nWidth, nHeight};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(hWnd, hdcScreen, &ptLocation, &szWnd, hDC, &ptSrc, 0, &blend, ULW_ALPHA);
ShowWindow(hWnd, SW_SHOW);
SelectObject(hDC, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hDC);
ReleaseDC(NULL, hdcScreen);
If you want GDI+ to draw to an image with an alpha channel, you have to draw to a Bitmap, not an HDC, and you have to specify that the Bitmap's format has alpha. To do that with an HBITMAP, you have to also point GDI+ to the bitmap bits.
Something like this:
BITMAPINFOHEADER bih;
HBITMAP hbmp;
HDC hdc;
void *bits;
bih.biSize = sizeof(bih);
bih.biWidth = width;
bih.biHeight = -height;
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
hdc = CreateCompatibleDC(NULL);
hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, &bits, NULL, 0);
Bitmap bitmap(width, height, 0, PixelFormat32bppPARGB, bits);
Graphics graphics(bitmap);
graphics->DrawWhatever(...);
graphics->Flush();
SelectObject(hdc, hbitmap);
UpdateLayeredWindow(hwnd, hdc, ...