How can make CMFCPropertyGridProperty support 64bit int?

Viewed 152

I am writing a property editor with MFC CMFCPropertyGridProperty. It seems it does not support int64_t/uint64_t. When I push int64_t/uint64_t value, the UI displays *** error ***.

int64_t val = 123456;
COleVariant varValue = (_variant_t)val;

CMFCPropertyGridProperty* pGrid = new CMFCPropertyGridProperty("Int64Val", varValue);
_pParentGrid->AddSubItem(pGrid);

The varValue is correct, its vt is VT_I8. The value is correct too. Has anyone ever done it successfully?

2 Answers

@dxiv Yes, I have checked CString CMFCPropertyGridProperty::FormatProperty() code (atlmfc\src\mfc\afxpropertygridctrl.cpp), it does not support VT_I8/VT_UI8. So I derived my own one, now the display is good. But can not edit it. After reading more code in afxpropertygridctrl.cpp, I found more work is needed to do to make CMFCPropertyGridPropertyInteger64 work fine.

virtual CString FormatProperty() override
{
    ASSERT_VALID(this);
    ASSERT_VALID(m_pWndList);

    COleVariant& var = m_varValue;
    ASSERT(var.vt == VT_I8 || var.vt == VT_UI8);

    CString strVal;

    switch (var.vt)
    {
    case VT_I8:
        strVal.Format(_T("%I64d"), var.llVal);
        break;

    case VT_UI8:
        strVal.Format(_T("%I64u"), var.ullVal);
        break;
    }

    return strVal;
}

To make it function well, I made a whole one. Share the code below(used some cheat to make code simple).

class CMFCPropertyGridInt64Property : public CMFCPropertyGridProperty
{
public:
    CMFCPropertyGridInt64Property(const CString& strName, const COleVariant& varValue, LPCTSTR lpszDescr = NULL, DWORD_PTR dwData = 0,
        LPCTSTR lpszEditMask = NULL, LPCTSTR lpszEditTemplate = NULL, LPCTSTR lpszValidChars = NULL);

    virtual ~CMFCPropertyGridInt64Property();

public:
    void EnableSpinControl(BOOL bEnable, int nMin, int nMax);
    virtual CWnd* CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat);

    virtual BOOL OnSetCursor() const;
    virtual BOOL PushChar(UINT nChar);
    virtual CString FormatProperty();

protected:

    virtual BOOL TextToVar(const CString& strText);
    virtual BOOL IsValueChanged() const;
    virtual HBRUSH OnCtlColor(CDC* pDC, UINT nCtlColor);
};

#include "stdafx.h"
#include "MFCPropertyGrid.h"


CMFCPropertyGridInt64Property::CMFCPropertyGridInt64Property(const CString& strName, const COleVariant& varValue
    , LPCTSTR lpszDescr /*= NULL*/, DWORD_PTR dwData /*= 0*/, LPCTSTR lpszEditMask /*= NULL*/
    , LPCTSTR lpszEditTemplate /*= NULL*/, LPCTSTR lpszValidChars /*= NULL*/)
    : CMFCPropertyGridProperty(strName, varValue, lpszDescr, dwData, lpszEditMask, lpszEditTemplate, lpszValidChars)
{

}

CMFCPropertyGridInt64Property::~CMFCPropertyGridInt64Property()
{

}

void CMFCPropertyGridInt64Property::EnableSpinControl(BOOL bEnable, int nMin, int nMax)
{

    VARTYPE backVT = m_varValue.vt;
    m_varValue.vt = VT_I4;

    CMFCPropertyGridProperty::EnableSpinControl(bEnable, nMin, nMax);

    m_varValue.vt = backVT;

    return;
}

BOOL CMFCPropertyGridInt64Property::TextToVar(const CString& strText)
{
    CString strVal = strText;

    switch (m_varValue.vt)
    {
    case VT_I8:
#ifdef _UNICODE
        m_varValue.llVal = wcstoll(strText, NULL, 10);
#else
        m_varValue.llVal = _strtoi64(strText, NULL, 10);
#endif
        return TRUE;

    case VT_UI8:
#ifdef _UNICODE
        m_varValue.ullVal = wcstoull(strText, NULL, 10);
#else
        m_varValue.ullVal = _strtoui64(strText, NULL, 10);
#endif
        return TRUE;
    }

    return FALSE;
}

BOOL CMFCPropertyGridInt64Property::IsValueChanged() const
{
    ASSERT_VALID(this);

    if (m_varValueOrig.vt != m_varValue.vt)
    {
        return FALSE;
    }

    const COleVariant& var = m_varValue;
    const COleVariant& var1 = m_varValueOrig;

    switch (m_varValue.vt)
    {
    case VT_I8:
        return var.llVal != var1.llVal;

    case VT_UI8:
        return var.ullVal != var1.ullVal;
    }

    return FALSE;
}

CWnd* CMFCPropertyGridInt64Property::CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat)
{
    VARTYPE backVT = m_varValue.vt;
    m_varValue.vt = VT_I4;

    CWnd* pWnd = CMFCPropertyGridProperty::CreateInPlaceEdit(rectEdit, bDefaultFormat);

    m_varValue.vt = backVT;

    return pWnd;
}

BOOL CMFCPropertyGridInt64Property::OnSetCursor() const
{
    if (m_bInPlaceEdit)
    {
        return FALSE;
    }

    if (m_bIsValueList)
    {
        SetCursor(AfxGetApp()->LoadStandardCursor(IDC_IBEAM));
        return TRUE;
    }

    switch (m_varValue.vt)
    {
    case VT_I8:
    case VT_UI8:
        SetCursor(AfxGetApp()->LoadStandardCursor(IDC_IBEAM));
        return TRUE;
    }

    return FALSE;
}

BOOL CMFCPropertyGridInt64Property::PushChar(UINT nChar)
{
    VARTYPE backVT = m_varValue.vt;
    m_varValue.vt = VT_I4;

    BOOL b = CMFCPropertyGridProperty::PushChar(nChar);

    m_varValue.vt = backVT;

    return b;
}


HBRUSH CMFCPropertyGridInt64Property::OnCtlColor(CDC* pDC, UINT nCtlColor)
{
    VARTYPE backVT = m_varValue.vt;
    m_varValue.vt = VT_I4;

    HBRUSH b = CMFCPropertyGridProperty::OnCtlColor(pDC, nCtlColor);

    m_varValue.vt = backVT;

    return b;
}

CString CMFCPropertyGridInt64Property::FormatProperty()
{
    ASSERT_VALID(this);
    ASSERT_VALID(m_pWndList);

    COleVariant& var = m_varValue;
    ASSERT(var.vt == VT_I8 || var.vt == VT_UI8);

    CString strVal;

    switch (var.vt)
    {
    case VT_I8:
        strVal.Format(_T("%I64d"), var.llVal);
        break;

    case VT_UI8:
        strVal.Format(_T("%I64u"), var.ullVal);
        break;
    }

    return strVal;
}

Related