You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

CMFCPropertyGridCtrl文本偏移问题:如何实现VS原生控件点击/编辑时文本不左移的效果?

CMFCPropertyGridCtrl文本偏移问题:如何实现VS原生控件点击/编辑时文本不左移的效果?

您好!我仔细梳理了您遇到的问题,确实挺困扰的——自己在对话框中使用CMFCPropertyGridCtrl时,不管是进入编辑状态,还是设置AllowEdit(false)后点击单元格,文本都会莫名向左偏移,但VS自带的原生属性网格却能保持文本位置纹丝不动。而且您还发现,把VS的属性网格拖到About对话框里也会出现同样的偏移,看来这个问题和控件所处的环境以及CMFC的默认实现逻辑有关。

先帮您梳理下已经做过的尝试,确认问题的共性:

  • 您自定义了CMFCPropertyGridEditProperty子类,重写CreateInPlaceEdit方法限制文本长度,但就算直接用原生的CMFCPropertyGridProperty,偏移问题依然存在;
  • 您通过COleVariant重载方法添加属性,并且给属性设置了AllowEdit(false)
  • 控件是直接拖到资源IDE的CDialog上的,而VS的MDI项目里集成的原生属性网格却能正常工作。

问题根源分析

这个偏移本质上是CMFCPropertyGridCtrl的默认布局逻辑导致的:在对话框环境下,控件绘制文本、创建原地编辑框时,默认的边距或矩形计算和VS原生定制的版本有差异,尤其是非MDI环境下,控件没有继承框架的布局参数,就会出现文本偏移的情况。

针对性解决方案

下面给您几个可行的解决思路,您可以根据自己的场景尝试:

方案1:重写属性的文本绘制逻辑,手动对齐

我们可以自定义CMFCPropertyGridProperty子类,重写OnDrawValue方法,手动修正文本的绘制位置,抵消默认的偏移:

class CMyAlignedProperty : public CMFCPropertyGridProperty
{
public:
    CMyAlignedProperty(const CString& strName, const COleVariant& varValue, LPCTSTR lpszDescr = NULL, DWORD_PTR dwData = 0)
        : CMFCPropertyGridProperty(strName, varValue, lpszDescr, dwData)
    {}

protected:
    virtual void OnDrawValue(CDC* pDC, CRect rect) override
    {
        // 根据自己的需求微调left偏移量,让文本和VS原生效果对齐
        rect.left += 2; 
        // 调用父类方法绘制文本
        CMFCPropertyGridProperty::OnDrawValue(pDC, rect);
    }
};

之后创建属性时,替换成这个自定义子类即可:

auto AddProperty = [&](CMFCPropertyGridProperty* pMeeting, CString strLabel, CString strValue)
{
    if (pMeeting != nullptr)
    {
        COleVariant vString(strValue);
        CMyAlignedProperty* pProperty = new CMyAlignedProperty(strLabel, vString, L"", 0);
        if (pProperty != nullptr)
        {
            pProperty->AllowEdit(false);
            pMeeting->AddSubItem(pProperty);
        }
    }
};

方案2:修正原地编辑控件的位置

如果主要是编辑状态下的文本偏移,可以在自定义属性的CreateInPlaceEdit方法里,手动调整编辑框的位置,让它和原文本位置对齐:

CWnd* CMyAlignedProperty::CreateInPlaceEdit(CRect rectEdit, BOOL& bDefaultFormat) override
{
    CWnd* pEdit = CMFCPropertyGridProperty::CreateInPlaceEdit(rectEdit, bDefaultFormat);
    if (pEdit && pEdit->IsKindOf(RUNTIME_CLASS(CEdit)))
    {
        CRect editRect;
        pEdit->GetWindowRect(editRect);
        GetParent()->ScreenToClient(editRect);
        // 微调left值抵消偏移,和文本绘制逻辑的偏移量保持一致
        editRect.left += 2; 
        pEdit->MoveWindow(editRect);
    }
    return pEdit;
}

方案3:检查控件样式与布局参数

您还可以检查下控件的基础设置,排除样式问题:

  • 右键对话框中的CMFCPropertyGridCtrl,打开属性面板,确认Alignment设置为Left
  • 移除不必要的扩展样式(比如WS_EX_CLIENTEDGE),避免额外的边框挤压文本;
  • 在对话框的OnInitDialog中,手动调用SetPropertyWidth调整属性名称和值的宽度比例,比如m_wndPropGrid.SetPropertyWidth(200),避免值区域过窄导致文本偏移。

备注:内容来源于stack exchange,提问作者Andrew Truckle

火山引擎 最新活动