sjwouc 2026-02-02 11:22 采纳率: 0%
浏览 4

DUI绘制透明窗口的异常,如何解决?(语言-c++|操作系统-windows)

CVerticalLayoutUI* pMainRect = static_cast<CVerticalLayoutUI*>(m_PaintManager.FindControl(L"mainRect"));
pMainRect->SetBkColor(0xFF0000FF);

COLORREF colorKey = RGB(255, 0, 0);
::SetWindowLongW(m_hWnd, GWL_EXSTYLE, ::GetWindowLongW(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
::SetLayeredWindowAttributes(m_hWnd, colorKey, 0, LWA_COLORKEY);

/*
一个很奇怪的现象,在使用DUILIB进行界面开发的时候,将窗口上某个LAYOUT组件的背景设置为0xFF0000FF时,此时通过::SetLayeredWindowAttributes设置RGB(255,0,0),对应颜色区域可以正常透明显示,但是没有鼠标穿透效果,考虑到可能是RGB的顺序问题,::SetLayeredWindowAttributes设置改为RGB(0,0,255),此时对应区域显示为蓝色,但是这个区域是可以正常鼠标穿透效果的。继续测试发现,只有当背景和::SetLayeredWindowAttributes的颜色参数中只包含绿色相关的值的时候,对应颜色区域的透明效果和鼠标穿透效果才均为正常的。不清楚这是不是因为DUILIB底层渲染BUG导致的问题
*/
  • 写回答

1条回答 默认 最新

  • 檀越@新空间 2026-02-02 11:23
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你提到的问题是关于 DUILIB(一个基于 C++ 的 UI 框架)在使用透明窗口时出现的异常现象。具体表现为:

    • 当设置 CVerticalLayoutUI 的背景颜色为 0xFF0000FF(即 ARGB 顺序,A=255, R=0, G=0, B=255),并使用 SetLayeredWindowAttributes 设置颜色键为 RGB(255, 0, 0)(红色)时,透明效果正常但鼠标无法穿透
    • 但如果将颜色键改为 RGB(0, 0, 255)(蓝色),透明效果和鼠标穿透都正常

    🔍 原因分析

    1. 颜色格式问题

      • DUILIB 中的颜色通常使用的是 ARGB 格式(Alpha, Red, Green, Blue)。
      • 例如:0xFF0000FF 表示 Alpha = 255(不透明),Red = 0,Green = 0,Blue = 255。
      • SetLayeredWindowAttributes 的参数是 RGB 格式(Red, Green, Blue),因此你可能混淆了两种颜色表示方式。
    2. 颜色键匹配问题

      • SetLayeredWindowAttributes 使用的是 RGB 颜色键,只有当窗口中的像素颜色与该颜色完全匹配时,才会被设为透明。
      • 如果你在 DUILIB 中设置了 0xFF0000FF(即蓝色),但调用 SetLayeredWindowAttributes(m_hWnd, RGB(255, 0, 0), ...),那么颜色键是红色,而窗口中是蓝色,两者不匹配,导致透明无效。
    3. DUILIB 渲染机制

      • DUILIB 可能对某些颜色值进行了特殊处理,特别是与透明相关的渲染逻辑。
      • 你发现只有绿色相关的颜色(如 RGB(0, 255, 0))能正常工作,这可能是 DUILIB 在底层处理颜色时存在兼容性或 Bug。

    ✅ 解决方案

    1. 确保颜色格式正确

    • DUILIB 中设置背景颜色应使用 ARGB 格式,例如:

      pMainRect->SetBkColor(0xFF0000FF); // 正确的 ARGB 格式
      
    • SetLayeredWindowAttributes 的颜色键应为 RGB 格式,例如:

      COLORREF colorKey = RGB(0, 0, 255); // 蓝色
      ::SetLayeredWindowAttributes(m_hWnd, colorKey, 0, LWA_COLORKEY);
      

    重点:确保两个颜色格式一致!


    2. 检查是否正确设置 Layered 窗口属性

    • 确保已经启用 WS_EX_LAYERED 样式:

      ::SetWindowLongW(m_hWnd, GWL_EXSTYLE, ::GetWindowLongW(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
      
    • 然后调用 SetLayeredWindowAttributes

      ::SetLayeredWindowAttributes(m_hWnd, colorKey, 0, LWA_COLORKEY);
      

    3. 确保颜色键与 DUILIB 设置的背景颜色一致

    • 如果你希望蓝色区域透明,DUILIB 中的背景颜色也必须是蓝色:

      pMainRect->SetBkColor(0xFF0000FF); // 0xFF0000FF 是 ARGB 格式,对应蓝
      
    • 同时设置颜色键为 RGB(0, 0, 255)(即蓝色):

      COLORREF colorKey = RGB(0, 0, 255);
      ::SetLayeredWindowAttributes(m_hWnd, colorKey, 0, LWA_COLORKEY);
      

    4. 测试其他颜色是否正常

    • 你可以尝试以下颜色进行测试:

      COLORREF colorKey = RGB(0, 255, 0); // 绿色
      pMainRect->SetBkColor(0xFFFF0000); // 红色(注意 ARGB 格式)
      

      注意: 0xFFFF0000 是红色(ARGB:A=255, R=255, G=0, B=0)


    5. 修改代码示例(修正后的版本)

    // 设置主布局的背景颜色(ARGB 格式)
    CVerticalLayoutUI* pMainRect = static_cast<CVerticalLayoutUI*>(m_PaintManager.FindControl(L"mainRect"));
    pMainRect->SetBkColor(0xFF0000FF); // 蓝色(ARGB)
    
    // 设置窗口为 layered 窗口
    ::SetWindowLongW(m_hWnd, GWL_EXSTYLE, ::GetWindowLongW(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    
    // 设置颜色键为蓝色(RGB)
    COLORREF colorKey = RGB(0, 0, 255);
    ::SetLayeredWindowAttributes(m_hWnd, colorKey, 0, LWA_COLORKEY);
    

    🧠 总结

    | 问题点 | 解决方法 | |--------|----------| | 颜色格式不一致 | 使用 SetBkColor(0xFF0000FF)SetLayeredWindowAttributes(RGB(0, 0, 255)) | | 未启用 WS_EX_LAYERED | 添加 SetWindowLongW(... | WS_EX_LAYERED) | | 颜色键与背景不匹配 | 确保颜色键和背景颜色相同(如均为蓝色) | | DUILIB 兼容性问题 | 尝试其他颜色(如绿色)以确认是否为框架 Bug |


    如果你仍然遇到问题,可以进一步检查 DUILIB 的源码,尤其是 CVerticalLayoutUI 的绘制逻辑,看是否对颜色进行了特殊处理。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月2日