【问题标题】:C++ CButton showing only bitmap iconC++ CButton 仅显示位图图标
【发布时间】:2016-08-31 08:05:40
【问题描述】:

我在 Visual Studio 2012 更新 4 上使用 C++,我有一个对话框,我想在其中显示一个显示位图(.bmp 文件)的按钮,没有边框

我已扩展 CButton 以添加我的工具提示等。

使用资源视图打开对话框.rc 文件,我将按钮属性Bitmap 设置为true。然后,从Dialog的OnInitDialog函数中,我用这段代码设置了位图,标识为IDB_HELP

myButton.SetBitmap((HBITMAP)LoadImage(AfxGetApp()->m_hInstance,
    MAKEINTRESOURCE(IDB_HELP), IMAGE_BITMAP, 16, 16, LR_COLOR));

但它显示了这个,我不想要那个半边框。

我尝试在资源视图中设置为FlatTransparent,但它只会变得更丑。

然后我尝试通过将Owner Draw 设置为true 然后在我的按钮类中重新定义DrawItem 来仅绘制图像,但我也无法完全弄清楚。

有什么简单的方法可以制作一个只有图标的按钮吗?

【问题讨论】:

    标签: c++ visual-studio button bitmap mfc


    【解决方案1】:

    您必须使用所有者绘制按钮或自定义绘制。下面是一个简单的例子,它使用图标而不是位图(为它分配透明背景更容易)

    class CMyButton:public CButton
    {
        void OnPaint()
        {
            CPaintDC dc(this);
            CRect rc = dc.m_ps.rcPaint;
            dc.FillSolidRect(&rc, GetSysColor(COLOR_3DFACE));
            BOOL offset = (BST_PUSHED & GetState()) ? 1 : 0;
            int w = 24;
            int h = 24;
            HICON hicon = (HICON)LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDC_ICON),
                        IMAGE_ICON, w, h, LR_DEFAULTCOLOR);
            DrawIconEx(dc, offset, offset, hicon, w, h, 0, 0, DI_NORMAL);
            DestroyIcon(hicon);
        }
    
        DECLARE_MESSAGE_MAP()
    };
    
    BEGIN_MESSAGE_MAP(CMyButton, CButton)
        ON_WM_PAINT()
    END_MESSAGE_MAP()
    

    用法:

    BOOL CMyDialog::OnInitDialog()
    {
        BOOL res = CDialogEx::OnInitDialog();
        static CMyButton bn;
        bn.SubclassDlgItem(IDC_BUTTON1, this);
        return res;
    }
    

    【讨论】:

    • 当按钮是所有者绘制时,我是否也必须重新定义 DrawItem?我从未重新定义 OnPaint。您能否详细说明一下代码中发生了什么?谢谢。
    • 如果按钮有BS_OWNERDRAW标志,你必须覆盖DrawItem,你不需要OnPaintDrawItem 对于 ListBox 等控件更为重要,因为DrawItem 可以单独绘制每个列表项。 DrawItem 也可以从按钮的所有者那里绘制按钮,它不需要单独的按钮类。 OnPaint 方法更有用,如果您想进行默认绘图并在此基础上进行其他绘图。在这个例子中,这两种方法是相似的。
    • 谢谢。我想删除按钮边框。这幅画是在旧边界上吗?我使用的是 16x16 位图,但我可以使用类似的 .ico
    【解决方案2】:

    如果您使用CMFCButton 并且您习惯使用 ICO 文件而不是 BMP,则您不需要执行自己的图标绘制算法。虽然你可以直接在你的资源文件中说一个按钮是这种类型的,但我不推荐它,因为它在 rc 文件中添加了一段不可维护的十六进制文本。如果你使用多个 rc 文件,每种语言一个,那真是太糟糕了!

    所以我们走吧。在你的表单类中,声明一个成员

    CMFCButton m_button1;
    

    DoDataExchange 应如下所示:

    void MyDialog::DoDataExchange(CDataExchange* pDX)
    {
        __super::DoDataExchange(pDX);
    
        DDX_Control(pDX, IDC_BUTTON1, m_button1);
    
        // ...
    }
    

    那么OnInitDialog 应该是这样的:

    BOOL CMyDialog::OnInitDialog()
    {
        if(!__super::OnInitDialog())
             return FALSE;
    
        m_button1.m_nFlatStyle= CMFCButton::BUTTONSTYLE_NOBORDERS;
        m_button1.SetIcon(IDI_HELP);
    
        return TRUE;
    }
    

    【讨论】:

    • CMFCButton 在 Visual Studio 2012 中是否可用?
    • 是的,我什至在 VS 2010 中也使用过它。甚至 2008 年的功能包中也有它。也许您可能缺少#include 指令。
    • 我正在使用 Visual Studio 2015 并自己使用 CMFCButton。我只是好奇而已。感谢您的确认。
    • 我看到这个类也支持工具提示和自定义光标。很不错。如果我让我的自定义按钮继承自 CMFCButton 而不是 CButton,它会弄乱可视化编辑器吗?
    • @Agostino:不。我可以说我有几个派生自它的类。光标和工具提示也很好用(我只有一种情况,工具提示不能正常工作,但是创建一个派生类并稍微调整一下就可以解决这种情况)
    【解决方案3】:

    使用CMFCbutton,设置边框样式为BUTTONSTYLE_NOBORDERS;

    对图片使用 .ico 而不是 png。

    还有一点需要注意

    1. 加载带有图标的库或exe。
    2. 将加载的 dll/exe 句柄传递给 loadicon。
    3. 使用MFC按钮句柄设置图标,属性设置为无边框。

    示例代码

    m_HResdll = LoadLibrary("C:\\Repos\\iFIX\\SCADABin\\en\\UAAClientConfigurationRes.dll");
    //m_hTrustIcon = LoadIcon(m_HResdll, MAKEINTRESOURCE(IDI_ICON1));
    m_hTrustIcon = (HICON)LoadImage(m_HResdll, MAKEINTRESOURCE(IDI_ICON2),1,18,22, LR_DEFAULTCOLOR);
    unsigned int  err = GetLastError();
    m_btnTrustIcon.SetIcon(m_hTrustIcon);
    this->m_btnTrustIcon.EnableWindow(true);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      相关资源
      最近更新 更多