代码之家  ›  专栏  ›  技术社区  ›  Pizza Äcke

创建带有内存映像的Windows托盘图标

  •  -1
  • Pizza Äcke  · 技术社区  · 3 年前

    我正在尝试构建一个Flutter插件,让我可以创建Windows系统托盘图标。现在,我可以将图像设置为从 .ico 文件,或者是 default images 窗户也有。然而,我无法使用内存中的图像工作(特别是通过在颤振中绘制某些东西创建的图像)。当然,代码可以编译,在运行时我没有收到任何错误,但托盘图标将始终为空(它占用空间,工具提示也可以工作,但它完全透明/不可见)。

    我使用的代码是 abridged from the AWT source code ,但我也试过 this StackOverflow answer 没用。

    这是我用来创建 HICON

    #pragma warning(disable : 4244)
          // https://cs.github.com/openjdk/jdk/blob/6013d09e82693a1c07cf0bf6daffd95114b3cbfa/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp#L649
        HICON CreateIconFromBytes(HWND hWnd, int width, int height, uint32_t *bytes, TrayIcon *icon)
        {
    
          BITMAPV5HEADER bmhHeader = {0};
          bmhHeader.bV5Size = sizeof(BITMAPV5HEADER);
          bmhHeader.bV5Width = width;
          bmhHeader.bV5Height = -height;
          bmhHeader.bV5Planes = 1;
          bmhHeader.bV5BitCount = 32;
          bmhHeader.bV5Compression = BI_BITFIELDS;
          bmhHeader.bV5RedMask = 0x00FF0000;
          bmhHeader.bV5GreenMask = 0x0000FF00;
          bmhHeader.bV5BlueMask = 0x000000FF;
          bmhHeader.bV5AlphaMask = 0xFF000000;
    
          char *ptrImageData = new char[width * height * 4];
    
          auto dc = GetDC(hWnd);
    
          HBITMAP hbmpBitmap = CreateDIBSection(dc, (BITMAPINFO *)&bmhHeader, DIB_RGB_COLORS, (void **)&ptrImageData, NULL, 0);
    
          uint32_t *srcPtr = bytes;
          char *dstPtr = ptrImageData;
    
          for (int y = 0; y < height; y++)
          {
            for (int x = 0; x < width; x++)
            {
              uint32_t pixel = *srcPtr++;
              uint8_t alpha = (pixel >> 24) & 0xFF;
              uint8_t blue = (pixel >> 16) & 0xFF;
              uint8_t green = (pixel >> 8) & 0xFF;
              uint8_t red = pixel & 0xFF;
              *dstPtr++ = blue;
              *dstPtr++ = green;
              *dstPtr++ = red;
              *dstPtr++ = alpha;
            }
          }
    #pragma warning(default : 4244)
    
          HBITMAP hBitmap = CreateDIBitmap(dc, (BITMAPINFOHEADER *)&bmhHeader, CBM_INIT, ptrImageData, (BITMAPINFO *)&bmhHeader, DIB_RGB_COLORS);
    
          ReleaseDC(hWnd, dc); // 1: success 0: failure
          DeleteObject(hbmpBitmap);
    
          HBITMAP hMask = CreateBitmap(width, height, 1, 1, NULL);
    
          ICONINFO iconInfo;
          memset(&iconInfo, 0, sizeof(ICONINFO));
          iconInfo.hbmMask = hMask;
          iconInfo.hbmColor = hBitmap;
          iconInfo.fIcon = TRUE;
          iconInfo.xHotspot = 0;
          iconInfo.yHotspot = 0;
    
          HICON hIcon = CreateIconIndirect(&iconInfo);
    
          DeleteObject(hBitmap);
          DeleteObject(hMask);
    
          return hIcon;
        }
    

    我有另一个函数,最后调用 Shell_NotifyIcon() 并采取了 希肯 作为论据。这个函数也从处理获取 希肯 从一个 .ico 文件或来自默认Windows资源(前者通过 LoadImage() ,后者通过 LoadIcon() ).

    通过调试和查看内存视图,我知道 bytes 签名正是我所期望的。在Flatter中,为了进行测试,我将画布作为图像保存到磁盘,字节与我在颜色选择器中看到的颜色对齐。

    在这一点上我有点崇拜货物,因为我没有得到错误;我都不知道 什么 这不管用。

    0 回复  |  直到 3 年前