【Demo 0047】阴影效果的窗体

本节我们继续学习UpdateLayeredWindow这个API, 通过它我们来实现一个阴影效果的窗体(像Window7窗体效果).

思路:  1.  创建二个层窗体, 一个作为控件窗件,另一个做阴影效果窗体;

         2.  在第一个窗体实现各种控件创建以及相关逻辑处理,此窗体设为全透明;

         3.  将第二个窗体重叠并保持重叠第一个窗体(即大小,位置,移动或改变大小都保持一致),此窗体选入一张边沿带有阴影效果通道图(BMP, PNG)通过UpdateLayeredWindow函数年

             来实现效果;

         4.  截取第一个窗体中控件的图并与第二个窗体叠加,因为UpdateLayeredWindow之后的窗体有穿透能力这样更好触及到被完成透明的第一个窗体上;

声明: 此方法源于Codeproject上一个中国程序员的文章

一. 代码演示

     1. 在主窗体WM_NCCREATE中调用_ShadowWnd函数,  通过此函数修改主窗体的两个属性 -- 1. 替换窗体过程函数(用于截获主窗体的消息); 2.  修改主窗体为层窗体

        

LRESULT CALLBACK _DefWndProc ( HWND hWnd , UINT nMsg , WPARAM wParam , LPARAM lParam )
{    
     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 ;
}

二、效果

     image

   备注: 本例中演示阴影窗体的实现,其中一些细节还要优化和实现

 

演示代码

你可能感兴趣的:(demo)