【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

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

 

演示代码

posted @ 2011-09-08 20:16  zTercel  阅读(1903)  评论(0编辑  收藏  举报