MFCPropertyGridCtrl是VC2008引入的控件,是MFC中功能比较抢到的控件之一。这篇博客将详细介绍空间的使用,包括空间的属性、方法、类的继承、点击、编辑、事件等,希望能有帮助。
1. MFCPropertyGridCtrl简介
MFCPropertyGridCtrl的外观如下图所示,主要由三部分组成:表头、属性、描述。对于属性,可以进行分组,每一组可以由多个不同属性组成,可以接受(不局限于)一下几项:颜色、字体、文件、选项等。
2. MFCPropertyGridCtrl的属性
选中控件,F4插卡属性,会弹出左边的属性窗口,可以简单控制控件的一些外观和行为:
| Description Rows Count | 描述部分的行数 |
| Enable Description Area | 是否启用描述功能 |
| Enable Header | 是否启用表头 |
| Notify | 是否允许编辑 |
| Mark Modified Properties | 是否着重显示修改 |
| Use Alphabetic mode | 启用该模式将按字母排列,不分组 |
3. 更改表头宽度
刚创建的空间,Property模式只有5pixel,我们需要添加一段代码来改变Property的宽度,让属性能够显示正常。

HDITEM item; item.cxy = 120; item.mask = HDI_WIDTH; m_properaty.GetHeaderCtrl().SetItem(0, new HDITEM(item));

4. 添加属性和分组
4.1 添加属性
CMFCPropertyGridProperty pProp1 = new CMFCPropertyGridProperty(
_T("天朝适合生存吗?"),
_T("51CTO不谈政治"),
_T("这是描述部分"));
m_propertyGrid.AddProperty(pProp1);

4.2 添加下拉菜单
CMFCPropertyGridProperty* pProp2 = new CMFCPropertyGridProperty(
_T("我是不是帅哥?"),
_T("看选项"),
_T(""));
pProp2->AddOption(_T("是"));
pProp2->AddOption(_T("肯定是"));
pProp2->AddOption(_T("绝对是"));
pProp2->AllowEdit(FALSE); //不允许对选项进行编辑
m_propertyGrid.AddProperty(pProp2);

4.3 添加颜色、文件、字体
CMFCPropertyGridColorProperty * pProp3 = new CMFCPropertyGridColorProperty(
_T("颜色"), RGB(0, 111, 200));
m_propertyGrid.AddProperty(pProp3);
CMFCPropertyGridFileProperty * pProp4 = new CMFCPropertyGridFileProperty(
_T("打开文件"), TRUE, _T("D://test.txt"));
m_propertyGrid.AddProperty(pProp4);
LOGFONT font = {NULL};
CMFCPropertyGridFontProperty * pProp5 = new CMFCPropertyGridFontProperty(
_T("选择字体"), font);
m_propertyGrid.AddProperty(pProp5);

4.4 添加分组
CMFCPropertyGridProperty * group1 = new CMFCPropertyGridProperty(_T("分组1"));
CMFCPropertyGridProperty * group2 = new CMFCPropertyGridProperty(_T("分组2"));
group1->AddSubItem(pProp1);
group1->AddSubItem(pProp2);
group2->AddSubItem(pProp3);
group2->AddSubItem(pProp4);
group2->AddSubItem(pProp5);
m_propertyGrid.AddProperty(group1);
m_propertyGrid.AddProperty(group2);

5. MFCPropertyGridCtrl控件的内建函数
5.1 控件的创建
CMFCPropertyGridCtrl * propertyGrid = new CMFCPropertyGridCtrl; propertyGrid->Create(WS_CHILD | WS_BORDER | WS_VISIBLE, CRect(400, 100, 600, 200), this, WM_USER + 100); propertyGrid->EnableHeaderCtrl(TRUE); //使用表头 propertyGrid->SetVSDotNetLook(); //使用样式 propertyGrid->MarkModifiedProperties(); //着重显示更改过的部分
5.2 清除所有属性
相当与控件复位
m_properaty.RemoveAll();
5.3 删除指定属性
CMFCPropertyGridProperty *pDelete;
int iCount=m_propertyGrid.GetPropertyCount();
if (iCount>0)
{
pDelete=m_propertyGrid.GetProperty(0);
m_propertyGrid.DeleteProperty(pDelete);
}
5.4 依次删除属性
int iCount=m_propertyGrid.GetPropertyCount();
CMFCPropertyGridProperty *pDelete;
for (int i=iCount-1;i>=0;i--)
{
pDelete=m_propertyGrid.GetProperty(i);
m_propertyGrid.DeleteProperty(pDelete);
}
5.5 数据读写
//读:
CMFCPropertyGridProperty *pSelected;
pSelected=m_propertyGrid.GetProperty(2)->GetSubItem(0);
COleVariant var=pSelected->GetValue();
float f1=var.fltVal;
//写:
pSelected->SetValue(var);
5.6 设置为初始值
pProp->ResetOriginalValue();
5.7 读取值、初值、名字、ID
GetData得到的值常常作为属性编号,用来区分控件
CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*)lParam; int i = (int)pProp->GetData(); CString s = pProp->GetName(); COleVariant t = pProp->GetValue(); t = pProp->GetOriginalValue(); CString d; d = t.bstrVal;
5.8 选择设置值
调用对应的Sel和Set方法
6. MFCPropertyGridPropery子类
- CCheckBoxProp
- CPasswordProp
- CSliderProp
- CBoundedNumberPairProp
- CBoundedNumberSubProp
- CIconListProp
- CComboBoxExProp
- COwnerDrawDescrProp
- CTwoButtonsProp
- CCustomDlgProp
7. MFCPropertyGridCtrl获取用户输入值
CMFCPropertyGridProperty *pProperty;//定义一个指向子项的指针 //输入重定向 pProperty=pGroup11->GetSubItem(0) ;//获得子项的指针 // pGroup11在对话框头文件中定义(公有成员变量) const COleVariant &strValue=pProperty->GetValue();//获得子项值 CString strTmp =(CString)strValue; MessageBox( strTmp);
8. MFCPropertyGridCtrl属性改变事件
.h中加入
afx_msg LRESULT OnPropertyChanged(WPARAM, LPARAM);
.cpp中加入ON_REGISTERED_MESSAGE
//注册消息, AFX_WM_PROPERTY_CHANGED:发送ctrl消息到父窗口 BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ON_WM_PAINT() ON_WM_CREATE() ON_REGISTERED_MESSAGE(AFX_WM_PROPERTY_CHANGED, OnPropertyChanged) END_MESSAGE_MAP()
然后添加函数 OnPropertyChanged
如果使用GetData的值作为空间ID来进行判断,则必须要在创建控件时手动SetData来设置ID,否则默认都是0
//用于区分Prop, 使用SetData, GetData方法
//CMFCPropertyGridProperty* pProp1 = new CMFCPropertyGridProperty(strTitle, (_variant_t)bVal, strDesc);
//pProp1->SetData(100);
//int nPropId = pProp1->GetData();
//消息处理, lParam是Property属性项, wParam是ctrl的id
LRESULT CWorkspaceBar::OnPropertyChanged (WPARAM,LPARAM lParam)
{
CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*) lParam;
BOOL bResetMDIChild = FALSE;
switch ((int) pProp->GetData ())
{
case :pProp->GetValue(); break ;
}
}
这里根据情况,还可以这样写:
LRESULT CCMFCPGCtrlDlg::OnPropertyChanged (WPARAM,LPARAM lParam) {
CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*) lParam;
int id = (int) pProp->GetData ();
CString s = pProp->GetName(); //被改变的参数名
COleVariant t = pProp->GetValue(); //改变之后的值
t = pProp->GetOriginalValue(); //改变之前的值
CString d;
d = t.bstrVal; //从COleVariant到CString
return 0;
}
还有就是可能需要做类型检查的情况
LRESULT CMyWnd::OnPropertyChanged( WPARAM wParam,LPARAM lParam )
{
CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*) lParam;
//is the property ctrl
if ( (long)wParam == 2 )
{
}
pProp->SetValue((_variant_t)false);
pProp->Redraw();
int pID = pProp->GetData();
CString str = pProp->GetName();
if ( str == _T("abc") )
{
COleVariant var = pProp->GetValue();
if ( var.boolVal == VARIANT_TRUE )
{
//AfxMessageBox(L"failed!");
//pProp->SetValue(VARIANT_FALSE);
}
}
if (pID == 1)
{
}
if (pID > 1)
{
}
return 0;
}
所有详细都会汇总到这个函数里,所以需要做手工判断
最后再贴一遍官方手册:–官方手册–