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; }
所有详细都会汇总到这个函数里,所以需要做手工判断
最后再贴一遍官方手册:–官方手册–