Chinaunix首页 | 论坛 | 博客
  • 博客访问: 185379
  • 博文数量: 90
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2017-08-23 16:48
文章分类

全部博文(90)

文章存档

2015年(1)

2011年(21)

2010年(59)

2009年(9)

我的朋友

分类: C/C++

2010-07-14 10:33:30

一客户要求定制一对话框,显示几个数据,本以为几分钟就能搞定的事,却突然被一要求砸晕:客户要求其中一编辑框显示百分比,而且小数点必须是两位,也就是是说,如果是百分比为0的话,就要显示0.00。虽然情急之下用CString来关联编辑框,加上Format成员函数和scanf函数,也很快搞定。但也惊出一身冷汗,发现原来最简单的东西下面还有不简单啊。
后仔细查阅资料,并翻看MFC源码,发现确实没有简单的方法来实现。用CString作为变量,再定义一double变量,再转换,这种方法也颇为可行,但是有一点,要自己添加判断字符串是否是double类型数字,即简单的验证数据,有点麻烦。
查查源码,可以发现MFC的DDX_Text(CDataExchange* pDX, int nIDC, double& value)和其它的几个DDX_Text的内部实现不同,甚至于实现的文件也不同,分别在dlgfloat.cpp和dlgdata.cpp中
void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, double& value)
{
    AfxTextFloatFormat(pDX, nIDC, &value, value, DBL_DIG);
}

void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, DWORD& value)
{
    if (pDX->m_bSaveAndValidate)
        _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%lu"), AFX_IDP_PARSE_UINT, &value);
    else
        _Afx_DDX_TextWithFormat(pDX, nIDC, _T("%lu"), AFX_IDP_PARSE_UINT, value);
}
追踪AfxTextFloatFormat的实现如下:
void AFXAPI AfxTextFloatFormat(CDataExchange* pDX, int nIDC,
    void* pData, double value, int nSizeGcvt)
{
    ASSERT(pData != NULL);
    HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
    TCHAR szBuffer[32];
    if (pDX->m_bSaveAndValidate)
    {
        ::GetWindowText(hWndCtrl, szBuffer, _countof(szBuffer));
        double d;
        if (!_AfxSimpleFloatParse(szBuffer, d))
        {
            AfxMessageBox(AFX_IDP_PARSE_REAL);
            pDX->Fail();            // throws exception
        }
        if (nSizeGcvt == FLT_DIG)
            *((float*)pData) = (float)d;
        else
            *((double*)pData) = d;
    }
    else
    {
        _stprintf(szBuffer, _T("%.*g"), nSizeGcvt, value);
        AfxSetWindowText(hWndCtrl, szBuffer);
    }
}
可以发现其实我们只要改动
_stprintf(szBuffer, _T("%.*g"), nSizeGcvt, value);       
AfxSetWindowText(hWndCtrl, szBuffer);
这部分代码就可以实现我们的目的了。
1.新建一测试工程tddx
2.在对话框模板中添加一编辑框,关联双精度变量double m_fPercent
3.添加自定义的数据交换函数
extern void AFXAPI AfxTextFloatFormat(CDataExchange* pDX, int nIDC,
    void* pData, double value, int nSizeGcvt);
void CTddxDlg::DDXEx_Text(CDataExchange *pDX, int nIDC, double &value, LPCTSTR lpszFormat)
{
    if(pDX->m_bSaveAndValidate){
        AfxTextFloatFormat(pDX, nIDC, &value, value, DBL_DIG);
    }
    else{
        HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
        CString str;
        str.Format(lpszFormat, value);
//        _stprintf(szBuffer, _T("%.*g"), nSizeGcvt, value);
        ::SetWindowText(hWndCtrl, str);
    }
}
这里AfxTextFloatFormat被定义为全局函数,所以我们只需要导入即可。
4.修改DoDataExchange如下:
void CTddxDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CTddxDlg)
//    DDX_Text(pDX, IDC_EDIT_PERCENT, m_fPercent);
    //}}AFX_DATA_MAP
    DDXEx_Text(pDX, IDC_EDIT_PERCENT, m_fPercent, "%0.2f");
}
运行即可发现已经实现目标如果在编辑框中输入非数字,会发现有错误提示。
差点忘了,由于DBL_DIG的存在,需要#include
本文来自CSDN博客,转载请标明出处:
阅读(2648) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~