将位图设置为静态控件MFC时出现问题 [英] Problems setting bitmaps to Static Control MFC

查看:77
本文介绍了将位图设置为静态控件MFC时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试基于对话框的GUI,同时尝试对其进行自定义.我已经绘制了一些位图,我想将它们用作dlg中的按钮和徽标.

I'm currently fighting with a dialog based GUI, while trying to customize it. I have drawn some bitmaps which I would like to use as buttons and as logos in the dlg.

我编写了两个成员函数,一个用于将位图设置为CButton s,另一个用于将位图设置为CStatic s.实际上,当按按钮调用它们时,两者都可以正常工作.但是在对话框初始化期间,只有用于设置CButton的成员函数可以正常工作.我的CStatic正在以某种方式被覆盖.

I have written two member functions, one for setting bitmaps to CButtons, and one for setting bitmaps to CStatics. Actually both are working, when calling them on button press. But only the member-function for setting the CButtons works properly during the initialisation of the dialog. My CStatics are getting overwritten somehow.

OnInitDialog()

void CMyDlg::setBitmapAsButton(std::string file, CButton &Button, int xPos, int yPos)
{
    CImage imgFromFile;
    CBitmap bitmap;
    std::wstring wfile(file.begin(), file.end());

    HRESULT ret = imgFromFile.Load(wfile.c_str());
    int width = imgFromFile.GetWidth();
    int height = imgFromFile.GetHeight();
    bitmap.Attach(imgFromFile.Detach());

    Button.Create(_T("My button"), WS_CHILD | WS_VISIBLE | BS_BITMAP,
    CRect(xPos, yPos, xPos + width, yPos + height), this, 1);
    Button.SetBitmap(bitmap);
}

OnInitDialog()中调用时不起作用:

void CVisTrayDlg::setBitmapAsStatic(std::string file, CStatic &Static, int xPos, int yPos)
{
    CImage imgFromFile;
    CBitmap bitmap;
    std::wstring wfile(file.begin(), file.end());

    HRESULT ret = imgFromFile.Load(wfile.c_str());
    int width = imgFromFile.GetWidth();
    int height = imgFromFile.GetHeight();
    bitmap.Attach(imgFromFile.Detach());

    Static.Create(_T("My Static"), WS_CHILD | WS_VISIBLE | SS_BITMAP,
    CRect(xPos, yPos, xPos + width, yPos + height), this);
    Static.SetBitmap(bitmap);
}

CButtonCStatic控件被声明为CMyDlg的成员.

CButton and CStatic controls are declared as member of CMyDlg.

关于如何避免这种行为的任何想法?还是有更好的方法将位图放置在对话框中? (我尝试过CImage::BitBlt(),它也以某种方式被覆盖了.)

Any ideas on how I can avoid this behaviour? Or is there even a better way to place bitmaps in a dialog? (I tried CImage::BitBlt() which got also overwritten somehow.)

推荐答案

问题是所有权之一:SetBitmap的调用返回后,单个位图实例具有2个所有者,CBitmap对象以及CButton/CStatic 1)控件.当CBitmap对象超出范围时,它将破坏单个实例,使控件具有无效位图的句柄.

The issue is one of ownership: After the call to SetBitmap returns, the single bitmap instance has 2 owners, the CBitmap object as well as the CButton/CStatic1) control. When the CBitmap object goes out of scope, it destroys the single instance, leaving the control with a handle to an invalid bitmap.

标准解决方案是通过调用 CImage :: Detach( ),然后将HBITMAP传递给按钮或静态控件:

The standard solution is to explicitly pass ownership, by invoking CImage::Detach() before passing the HBITMAP off to the button or static control:

void CVisTrayDlg::setBitmapAsStatic(std::string file, CStatic &Static, int xPos, int yPos)
{
    CImage bitmap;
    // Convert from ANSI codepage to UTF-16
    CStringW wfile(file.c_str());

    // Error handling needed. Use the SUCCEEDED() or FAILED() macros here:
    HRESULT ret = bitmap.Load(wfile);
    int width = bitmap.GetWidth();
    int height = bitmap.GetHeight();

    Static.Create(_T("My Static"), WS_CHILD | WS_VISIBLE | SS_BITMAP,
                  CRect(xPos, yPos, xPos + width, yPos + height), this);
    // Pass ownership from CImage to CStatic:
    HBITMAP hbmOld = Static.SetBitmap(bitmap.Detach());
    // SetBitmap() passes ownership of the previous image (if set).
    // We are responsible for cleanup:
    if (hbmOld != nullptr ) {
        ::DeleteObject(hbmOld);
    }
}

有关实现的一些注意事项:

A few notes on the implementation:

  • stringwstring的转换失败,除非 file 仅使用ASCII字符.我更改了代码以处理ANSI代码页编码,但这可能不是源编码.您可能需要更改它. 2)
  • 不需要从CImageCBitmap的转换. CImage既有operator HBITMAP()成员又有Detach()成员,这就是我们在这里真正需要的全部内容.
  • SetBitmap的调用将返回先前关联的位图的句柄.我们负责清理.
  • Your conversion from string to wstring fails unless file uses ASCII characters only. I changed the code to deal with ANSI codepage encoding, but that may not be the source encoding. You may have to change this.2)
  • The conversion from CImage to CBitmap is not needed. CImage has both an operator HBITMAP() as well as a Detach() member, and that's all we really need here.
  • The call to SetBitmap returns a handle to the previously associated bitmap. We are responsible for cleanup.


1) 没有书面合同,按钮和静态控件的行为不同.如果它似乎适用于按钮,则仅出于巧合.这不是您应该依靠的任何东西.建议对按钮和静态控件使用相同的解决方案.

2) Windows始终使用UTF-16.通常最好也将UTF-16用作应用程序的内部字符编码.建议使用std::wstring.

这篇关于将位图设置为静态控件MFC时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆