GetPEM(), PEMStatus()
These two functions were added in version 3.0b. They let you ask questions about the properties, events and methods of objects and classes. Although these two are extremely useful, they have some problems.
Usage |
uValue = GetPEM( oObject | cClass, cPEMName ) uResult = PEMStatus( oObject | cClass, cPEMName | cObjectName, nAttribute ) |
Parameter |
Value |
Meaning |
oObject |
Object |
The object about which PEM information is to be returned. |
cClass |
Character |
The name of a class about which PEM information is to be returned. |
cPEMName |
Character |
The name of the property, event or method about which information is to be returned. |
cObjectName |
Character |
Name of a contained object of oObject or cClass. |
nAttribute |
0 |
Has the property changed? |
1 |
Is the property read-only? |
|
2 |
Is the PEM protected? |
|
3 |
Which is this: property, event, method or (contained) object? |
|
4 |
Is the PEM user-defined? |
|
5 |
Is there such a PEM? |
|
6 |
Is this PEM inherited from a class higher in the class hierarchy? |
|
uValue |
Character, Numeric, Currency, Date, DateTime, Logical |
The current value of the specified PEM. If cPEMName refers to an event or method, uValue receives (as a character string) the code contained in the event or method. |
uResult |
Logical or Character |
The value of the specified attribute for the specified PEM. |
Both functions have a nasty bug when working with classes at runtime. In order to use the function, the class definition has to be in memory. To get it there, you have to instantiate the class at least once. You can destroy the instance immediately, but you have to have done it. Since we understand why it works this way, we might be inclined to lay this one at design's door, if only it were documented. |
Passing 0 for PEMStatus()'s third parameter is supposed to work only for properties. In fact, you can do it with methods of visual classes (though not code classes), too, but the results aren't quite what you'd expect. If the method has code at any level in the class hierarchy, PEMStatus() returns .T. While this is somewhat useful (and more than the docs would lead you to expect), it doesn't help you figure out if you've overridden a method in this particular subclass or instance. Use AMembers() to do that. |
And yet another bug, this one more serious than either of the others. In some situations, if an object calls PEMStatus() more than twice in the same line of code, the object can't be released. We've been unable to nail down exactly the combination of circumstances that causes this one. For sure, using PEMStatus(_SCREEN.ActiveForm,�,5) three or more times in a line is one way to do it. In general, if you have an object that won't go away, check for multiple uses of PEMStatus(). It appears that this bug was fixed in one of the VFP 6 service packs. We're reluctant to commit absolutely on the subject, since the bug was so hard to pin down, but our test form that demonstrates the problem in VFP 5 and the original release of VFP 6 works properly in VFP 6 SP5 and VFP 7. |
Example |
oForm = CreateObject("FORM") oForm.Left = 20 ? GetPEM(oForm, "Left") && Returns 20 ? PEMStatus(oForm, "Left", 0) && Returns .T. ? PEMStatus(oForm, "BaseClass", 1) && Returns .T. ? PEMStatus(oForm, "Init", 3) && Returns "Event" SET CLASSLIB TO CoolStuf && From the Downloads oSpin = CreateObject("DateSpin") && To work around bug RELEASE oSpin ? GetPEM("DateSpin", "BackStyle") && Returns 0 ? PEMStatus("DateSpin", "nYear", 2) && Returns .F. ? PEMStatus("DateSpin", "nYear", 4) && Returns .T. |
See Also |
AMembers(), ReadExpression, ReadMethod, Sys(1269), WriteExpression, WriteMethod |