使用Win32 API创建不规则形状&带透明色的窗口
前一阵突然想起了9月份电面某公司实习时的二面题,大概就是说怎么用Win32 API实现一个透明的窗口,估计当时我的脑残答案肯定让面试官哭笑不得吧。所以本人决定好好研究下这个问题。经过一下午的摸索,基本掌握了使用Win32 API创建各种匪夷所思的窗口的基本思路。
(以下文字基于本人的个人理解,由于本人技术和经验原因不保证正确性,希望各位不吝指正)
首先我们需要了解一些基础知识。
1、Layered Windows。这是Windows2000开始引入的新概念,重新定义了窗口的Hit Testing方法,以前都是把窗口按rectangle的方式裁剪,而把窗口加上WS_EX_LAYERED的Style后就可以根据窗口的形状和像素值进行Hit Testing[1],这样我们的不规则窗口就变成了真正意义上的独立窗口,而不是传统的被一个不可见的矩形窗口所包含。
Layered Windows支持两种绘制方式,一种是采用UpdateLayeredWindow函数,优点是是一劳永逸,不需要在窗口函数中响应各种重绘事件,缺点嘛大概就是这高科技玩意让人一时半会接受不了= =另一种方式就是先用SetLayeredWindowAttributes函数设置关于窗口透明度的信息,然后用传统方式,在窗口函数中响应各种重绘事件。然而我们其实似乎并不需要关注WM_PAINT,只要在WM_CREATE中初始化一下窗口的全局背景(颜色和SetLayeredWindowAttributes所定义的相同),然后在WM_ERASEBKGND中更新一些颜色与SetLayeredWindowAttributes定义的不同的细节区域之处便可。
2、SetWindowRgn函数。这个函数用来定义窗口的区域,我们的不规则形状由此而来。这个函数和它的朋友们十分强大,不仅可以定义独立的基本形状的区域,还可以通过运算来组合已有区域从而产生新的区域。下面的实例就通过CombineRgn函数的帮助来产生了一个孔方兄形状的窗口。
好了,基本知识我们已经掌握了,下面来看看我做的示例程序的运行效果:

怎么样,还算比较cool吧。下面是完整代码:
LRESULT _stdcall WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC hDC = GetWindowDC(hWnd);
static HRGN hRgn = CreateRectRgn(120, 70, 280, 230);
switch(uMsg)
{
case WM_ERASEBKGND:
{
DefWindowProc(hWnd, uMsg, wParam, lParam);
FillRgn(hDC, hRgn, CreateSolidBrush(RGB(255, 165, 0))); // Orange
SelectObject(hDC, hRgn);
return 0;
}
case WM_CREATE:
{
HRGN hRgn1 = CreateEllipticRgn(0, 0, 400, 300);
HRGN hRgn2 = CreateEllipticRgn(150, 100, 250, 200);
CombineRgn(hRgn1, hRgn1, hRgn2, RGN_XOR);
SetWindowRgn(hWnd, hRgn1, TRUE);
DeleteObject(hRgn1);
DeleteObject(hRgn2);
break;
}
case WM_LBUTTONDOWN:
{
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
break;
}
case WM_DESTROY:
{
DeleteObject(hRgn);
ReleaseDC(hWnd, hDC);
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);;
}
int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, BOOL)
{
WNDCLASS wc = {0};
wc.lpszClassName = L"wndclass";
wc.hbrBackground = CreateSolidBrush(RGB(255, 99, 71));
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpfnWndProc = WinProc;
RegisterClass(&wc);
HWND hWnd = CreateWindowExW(WS_EX_LAYERED, L"wndclass", L"Window", WS_POPUP|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, 0, 0, hInstance, 0);
if (hWnd == NULL)
return 1;
SetLayeredWindowAttributes(hWnd, NULL, 178, LWA_ALPHA); // Tomato
MSG msg = {0};
while (GetMessage(&msg, 0, 0, 0))
{
DispatchMessage(&msg);
}
return 0;
}
参考资料:
[1] MSDN:Layered Windows
[2] WindowsAPI_001:创建一个不规则的窗口的方法(用到Region系列API)
» 转载请注明来源及链接:未来代码研究所
使用Win32 API创建不规则形状&带透明色的窗口的更多相关文章
- CAD创建不规则形状视口
选择CAD模型空间中多段线,在指定的布局中创建视口,方法如下: /// <summary> /// 创建视口 /// </summary> /// <param name ...
- 使用Win32 API实现生产者消费者线程同步
使用win32 API创建线程,创建信号量用于线程的同步 创建信号量 语法例如以下 HANDLE semophore; semophore = CreateSemaphore(lpSemaphoreA ...
- (译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0)
(译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0) 更新:ios4.1现在已经将这个做到SDK了.你可以设置键盘类型为UIKeyboardTypeDecimal ...
- win32 api Windows窗口的创建
windows窗口的创建有以下几个步骤: 1.创建注册窗口类 2.创建窗口句柄 3.显示更新窗口 4.消息循环 1.创建注册窗口类 所谓创建窗口类就是定义一个WNDCLASS类对象,并将该对象进行初始 ...
- 【C#】分享基于Win32 API的服务操作类(解决ManagedInstallerClass.InstallHelper不能带参数安装的问题)
注:这里的服务是指Windows 服务. ------------------201508250915更新------------------ 刚刚得知TransactedInstaller类是支持带 ...
- 【.Net】从.NET平台调用Win32 API
小序 Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制 ...
- 【C++】从零开始,只使用FFmpeg,Win32 API,实现一个播放器(一)
前言 起初只是想做一个直接读取视频文件然后播放字符动画的程序.我的设想很简单,只要有现成的库,帮我把视频文件解析成一帧一帧的原始画面信息,那么我只需要读取里面的每一个像素的RGB数值,计算出亮度,然后 ...
- 使用CSS 3创建不规则图形 文字围绕
前言 CSS 创建复杂图形的技术即将会被广泛支持,并且应用到实际项目中.本篇文章的目的是为大家开启它的冰山一角.我希望这篇文章能让你对不规则图形有一个初步的了解. 现在,我们已经可以使用CSS 3 常 ...
- C#调用Win32 api学习总结
从.NET平台调用Win32 API Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微 ...
随机推荐
- Android - 不管在应用的哪个activity按Home键整个App就结束了
最开始,客户反映说在用app的时候,来个电话,接完再点app,不是原来的界面,而是重启了.数据都没了,所以就在activity重写onSaveInstanceState方法,将数据保存起来.后经测试发 ...
- SQL知识三(Day 27)
大家好,好几天都没写博客了.因为自己的一些原因,落下了很多.今天没有学什么新的知识,自己就把以前落下的好好看了一下.好了,今天就先总结一下SQL剩下的一些知识吧. 主要学的知识有:循环语句(case语 ...
- oracle 导入txt
没有Oraclehoume的情况下,执行下环境变量文件 sqlldr userid= DM/DM control = /home/oracle/libc/load.ctl load data infi ...
- js中&& 和 ||
原文链接:http://wenrunchang123.iteye.com/blog/1749802 a() && b() 1). 如果执行a() 返回true:那么执行b()并 ...
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(二)高精度计时、延时函数
学过单片机的同学应该清楚,我们在编写传感器驱动时,需要用到高精度的定时器.延时等功能,wiringpi提供了一组函数来实现这些功能,这些函数分别是: micros() #返回当前的微秒数,这个数在调用 ...
- CSS 基础总结
CSS基础 Doctype 声明位于文档中的最前面,处于 标签之前.告知浏览器的解析器,用什么文档类型 规范来解析这个文档. 在标准模式中,浏览器根据规范呈现页面: 在混杂模式中,页面以一种比较宽松的 ...
- 用1个 2个3个 5个div实现 十字架
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- SQL Server 数据岸问题
create table t2(x int constraint pk_t2 primary key);go insert into t2(x) values(1),(2),(3),(5),(7),( ...
- Linux 查看支持的语言,日期,时间,计算器
1.查看系统目前支持的语言 echo %LANG 2.查看日历 cal 3.查看日期时间 date 4.计算器 bc
- Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...