2
votes

I just installed Visual Studio 2017 community edition. I created a MFC project using the app wizard taking all the defaults. Then I added two edit boxes on the about dialog. Then I mapped two variables of type double to these two edit boxes. Then I added a handler for OK button. Here is relevant code:

class CAboutDlg : public CDialogEx
{
    double m_f;
    afx_msg void OnBnClickedOk();
    double m_f2;
};

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT1, m_f);
    DDX_Text(pDX, IDC_EDIT2, m_f2);
}

void CAboutDlg::OnBnClickedOk()
{
    if (!UpdateData(TRUE))
    {
        return;
    }

    CString s;
    s.Format(_T("m_f = %g"), m_f);
    AfxMessageBox(s);
    s.Format(_T("m_f2 = %g"), m_f2);
    AfxMessageBox(s);

    CDialogEx::OnOK();
}

What I noticed is that in Release mode, if I entered 0.56 in the first edit box and 0 in the second edit box and click OK button. The m_f and m_f2 values are displayed as 0.56 and 56 (instead of 0). Anyone else notice this bug? I cannot believe existence of such a bug.

I also played around with the project general settings such as Windows SDK version, Platform Toolset, use of MFC (static or shared library) and character set (Unicode or nonUnicode). The only setting that I get the values displayed correctly is to use Windows SDK version = 10.0.15063.0, Platform toolset=Visual Studio 2017 v141, use MFC static library.

1
Maybe you are hit by this problemJabberwocky
What does GetWindowText give?Ajay
GetWindowText gives correct value.user1998863

1 Answers

1
votes

I had a similar problem with MFC related to this issue

In order to circumvent this problem, I reimplemented the DDX_Text function calling it DDX_Text2 and using this function instead of DDX_Text for doubles and floats.

The code of AfxTextFloatFormat is copied from the MFC sources, the only difference is that szBuffer is zero filled before the call to GetWindowText.

//
// Reimpelementation of AfxTextFloatFormat because of buggy _sntscanf_s function
//
// See:
// - https://social.msdn.microsoft.com/Forums/vstudio/en-US/4a04b861-8b16-4bb3-8a0d-f4e78b1c2a5a/sntscanfs-doesnt-work-as-expected-in-vs2015?forum=vcgeneral
// - https://connect.microsoft.com/VisualStudio/feedback/details/1773279/bug-in-sntscanf-s
// - https://connect.microsoft.com/VisualStudio/feedback/details/1642606/mfc-cdialog-dodataexchange-cdataexchange-pdx-fails-when-value-is-zero

#include "stdafx.h"
#include "TextFloatFormatPatch.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


// Copied from MFC source code

static void AFXAPI AfxTextFloatFormat(CDataExchange* pDX, int nIDC,
  void* pData, double value, int nSizeGcvt)
{
  ASSERT(pData != NULL);

  pDX->PrepareEditCtrl(nIDC);
  HWND hWndCtrl;
  pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);

  const int TEXT_BUFFER_SIZE = 400;
  TCHAR szBuffer[TEXT_BUFFER_SIZE] = { 0 };          // added: initlialize whole buffer with 0
                                             
  if (pDX->m_bSaveAndValidate)
  {
    ::GetWindowText(hWndCtrl, szBuffer, _countof(szBuffer));

    double d;
    if (_sntscanf_s(szBuffer, _countof(szBuffer), _T("%lf"), &d) != 1)
    {
      AfxMessageBox(AFX_IDP_PARSE_REAL);
      pDX->Fail();            // throws exception
    }
    if (nSizeGcvt == FLT_DIG)
      *((float*)pData) = (float)d;
    else
      *((double*)pData) = d;
  }
  else
  {
    ATL_CRT_ERRORCHECK_SPRINTF(_sntprintf_s(szBuffer, _countof(szBuffer), _countof(szBuffer) - 1, _T("%.*g"), nSizeGcvt, value));
    AfxSetWindowText(hWndCtrl, szBuffer);
  }
}


void AFXAPI DDX_Text2(CDataExchange* pDX, int nIDC, float& value)
{
    AfxTextFloatFormat(pDX, nIDC, &value, value, FLT_DIG); // float
}


void AFXAPI DDX_Text2(CDataExchange* pDX, int nIDC, double& value)
{
    AfxTextFloatFormat(pDX, nIDC, &value, value, DBL_DIG); // double
}