简体   繁体   中英

Draw semitransparently in invisible layered window

My goal is to have a fullscreen overlaying invisible "canvas" on which I can draw using win32's various drawing functions.

The way I am currently attempting it is this:

WNDCLASSA myclass = { 0 };
myclass.lpfnWndProc = WindowProc3;
myclass.hInstance = GetModuleHandle(0);
myclass.lpszClassName = "MyCanvas";
myclass.hbrBackground = CreateSolidBrush(0xFEEDBEEF);
myclass.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassA(&myclass);

...

HWND wnd = CreateWindowExA(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, "MyCanvas", 0, WS_POPUP | WS_VISIBLE, 0, 0, screen_width, screen_height, 0, 0, GetModuleHandle(0), 0);
SetLayeredWindowAttributes(wnd, 0xFEEDBEEF, 0, LWA_COLORKEY);

Although this serves as a canvas, hours of googling later, I am still unable to draw on it semitransparently.

I have added a screenshot of what my program is currently displaying as I am writing this. What I would like to be able to do is, for example, make the black box in the top right corner (drawn with Rectangle ) semitransparent so as to reveal the stackoverflow page content below it.

This is a question I found that I was hopeful about, but the resulting text is just a blended combination of the background color ((COLORREF)0xFEEDBEEF) and text color. Other things I have found have either just made the element fully invisible, done nothing at all, or required some library like MFC. I want to only use win32 functions if at all possible, as I would like to be able to achieve the highest FPS possible.

I do not care if this doesn't work on all Windows versions as long as it does on 7 up to 10.

问题的当前状态

If you only need transparency for a rectangular area where all pixels either have the same transparency (aka alpha ) value or are completely transparent, you can use SetLayeredWindowAttributes() with a combination of alpha value and/or color key.

UpdateLayeredWindow() is the way to go if you need to be able to define transparency per-pixel.

For that you have to create memory DC and select a 32bpp bitmap into it. You may use the buffered paint API to ease the task. Raymond Chen has a blog post with a code sample about that.

You can draw into the memory DC, but you can't use most of GDI API for that, because GDI ignores the alpha channel (transparency). I suggest using GDI+ which allows you to specify the alpha values.

After you have completed drawing into the memory DC, you would call UpdateLayeredWindow() and pass that memory DC as the argument for the hdcSrc parameter to make the result visible on screen.

Illustration of possible effects:

具有LWA_ALPHA的SetLayeredWindowAttributes

SetLayeredWindowAttributes( hwnd, 0, 176, LWA_ALPHA ); 

具有LWA_COLORKEY的SetLayeredWindowAttributes

SetLayeredWindowAttributes( hwnd, colorkey, 0, LWA_COLORKEY ); 

具有LWA_ALPHA | LWA_COLORKEY的SetLayeredWindowAttributes

SetLayeredWindowAttributes( hwnd, colorkey, 176, LWA_ALPHA|LWA_COLORKEY ); 

UpdateLayeredWindow

UpdateLayeredWindow( ... )

Note the antialiased edge of the shape and the transparency gradient in the last example. Things like that are only possible with UpdateLayeredWindow() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM