前一阵突然想起了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吧。下面是完整代码:

#include <windows.h>

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创建不规则形状&带透明色的窗口的更多相关文章

  1. CAD创建不规则形状视口

    选择CAD模型空间中多段线,在指定的布局中创建视口,方法如下: /// <summary> /// 创建视口 /// </summary> /// <param name ...

  2. 使用Win32 API实现生产者消费者线程同步

    使用win32 API创建线程,创建信号量用于线程的同步 创建信号量 语法例如以下 HANDLE semophore; semophore = CreateSemaphore(lpSemaphoreA ...

  3. (译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0)

    (译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0) 更新:ios4.1现在已经将这个做到SDK了.你可以设置键盘类型为UIKeyboardTypeDecimal ...

  4. win32 api Windows窗口的创建

    windows窗口的创建有以下几个步骤: 1.创建注册窗口类 2.创建窗口句柄 3.显示更新窗口 4.消息循环 1.创建注册窗口类 所谓创建窗口类就是定义一个WNDCLASS类对象,并将该对象进行初始 ...

  5. 【C#】分享基于Win32 API的服务操作类(解决ManagedInstallerClass.InstallHelper不能带参数安装的问题)

    注:这里的服务是指Windows 服务. ------------------201508250915更新------------------ 刚刚得知TransactedInstaller类是支持带 ...

  6. 【.Net】从.NET平台调用Win32 API

    小序        Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制 ...

  7. 【C++】从零开始,只使用FFmpeg,Win32 API,实现一个播放器(一)

    前言 起初只是想做一个直接读取视频文件然后播放字符动画的程序.我的设想很简单,只要有现成的库,帮我把视频文件解析成一帧一帧的原始画面信息,那么我只需要读取里面的每一个像素的RGB数值,计算出亮度,然后 ...

  8. 使用CSS 3创建不规则图形 文字围绕

    前言 CSS 创建复杂图形的技术即将会被广泛支持,并且应用到实际项目中.本篇文章的目的是为大家开启它的冰山一角.我希望这篇文章能让你对不规则图形有一个初步的了解. 现在,我们已经可以使用CSS 3 常 ...

  9. C#调用Win32 api学习总结

    从.NET平台调用Win32 API Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微 ...

随机推荐

  1. GWT工程 —— HostedMode(宿主模式下调试) 所有的运行命令

    Unknown argument: -helpGoogle Web Toolkit 1.7.0HostedMode [-noserver] [-port port-number | "aut ...

  2. 并发编程:c++11 多线程中随机数重复问题

    srand(time(NULL)); 是我们熟悉的c++随机函数,用时间做种子.但由于在多线程环境下若想在子线程中随机出不同的随机数则需随机种子的不同.但time以秒计算,略显不足,故参考这篇文章解决 ...

  3. Linux流量监控工具使用总结 - iftop

    在类Unix系统中可以使用top查看系统资源.进程.内存占用等信息.查看网络状态可以使用netstat.nmap等工具.若要查看实时的网络流量,监控TCP/IP连接等,则可以使用iftop. 一.if ...

  4. codeforces 617E. XOR and Favorite Number 莫队

    题目链接 给n个数, m个询问, 每次询问问你[l, r]区间内有多少对(i, j), 使得a[i]^a[i+1]^......^a[j]结果为k. 维护一个前缀异或值就可以了. 要注意的是 区间[l ...

  5. poj 2155 matrix 二维线段树

    题目链接 区间翻转, 单点查询, 查询操作我真是不太明白...... #include <iostream> #include <vector> #include <cs ...

  6. python自学笔记(一)简单了解python

    脚本解释型语言的内部机制 python先将脚本编译成字节码文件(pyc,pyo) python虚拟机解释并运行字节码文件 编译型语言的内部机制 先将源代码编译成机器码(机器能读懂的代码),生成可执行文 ...

  7. VM Agent 和扩展程序

    VM Agent 和扩展程序 - 第 1 部分  Windows Azure基础结构服务最近宣布了一项新功能VM Agent.VMAgent是一个轻量级进程,用于启动由Microsoft或合作伙伴 ...

  8. HDU 4436 str2int(后缀自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4436 [题目大意] 给出一些字符串,由0~9组成,求出所有不同子串的和. [题解] 将所有字符串添 ...

  9. InnerException 消息是“反序列化对象 属于类型 *** 时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。(注意细节)

    WEB站点在调用我们WCF服务的时候,只要传入的参数过长,就报如下错误: 格式化程序尝试对消息反序列化时引发异常: 尝试对参数 http://tempuri.org/ 进行反序列化时出错: formD ...

  10. 第八届河南省赛D.引水工程(kruthcra+prime)

    D.引水工程 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 118  Solved: 41 [Submit][Status][Web Board] D ...