以前没接触过这么深入的windowsUI的问题. 现在由于需要做触摸屏鼠标, 不得不专研这么技术. 现在把研究的结果记下来, 帮助自己, 也帮助别人.
先说比较简单的, 如何把窗口始终置顶.
1:::SetWindowPos()传入参数 SWP_TOPMOST.
2: 如上的方法如果调用一次, 则把窗口放入系统维护的顶层窗口列表中.并不能把窗口置于顶层的顶层(最顶层)
解决办法就是, 不断的调用SetWindowPos()函数, 使之始终被放置在最顶层.
3:要么设置一个定时器,每隔一段时间就调用SetWindowPos(), 要么当窗口的位置信息改变时调用SetWindowPos函数.
当窗口的位置改变时,包括Z-order的位置改变时, windows会给窗口发送WM_WindowPosChanging消息.
4: 如果想仅在窗口位置改变时调用SetWindowPos,则响应WM_MOVE消息即可.
5: 如果想让窗口在置顶的同时, 不夺取原窗口的输入焦点, 在调用SetWindowPos()时,指定SWP_NOACTIVITY变量.(这个问题困扰了我许久.大概一个星期,才搞定)
逐像素alphablend的透明窗口
经过研究发现,如果想实现逐像素混合的窗口,只有使用UpdateLayeredWindow函数.
使用别的方法,要么是指定透明色,要么是程序自己可以实现alphablend,但是和别的应用程序的窗口混合时就会出现问题.
本质上,正确使用UpdateLayeredWindow要注意以下问题:
1) 必须使用32 bpp(bitsPerPixel)的位图.RGBA格式.
2) 使用AlphaBlend()函数或UpdateLayedredWindow函数. 只有这两个函数支持逐像素的alphablend.
3) 在AlphaBlend之前,必须对原图RGB像素的值进行Alpha运算(PreMultiplyRGBChannels),详细见msdn 运算后的RGB值被AlphaBlend()和UpdateLayedredWindow函数用到.
4) 想进行PreMultiplyRGBChannels运算,必须得到像素的数据的指针,怎么指向数据的得到指针?下面给出了答案.使用DIB.
///////////////
如何得到一个HBITMAP的图像数据的指针?
目前为止,好像只有CreateDIBSection才支持!!!
他同时返回,指向rawdata的指针.
用法如下:
Try using a memory HDC wich contains a 32 bpp Device
independant bitmap. ( DIB )
here's one simple exemple to create a 32 bpp buffer :
BITMAPINFO bi32 = {0};
bi32.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi32.bmiHeader.biWidth = 100;
bi32.bmiHeader.biHeight = 100;
bi32.bmiHeader.biPlanes = 1;
bi32.bmiHeader.biBitCount = 32;
bi32.bmiHeader.biCompression = BI_RGB;
void* pBits = NULL;
HDC hTarget = CreateCompatibleDC(NULL); //or any compatible dc.
HBITMAP hbmp = CreateDIBSection(NULL, &bi32, DIB_RGB_COLORS,
(void**)&pBits, NULL, NULL)
HGDIOBJ hold = SelectObject( hTarget, (HGDIOBJ )hbmp );
etc...