0

I'm developing a UI system that has all those smart features like panel tearing off and docking, etc. Right now my task is to create an overlay on the screen that shows the position where the teared off or dockable panel would land. Pretty much same thing that visual studio has got. For that I'm using a custom layered window class that would show up when it is needed. After that I've started digging to achieve the needed effect. I was working with standart GDI functions before and basicly they are ok. But this time I followed the documentation advice to use UpdateLayeredWindow for my tasks and to load 32bit image from bitmap instead of drawing it with GDI functions. So here I have a 128x128pixel wide bmp with 222 in alpha channel and 255 0 0 in RGB

Here are methods which I use for initialization and drawing.

void Init(HDC in_hdc,HWND in_hwnd)
    {
        bf = { 0, 0, 200, AC_SRC_ALPHA };
        hwnd = in_hwnd;
        hdc_mem = CreateCompatibleDC(in_hdc);
        hBitmap_mem = CreateCompatibleBitmap(in_hdc, canvas_size.cx, canvas_size.cy);
        hBitmap_mem_default = (HBITMAP)SelectObject(hdc_mem, hBitmap_mem);
        hdc_bitmap = CreateCompatibleDC(in_hdc);
    }
    void DrawArea(RECT& in_rect)
    {
        hBitmap_area_default = (HBITMAP)SelectObject(hdc_bitmap, hBitmap_area);
        AlphaBlend(hdc_mem, in_rect.left, in_rect.top, in_rect.right, in_rect.bottom, hdc_bitmap, 0, 0, 2, 2, bf);
        hBitmap_area = (HBITMAP)SelectObject(hdc_bitmap, hBitmap_area_default);
    }
    void Update()
    {
        POINT p = { 0, 0 };
        HDC hdc_screen = GetDC(0);
        UpdateLayeredWindow(hwnd, hdc_screen, &p, &canvas_size, hdc_mem, &p, 0, &bf, ULW_ALPHA);
    }

The window style has this extras WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOPMOST

And here is what I get. So as you can see the blending that takes place DOES take into account per-pixel alpha, but it does a bad blending job. Any ideas how to tune it? enter image description here

Antiusninja
  • 157
  • 1
  • 17

1 Answers1

1

I suspect the problem is in the source bitmap. This is the kind of effect you get when the RGB values aren't premultiplied with the alpha. But ignore that because there is a far simpler way of doing this.

  • Create a layered window with a solid background colour by setting hbrBackground in the WNDCLASSEX structure.

  • Make the window partially transparent by calling SetLayeredWindowAttributes.

  • Position the window where you want it.

That's it.

This answer has code that illustrates the technique for a slightly different purpose.

Community
  • 1
  • 1
arx
  • 16,686
  • 2
  • 44
  • 61
  • Thanks for the hint. And what if I need some pictograms and icons drawn with some transparency effects. (the NavigationDiamond as in VS editor – Antiusninja Apr 16 '15 at 12:34
  • Then you need to fix the bitmap. I don't know how you create it so I can't add much. – arx Apr 16 '15 at 13:07
  • Thanks. Actually premultiplication has worked. Yet, I can not see the idea of this premultiplication. So if for example i have pure red color which is 255 0 0 and 222 alpha then multiplying 255 by 222(0,87) i get ~222 0 0 and alpha with 222 so when after that I multiply it on 1/0.87 I get back the wanted color But if i dont premultiply then 255 by 1/.087 goes out of one byte range and different wrong stuff happens. Why not take original RGB values in the first place? – Antiusninja Apr 16 '15 at 13:23
  • The reason is simple: alpha-blending with Porter-Duff composition (and possibly without; IDK) involves a lot of multiplications, which are slow from a hardware standpoint. By multiplying the red, green, and blue components with the alpha component ahead of time, you can reduce the number of multiplications your blending code does, making things faster and more efficient. – andlabs Apr 16 '15 at 13:27