透明窗口. 顶层窗口.总结

来源:互联网 发布:nginx怎么配置ssl 编辑:程序博客网 时间:2024/06/11 22:32

以前没接触过这么深入的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...