|
Download source code with sample project - 188 Kb
Download ImgDecoder project - 14 Kb
Download some test images - 108 Kb
Introduction
In this article I will give you some source code to create per pixel alpha blending windows.
First, some images:

Nice, heim?
For creating a per-pixel window we are going to use:
- One 24bit Bitmap with alpha channel.
- The GDI function,
UpdateLayeredWindow.
24bit Bitmap with alpha channel
The most tricky part of creating the bitmap is finding a simple file format that
has an embedded alpha channel.
The selected file format for the first incarnation of this article was PSP (Paint Shop Pro™ from Jasc®), but now the recommended file format has been changed to PNG (Portable Network Graphics).
For loading PNG files I use the paintlib library. This library can also load files from PCX, TGA and TIFF formats.
This demo application does not use paintlib directly; instead it uses a paintlib
wrapper dll, ImgDecoder.Dll.
For loading PSP files I've created a function called LoadPSPFileToDIB(PSPLoader.h/cpp).
UpdateLayeredWindow
To use this function we must have a top-level window (in this sample this is
implemented by the class CDummyDialog) with the extended style
WS_EX_LAYERED set.
Before we can pass the bitmap to the UpdateLayeredWindow function, we must pre-multiply the rgb channels with the alpha channel. For this you just have to call the PreMultiplyRGBChannels function (take a look at CPerpixelalphaDlg::DoLoadFile).
From here on read the source code in CPerpixelalphaDlg::DoUpdateDummyDialog.
Installing & Building
- Make sure you have the SDK for Windows® NT 5.0.
- Download and extract the source code of this article.
- Build and enjoy!
If you want to build the ImgDecoder.Dll you also have to,
- Download paintlib and all the required libraries.
- Download the ImgDecoder project.
- Extract the ImgDecoder project to the paintlib library.
- Build the ImgDecoder project.
- Copy the resulting ImgDecoder.dll and ImgDecoder.lib to the bin directory of this article's demo application.
License
- You must mention my name in your application documentation/help box,
something like, Portions © 2001 by Rui Godinho Lopes
<ruiglopes@yahoo.com>.
- I would appreciate it if you send me an email letting me know that you are using this code.
- I cannot be held responsible of any kind of data loss caused directly or
indirectly by the use of this code - use it at your own risk.
- You cannot sell this code - this is free software.
Don't forget if you have any constructive thoughts just email me!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 90 (Total in Forum: 90) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi, I am trying to write code in clear WinAPI, but I am doing some mistake (probably I wasn't able to understand the MFC code):
#ifndef WINVER # define WINVER 0x0502 #endif #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0502 #endif #ifndef _WIN32_WINDOWS # define _WIN32_WINDOWS 0x0410 #endif #ifndef _WIN32_IE # define _WIN32_IE 0x0600 #endif #include #include "path_to_CxImage_library/ximage.h"
#define MAIN_CLASS_NAME L"AlphaBlendingWindowClass"
HWND mainWindow; CxImage image;
LRESULT CALLBACK WindowProcMain(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch ( uMsg ) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); image.Draw(hdc, 0, 0, 200, 200, NULL, true); EndPaint(hwnd, &ps); } break; case WM_LBUTTONDOWN: case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
void Update() { POINT position = {100,100}; SIZE size = {200, 200}; POINT src = {0, 0};
HDC screenDC = GetDC(NULL); HDC memDC = CreateCompatibleDC(NULL); UINT32 *data = new UINT32[size.cx*size.cy]; ZeroMemory(data, sizeof(UINT32)*size.cx*size.cy); HBITMAP newBitmap = CreateBitmap(size.cx, size.cy, 1, 32, data); HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, newBitmap); image.Draw(memDC, 0, 0, 200, 200, NULL, true); BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
if (!UpdateLayeredWindow(mainWindow, screenDC, &position, &size, memDC, &src, 0, &bf, ULW_ALPHA)) { MessageBox(NULL, L"Window wasn't updated!", L"Error", MB_OK | MB_ICONERROR); } delete[] data; SelectObject(memDC, oldBitmap); DeleteObject(newBitmap); DeleteDC(memDC); ReleaseDC(NULL, screenDC); }
BOOL InitApp(HINSTANCE instance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wc.hInstance = instance; wc.lpfnWndProc = WindowProcMain; wc.lpszClassName = MAIN_CLASS_NAME; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; if ( !RegisterClassEx(&wc) ) return FALSE;
mainWindow = CreateWindowEx(WS_EX_LAYERED, MAIN_CLASS_NAME, L"AlphaBlendedWindow", WS_VISIBLE | WS_POPUP, 100, 100, 200, 200, NULL, NULL, instance, NULL); if ( mainWindow == NULL ) { MessageBox(NULL, L"Cannot create window!", L"Error", MB_OK | MB_ICONERROR); return FALSE; } if (!image.Load(L"../debug/image.png")) { MessageBox(NULL, L"Cannot load image!", L"Error", MB_OK | MB_ICONERROR); } Update();
return TRUE; }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShow) { MSG msg; InitApp(hInstance); while ( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
Thanks for any help
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
How can I draw text on the alpha window? Do I have to draw the text into the bitmap and then premultiply it after ? anyone have an example of how to do this:?
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Ok I figured out how to draw text and whatever I wanted on the window now my premultiplying everything, but now how can I put windows controls on the window?
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
This is real world article. How to use controls (ie, button, editbox, ...) in layered windows. Any help?
Thanks,
Pherosiden
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
I need the UNICODE version of this Code and i need unicode version of imagdecoder.dll So far, i have followed the instructions and have not been able to build a unicode version. Can anyone help me?
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
I have MS Visual Studio 2005 (no SP) and "anydec.h" is missing. I couldn't find it over internet, so please someone send me it, armaza@mail.ru. thancks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The exe file works great but when i open the dsw (project file) in visual c++ 6.0 and compile it i get about 5 compiler errors saying "identifier undeclared".
I tried everything but nothing works.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hey,
gr8 work man... actually have implemented alpha compositions equations as well.. but i dont have enough test images, specially the ones with some meaningful per-pixel alpha.
I downloaded what is here on this page but would be gr8 if you could share more or give me pointer to get'em.
Regards, Ninad
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Dude
this is good... copied or not copied this was the only excellent working example of Pixel Blending of Dialog which I could find anywhere.
And after all we all learn from each other. But what counts is the effort put up by someone to actually post this on the internet is awesome. Remember, Man is a mimicking animal
Good going dude
Glax
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I don't know how to add control to the dialog when i use UpdateLayeredWindow API.Because WM_PAINT message can not send.Can you give me some methods to solve it.Thank you!
|
| Sign In·View Thread·PermaLink | 2.56/5 (5 votes) |
|
|
|
 |
|
|
Hi I have an application that constantly is updating its image. Now when I place a layered transparent window on the top of it - I made one with your application using color keying instead of alpha - then I observe with Windows Task Manager that the CPU time of my application goes from 3 to 5% to 20 to 25%. Now my question is, is Window really that bad in handling layered windows or am I doing something wrong. Can I make an overlay with markers/cursors for my application in another way?
Jens M P
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
I've been messing with your code and first off thank you for enlightening me on the use of per-pixel alpha blending But when I try to write text on the window via Device Context I can't "erase" the old text. Is there any special way of resetting the picture back to its default or just a specific region? Or is there maybe a better way to write text on a layered window altogether?
Thank you in advance 
-ObsidianX
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hello there,
I also like this soo much... but can u plese tell me that how did u write text on this Layered dialog using GDI.
PLease tell me !!
Thanks you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is a little late, but I just figured it out. You have to do your GDI drawing to an offscreen bitmap/DC and then when you are done drawing you must premultiply the bitmap pixels, then you must use the AlphaBlend function to finally blit it all to the orignal bitmap and call DoUpdateDummyDialog.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
D:\perpixelalpha\perpixelalphaDlg.cpp(251) : error C2065: 'WS_EX_LAYERED' : undeclared identifier D:\perpixelalpha\perpixelalphaDlg.cpp(283) : error C2065: 'AC_SRC_ALPHA' : undeclared identifier D:\perpixelalpha\perpixelalphaDlg.cpp(287) : error C2039: 'UpdateLayeredWindow' : is not a member of '`global namespace'' D:\perpixelalpha\perpixelalphaDlg.cpp(287) : error C2065: 'UpdateLayeredWindow' : undeclared identifier D:\perpixelalpha\perpixelalphaDlg.cpp(288) : error C2065: 'ULW_ALPHA' : undeclared identifier
I'm not too conversant with MFC, but I'm getting these all the time, no matter what. I do have the sdk, I try putting the winuser.h everywhere, it's not taken apparently. It's a mystery to me how this thing gets built.
|
| Sign In·View Thread·PermaLink | 1.40/5 (5 votes) |
|
|
|
 |
|
|
 |
|
|
This article is bad! Writer has stolen code he does not under stand! Article also does not show proper way to do this. 
Code he use for premultiply alpha is stolen from Feng Yuans book. Image drawing is from Free Image library.
But even worse, here is proof that this article is broken. Try to draw an big line across image. Make one line of solid blue (rgb(0, 0, 255)), like this in CPerpixelalphaDlg::DoUpdateDummyDialog
// get the bitmap dimensions BITMAP bmpInfo; bmp.GetBitmap(&bmpInfo);
// ADD THIS CODE CPen kPen; kPen.CreatePen(PS_SOLID, 4, RGB(0, 0, 255)); dcMemory.SelectObject(&kPen); dcMemory.MoveTo(0, 0); dcMemory.LineTo(bmpInfo.bmWidth, bmpInfo.bmHeight); // ADD THIS CODE
// get the window rectangule (we are only interested in the top left position) CRect rectDlg; wnd.GetWindowRect(rectDlg);
You see what happen....
|
| Sign In·View Thread·PermaLink | 1.00/5 (4 votes) |
|
|
|
 |
|
|
George987654321 wrote: Writer has stolen code
What? Why you say it was stolen?
George987654321 wrote: Article also does not show proper way to do this.
Care to show us the way?
George987654321 wrote: Code he use for premultiply alpha is stolen from Feng Yuans book.
Nonsense...
George987654321 wrote: Image drawing is from Free Image library.
More nonsense... the PSP loading code is mine; the other formats (PNG, etc) is from paintlib.
George987654321 wrote: But even worse, here is proof that this article is broken.
Oh, and why is that?
---- Rui Lopes
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is all I need say:
http://www.fengyuan.com/article/alphablend.html
Rui Godinho Lopes wrote: George987654321 wrote: But even worse, here is proof that this article is broken.
Oh, and why is that?
Why? Add code I show in first message to draw line on image. It not work, no blue line acorss image. Why? Well I leave you to understand problem, if you really wrote any code and not copy pasted it, you should understand it.
Only thing your code show is how to use paintlib to load PNG.
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
You can say whatever you want... its all nonsenses.
George987654321 wrote: Why? Well I leave you to understand problem, if you really wrote any code and not copy pasted it, you should understand it.
I'll bite, its quite easy to explain... you are using a GDI Pen that doesn't have support for the alpha channel (it sets alpha to 0, which is transparent); you are then drawing it on a memory dc that is expected to have its RGB channels premultiplied with the alpha (again, the GDI Pen does not do that)... then when UpdateLayeredWindow uses it for alpha blending with the desktop, well, you see what you see, and it can be easily explained by looking at the composition algorithm...
---- Rui Lopes
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This looks like the answer of a person who understands the code. I enjoyed the article. Keep on writing man.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Agreed with OJ. I don't care whether the codes are stolen or copied from somewhere, don't even care whether the author understand the code. The core thing is: He willing to share and ... The samples works in my machine! And look cool!! So, Rui, don't be discouraged.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
LOL! Thanks George for the laugh. It seems to me that you are complaining that the article doesn't explain how to do what you want, when it was designed to explain something else entirely. You will notice that the focus of the article is transparent windows, not image manipulation. So it may have a bug, big deal, if we boycott every article that has a bug we might as well boycott codeproject.
As to your claim of theft, a premultiply routine is what it is, there are only a couple of ways to write it. You can't steal it any more than you can steal a routine to add an element to a linked list. If the drawing routine is from FI, big deal, it's FREE after all.
Next time you try to sink a clear, concise, description of how to do something difficult and valuable, make sure YOU know what YOU are talking about.
John Crenshaw
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
...MyApp.cpp(136): error C3861: 'UpdateLayeredWindow': identifier not found, even with argument-dependent lookup
Working on Win XP SP2, have latest PSDK installed.
tried everything, nothing works.
Any thoughts ?
S. Wininger
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, Well I have a configuration quite similar to yours and I coped the same problem. Well I just tried to modify StdAfx.h . Then I re compiled and all was fine.
Hope this will work for you. Let me know.
Jong
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|