0

I am stumped so far by this one. Any MFC experts out there?

I had a working C++ MFC application. It's supposed to just bring up a dialog, then do other things.

I can run the EXE but I have a problem when I run it under the debugger...

My application has a bitmap (in "logo.bmp") that it displays in its dialog. I wanted to update what it shows, so, with the IDE not running, I renamed the existing file to "old-logo.bmp", copied a new file in that "res" folder with the name "new-logo.bmp", and made a copy of the new image and called it "logo.bmp".

I was not very careful to make sure that the DPI, width and height were the same as the original file; in retrospect, I observe that the bit depth was the same but the dimensions were different (old: 445x106, new: 445x123).

I brought up the IDE (Visual Studio 2022 Community, version 17.5) and the application compiled without any errors and without any new warnings.

I thought I was OK. I started it up in the debugger and immediately got an exception:

Exception thrown at 0x727C8B96 (comctl32.dll) in mywindow.exe: 0xC0000005: Access violation writing location 0x00BA4114.

I found that the call stack was something like this:

CMyWindowApp::InitInstance() ->
CMyDialog::DoModal() ->
// ... windows stuff ...
CMyDialog::OnInitDialog() -> CPropertySheet::OnInitDialog()

In that last call I get the exception.

Here's something strange: if I hit continue, then the application starts up normally - except it does not show any bitmap at all in the expected region of the dialog.

I tried restoring the "res" folder to its prior set of files: I still get the same exception.

I created a new workspace from prior files and I still get the same error!

I rolled back VS2022 to a prior version (I had the latest which I think was 17.5.5 - I rolled it back to 17.5.0) - still the same error.

I don't get it. The application doesn't even load the image until they call its OnPaint() or ResizeSheet() member functions (neither of which is getting called yet - I've got breakpoints on them).

I'm wondering whether there's some cache for VS2022 that is stored centrally, that I messed up by switching the .bmp file manually (I will never, never do that again!), that I might be able to clobber so it gets rebuilt.

I'm stumped. Any ideas, mates?

Relevant Code

in MyWindow.cpp:

// MyWindow.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"

#include "afxvisualmanager.h"           // to clean up instance allocated by others

#include "MyWindow.h"
#include "MyDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

const COleDateTime CExporterApp::m_StarterCard(2037, 12, 31, 0, 0, 0);

// CMyWindowApp

BEGIN_MESSAGE_MAP(CMyWindowApp, CWinApp)
//  ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CMyWindowApp construction

CMyWindowApp::CMyWindowApp()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
}

CMyWindowApp::~CMyWindowApp()
{
    // To make sure base class destructor is getting called.
}

// The one and only CMyWindowApp object

CMyWindowApp theApp;



BOOL CMyWindowApp::InitInstance()
{
    // InitCommonControlsEx() is required on Windows XP if an application
    // manifest specifies use of ComCtl32.dll version 6 or later to enable
    // visual styles.  Otherwise, any window creation will fail.
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // Set this to include all the common control classes you want to use
    // in your application.
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();

    if (!AfxSocketInit())
    {
        AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
        return FALSE;
    }

    AfxEnableControlContainer();

    CMyDialog sht;

    INT_PTR nResponse = sht.DoModal();

    // stuff we never get to...

}

in MyDialog.cpp:

// MyDialog.cpp : implementation file
//

#include "stdafx.h"
#include "MyWindow.h"
#include "MyDialog.h"
#include "bitmap.h"
// ... some other application-specific includes ...

// CMyDialog

const COLORREF CMyDialog::m_dwBkColor   = RGB(246, 243, 234);

IMPLEMENT_DYNAMIC(CMyDialog, CPropertySheet)

CMyDialog::CMyDialog()
    :CPropertySheet()
{
    EnableStackedTabs(FALSE);

    m_wndbkBrush.CreateSolidBrush(m_dwBkColor);         //  background brush.

    m_Page1.SetBackgroundColor(m_dwBkColor);

    AddPage(&m_Page1);
}

CMyDialog::CMyDialog(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
    :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
}

CMyDialog::CMyDialog(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
    :CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
}

CMyDialog::~CMyDialog()
{
    m_wndbkBrush.DeleteObject();                        //  Unload background brush.
}

void CMyDialog::OnDestroy()
{
    CPropertySheet::OnDestroy();
    m_TabCtrl.UnsubclassWindow();
}

BEGIN_MESSAGE_MAP(CMyDialog, CPropertySheet)
    //{{AFX_MSG_MAP(CMyDialog)
    //}}AFX_MSG_MAP
    //ON_COMMAND(ID_APPLY_NOW, OnApplyNow)
    ON_WM_PAINT()
    ON_WM_CTLCOLOR()
    ON_WM_ERASEBKGND()
    ON_BN_CLICKED(IDOK, OnOK)
    ON_BN_CLICKED(IDCANCEL, OnCancel)
    ON_WM_DESTROY()
    ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange)
    ON_MESSAGE(WM_SETACTIVEPAGE, OnSetActivePage)
    ON_WM_SYSCOMMAND()
END_MESSAGE_MAP()

// CMyDialog message handlers

BOOL CMyDialog::OnInitDialog()
{
    BOOL bResult = CPropertySheet::OnInitDialog();

    // other stuff we don't reach - we hit the exception in the call above...
)

// other stuff
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
rich p
  • 1,005
  • 9
  • 16
  • This could well be an exception that's handled internally, and it may indeed come down to a failure to load the bitmap image. The bitmap file format is surprisingly complex, and few graphics programs get it right. The most reliable way to get a *valid* BMP file is to load it up in MS Paint, and without any changes saving it straight away. Try doing that with your BMP and see if the exception disappears. Make sure to keep the old bitmap file around so that you can later compare the original with the one produced by MS Paint. – IInspectable May 06 '23 at 06:03

1 Answers1

1

xception thrown at 0x727C8B96 (comctl32.dll) in mywindow.exe: 0xC0000005: Access violation writing location 0x00BA4114.

At this time, could you please click Break button and see where that exception was thrown from? Here might be a comment around that piece of code hinting to what went wrong.

The application doesn't even load the image until they call its OnPaint() or ResizeSheet() member functions (neither of which is getting called yet - I've got breakpoints on them).

Are you loading that bitmap explicitly??? Usually it is referenced by your .rc file, in the DIALOG resource. It might be loaded in OnInitDialog().

I'm wondering whether there's some cache for VS2022 that is stored centrally, that I messed up by switching the .bmp file manually (I will never, never do that again!), that I might be able to clobber so it gets rebuilt.

I am not aware of such cache. But you can try to delete the .vs subfolder in your project folder. I doubt that it will help.

Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
  • *"Here might be a comment around that piece of code hinting to what went wrong."* - The exception originated in *comctl32.dll*. The source code used to compile this binary is not commonly available. – IInspectable May 06 '23 at 06:46
  • @VladFeinstein I discovered a file called `App.aps` which looks a little like what I was talking about - see [this page on the .aps file](https://stackoverflow.com/a/50634641/2145105) – rich p May 10 '23 at 01:17
  • @VladFeinstein I think you're right. I didn't understand how the framework works. In retrospect, the bitmap resource file *is* referred to in the .rc file - that explains to me why the bitmap file is being read during `OnInitDialog`. My code (inherited) uses not the file path but the #define'ed ID for the resource (in my case, `IDB_LOGO`). – rich p May 10 '23 at 01:27
  • I'll have to try the `Break` idea - thanks. – rich p May 10 '23 at 01:28
  • This answer has enough useful content - I'm ok with marking it as the answer (ya and there's currently no competition!) :) – rich p May 10 '23 at 01:28
  • @richp There's no requirement to accept a proposed solution. If an answer is accepted, the question falls out of anyone's radar that's filtering on unanswered questions, making it ever more unlikely to receive a comprehensive answer. There's nothing here that could explain how this could result in an attempt to **write** into invalid memory. – IInspectable May 10 '23 at 08:14
  • As for managing resources, that's incredibly simple: You author a .rc script, using a human-readable syntax to describe resources. This script is passed through rc.exe which translates it into a binary format (.res), that is later passed to the linker to include it in the final binary. The connection between C++ source code and binary resources is commonly established through a header file that assigns symbolic names to integer values (resource IDs), that gets ingested into both C++ code and the .rc script. – IInspectable May 10 '23 at 08:17
  • @richp Do you still get that exception after deleting cached files? Could you produce a minimal example with just that bitmap so someone can help you troubleshoot the issue? – Vlad Feinstein May 11 '23 at 23:55
  • @vlad I adopted a workaround (troubleshoot by log messages and don't use the debugger) and moved on. Thanks for your help. – rich p Aug 04 '23 at 18:22