Results 1 to 9 of 9

Thread: New Layered Window Example

  1. #1
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default New Layered Window Example

    For upcoming ClanLib 2.0.5

    A new layered window example

    See attached
    Attached Images Attached Images  

  2. #2
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Updated the example, so it's more useful

    See attached image.

    You can drag the rock around the screen

    The rotating penguin moves around the rock

    It demonstrates, that you can have smooth animation with opengl using layered windows. Although, it would be better to use GDI - If opengl is not required

    This could be used as a splash screen, or a fancy "set options screen"
    Attached Images Attached Images  
    Last edited by rombust; 10-08-2009 at 07:24 AM. Reason: updated image

  3. #3
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    And yet another example...

    A different technique at using layered windows...

    OpenGL displaying 256 sprites

    It creates 5 windows as follows

    AAAAA
    B###C
    B###C
    DDDDD

    A,B,C,D are layered windows
    # is the main window.
    Attached Images Attached Images  

  4. #4
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    We have a little problem with layered windows.

    At the monent, we have:

    Code:
    CL_Win32Window::create_new_window()
    {
    ...
    	SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 0, LWA_COLORKEY);
    ...
    }
    This is very limiting for 2 reasons.

    First, if we translucent windows:

    Code:
    	SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 128, LWA_ALPHA);
    There is no API to set it

    Secondly, this would cause UpdateLayeredWindow() to fail ( http://msdn.microsoft.com/en-us/libr...56(VS.85).aspx )
    because it is not compatible with SetLayeredWindowAttributes() unless the layering style bit is cleared and set again.

    Also it maybe faster to use UpdateLayeredWindow() than WM_PAINT - For partial or full update of the window.

    Finally. UpdateLayeredWindow() can use the alpha channel.

    Anyone want to explore????

    See attached image of "128, LWA_ALPHA"
    Attached Images Attached Images  

  5. #5
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    I actually thought that it was using UpdateLayeredWindow for the rendering.

    At least with the GDI target, I'd assume this is both faster and better than using the other function. The UpdateLayeredWindow function has the advantage that you can use the alpha channel of the backbuffer as transparency, instead of using a color key or fixed global transparency.

    The only real catch about it is that the image blitted to the bitmap DC (using SetDIBitsToDevice) must be in pre-multiplied ARGB format.

    clanGDI already uses the ARGB format for its backbuffer, but the alpha channel is not premultiplied, so that change would have to be applied before calling SetDIBitsToDevice for that target.

    I have some old code that shows how to use this function with pre-multiplied alpha, and it looks like this:

    Code:
    void LayeredWindow::update_layered(const CL_PixelBuffer &image, const CL_Color &colorkey, int window_alpha, bool use_colorkey)
    {
    	// Convert pixel buffer to DIB compatible format:
    	CL_PixelFormat argb8888(
    		32,
    		0x00ff0000,
    		0x0000ff00,
    		0x000000ff,
    		0xff000000);
    
    	int pitch = image.get_width() * 4;
    	CL_PixelBuffer bmp_image(image.get_width(), image.get_height(), pitch, argb8888);
    
    	image.convert(
    		bmp_image.get_data(), bmp_image.get_format(), pitch,
    		CL_Rect(0, 0, bmp_image.get_width(), bmp_image.get_height()));
    
    	// Note that the APIs use pre-multiplied alpha, which means that the red,
    	// green and blue channel values in the bitmap must be pre-multiplied with
    	// the alpha channel value. For example, if the alpha channel value is x,
    	// the red, green and blue channels must be multiplied by x and divided by
    	// 0xff prior to the call.
    	int w = bmp_image.get_width();
    	int h = bmp_image.get_height();
    	cl_uint32 *p = (cl_uint32 *) bmp_image.get_data();
    	for (int y = 0; y < h; y++)
    	{
    		int index = y * w;
    		cl_uint32 *line = p + index;
    		for (int x = 0; x < w; x++)
    		{
    			cl_uint32 a = ((line[x] >> 24) & 0xff);
    			cl_uint32 r = ((line[x] >> 16) & 0xff);
    			cl_uint32 g = ((line[x] >> 8) & 0xff);
    			cl_uint32 b = (line[x] & 0xff);
    
    			r = r * a / 255;
    			g = g * a / 255;
    			b = b * a / 255;
    
    			line[x] = (a << 24) + (r << 16) + (g << 8) + b;
    		}
    	}
    
    	BITMAPV5HEADER bmp_header;
    	memset(&bmp_header, 0, sizeof(BITMAPV5HEADER));
    	bmp_header.bV5Size = sizeof(BITMAPV5HEADER);
    	bmp_header.bV5Width = bmp_image.get_width();
    	bmp_header.bV5Height = -bmp_image.get_height();
    	bmp_header.bV5Planes = 1;
    	bmp_header.bV5BitCount = 32;
    	bmp_header.bV5Compression = BI_RGB;
    
    	HDC hdc = GetDC(hwnd);
    	HDC bitmap_dc = CreateCompatibleDC(hdc);
    	HBITMAP bitmap = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) &bmp_header, CBM_INIT, bmp_image.get_data(), (BITMAPINFO *) &bmp_header, DIB_RGB_COLORS);
    	HGDIOBJ old_bitmap = SelectObject(bitmap_dc, bitmap);
    
    	SIZE size = { bmp_image.get_width(), bmp_image.get_height() };
    	POINT point = { 0, 0 };
    	COLORREF rgb_colorkey = RGB(colorkey.get_red(), colorkey.get_green(), colorkey.get_blue());
    	BLENDFUNCTION blend;
    	memset(&blend, 0, sizeof(BLENDFUNCTION));
    	blend.BlendOp = AC_SRC_OVER;
    	blend.SourceConstantAlpha = (BYTE) window_alpha;
    	blend.AlphaFormat = AC_SRC_ALPHA;
    	if (use_colorkey)
    		UpdateLayeredWindow(hwnd, 0, 0, &size, bitmap_dc, &point, rgb_colorkey, &blend, ULW_COLORKEY);
    	else
    		UpdateLayeredWindow(hwnd, 0, 0, &size, bitmap_dc, &point, rgb_colorkey, &blend, ULW_ALPHA);
    
    	SelectObject(bitmap_dc, old_bitmap);
    	DeleteObject(bitmap);
    	DeleteDC(bitmap_dc);
    	ReleaseDC(hwnd, hdc);
    }
    I personally do not see the advantage in using SetLayeredWindowAttributes, unless that somehow magically would allow OpenGL to use wglSwapBuffers, but I don't think it works that way.

  6. #6
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Needless to say, this pre-multiplied step could be done with some SSE code.

  7. #7
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Yes, that's the best way to do it.

    And because, GL, GL1 and GDI produce a CL_PixelBuffer ready for the layered window, we could simply add a CL_Win32Window::update_layered() using your code.

    I was worried about the speed with creating the pre-multiplied alpha,, and relying on WM_PAINT doing it automatically. But, initial tests showed that is was about the same speed.

    Looking it http://www.codeproject.com/KB/GDI/pxalphablend.aspx ... It's a must

    I personally do not see the advantage in using SetLayeredWindowAttributes, unless that somehow magically would allow OpenGL to use wglSwapBuffers, but I don't think it works that way.
    No, it does not perform magic. You still have to have the opengl shadow window that is rendered to.

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Also, remember to remove
    SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 0, LWA_COLORKEY);
    from CL_Win32Window::create_new_window()

    I forgot, and wasted an hour trying to work out why the UpdateLayeredWindow() returned a parameter is incorrect error

  9. #9
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Done!

    2 Problems:

    1) At the moment window.update() forces the entire window to update for layered windows.

    2) GDI layered window support is not implemented
    (Use CL_Win32Window::update_layered() )

    See attached
    Attached Images Attached Images  
    Last edited by rombust; 02-04-2010 at 10:05 PM.

Similar Threads

  1. Layered windows now available in the gui example
    By rombust in forum Official ClanLib SDK Forums
    Replies: 0
    Last Post: 09-08-2009, 10:37 AM
  2. How to : Delete/Close a Window and Center a Window ?
    By Fr3DBr in forum Official ClanLib SDK Forums
    Replies: 0
    Last Post: 08-24-2009, 02:55 AM
  3. Preview of ClanLib 2.0.3 - Layered Windows In OpenGL
    By rombust in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 06-23-2009, 05:05 PM
  4. Two apps, one window?
    By stodge in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 11-28-2007, 06:26 AM
  5. Trying to set the window icon
    By JonR in forum Official ClanLib SDK Forums
    Replies: 4
    Last Post: 08-09-2007, 08:14 AM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •