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




