本节我们继续学习UpdateLayeredWindow这个API, 通过它我们来实现一个阴影效果的窗体(像Window7窗体效果).
思路: 1. 创建二个层窗体, 一个作为控件窗件,另一个做阴影效果窗体;
2. 在第一个窗体实现各种控件创建以及相关逻辑处理,此窗体设为全透明;
3. 将第二个窗体重叠并保持重叠第一个窗体(即大小,位置,移动或改变大小都保持一致),此窗体选入一张边沿带有阴影效果通道图(BMP, PNG)通过UpdateLayeredWindow函数年
来实现效果;
4. 截取第一个窗体中控件的图并与第二个窗体叠加,因为UpdateLayeredWindow之后的窗体有穿透能力这样更好触及到被完成透明的第一个窗体上;
声明: 此方法源于Codeproject上一个中国程序员的文章
一. 代码演示
1. 在主窗体WM_NCCREATE中调用_ShadowWnd函数, 通过此函数修改主窗体的两个属性 -- 1. 替换窗体过程函数(用于截获主窗体的消息); 2. 修改主窗体为层窗体
{
static const UINT IDC_BTNEXIT = 1002;
switch ( nMsg )
{
case WM_NCCREATE :
{
_ShadowWnd ( hWnd );
break ;
}
...
}
return :: DefWindowProc ( hWnd , nMsg , wParam , lParam );
}
void _ShadowWnd ( HWND hWnd )
{
LONG _OldWndProc = GetWindowLongPtr ( hWnd , GWL_WNDPROC );
if ( NULL != _OldWndProc )
{
SetWindowLongPtr ( hWnd , GWL_WNDPROC , ( LONG ) _WndProc );
SetWindowLongPtr ( hWnd , GWL_EXSTYLE , GetWindowLongPtr ( hWnd , GWL_EXSTYLE )| WS_EX_LAYERED );
SetLayeredWindowAttributes ( hWnd , 0, 3, LWA_ALPHA );
}
return ;
}
2. 处理_WndProc中消息
a. 首先创建一个层窗体(阴影窗体)
b. 加载边沿带有阴影的效果图PNG(使用gdi+)将做为背影
c. 遍历主窗体中控件的DC, 将绘到背影上
d. 使用UpdateLayeredWindow将含有控件图的背影绘制到阴影窗体上
LRESULT CALLBACK _WndProc ( HWND hWnd , UINT nMsg , WPARAM wParam , LPARAM lParam )
{
HRESULT hResult = _DefWndProc ( hWnd , nMsg , wParam , lParam );
static bool bUpdate = false ;
static Image * pImage ;
static HWND hShadowWnd = NULL ;
switch ( nMsg )
{
case WM_CREATE :
{
pImage = _LoadImage ( IDB_PNG1 , _T ( "PNG" ), GetModuleHandle ( NULL ));
hShadowWnd = _CreateShadowWnd ( hWnd );
break ;
}
case WM_MOVE :
{
RECT rtWnd ;
GetWindowRect ( hWnd , & rtWnd );
if ( NULL != hShadowWnd && IsWindow ( hShadowWnd ))
{
SetWindowPos ( hShadowWnd , NULL , rtWnd . left , rtWnd . top , 0, 0, SWP_NOZORDER | SWP_NOSIZE );
}
break ;
}
case WM_SIZE :
{
RECT rtWnd ;
GetWindowRect ( hWnd , & rtWnd );
if ( NULL != hShadowWnd && IsWindow ( hShadowWnd ))
{
SetWindowPos ( hShadowWnd , NULL , 0, 0, rtWnd . right - rtWnd . left , rtWnd . bottom - rtWnd . top , SWP_NOZORDER | SWP_NOMOVE );
}
break ;
}
case WM_PAINT :
case WM_CAPTURECHANGED :
case WM_CTLCOLOREDIT :
case WM_CTLCOLORBTN :
case WM_CTLCOLORSTATIC :
case WM_CTLCOLORMSGBOX :
case WM_CTLCOLORDLG :
case WM_CTLCOLORLISTBOX :
case WM_CTLCOLORSCROLLBAR :
{
if ( NULL != pImage )
{
_BlendRefresh ( hShadowWnd , hWnd , pImage , 200);
}
break ;
}
case WM_DESTROY :
{
if ( NULL != hShadowWnd && IsWindow ( hShadowWnd ))
{
DestroyWindow ( hShadowWnd );
}
break ;
}
}
return hResult ;
}
二、效果
备注: 本例中演示阴影窗体的实现,其中一些细节还要优化和实现