Windows半透明窗口开发技巧

2019-09-02

www.qt-ui.com 原创技术文章

在windows平台上从窗口绘图有两种方法:

  1. 第一种响应窗口的WM_PAINT消息,使用窗口DC进行绘制

  2. 第二种是将窗口样式设置为层窗口,即 WS_EX_LAYERED 设置为该样式之后窗口将不会产生任何的WM_PAINT消息,我们通过GetDC等方法在DC上绘图也不会有任何的效果。 我们只能通过UpdateLayeredWindow这个API将我们需要显示的内容提交给窗口。

窗口的内容显示将全部交给用户进行处理,任何的窗口内容改变我们都需要重建位图,并调用该API进行显示内容提交。

默认的非层窗口是无法让窗口半透明显示,因为绘制到最后都会和黑色进行混合填充到DC上。 而层窗口则允许我们可以使用半透明位图显示窗口内容,这样我们就可以实现半透明窗口效果。

具体代码如下:

首先设置窗口样式为层窗口

    LONG_PTR dwExStyle = GetWindowLongPtr((HWND)_handle, GWL_EXSTYLE);
    if ((dwExStyle & WS_EX_LAYERED) != WS_EX_LAYERED)
    {
        SetWindowLongPtr((HWND)_handle, GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED);
    }

首先建立一个内存位图和内存DC

    HBITMAP CreateGDIBitmap(int nWid, int nHei, void ** ppBits)
    {
        BITMAPINFO bmi;
        memset(&bmi, 0, sizeof(bmi));
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth = nWid;
        bmi.bmiHeader.biHeight = -nHei;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biSizeImage = 0;

        HDC hdc = GetDC(NULL);
        LPVOID pBits = NULL;
        HBITMAP hBmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, ppBits, 0, 0);
        ReleaseDC(NULL, hdc);
        return hBmp;
    }
...
    _hBmp = CreateGDIBitmap(_w, _h, &_pBmpBits);
    _hMemDc = CreateCompatibleDC(hdc);
    SelectObject(_hMemDc, _hBmp);

此时我们可以在这个内容DC上做任何我们想要的绘制,由于这张位图是一个32位位图所以带有透明通道。 当我们完成绘制之后我们通过UpdateLayeredWindow就可以提交显示内容到窗口上了。

            HDC hdc = ::GetDC(_hwnd);
            RECT rcClient;
            GetWindowRect(_hwnd, &rcClient);

            POINT ptDest = { rcClient.left, rcClient.top };
            POINT ptSrc = { 0, 0 };
            SIZE szLayered = { rcClient.right - rcClient.left, rcClient.bottom - rcClient.top };
            BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

            ::UpdateLayeredWindow(_hwnd, hdc, &ptDest, &szLayered, _hMemDc, &ptSrc, (COLORREF)0, &bf, ULW_ALPHA);
            ::ReleaseDC(_hwnd, hdc);

需要注意的是:

  1. 层窗口不会影响WM_PAINT消息以外的任何消息,鼠标键盘消息仍然可以使用。
  2. 由于层窗口没有了的WM_PAINT消息,所有窗口上的任何子窗口控件都不会进行显示,如按钮,复选框等等。
  3. 层窗口显示性能要低于非层窗口,因为带上透明通道的处理过程。
  4. 每次窗口内容的改变都需要重新提交UpdateLayeredWindow到窗口上。
  5. 层窗口的显示内容不能超过窗口的原始大小,超出部分窗口会自动进行裁剪。

相关示例代码可登陆www.visual-gear.com上下载开源工程了解。

Qt商用模板项目

支持C++/Python语言,支持Windows\Linux\MacOS系统,支持X86\ARM\MIPS架构

img02

Qt Stock Exchange Sys

View more

Qt股票交易系统

Qt Stock Exchange System

img02

Qt Robot

View more

QtRobot 视频高清机器人控制系统

Qt Robot System

img02

Qt LED Editor

View more

Qt LED 灯效编辑器

Qt LED Editor

img02

Qt IOT Bike

View more

Qt IOT 物联网自行车

Qt IOT Bike

img02

Qt ECG Monitor

View more

Qt嵌入式床旁心电监护仪

Qt ECG Monitor

img02

Qt AutoDashboard

View more

Qt汽车仪表盘系统

Qt Auto Dashboard

img02

Qt DataMonitor

View more

Qt数据监控系统

Qt Data Monitor

img02

Qt Conference

View more

Qt会议终端系统

Qt Conference System

img02

Qt Video Player

View more

Qt视频播放器

Qt Video Player

img02

Qt NetDisk

View more

Qt网盘系统

Qt SkyDrive

img02

Qt IM

View more

Qt即时通讯系统

Qt IM

img02

Qt Cashier

View more

Qt便利店收银系统

Qt CashierSystem

产品文档

0基础赋能高级Qt界面开发

author

Qt控件库 API

author

使用视频教程

author

New Qt Designer使用文档

author

模板项目文档



武汉维仕杰科技有限公司 ( Wuhan VisualGear Co.,ltd )
Copyright © 2018-2024 www.qt-ui.com
鄂ICP备20004169号