VC++界面编程之--阴影窗口的实现详解
转载:http://blog.csdn.net/rmxming/article/details/11661365
对于我们这些控件狂来说,窗口阴影也是一个必不可少的实现需求。虽说其没多大用,但对于增加窗口立体感来说,那是挺有帮助的。
我实现了一个类似于360界面的阴影效果,其可以支持正常窗口,也支持半透明窗口。
阴影窗口对于正常窗口和半透明窗口,有区别么?且让我慢慢写来:)
阴影窗口的实现原理,简单来讲:就是在主窗口创建时,创建一个子窗口,吸附于主窗口的底部。然后在子窗口上做一个带半透明阴影效果的描绘。
以下代码是阴影窗口在父窗口的创建代码,是不是很简单?
- LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- m_Shadow.Create(m_hWnd);
- m_Shadow.SetShadowSize(8);
- return TRUE;
- }
下面是阴影窗口实现步骤:
1. 在阴影窗口创建时,只设定阴影窗口的样式为WS_VISIBLE,我们这里不能用WS_CHILD,否则阴影窗口就跑到主窗口里面去了。
- // Create shadow window.
- HWND Create(const HWND wndParent)
- {
- ATLASSERT( ::IsWindow(wndParent) );
- m_hParentWnd = wndParent;
- CRect rc(1, 1, 1, 1);
- return CWindowImpl<CThemedShadowWnd, CWindow, CControlWinTraits>::Create(0, rc, NULL, WS_VISIBLE, NULL);
- }
2. 在阴影窗口执行WM_CREATE消息时,修改其样式为WS_EX_LAYERED | WS_EX_TRANSPARENT,注意这两个样式都要要。WS_EX_TRANSPARENT是让窗口无法接收点击消息,你总不想你的窗口阴影可以被用户点击且激活吧:)
- SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT);
- ModifyStyleEx(WS_EX_TOPMOST, WS_EX_NOACTIVATE);
3. 与此同时,阴影窗口注册父窗口的消息处理回调函数,此举是为了获取父窗口的移动、重绘和隐藏等重要消息。因为阴影窗口要跟随着父窗口的状态改变而改变。
- // Set parent window original processing.
- m_OriParentProc = ::GetWindowLong(m_hParentWnd, GWL_WNDPROC);
- ::SetWindowLong(m_hParentWnd, GWL_WNDPROC, (LONG)ParentProc);
回调函数要做的事情很简单,吸附于父窗口之下,像个小尾巴一样:
- // Get parent message.
- static LRESULT CALLBACK ParentProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- // Find the shadow window pointer via parent window handle.
- ATLASSERT( m_szShadowWindows.find(hwnd) != m_szShadowWindows.end() );
- CThemedShadowWnd *pThis = m_szShadowWindows[hwnd];
- WNDPROC pDefProc = (WNDPROC)pThis->m_OriParentProc;
- switch(uMsg)
- {
- case WM_ERASEBKGND:
- case WM_PAINT:
- case WM_MOVE:
- case WM_ACTIVATE:
- case WM_NCACTIVATE:
- {
- if (::IsWindowVisible(hwnd))
- {
- pThis->AdjustWindowPos();
- }
- break;
- }
- case WM_DESTROY:
- {
- // Destroy the shadow window.
- pThis->DestroyWindow();
- break;
- }
- case WM_NCDESTROY:
- {
- // Remove shadow window from map.
- m_szShadowWindows.erase(hwnd);
- break;
- }
- case WM_SHOWWINDOW:
- {
- // the window is being hidden
- if (!wParam)
- {
- pThis->ShowWindow(SW_HIDE);
- }
- else
- {
- pThis->ShowWindow(SW_SHOW);
- }
- break;
- }
- default:
- {
- break;
- }
- }
- return pDefProc(hwnd, uMsg, wParam, lParam);
- }
好了,窗口消息机制处理完了,就要处理阴影画法了,我这里用的是GDI+的画法,如果有童鞋觉得效果不够好,可以尝试多改改参数配置,以达到理想效果:
- // Create shadow brush.
- PathGradientBrush brShadow(m_ShadowPath.m_pPath);
- Color clrShadow[3] = {Color::Transparent, Color(255, 0, 0, 0), Color(255, 0, 0, 0)};
- int nCount = 3;
- REAL szPos[3] = {0.0F, 0.05F, 1.0F};
- brShadow.SetInterpolationColors(clrShadow, szPos, nCount);
- // Draw shadow.
- rcShadow.Width = rcShadow.Width - m_nShadowSize - m_nBlankArea;
- rcShadow.Height = rcShadow.Height - m_nShadowSize - m_nBlankArea;
- graphics.ExcludeClip(rcShadow);
- graphics.FillPath(&brShadow, m_ShadowPath.m_pPath);
注意我这里排除了一部分的阴影部分,那是为透明窗口制作的,排除的效果图如下,阴影窗口只显示在矩形的右下角,而其他地方是透明的。
如果我不排除一部分阴影区域,那么透明的窗口效果将变得很难看,如下图,透明背景被阴影遮盖了,这显然不符合美学的要求。
如果你的窗口的角是椭圆的,你可能还需要增宽阴影的显示区域,那么可以用如下函数进行阴影的宽度增长:
- // Set blank area right position.
- void SetRightOffsetArea(const int nRightPos)
- {
- m_nBlankArea = nRightPos;
- if (nRightPos < 0)
- {
- m_nBlankArea = 1;
- }
- }
阴影窗口免费实例代码下载:http://download.csdn.net/detail/renstarone/6267677
VC++界面编程之--阴影窗口的实现详解的更多相关文章
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- Android 之窗口小部件详解--App Widget
Android 之窗口小部件详解--App Widget 版本号 说明 作者 日期 1.0 添加App Widge介绍和示例 Sky Wang 2013/06/27 1 App ...
- 转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解
目标大纲 文章转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解 IE中CSS-filter滤镜小知识大全 CSS实现跨浏览器兼容性的盒阴影效果
- [置顶] VC++界面编程之--使用分层窗口实现界面皮肤
使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果. 在很多情况下,界面的漂亮与否,取决于PS的制作 ...
- VC++界面编程之--使用分层窗口实现界面皮肤
使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果. 在很多情况下,界面的漂亮与否,取决于PS的制作 ...
- VC/MFC中的CComboBox控件使用详解
CComboBox控件详解 CComboBox控件又称作组合框控件,其有三种形态可供选择,1.简单组合框(Simple)2.下拉组合框(Drop-down)3.下拉列表式组合框(Drop-down l ...
- VMware 虚拟化编程(14) — VDDK 的高级传输模式详解
目录 目录 前文列表 虚拟磁盘数据的传输方式 Transport Methods Local File Access NBD and NBDSSL Transport SAN Transport Ho ...
- 网页打开新窗口——Window.open()详解
转载自:http://blog.csdn.net/business122/article/details/8281142 Window.Open详解 一.window.open()支持环境:JavaS ...
- Java 异步编程 (5 种异步实现方式详解)
同步操作如果遇到一个耗时的方法,需要阻塞等待,那么我们有没有办法解决呢?让它异步执行,下面我会详解异步及实现@mikechen 目录 什么是异步? 一.线程异步 二.Future异步 三.Comp ...
随机推荐
- Linux内核之旅 链表实现
#include "stdio.h" #include "stdlib.h" struct list_head{ struct list_head *prev; ...
- paper 81:HDR成像技术
什么是HDR?谈HDR照片的制作方法和效果 HDR,是英文High-Dynamic Range的缩写,意为“高动态范围”.这是一个简单的术语,HDR照片是使用多张不同曝光的图片,然后再用软件将其叠加合 ...
- paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)
1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual ...
- notepad++ 行末尾添加指定字符
在查找目标中输入“^”代表行首,“$”代表行末,下方的查找模式要改成“正则表达式”. 如果替换中有字符,则用“\”转义, 例如 : 目标中输入: $ 替换字符输入: \, 则是每行后面加 ...
- 夺命雷公狗---DEDECMS----31dedecms数据库创建一张表完成curl操作
首先我们创建一张测试表,格式如下所示: 然后我们还是在plus目录下创建一个test3.php进行测试,首先写一个添加的: <?php header("Content-Type:tex ...
- 给uefi引导的方式安装archlinux
基本就是照着官方的wiki来的,不过官方的wiki的内容太杂了,或许我们需要的是一个瀑布似的流程. 其实大体上与mbr引导的方式类似,只凭借回忆说一下有区别的地方,等下一次有机会的时候再验证一下. 换 ...
- 关于全站https必要性http流量劫持、dns劫持等相关技术
关于全站https必要性http流量劫持.dns劫持等相关技术 微信已经要求微信支付,申请退款功能必须12月7号之前必须使用https证书了(其他目前为建议使用https),IOS也是2017年1月1 ...
- 模块已加载,但对dllregisterServer的调用失败
在注册dll或者ocx的时候, 经常会遇到这么一个问题: 模块 已加载,但对dllregisterServer的调用失败,错误代码为0x8004***** 网上有网友回复说需要在管理员的模式下进行注 ...
- JavaEE基础(十一)/Eclipse介绍
1.Java开发工具(常见开发工具介绍) A:操作系统自带的记事本软件 B:高级记事本软件 C:集成开发环境 IDE (Integrated Development Environment) D:Ec ...
- C++11 std::function用法
转自 http://www.hankcs.com/program/cpp/c11-std-function-usage.html function可以将普通函数,lambda表达式和函数对象类统一起来 ...