2

I am trying to add a bitmap image(.bmp) to background of a main Dialog in visual studio c++. I created a close button which normally works well but after putting background image and when I press close button I get this error:

Debug assertion failed.

File:c:\program files(x86)\microsoft visual studio12.0\vc\atlmfc\include\atlwin.h

Line:3604 Expression:m_hWnd==0

For information on how your program can cause an assertion failure, see the Visual C++ documantation an asserts.

Abort Retry Ignore

For loading bitmap image a class defined. Header:

#if !defined(AFX_PICTUREWINDOW_H__44323373_9E89_11D3_A393_00C0DFC59237__INCLUDED_)
#define AFX_PICTUREWINDOW_H__44323373_9E89_11D3_A393_00C0DFC59237__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <atlbase.h>
#include <atlwin.h>

class CPictureWindow : public CWindowImpl<CPictureWindow>
{
public:
    typedef enum HandlerTypeEnum
    {
        ClientPaint = WM_PAINT,
        BackGroundPaint = WM_ERASEBKGND
    } HandlerTypeEnum;

    CPictureWindow()
    {
        m_nMessageHandler = ClientPaint;
    };
    virtual ~CPictureWindow()
    {
    };

    BEGIN_MSG_MAP(CPictureWindow)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkGnd)
    END_MSG_MAP()

    virtual BOOL Load(LPCTSTR szFileName)
    {
        BOOL bResult = FALSE;
        Close();
        if (szFileName)
        {
            OFSTRUCT of;
            HANDLE hFile = NULL;;
            if ((hFile = (HANDLE)OpenFile((LPCSTR)szFileName, &of, OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR)
            {
                DWORD dwHighWord = NULL, dwSizeLow = GetFileSize(hFile, &dwHighWord);
                DWORD dwFileSize = dwSizeLow;
                HRESULT hResult = NULL;
                if (HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize))
                if (void* pvData = GlobalLock(hGlobal))
                {
                    DWORD dwReadBytes = NULL;
                    BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwReadBytes, NULL);
                    GlobalUnlock(hGlobal);
                    if (bRead)
                    {
                        CComPtr<IStream> spStream;
                        _ASSERTE(dwFileSize == dwReadBytes);
                        if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &spStream)))
                        if (SUCCEEDED(hResult = OleLoadPicture(spStream, 0, FALSE, IID_IPicture, (void**)&m_spPicture)))
                            bResult = TRUE;
                    }
                }
                CloseHandle(hFile);
            }
        }
        Invalidate();
        return bResult;
    }

    HandlerTypeEnum m_nMessageHandler;

protected:

    inline virtual BOOL IsHandlerMessage(UINT uMsg)
    {
        return m_nMessageHandler == (HandlerTypeEnum)uMsg;
    }

    void PutPicture(IPicture* pPicture, HDC hDC, RECT rPicture)
    {
        OLE_XSIZE_HIMETRIC nWidth = NULL; OLE_YSIZE_HIMETRIC nHeight = NULL;
        pPicture->get_Width(&nWidth); pPicture->get_Height(&nHeight);
        pPicture->Render(hDC, rPicture.left, rPicture.top, rPicture.right - rPicture.left, rPicture.bottom - rPicture.top, 0, nHeight, nWidth, -nHeight, NULL);
    };

    LRESULT OnEraseBkGnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        if (IsHandlerMessage(uMsg))
        {
            if (m_spPicture)
            {
                BeginPaint(NULL);
                RECT r; GetClientRect(&r);
                HDC hDC = GetDC();
                HWND hWndChild = GetWindow(GW_CHILD);
                while (::IsWindow(hWndChild))
                {
                    if (::IsWindowVisible(hWndChild))
                    {
                        RECT rChild; ::GetWindowRect(hWndChild, &rChild);
                        ScreenToClient(&rChild);
                        ExcludeClipRect(hDC, rChild.left, rChild.top, rChild.right, rChild.bottom);
                    }
                    hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT);
                }
                PutPicture(m_spPicture, hDC, r);
                ReleaseDC(hDC);
                EndPaint(NULL);
                return TRUE;
            }
        }
        bHandled = FALSE;
        return FALSE;
    };

    LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        if (IsHandlerMessage(uMsg))
        {
            if (m_spPicture)
            {
                BeginPaint(NULL);
                RECT r; GetClientRect(&r);
                HDC hDC = GetDC();
                PutPicture(m_spPicture, hDC, r);
                ReleaseDC(hDC);
                EndPaint(NULL);
            }
        }
        bHandled = FALSE;
        return NULL;
    };

    void Close()
    {
        m_spPicture = NULL;
    }

    //Attributes
    CComPtr<IPicture> m_spPicture;
};

#endif 

and in DoDataExchange of .Cpp file:

objPictureWindow.SubclassWindow(m_hWnd);
    objPictureWindow.m_nMessageHandler = CPictureWindow::BackGroundPaint;
    objPictureWindow.Load((LPCTSTR)"D:\\bitmap2.bmp");

Size of this bitmap is about 2Mb. However I resized it to 500Kb but again I had the same error after pressing the close button to close this dialog.

By following this error compiler shows this line to me:

template <class TBase, class TWinTraits>
BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(_In_ HWND hWnd)
{
    ATLASSUME(m_hWnd == NULL);
    ATLASSERT(::IsWindow(hWnd));
J2015
  • 320
  • 4
  • 24
  • How is `m_hWnd` (from the 2nd code snippet) initialized? – CristiFati Jun 11 '15 at 16:13
  • I did not initialize this handler!! – J2015 Jun 11 '15 at 16:26
  • `objPictureWindow.Load((LPCTSTR)"D:\\bitmap2.bmp");` No. This does not turn an ANSI string into one that isn't. Get rid of the cast and actually fix whatever compiler error comes up by using the proper string type(s). If your code is compiled as Unicode, that string is going to be garbage, and that cast is not going to help you. – PaulMcKenzie Jun 11 '15 at 16:37
  • The same thing here: `(LPCSTR)szFileName` **Stop the casting**. Remove all of the castings of your strings and fix the errors legitimately by using the proper string types, or changing the function call to match your string type, or actually **convert** the string. Casting does not convert -- it only fools the compiler into thinking the string is the correct type when it isn't. All you did when you casted is tell the compiler "shut up, I don't want to listen to you". Well you better listen, as these types of errors many times result in erratic behavior. – PaulMcKenzie Jun 11 '15 at 16:45
  • @PaulMcKenzie I tried to put different sting types like **WCHAR**, **LPOLESTR**, **LPSTR** and ... but all of them are effectless and this error still appears.Moreover I'm confused you said If your code is compiled as Unicode, that string is going to be garbage while this code inserts this bitmap image on background after running!! – J2015 Jun 12 '15 at 12:43
  • @Jessica When you build an application, the default character set type is very important, and you should know what it is. Do not use different string types -- know the string type that you should be using. If you're casting, then the type you are using is wrong. If you're using Visual Studio as an IDE, there is a setting in your project for "Character Set". It will be either `MBCS` or `Unicode`. If it is `Unicode`, then the type of strings the Windows API functions expect are wide character strings. If it is MBCS, then the string type expected are narrow or ANSI strings. – PaulMcKenzie Jun 12 '15 at 13:21
  • This also means that the string literals you use (the strings in quotes) are either wide string literals or not. A wide string literal is prefaced by `L`. The reason why you should not be casting is that if you send a narrow string to a function that is expecting a wide string, it will not assume what you're sending are 8 bit characters, but 16-bit characters. Casting does **not** turn an 8 bit character string into a 16-bit character string. Again, remove **all** casts from your string, recompile. If you get **any** compiler error, stop and fix the code by using the proper type. – PaulMcKenzie Jun 12 '15 at 13:25
  • @Jessica Refer to this: http://stackoverflow.com/questions/27049481/problems-with-cfiledialog-instantiation/27049624#27049624 and this http://stackoverflow.com/questions/29498608/windows-api-and-string-concatenation/29498890#29498890 – PaulMcKenzie Jun 12 '15 at 13:29
  • @PaulMcKenzie I am using Visual Studio as an IDE my project "Character Set" is "Use Multi-Byte Character Set" and as I got from your explanation LPCSTR can be used since it is a 32-bit pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters. however now I have problem with casting concept here! – J2015 Jun 12 '15 at 15:55
  • 1
    I highly suggest you change to `Unicode` character set. Once you do that, then use either `TCHAR` or wide strings for all your string data that you intend to send or receive from the Windows functions. Only use `char` based string for your own functions and other code that actually takes `char` arrays and pointers. – PaulMcKenzie Jun 12 '15 at 16:18
  • @PaulMcKenzie Firstly I tried to change LPCSTR type to another type and then I removed these wide string literals but again nothing happened. Then I changed Charecter Set to Unicode but I received a bunch of errors which were related to the **SetWindowText** function and their arguments which are in my main project. Also I used **SetWindowTextW** with L"..." in its arguments this syntax error solved but sttill there are some errors in sprintf_s because of incompatibility of its arguments which SetWindowTextW is one of them!! – J2015 Jun 15 '15 at 08:41
  • @Jessica Please go to MSDN here and use the correct form of sprintf_s: https://msdn.microsoft.com/en-us/library/ce3zzk1k.aspx You see there are variations. Every MS runtime function that takes strings has variations that take wide strings. Your main project should be using all wide strings if you intend to use those strings with the Windows API and the MS string routines. All I can tell you is that casting strings to satisfy the compiler is a non-starter, so it's unfortunate this is what you originally coded, but those are the consequences. – PaulMcKenzie Jun 15 '15 at 09:21

0 Answers0