【问题标题】:MFC Image Button with transparency具有透明度的 MFC 图像按钮
【发布时间】:2012-03-06 18:57:08
【问题描述】:

我正在更新一个带有许多按钮的 MFC 对话框。

目前,对话框有一个图片控件覆盖整个对话框,提供图案背景。最重要的是,每个按钮都是一个 CBitmapButton,使用精心生成的(不透明)图像来匹配它们所覆盖的背景区域。

如果图像可以创建为大部分透明的,那么背景会自动显示出来,这显然会容易得多。但是,在这种情况下,我无法弄清楚如何让 MFC 正确渲染透明图像。

我知道我可能想要一个与 CBitmapButton 不同的类,或者需要编写一个自定义子类;很好,但我不知道从哪里开始。支持带有 alpha 通道的 32 位 BMP 或 PNG 会很好,但我会选择“指定的颜色应该是透明的”类型。

【问题讨论】:

    标签: c++ button mfc transparency


    【解决方案1】:

    这可能不是最好的方法,但我要做的是创建一个自定义 CButton 派生类(假设您实际上正在使用其余的 CButton 功能),然后重写 DrawItem 函数以放置你的自定义绘制代码。

    对于图像本身,我将使用 Bitmap GDI+ 对象(这将允许您加载带有 alpha 通道的 BMP 或 PNG),然后使用常规 DrawImage 函数来绘制位图。

    如果您要将 PNG 放入资源文件中,则需要将它们作为“PNG”类型放入。确保在查看资源文件代码时,该条目看起来像

    IDB_PNG1 PNG "C:\temp\test.png"

    并且不要尝试将其视为 BITMAP 资源,否则您将无法加载它们。

    编辑

    将我的回复放在这里,以便我可以发布代码。是的,我的意思是从 CButton 派生一个自定义类,然后添加一个 Gdiplus::Bitmap 成员变量。这大致是您需要做的事情才能让它工作,虽然我还没有检查代码是否真正编译和工作,但希望你能明白这一点。这不是最有效的方法,但如果您之前没有做过很多自定义绘图,那么它确实具有简单的优势!

    void CMyButton::LoadImage(const int resourceID)
    {
        m_pBitmap = Gdiplus::Bitmap::FromResource(NULL, MAKEINTRESOURCE(resourceID));
        ASSERT(m_pBitmap);
    }
    
    void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
        ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
    
        CRect rcClient;
        GetClientRect(&rcClient);
        if (lpDrawItemStruct->itemState & ODS_SELECTED)
        {
            // If you want to do anything special when the button is pressed, do it here
            // Maybe offset the rect to give the impression of the button being pressed?
            rcClient.OffsetRect(1,1);
        }
        Graphics gr(lpDrawItemStruct->hDC);
        gr.DrawImage(m_pBitmap, rcClient.left, rcClient.top);
    }
    

    【讨论】:

    • 我对在 MFC 中绘图还很陌生。您是否建议我将 CButton 子类化为具有 Bitmap 类型的成员,然后覆盖子类的 DrawItem 以在成员 Bitmap 上调用 DrawImage?覆盖的DrawItem 需要做什么?我在 MSDN 文档中找不到合适的 DrawImage 方法。你能发布一些代码sn-ps吗?
    • FromResource 返回 NULL。如何确定加载失败的原因?
    • 尝试使用 GetModuleHandle(NULL) 而不是 NULL 作为 Gdiplus::Bitmap::FromResource 函数的第一个参数。
    • 没有更好的。如果我尝试使用 PNG 资源而不是 BITMAP,我也会遇到同样的问题;或使用FromFile。有没有办法问代码是什么原因?
    • 抱歉,我刚刚记得你需要初始化 GDI+(你做的那些事情之一然后忘记了)。你需要“GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);”在您的应用程序启动中,然后“GdiplusShutdown(m_gdiplusToken);”当它关闭时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 2020-06-11
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 2021-09-18
    相关资源
    最近更新 更多