将 HBITMAP 绘制到分层窗口上。怎么了?

2024-01-09

大家好,美好的一天,

我的最终目标是在屏幕上绘制一个包含 Alpha 的 PNG 文件 - 这意味着不是在自己的窗口中,而是在桌面上的某个位置。 将 PNG 加载到 HBITMAP 的部分现在可以工作(以不同的方式进行测试),但我无法做到绘制它,包括阿尔法。

据我所知,最好的方法是使用多层窗户。因此,我做了很多工作来重做几个示例和小教程。

以下代码编译没有问题,并且不会提示任何消息(这意味着永远不会调用 showError("#") 函数)。

然而还有nothing在屏幕上可见:/

抱歉,这么长......希望有人愿意至少快点看一下......

LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);


int main(HINSTANCE hInstance)
{


    WNDCLASSEX WndClass;
    char sClassName[]  = "mainClass";
    WndClass.cbSize     = sizeof(WNDCLASSEX);
    WndClass.style      = NULL;
    WndClass.lpfnWndProc   = WndProc;//WndProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance  = hInstance;
    WndClass.hIcon      = NULL;
    WndClass.hCursor    = LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    WndClass.lpszMenuName  = NULL;
    WndClass.lpszClassName = sClassName;
    WndClass.hIconSm    = LoadIcon(NULL, IDI_APPLICATION);
    if (RegisterClassEx(&WndClass) == 0) showError("-1");





    HWND screen = CreateWindowEx(WS_EX_LAYERED,//WS_EX_LEFT
        "mainClass",
        "UpdateLayeredWind",
        WS_DISABLED | WS_VISIBLE,
        200,200,260,260,
        NULL /*eventuelly, GM window*/,
        NULL,
        hInstance,
        NULL);  


    if (screen == NULL) showError("0");




        HBITMAP img = LoadImageResource("D://ThreadDraw/ThreadDraw-test/ThreadDraw/test.png");
            if (img == NULL) showError("1");






    BLENDFUNCTION blend = {0};

    blend.AlphaFormat = AC_SRC_ALPHA;
    blend.SourceConstantAlpha = 155;

    POINT ptPos = {200,300};
    SIZE sizeWnd = {260,260};
    POINT ptPos2 = {200,300};


    ShowWindow(screen, SW_SHOW);



    while (1)
    {


        PAINTSTRUCT             ps;
        HDC                     hdc;
        BITMAP                  bitmap;
        HDC                     hdcMem;
        HGDIOBJ                 oldBitmap;

        hdc = BeginPaint(screen, &ps);

        hdcMem = CreateCompatibleDC(hdc);
        oldBitmap = SelectObject(hdcMem, img);

        GetObject(img, sizeof(bitmap), &bitmap);


        if (SetLayout(hdc,LAYOUT_RTL) == GDI_ERROR)
            showError("5");



            if (!BitBlt(hdc, 0, 0, 64, 64, hdcMem, 0, 0, SRCCOPY))
                showError("4");



            if (!UpdateLayeredWindow(screen,hdcMem,&ptPos,&sizeWnd,hdc,&ptPos2,RGB(255,255,255),&blend,ULW_ALPHA))//ULW_OPAQUE))
            showError("2");



        EndPaint(screen, &ps);

        SelectObject(hdcMem, oldBitmap);
        DeleteDC(hdcMem);


        Sleep(10);

    }



    return 0;
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 
{
    switch(Message) 
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}

顺便说一句,如果我在 UpdateLayeredWindow 中使用 ULW_OPAQUE 而不是 ULW_ALPHA,则会出现一个大小合适的黑色窗口,因此我认为问题与 PAINTSTRUKT 或 BitBlt 函数相关的程度很小。但是我尝试了很多方法,但没有任何改变。

希望有人能帮忙。预先非常感谢您!


这大多是错误的。你的代码应该:

  • 创建分层窗口CreateWindowEx.
  • 将位图附加到它上面UpdateLayeredWindow.
  • 显示窗口ShowWindow。 Windows 将负责绘制分层窗口,因此您无需处理WM_PAINT或致电BeginPaint.
  • 输入消息循环。

就是这样。

如果您使用的是 Visual Studio,请创建一个新的 Win32 项目,它将为您创建一个带有消息循环的新项目。

Update

这是一个创建透明分层窗口的示例程序。它需要一个函数来加载 PNG 作为透明位图。并且它没有错误检查。

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    LPCTSTR szWindowClass = _T("TransparentClass");

    // Register class
    WNDCLASSEX wcex = {0};

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc    = DefWindowProc;
    wcex.hInstance      = hInstance;
    wcex.lpszClassName  = szWindowClass;

    RegisterClassEx(&wcex);

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, 0, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    int width;
    int height;
    HBITMAP hbmp = LoadPng(L"sample.png", &width, &height);

    HDC hdcScreen = GetDC(0);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    ReleaseDC(0, hdcScreen);
    HBITMAP hbmpold = (HBITMAP)SelectObject(hdc, hbmp);

    POINT dcOffset = {0, 0};
    SIZE size = {width, height};
    BLENDFUNCTION bf;
    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = 255;
    bf.AlphaFormat = AC_SRC_ALPHA;
    UpdateLayeredWindow(hWnd, 0, 0, &size, hdc, &dcOffset, 0, &bf, ULW_ALPHA);
    SelectObject(hdc, hbmpold);
    DeleteDC(hdc);
    DeleteObject(hbmp);

    ShowWindow(hWnd, SW_SHOW);

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

另一个更新

下面是一些将红色、绿色和蓝色值预乘 alpha 的代码。它假设splash_image指向大小为 32bpp ARGB 数据width*height.

LPBYTE bits = (LPBYTE)splash_image;
int size = width * height;
for (int pixel = 0; pixel != size; ++pixel)
{
    bits[0] = bits[0] * bits[3] / 255;
    bits[1] = bits[1] * bits[3] / 255;
    bits[2] = bits[2] * bits[3] / 255;
    bits += 4;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 HBITMAP 绘制到分层窗口上。怎么了? 的相关文章

随机推荐

  • Excel:从整数部分时间转换为分钟时间

    我有一些列 其中日期值采用整数格式 即 14 06736111 1 37 我想把格式变成几分钟 我尝试使用自定义格式的 m 格式 这适用于许多单元格 但其中一些会抛出疯狂的数字 例如 对于时间为 1 37 的单元格 我得到的是 20257
  • 编写一个以 root 身份运行的 perl cgi 应用程序

    我正在编写一个 Perl CGI 应用程序 在某些时候 此 cgi 应用程序需要以 root 身份运行才能访问和写入特定文件 我想知道我到底应该如何执行此操作以及执行此操作时应采取的安全预防措施 你几乎不应该 如果您无法避免它 请创建一小段
  • Python 字符串到 unicode [重复]

    这个问题在这里已经有答案了 可能的重复 如何在 python 中将 ASCII 字符串视为 unicode 并对其中的转义字符进行转义 https stackoverflow com questions 267436 how do i tr
  • 如何使用 Python 将专辑封面嵌入到 MP3 中?

    我一直在使用 mutagen 来读取和写入 MP3 标签 但我希望能够将专辑封面直接嵌入到文件中 以下是如何使用 mutagen 将 example png 作为专辑封面添加到 example mp3 中 from mutagen mp3
  • C++ pow 函数 - 结果无效?

    为什么 dResult 的输出无效 环境 Visual Studio 2008 int tmain int argc TCHAR argv double dN 0 091023604111478473 double dD 0 1277777
  • jQuery - 禁用基于另一个字段选定值的输入字段

    我正在寻找一个可以执行此操作的 jQuery 插件 例如
  • thymeleaf - 将 th:each 与 th:href 结合起来

    我是 Thymeleaf 和 webdev 的新手 我正在尝试将 Thymeleaf 迭代 th each 与 URL 重写 th href 结合起来 a hello a 这会产生以下结果 其中lid 45 a href list l li
  • 在练习 TDD 的同时学习 OpenGL(单元测试)

    我已经开始了一个新的游戏项目 并决定为其学习和使用OpenGL 项目正在Windows和Linux上同时开发 同时 我也对测试驱动开发非常感兴趣 并且正在尽最大努力在任何实际代码之前编写单元测试来引导设计 然而 我认为我缺乏知识可能会绊倒我
  • 模拟两个方块碰撞以计算 PI 时的动画故障

    我在用pygame创建两个方块碰撞的模拟质量比为 100 次方 明确地说 这意味着较大块与较小块的比率可以是100 0 100 1 100 2等等 我在必要时添加了注释和文档字符串 以使逻辑易于理解 import pygame from c
  • 使用ServiceStack的Swagger Plugin,如何实现带有预设值列表的字符串字段

    我正在使用 ServiceStack 的新 Swagger 插件实现 Swagger API 文档 并尝试确定如何使用 容器 数据类型 我需要显示一个字符串字段 其中包含预定值列表和其他作为子对象列表的参数 除非我遗漏了一些东西 否则我相信
  • 在 Ubuntu 11.04 Natty 上进行 Android 调试

    我放置了一个名为 70 android rules 的文件 在 etc udev rules d with 子系统 USB SYSFS 22b8 22b8 模式 0666 但它仍然无法读取我的摩托罗拉 Atrix 是我做错了什么吗 我找到的
  • 将 QByteArray 附加到 QDataStream?

    我必须填充一个QByteArray具有不同的数据 所以我正在使用QDataStream QByteArray buffer QDataStream stream buffer QIODevice WriteOnly qint8 dataHe
  • 非聚集索引在 SQL Server 中的工作原理

    我有一个与数据库理论相关的问题 假设我们有一个包含 3 列的表 PersonID PersonName PersonAge 我们知道 当我们有一个一列的非聚集索引时 SQL Server会按照指定的列对表数据进行排序 并从中构建B 树 当我
  • 在 Python 中使用 readlines 是坏代码吗?

    我因使用 file readlines 的答案而被否决 批评者说使用 readlines 是垃圾代码 以及其他非常粗鲁的语句 有那么糟糕吗 我认为问题在于readlines 将整个文件加载到内存中 理论上 内存可能很大 就内存使用而言 惰性
  • 如何在谷歌浏览器扩展中创建套接字?

    我为谷歌浏览器创建了一个小 hello world 扩展http code google com chrome extensions getstarted html http code google com chrome extension
  • Twitter 的 OAuth 系统如何工作?

    我有一个演示脚本 可以让我使用我的应用程序进行授权并发回我的令牌 但这很令人困惑 我一直在 CURL 或 simpleXML 函数中使用用户名和密码来授权 API 调用 我不明白这与 oauth 有什么关系 我知道我将存储令牌 但是一旦我拥
  • Windows 上的 .NET Core 3.0 忽略 NO_PROXY

    我们正在尝试让代理功能在 Windows 上的 NET Core 3 0 或 3 1 应用程序中工作 我们发现 HTTPS PROXY 和 HTTP PROXY 变 量按预期进行识别和处理 但默认代理似乎不支持 NO PROXY 变 量 这
  • Git 通过 ngrok 隧道转发

    我的本地实例上有一个 git 存储库 我想从家庭网络外部访问它 我应该为此在本地实例上创建 git 服务器和 ssh 服务器吗 另外我应该使用 ngrok 建立隧道的端口是什么 任何意见都将不胜感激 如图所示第193期 https gith
  • Perl 中的反向 DNS 查找

    如何执行反向 DNS 查找 即如何在 Perl 中将 IP 地址解析为其 DNS 主机名 如果您需要更详细的 DNS 信息 请使用Net DNS http search cpan org olaf Net DNS 0 63 lib Net
  • 将 HBITMAP 绘制到分层窗口上。怎么了?

    大家好 美好的一天 我的最终目标是在屏幕上绘制一个包含 Alpha 的 PNG 文件 这意味着不是在自己的窗口中 而是在桌面上的某个位置 将 PNG 加载到 HBITMAP 的部分现在可以工作 以不同的方式进行测试 但我无法做到绘制它 包括