Visual C ++ 2017 bug - MFC DDX_Text for double

时间:2017-05-19 00:44:47

标签: visual-c++ mfc

我刚刚安装了Visual Studio 2017社区版。我使用应用程序向导创建了一个MFC项目,采用了所有默认值。然后我在about对话框中添加了两个编辑框。然后我将两个double类型的变量映射到这两个编辑框。然后我为OK按钮添加了一个处理程序。以下是相关代码:

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();
}

我注意到在发布模式下,如果我在第一个编辑框中输入0.56,在第二个编辑框中输入0并单击确定按钮。 m_f和m_f2值显示为0.56和56(而不是0)。有人注意到这个bug吗?我无法相信存在这样的错误。

我还参与了项目常规设置,例如Windows SDK版本,Platform Toolset,MFC(静态或共享库)和字符集(Unicode或nonUnicode)的使用。我正确显示值的唯一设置是使用Windows SDK版本= 10.0.15063.0,平台工具集= Visual Studio 2017 v141,使用MFC静态库。

1 个答案:

答案 0 :(得分:1)

我遇到了与this issue

相关的MFC类似问题

为了避免这个问题,我重新实现了DDX_Text函数调用它DDX_Text2并使用此函数而不是DDX_Text来实现双精度和浮点数。

从MFC来源复制AfxTextFloatFormat的代码,唯一的区别是在调用szBuffer之前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);
}


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