VC6.0使用 SetLayeredWindowAttributes函数

 

USER32.DLL SetLayeredWindowAttributes函数



SetLayeredWindowAttributes函数:
hwnd是透明窗体的句柄,
crKey为颜色值,
bAlpha是透明度,取值范围是[0,255],
dwFlags是透明方式,能够取两个值:
当取值为LWA_ALPHA时,crKey参数无效,bAlpha参数有效;
当取值为LWA_COLORKEY时,bAlpha参数有效而窗体中的全部颜色为crKey的地方将变为透明。
LWA_ALPHA = 0x2        LWA_COLORKEY=0x1 
要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性 (旧的sdk没有定义这个属性,因此能够直接指定为0x80000). WS_EX_LAYERED = 0x80000

  Windows 2000操做系统不管是在品质上仍是在用户界面上都有了很大的改善与提升,用户对系统的操做变的更加简单、方便,感受也更加舒

适。若是用户在使用时留意一下,不难发现其中界面上的一些新特性。例如,Windows 2000提供了对带阴影阿尔法混合光标的支持、提供对菜单

、提示框淡入淡出效果的支持以及在外壳拖拽具备阿尔法混合效果图片等透明特效。全部这些特效看似不一样但实际都是经过对Windows 2000新提

供的一个分层窗口API函数的调用而实现的。 既然是Windows 2000系统提供的API函数,那么也就意味着在本身的应用程序中一样可以实现该函

数作作支持的各类特效。

  在程序设计时,有时一些微小的改善就足以加强用户界面的显示效果。例如,使用一个具备阿尔法混合效果的光标显然要比一只普通光标的

感受要好的多,尤为是在大屏幕显示器或多显示器系统下这种光标也更容易找到。更进一步,显示器的屏幕大小是有限的,若是想同时查看多个

窗口的内容显然是不太方便的,尽管采起大屏幕显示器或多显示器系统能在必定程度上缓解但远不如将这些应用程序窗体设置为透明或半透明来

的完全和方便。下图显示的两个应用程序虽然存在覆盖,但位于前台的程序窗体显然没有影响后台Word文档内容的显示。鉴于分层窗口函数在程

序设计中的实用做用,本文将对其做具体的介绍以充分挖掘其潜力并将其应用到程序设计中去。

 
  分层窗口

  在介绍分层窗口函数以前,首先要介绍一下WS_EX_LAYERED扩展窗口风格。该窗口风格也是Windows 2000新增长的,若是使用了该属性,窗

体将具有复合形状、动画、阿尔法混合等方面的视觉特效。

  窗口经过被其余窗口的裁剪而在屏幕上以矩形出现。为了实现一个圆形窗体,仅仅简单绘制一个圆形窗体是不够的,这样的话系统还会把窗

体按原矩形进行点击检测,并且位于该窗体下的窗口仍将被该窗体矩形所裁剪。或许能够考虑在园形窗体显示出来前取得位于该窗体矩形下可视

区域的快照,并在稍后窗体显示完毕后将其绘制到当前窗体。但因为其余窗口可以绘制该窗体覆盖下的区域,而前台程序没法获知这种绘制将于

什么时候发生而不会及时获取下面可视区域的新的快照,所以这种解决方法并不能在多进程、多任务环境下很正常的工做。对于这种状况,在

Windows 95/98和Windows NT 4.0下的正确作法是经过SetWindowRgn()API函数指出须要的窗体形状,可是这种处理在频繁更改窗体形状或是在

屏幕上拖拽时仍有缺陷存在:前台窗体将要求位于其下的窗体重绘整个区域,这将生过多的消息和计算量。并且使用SetWindowRgn()只能实现

窗体的全透明而没法实现半透明效果。或许这也正是分层窗口被提出的缘由。

  分层窗口真正实现了两个大相径庭的概念:分层和重定向。为了可以去除任何一个层,WS_EX_LAYERED标志位必需要设置,这能够在窗体创

建时设置也能够在建立后经过以GWL_EXSTYLE标志调用SetWindowLong()来进行设置。接下来,能够经过UpdateLayeredWindows()函数来更新

分层窗口。在具体使用时,须要在位图中绘制出可视区域,并将其与关键色、阿尔法混合参数等一块儿提供给UpdateLayeredWindows()函数。需

要注意的是,在使用UpdateLayeredWindows()函数时,应用程序并不须要响应WM_PAINT或其余绘制消息。

  除此以外,还可使用传统的Win32绘制机制来实现,这须要调用另外一个API函数SetLayeredWindowAttributes()来完成对关键色或阿尔法

混合参数值的设定。一旦该函数被调用,系统将开始为分层窗口重定向全部的绘制并自动应用指定的特效。

窗体半透明特效的实现

  前面已经对分层窗口作了较为详细的介绍。这里将对SetLayeredWindowAttributes()函数及其使用方法作具体的介绍,并在此基础上实现

窗体半透明特效。首先给出SetLayeredWindowAttributes()原形:


BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window 透明窗体的句柄
COLORREF crKey, // specifies the color key 颜色值
BYTE bAlpha, // value for the blend function 透明度,取值范围是[0,255]
DWORD dwFlags // action 透明方式,能够取两个值:
         当取值为LWA_ALPHA时,crKey参数无效,bAlpha参数有效;
         当取值为LWA_COLORKEY时,bAlpha参数有效,而窗体中的全部颜色为crKey的地方将变为透明。
        LWA_ALPHA = 0x2
        LWA_COLORKEY=0x1
);
  其中dwFlags有LWA_ALPHA(值为2)和LWA_COLORKEY(值为1)两种设置,若是LWA_ALPHA被设置的话,经过bAlpha参数指定窗体的透明度;

若是LWA_COLORKEY标志被设置的话,则指定关键色为crKey,该颜色所覆盖的区域将从窗体去除,去除后的区域将再也不进行点击检测,其余颜色

则正常显示。若是阿尔法混合值设置为0,其窗口区域一样不进行点击检测。

  前面说过,SetLayeredWindowAttributes()函数是Windows 2000新增的一个API函数,它所在的模块为USER32.DLL。在用GetModuleHandle

()装载USER32.DLL模块并调用GetProcAddress()获得函数 SetLayeredWindowAttributes()在User32.dll中的指针后就能够经过

SetLayeredWindowAttributes()函数将窗体设置为半透明了:

// 全局变量
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
lpfn g_pSetLayeredWindowAttributes;
……
// 获取函数 SetLayeredWindowAttributes 在User32.dll中的指针
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32, "SetLayeredWindowAttributes");
if (g_pSetLayeredWindowAttributes == NULL)
::PostQuitMessage(0);
  这段代码一般在程序初始化时运行以及时将USER32.DLL模块装载到内存并获取获得SetLayeredWindowAttributes()函数指针。在程序退出

前须要经过FreeLibrary()函数释放先前加载的模块:

// 卸载模块
if (m_hUser32 != NULL)
FreeLibrary(m_hUser32);
  在将窗体设置为半透明时,首先要获取获得该窗体的窗口句柄,以指明要操做的是哪个窗口。若是是对本应用程序中的某个窗口进行设置

,能够经过传递窗口句柄或是用GetSafeHwnd()来动态获取。若是要对本程序外的某个程序窗口进行设置,通常的作法是经过对FindWindow(

)函数的调用来获取指定窗口标题的窗口句柄。在获得窗口句柄以后并不能直接调用SetLayeredWindowAttributes()进行设置,须要在

GetWindowLong()获取获得当前窗口风格设置后在其基础之上添加WS_EX_LAYERED扩展风格,并经过SetWindowLong()函数将其设置:

// 半透明
HWND hWnd = GetSafeHwnd();
LONG lWindowLong = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
::SetWindowLong(hWnd, GWL_EXSTYLE, lWindowLong);
g_pSetLayeredWindowAttributes(hWnd, 0, (BYTE)m_sldAlpha.GetPos(), 2);
::RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
  为了可以使用该函数,还必须在上述语句以前添加预约义语句:

#define WS_EX_LAYERED 0x00080000
  异形窗体特效的实现

  使用SetLayeredWindowAttributes()建立异形窗体是很是简单的,具体过程与半透明窗体的实现极为相似,所不一样的只是将标志设置为

LWA_COLORKEY并指定须要透明显示的关键色:

// 指定关键色
HWND hWnd = GetSafeHwnd();
LONG lWindowLong = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
::SetWindowLong(hWnd, GWL_EXSTYLE, lWindowLong);
g_pSetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, 1);
::RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
  小结

  本文经过对Windows 2000新增API函数SetLayeredWindowAttributes()的使用很是简单的实现了窗体的半透明设置和异形窗体的建立。除

了SetLayeredWindowAttributes()函数,Windows 2000还提供了其余许多相似的特效函数好比用于窗体动态滑动显示的AnimateWindow()。

因为这些函数是系统提供的API函数,所以不会受编程语言的制约,也就是说,并不仅在VC++下能够实现上述特效。在C++ Builder、Delphi等其

他开发环境下也是能够用相似的方法来实现的。本文所述程序代码在Windows 2000 Professional下由Microsoft Visual C++ 6.0编译经过编程

相关文章
相关标签/搜索