• 【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

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

    演示代码

  • 相关阅读:
    CDQ分治
    K-th Number POJ
    A * B Problem Plus HDU
    Prime Test POJ
    数据结构
    FFT
    mysql查询出相同数据出现的次数,统计相同值的数量
    Laravel 清空配置缓存
    php7 数据导出Excel office 2011中文乱码问题
    PHP file_put_contents函数数据导出csv文件,屏幕字符串逗号分隔符
  • 原文地址:https://www.cnblogs.com/ztercel/p/2171783.html
Copyright © 2020-2023  润新知