Search code examples
visual-c++mfccmfcpropertygridctrl

Text position in CMFCPropertyGridCtrl


When editing (or clicking with AllowEdit set to false) the text is moved left:

enter image description here

But Visual Studio itself does not suffer from this issue:

enter image description here

The text stays exactly where it is before getting focus.

How do we achieve this?

I should clarify that my CMFCPropertyGridEditProperty is doing this:

CWnd* CMFCPropertyGridEditProperty::CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat)
{
    CEdit *pEdit = (CEdit*)CMFCPropertyGridProperty::CreateInPlaceEdit(rectEdit, bDefaultFormat);
    CString strClassName;

    // Note that CreateInPlaceEdit can also return a CMFCMaskedEdit.
    // But we are only supporting the CEdit.
    GetClassName(pEdit->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH);
    strClassName.ReleaseBuffer();

    if (pEdit != NULL && strClassName == _T("Edit"))
        pEdit->SetLimitText(m_iTextLimit);

    return (CWnd*)pEdit;
}

But it does the same even if I use CMFCPropertyGridProperty.

To answer question 1 in the comments, I use the COLeVariant overload:

auto AddProperty = [&](CMFCPropertyGridProperty* pMeeting, CString strLabel, CString strValue)
    {
        if (pMeeting != nullptr)
        {
            COleVariant vString(strValue);
            //CMFCPropertyGridEditProperty* pProperty = nullptr;
            CMFCPropertyGridProperty* pProperty = nullptr;

            //pProperty = new CMFCPropertyGridEditProperty(strLabel, vString, L"", 0, 50);
            pProperty = new CMFCPropertyGridProperty(strLabel, vString, L"", 0);
            if (pProperty != nullptr)
            {
                pProperty->AllowEdit(false);
                pMeeting->AddSubItem(pProperty);
            }
        }
    };

To answer question 2, the answer is no. This is a property grid control dragged onto a CDialog in the resource IDE.


If I create a Visual Studio style MDI then the built-in prop grid on the right behaves. Click a cell and text does not move.

Add a prop grid to the about dialog and display about window:

about

Get same behaviour as for me in my dialog app.


Solution

  • This is a working solution (for me on my PC) but I would still like more information about this matter.

    I decided to use my CMFCPropertyGridEditProperty class after all with one minor tweak to CreateInPlaceEdit:

    CWnd* CMFCPropertyGridEditProperty::CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat)
    {
        rectEdit.OffsetRect(3, 0);
        CEdit *pEdit = (CEdit*)CMFCPropertyGridProperty::CreateInPlaceEdit(rectEdit, bDefaultFormat);
        CString strClassName;
    
        // Note that CreateInPlaceEdit can also return a CMFCMaskedEdit.
        // But we are only supporting the CEdit.
        GetClassName(pEdit->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH);
        strClassName.ReleaseBuffer();
    
        if (pEdit != nullptr && strClassName == L"Edit")
            pEdit->SetLimitText(m_iTextLimit);
    
        return (CWnd*)pEdit;
    }
    

    I inserted this line to offset the rectangle:

    rectEdit.OffsetRect(3, 0);
    

    Now the text does not shift when I click on a property.


    Things I have learned:

    • Using a property grid inside a CDialog causing the moving of the text.

    Things I am curious about:

    • What is causing this issue?
    • Will offsetting by 3 pixels be correct for all PC configurations?
    • Can this issue be prevented to avoid the need of this workaround?

    After more thinking on the matter I have come up with:

    CWnd* CMFCPropertyGridEditProperty::CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat)
    {
        rectEdit.OffsetRect(::GetSystemMetrics(SM_CXDLGFRAME), 0);
        CEdit *pEdit = (CEdit*)CMFCPropertyGridProperty::CreateInPlaceEdit(rectEdit, bDefaultFormat);
        CString strClassName;
    
        // Note that CreateInPlaceEdit can also return a CMFCMaskedEdit.
        // But we are only supporting the CEdit.
        GetClassName(pEdit->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH);
        strClassName.ReleaseBuffer();
    
        if (pEdit != nullptr && strClassName == L"Edit")
            pEdit->SetLimitText(m_iTextLimit);
    
        return (CWnd*)pEdit;
    }
    

    I have adjust the first line of code to:

    rectEdit.OffsetRect(::GetSystemMetrics(SM_CXDLGFRAME), 0);
    

    I now use ::GetSystemMetrics(SM_CXDLGFRAME). To quote:

    The thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels. SM_CXFIXEDFRAME is the height of the horizontal border, and SM_CYFIXEDFRAME is the width of the vertical border.

    This value is the same as SM_CXDLGFRAME.

    I have reported this issue:

    https://developercommunity.visualstudio.com/t/Using-CMFCPropertyGridCtrl-inside-a-CDia/10565729