1

Some days ago, I was trying to implement a method that would detect when a value was updated in my Properties Window (CPropertiesWnd) and do some other stuff in a MFC application of mine. Since I was mostly using CMFCPropertyGridProperty instances in order to deal with the information contained in my Properties Window, I've decided to implement the method BOOL CMFCPropertyGridProperty::OnUpdateValue() (virtual), which is called automatically by the framework whenever something in my property grid has changed. So, since I am not able to modify the CMFCPropertyGridProperty class (and other files like afxpropertygridctrl.h), I've created an auxiliary class to do so:

#pragma once


// CMFCPropertyGridPropertyAux

class CMFCPropertyGridPropertyAux : public CMFCPropertyGridProperty
{
public:

    CMFCPropertyGridPropertyAux(const CString& strGroupName, DWORD_PTR dwData=0, BOOL bIsValueList=FALSE);
    CMFCPropertyGridPropertyAux(const CString& strName, const COleVariant& varValue, LPCTSTR lpszDescr = NULL, DWORD_PTR dwData = 0,
        LPCTSTR lpszEditMask = NULL, LPCTSTR lpszEditTemplate = NULL, LPCTSTR lpszValidChars = NULL);
    virtual ~CMFCPropertyGridPropertyAux();
    BOOL OnUpdateValue();
};


// MFCPropertyGridPropertyAux.cpp : implementation file
//

#include "stdafx.h"
#include "MFCProject.h"
#include "MFCPropertyGridPropertyAux.h"


// CMFCPropertyGridPropertyAux

CMFCPropertyGridPropertyAux::CMFCPropertyGridPropertyAux(const CString& strGroupName, DWORD_PTR dwData,BOOL bIsValueList):CMFCPropertyGridProperty(strGroupName, dwData, bIsValueList)
{
}

CMFCPropertyGridPropertyAux::CMFCPropertyGridPropertyAux(const CString& strName, const COleVariant& varValue, LPCTSTR lpszDescr, DWORD_PTR dwData,
        LPCTSTR lpszEditMask, LPCTSTR lpszEditTemplate, LPCTSTR lpszValidChars):CMFCPropertyGridProperty(strName, varValue, lpszDescr, dwData, lpszEditMask, lpszEditTemplate, lpszValidChars)
{
}


CMFCPropertyGridPropertyAux::~CMFCPropertyGridPropertyAux()
{
}


BOOL CMFCPropertyGridPropertyAux::OnUpdateValue() //virtual method implementation
{
    AfxMessageBox(L"Value Changed");
        //do other stuff
    return true;
}

I was able to detect whenever a property was in fact changed, but there were a few bugs (like erasing the whole updated information after the appearance of the MessageBox), which are possibly related to the other methods and attributes from the CMFCPropertyGridProperty that still weren't implemented in this auxiliary class. I was wondering: It will be a whopping job to implement everything that is contained in the CMFCPropertyGridProperty class in my auxiliary class (just like I've done with the constructors). Should there be an strategy regarding OOP that should do the trick? Also, I don't know if my approach is the best one. I mean, is there a simplier way in order to implement the BOOL CMFCPropertyGridProperty::OnUpdateValue() without rewriting codes from another class? Any ideas are welcome!

Mudkip
  • 373
  • 6
  • 27
  • Can you subclass `CMFCPropertyGridProperty` and hack around the bugs? I've done that in the past with Winforms objects. – Robert Harvey Dec 10 '13 at 20:46
  • What do you mean with "subclass"? Sorry, I'm kind of newbie in C++/MFC – Mudkip Dec 10 '13 at 20:54
  • Subclass means that you would write a new class, inheriting from `CMFCPropertyGridProperty` Ah, I'm sorry. I see from your code that you've already done that. – Robert Harvey Dec 10 '13 at 20:56
  • The OOP strategy is called inheritance. You inherit the base class members and override virtual members that you want to specialize, possibly calling into the base class implementation if required. If there are bugs, fix them. And check out [The Definitive C++ Book Guide and List](http://stackoverflow.com/q/388242/1889329) - this is basic C++. – IInspectable Dec 10 '13 at 21:57

2 Answers2

4

The MFC implemented such a "message" already. You don't need to do such things on your own.

There is a registered windows message AFX_WM_PROPERTY_CHANGED that is sent wehen ever a property changes. It is sent to the owner of the grid.

See documentation here in the MSDN.

Also there is already a virtual function CMFCPropertyGridCtrl::OnPropertyChanged that is called when ever a property changes.

Even if you want that your internal OnUpdateValue value should be called. It is easy. Implement you own CMFCPropertyGridCtrl::OnPropertyChanged. Use DYNAMIC_DOWNCAST to get a pointer to your Aux class and just call OnUpdateValue... no big deal.

xMRi
  • 14,982
  • 3
  • 26
  • 59
  • thank you for the advice! ON_REGISTERED_MESSAGE(AFX_WM_PROPERTY_CHANGED, &CPropertiesWnd::OnAfxWmPropertyChanged) have done the job! Here is one fairly nice tutorial: http://social.msdn.microsoft.com/Forums/vstudio/en-US/8922d2a5-eeef-4a86-81a0-b3ffc2d55dd1/cmfcpropertygridctrl-how-to-validate-and-update-data?forum=vcgeneral – Mudkip Dec 13 '13 at 01:41
2

To achieve value change and updated in my Properties Window.

In PropertiesWnd.h file add below codes

afx_msg LRESULT OnPropertyChanged( __in WPARAM wparam, __in LPARAM lparam );

In PropertiesWnd.cpp file add below codes

ON_REGISTERED_MESSAGE(AFX_WM_PROPERTY_CHANGED, OnPropertyChanged)

below code will be call once any property value change

// [in] lparam: pointer to the CMFCPropertyGridProperty

LRESULT CPropertiesWnd::OnPropertyChanged(__in WPARAM wparam,__in LPARAM lParam )

{

// pProp will have all the variables and info of the active or change property
CMFCPropertyGridProperty* pProp = (CMFCPropertyGridProperty*) lParam;
int pID = pProp->GetData();

CString str = pProp->GetName() ; // get the change property name.
COleVariant i = pProp->GetValue();// get the change value.

//below is the code to change COleVariant to other variable type
LPVARIANT pVar = (LPVARIANT)i;
    int x;
    short y;
    double d;
    float f;
    bool status;
    CString str1;
    switch(pVar->vt)
    {
        case VT_I2:    // short
            y = pVar->iVal;
            break;
        case VT_I4:     // int
            x = pVar->lVal;
           break;
        case VT_R4:    // float
            f = pVar->fltVal;
            break;
        case VT_R8:    // double
            d = pVar->dblVal;
            break;
        case VT_INT:
            x = pVar->lVal;
            break;
        case VT_BOOL:
            status = pVar->boolVal;
            break;
        case VT_BSTR:
            str1 = pVar->bstrVal;
            break;
        // etc.
    }

return 0;

}

Im done this using visual studio 2010.

Rick Wong
  • 21
  • 1