MFC 中的动态透明几何体

Posted

技术标签:

【中文标题】MFC 中的动态透明几何体【英文标题】:Dynamic transparency geometry in MFC 【发布时间】:2020-09-01 16:37:34 【问题描述】:

我正在为我的 MFC 应用程序创建一个新的 UI 演练,并希望在演练进行时突出显示某些控件。具体来说,我想让整个窗口变暗,除了我要强调的控件。

我尝试使用SetLayeredWindowAttributes 创建一个部分透明的黑色叠加层,但这并不能让我设置一个子区域完全透明。 UpdateLayeredWindow 可以做到这一点,但我并不急于为需要突出显示的每个控件创建 BMP/PNG 文件。

我可以动态创建透明几何吗?例如,我可以从头开始绘制位图透明度然后将其加载到UpdateLayeredWindow吗?

我还需要兼容 Windows 7(尽管它支持 EOL)。

跟进: 尝试绘制透明 GDI+ 区域,但不起作用:


    void ApplicationDlg::Highlight(const CRect& rect)
    
        CRect wndRect;
        GetWindowRect(&wndRect);
        Gdiplus::Rect wndRectPlus(wndRect.left, wndRect.top, wndRect.Width(), wndRect.Height());
        Gdiplus::Region wndRegion(wndRectPlus);
    
        Gdiplus::Rect controlRectPlus(rect.left, rect.top, rect.Width(), rect.Height());
        Gdiplus::Region highlightRegion(controlRectPlus);
    
        wndRegion.Exclude(&highlightRegion);
    
        Gdiplus::SolidBrush transparentBrush(Gdiplus::Color(0, 0, 0, 0));
        Gdiplus::SolidBrush darkenBrush(Gdiplus::Color(128, 0, 0, 0));
    
        CDC* pDCScreen = m_WalkthroughDlg.GetDC();
        HDC hDC = CreateCompatibleDC(pDCScreen->m_hDC);
        HBITMAP hBmp = CreateCompatibleBitmap(hDC, wndRect.Width(), wndRect.Height());
        HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
    
        Gdiplus::Graphics graphics(hDC);
        graphics.FillRegion(&darkenBrush, &wndRegion);
        graphics.FillRegion(&transparentBrush, &highlightRegion);
    
        BLENDFUNCTION blend = 0;
        blend.BlendOp = AC_SRC_OVER;
        blend.SourceConstantAlpha = 255;
        blend.AlphaFormat = AC_SRC_ALPHA;
        SIZE sizeWnd = wndRect.Width(), wndRect.Height();
        POINT ptSrc = 0,0;
        m_WalkthroughDlg.UpdateLayeredWindow(pDCScreen, NULL, &sizeWnd, CDC::FromHandle(hDC), &ptSrc, NULL, &blend, ULW_ALPHA); // TODO cleanup FromHandle refs
        m_WalkthroughDlg.BringWindowToTop();
    
        SelectObject(hDC, hBmpOld);
        DeleteObject(hBmp);
        DeleteDC(hDC);
    

【问题讨论】:

【参考方案1】:

您可以使用CRgn 类动态创建掩码:https://docs.microsoft.com/en-us/cpp/mfc/reference/crgn-class?view=vs-2019

它允许您组合区域(如果您需要突出显示多个区域)。然后您可以使用FillRgn 函数来更新UpdateLayeredWindow 中使用的hdcSrc DC。

或者,如果您的高光是矩形的,您可以在 hdcSrc 上绘制矩形。

【讨论】:

尝试使用 GDI+ Region 类,因为 GDI CRgn 缺乏透明度。但一定是做错了什么,覆盖窗口没有绘制。 非常感谢您能看一下我更新问题的代码。 您对这个最新代码有什么看法?我对 GDI+ 不熟悉,但如果您以某种方式在此处附加您的项目,可以看看。 窗口完全 100% 透明,尽管验证控件 Rect 比窗口 Rect 小得多。很遗憾,我无法分享该项目。 我真的没有时间创建一个虚拟骨架项目来玩这个。但是,您可以回到原来的解决方案,但不要使用一个深色叠加层,而是创建四个围绕您突出显示的控件:顶部一个,底部一个,每侧两个。

以上是关于MFC 中的动态透明几何体的主要内容,如果未能解决你的问题,请参考以下文章

静态控制不透明+MFC

MFC中透明位图原理

mfc中让编辑框透明为啥总显示黑色背景的编辑框啊?

[MFC]透明图展示

MFC中richedit控件设置为透明后出现文字残留现象

如何在 Mfc c++ 中创建透明矩形?