X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/58935d4a5c5546124b4903907b5785da270b4c31..c6ea1fdaf924be4ee49a19d12f76e4fcd257bb0a:/include/wx/propgrid/property.h diff --git a/include/wx/propgrid/property.h b/include/wx/propgrid/property.h index ca40fb7765..cc5e30fe14 100644 --- a/include/wx/propgrid/property.h +++ b/include/wx/propgrid/property.h @@ -6,12 +6,14 @@ // Created: 2008-08-23 // RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PROPGRID_PROPERTY_H_ #define _WX_PROPGRID_PROPERTY_H_ +#include "wx/defs.h" + #if wxUSE_PROPGRID #include "wx/propgrid/propgriddefs.h" @@ -47,9 +49,6 @@ struct wxPGPaintData }; -#ifndef SWIG - - // space between vertical sides of a custom image #define wxPG_CUSTOM_IMAGE_SPACINGY 1 @@ -98,7 +97,11 @@ public: DontUseCellBgCol }; - virtual void Render( wxDC& dc, + /** + Returns @true if rendered something in the foreground (text or + bitmap. + */ + virtual bool Render( wxDC& dc, const wxRect& rect, const wxPropertyGrid* propertyGrid, wxPGProperty* property, @@ -137,14 +140,53 @@ public: wxPGProperty* property, const wxPGEditor* editor ) const; - /** Utility to render cell bitmap and set text colour plus bg brush colour. + /** Utility to render cell bitmap and set text colour plus bg brush + colour. - Returns image width that, for instance, can be passed to DrawText. + @return Returns image width, which, for instance, can be passed to + DrawText. */ int PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& cell, int flags ) const; + + /** + Utility to be called after drawing is done, to revert whatever + changes PreDrawCell() did. + + @param flags + Same as those passed to PreDrawCell(). + */ + void PostDrawCell( wxDC& dc, + const wxPropertyGrid* propGrid, + const wxPGCell& cell, + int flags ) const; +}; + + +/** + @class wxPGDefaultRenderer + + Default cell renderer, that can handles the common + scenarios. +*/ +class WXDLLIMPEXP_PROPGRID wxPGDefaultRenderer : public wxPGCellRenderer +{ +public: + virtual bool Render( wxDC& dc, + const wxRect& rect, + const wxPropertyGrid* propertyGrid, + wxPGProperty* property, + int column, + int item, + int flags ) const; + + virtual wxSize GetImageSize( const wxPGProperty* property, + int column, + int item ) const; + +protected: }; @@ -162,6 +204,7 @@ public: void SetBitmap( const wxBitmap& bitmap ) { m_bitmap = bitmap; } void SetFgCol( const wxColour& col ) { m_fgCol = col; } void SetBgCol( const wxColour& col ) { m_bgCol = col; } + void SetFont( const wxFont& font ) { m_font = font; } protected: virtual ~wxPGCellData() { } @@ -170,14 +213,17 @@ protected: wxBitmap m_bitmap; wxColour m_fgCol; wxColour m_bgCol; + wxFont m_font; // True if m_text is valid and specified bool m_hasValidText; }; -/** @class wxPGCell - Base class for simple wxPropertyGrid cell information. +/** + @class wxPGCell + + Base class for wxPropertyGrid cell information. */ class WXDLLIMPEXP_PROPGRID wxPGCell : public wxObject { @@ -210,6 +256,11 @@ public: return (m_refData && GetData()->m_hasValidText); } + /** + Sets empty but valid data to this cell object. + */ + void SetEmptyData(); + /** Merges valid data from srcCell into this. */ @@ -218,11 +269,32 @@ public: void SetText( const wxString& text ); void SetBitmap( const wxBitmap& bitmap ); void SetFgCol( const wxColour& col ); + + /** + Sets font of the cell. + + @remarks Because wxPropertyGrid does not support rows of + different height, it makes little sense to change + size of the font. Therefore it is recommended + to use return value of wxPropertyGrid::GetFont() + or wxPropertyGrid::GetCaptionFont() as a basis + for the font that, after modifications, is passed + to this member function. + */ + void SetFont( const wxFont& font ); + void SetBgCol( const wxColour& col ); const wxString& GetText() const { return GetData()->m_text; } const wxBitmap& GetBitmap() const { return GetData()->m_bitmap; } const wxColour& GetFgCol() const { return GetData()->m_fgCol; } + + /** + Returns font of the cell. If no specific font is set for this + cell, then the font will be invalid. + */ + const wxFont& GetFont() const { return GetData()->m_font; } + const wxColour& GetBgCol() const { return GetData()->m_bgCol; } wxPGCell& operator=( const wxPGCell& other ) @@ -234,37 +306,20 @@ public: return *this; } -protected: + // Used mostly internally to figure out if this cell is supposed + // to have default values when attached to a grid. + bool IsInvalid() const + { + return ( m_refData == NULL ); + } + +private: virtual wxObjectRefData *CreateRefData() const { return new wxPGCellData(); } virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; }; - -/** @class wxPGDefaultRenderer - - Default cell renderer, that can handles the common - scenarios. -*/ -class WXDLLIMPEXP_PROPGRID wxPGDefaultRenderer : public wxPGCellRenderer -{ -public: - virtual void Render( wxDC& dc, - const wxRect& rect, - const wxPropertyGrid* propertyGrid, - wxPGProperty* property, - int column, - int item, - int flags ) const; - - virtual wxSize GetImageSize( const wxPGProperty* property, - int column, - int item ) const; - -protected: -}; - // ----------------------------------------------------------------------- /** @class wxPGAttributeStorage @@ -314,7 +369,6 @@ protected: wxPGHashMapS2P m_map; }; -#endif // !SWIG // ----------------------------------------------------------------------- @@ -322,7 +376,7 @@ protected: @{ */ -enum wxPG_PROPERTY_FLAGS +enum wxPGPropertyFlags { /** Indicates bold font. @@ -356,8 +410,8 @@ wxPG_PROP_COLLAPSED = 0x0020, If property is selected, then indicates that validation failed for pending value. - If property is not selected, then indicates that the the actual property - value has failed validation (NB: this behavior is not currently supported, + If property is not selected, that indicates that the actual property + value has failed validation (NB: this behaviour is not currently supported, but may be used in future). */ wxPG_PROP_INVALID_VALUE = 0x0040, @@ -399,7 +453,9 @@ wxPG_PROP_CATEGORY = 0x2000, */ wxPG_PROP_MISC_PARENT = 0x4000, -/** Property is read-only. Editor is still created. +/** Property is read-only. Editor is still created for wxTextCtrl-based + property editors. For others, editor is not usually created because + they do implement wxTE_READONLY style or equivalent. */ wxPG_PROP_READONLY = 0x8000, @@ -426,6 +482,8 @@ wxPG_PROP_USES_COMMON_VALUE = 0x00020000, @remarks This flag cannot be used with property iterators. + + @see wxPGProperty::SetAutoUnspecified() */ wxPG_PROP_AUTO_UNSPECIFIED = 0x00040000, @@ -452,7 +510,9 @@ wxPG_PROP_BEING_DELETED = 0x00200000 Code should automatically take care of this, however. */ #define wxPG_PROP_PARENTAL_FLAGS \ - (wxPG_PROP_AGGREGATE|wxPG_PROP_CATEGORY|wxPG_PROP_MISC_PARENT) + ((wxPGPropertyFlags)(wxPG_PROP_AGGREGATE | \ + wxPG_PROP_CATEGORY | \ + wxPG_PROP_MISC_PARENT)) /** @} */ @@ -463,8 +523,6 @@ wxPG_PROP_BEING_DELETED = 0x00200000 // ----------------------------------------------------------------------- -#ifndef SWIG - /** @section propgrid_property_attributes wxPropertyGrid Property Attribute Identifiers. @@ -498,10 +556,17 @@ wxPG_PROP_BEING_DELETED = 0x00200000 */ #define wxPG_ATTR_UNITS wxS("Units") -/** Universal, string. When set, will be shown in property's value cell - when displayed value string is empty, or value is unspecified. +/** When set, will be shown as 'greyed' text in property's value cell when + the actual displayed value is blank. +*/ +#define wxPG_ATTR_HINT wxS("Hint") + +#if wxPG_COMPATIBILITY_1_4 +/** + @deprecated Use "Hint" (wxPG_ATTR_HINT) instead. */ #define wxPG_ATTR_INLINE_HELP wxS("InlineHelp") +#endif /** Universal, wxArrayString. Set to enable auto-completion in any wxTextCtrl-based property editor. @@ -590,6 +655,15 @@ wxPG_PROP_BEING_DELETED = 0x00200000 */ #define wxPG_DIR_DIALOG_MESSAGE wxS("DialogMessage") +/** + wxArrayStringProperty's string delimiter character. If this is a quotation + mark or hyphen, then strings will be quoted instead (with given + character). + + Default delimiter is quotation mark. +*/ +#define wxPG_ARRAY_DELIMITER wxS("Delimiter") + /** Sets displayed date format for wxDateProperty. */ #define wxPG_DATE_FORMAT wxS("DateFormat") @@ -600,7 +674,7 @@ wxPG_PROP_BEING_DELETED = 0x00200000 #define wxPG_DATE_PICKER_STYLE wxS("PickerStyle") /** SpinCtrl editor, int or double. How much number changes when button is - pressed (or up/down on keybard). + pressed (or up/down on keyboard). */ #define wxPG_ATTR_SPINCTRL_STEP wxS("Step") @@ -623,6 +697,12 @@ wxPG_PROP_BEING_DELETED = 0x00200000 */ #define wxPG_COLOUR_ALLOW_CUSTOM wxS("AllowCustom") +/** + wxColourProperty and its kind: Set to True in order to support editing + alpha colour component. +*/ +#define wxPG_COLOUR_HAS_ALPHA wxS("HasAlpha") + /** @} */ @@ -635,15 +715,15 @@ wxPG_PROP_BEING_DELETED = 0x00200000 #define wxPG_ATTR_MAX wxPGGlobalVars->m_strMax #undef wxPG_ATTR_UNITS #define wxPG_ATTR_UNITS wxPGGlobalVars->m_strUnits +#undef wxPG_ATTR_HINT +#define wxPG_ATTR_HINT wxPGGlobalVars->m_strHint +#if wxPG_COMPATIBILITY_1_4 #undef wxPG_ATTR_INLINE_HELP #define wxPG_ATTR_INLINE_HELP wxPGGlobalVars->m_strInlineHelp - -#endif // !SWIG +#endif // ----------------------------------------------------------------------- -#ifndef SWIG - /** @class wxPGChoiceEntry Data of a single wxPGChoices choice. */ @@ -724,7 +804,6 @@ private: #define wxPGChoicesEmptyData ((wxPGChoicesData*)NULL) -#endif // SWIG /** @class wxPGChoices @@ -775,7 +854,7 @@ public: @param values Values for choices. If NULL, indexes are used. */ - wxPGChoices( const wxChar** labels, const long* values = NULL ) + wxPGChoices( const wxChar* const* labels, const long* values = NULL ) { Init(); Set(labels,values); @@ -823,7 +902,7 @@ public: @param values Values for added choices. If empty, relevant entry indexes are used. */ - void Add( const wxChar** labels, const ValArrItem* values = NULL ); + void Add( const wxChar* const* labels, const ValArrItem* values = NULL ); /** Version that works with wxArrayString and wxArrayInt. */ void Add( const wxArrayString& arr, const wxArrayInt& arrint = wxArrayInt() ); @@ -949,14 +1028,14 @@ public: /** Removes count items starting at position nIndex. */ void RemoveAt(size_t nIndex, size_t count = 1); -#ifndef SWIG - /** Does not create copies for itself. */ - void Set( const wxChar** labels, const long* values = NULL ) + /** Does not create copies for itself. + TODO: Deprecate. + */ + void Set( const wxChar* const* labels, const long* values = NULL ) { Free(); Add(labels,values); } -#endif // SWIG /** Version that works with wxArrayString and wxArrayInt. */ void Set( const wxArrayString& labels, @@ -993,7 +1072,6 @@ public: wxArrayString GetLabels() const; -#ifndef SWIG void operator= (const wxPGChoices& a) { if (this != &a) @@ -1015,7 +1093,6 @@ protected: void Init(); void Free(); -#endif // !SWIG }; // ----------------------------------------------------------------------- @@ -1078,7 +1155,6 @@ public: */ virtual wxVariant DoGetValue() const { return m_value; } -#if !defined(SWIG) || defined(CREATE_VCW) /** Implement this function in derived class to check the value. Return true if it is ok. Returning false prevents property change events from occurring. @@ -1113,7 +1189,7 @@ public: You might want to take into account that m_value is Null variant if property value is unspecified (which is usually only case if - you explicitly enabled that sort behavior). + you explicitly enabled that sort behaviour). */ virtual bool StringToValue( wxVariant& variant, const wxString& text, @@ -1145,12 +1221,12 @@ public: instead of OnEvent. - You might want to take into account that m_value is Null variant if property value is unspecified (which is usually only case if you - explicitly enabled that sort behavior). + explicitly enabled that sort behaviour). */ virtual bool IntToValue( wxVariant& value, int number, int argFlags = 0 ) const; -#endif // !defined(SWIG) || defined(CREATE_VCW) + /** Converts property value into a text representation. @@ -1171,7 +1247,7 @@ public: virtual wxString ValueToString( wxVariant& value, int argFlags = 0 ) const; /** Converts string to a value, and if successful, calls SetValue() on it. - Default behavior is to do nothing. + Default behaviour is to do nothing. @param text String to get the value from. @return @@ -1179,8 +1255,8 @@ public: */ bool SetValueFromString( const wxString& text, int flags = wxPG_PROGRAMMATIC_VALUE ); - /** Converts integer to a value, and if succesful, calls SetValue() on it. - Default behavior is to do nothing. + /** Converts integer to a value, and if successful, calls SetValue() on it. + Default behaviour is to do nothing. @param value Int to get the value from. @param flags @@ -1199,7 +1275,7 @@ public: @param item Normally -1, but can be an index to the property's list of items. @remarks - - Default behavior is to return wxSize(0,0), which means no image. + - Default behaviour is to return wxSize(0,0), which means no image. - Default image width or height is indicated with dimension -1. - You can also return wxPG_DEFAULT_IMAGE_SIZE, i.e. wxSize(-1, -1). */ @@ -1233,7 +1309,7 @@ public: /** Called after value of a child property has been altered. Must return - new value of the whole property (after any alterations warrented by + new value of the whole property (after any alterations warranted by child's new value). Note that this function is usually called at the time that value of @@ -1393,12 +1469,16 @@ public: */ virtual void RefreshChildren(); - /** Special handling for attributes of this property. + /** + Reimplement this member function to add special handling for + attributes of this property. - If returns false, then the attribute will be automatically stored in - m_attributes. + @return Return @false to have the attribute automatically stored in + m_attributes. Default implementation simply does that and + nothing else. - Default implementation simply returns false. + @remarks To actually set property attribute values from the + application, use wxPGProperty::SetAttribute() instead. */ virtual bool DoSetAttribute( const wxString& name, wxVariant& value ); @@ -1460,6 +1540,17 @@ public: */ void DeleteChoice( int index ); + /** + Enables or disables the property. Disabled property usually appears + as having grey text. + + @param enable + If @false, property is disabled instead. + + @see wxPropertyGridInterface::EnableProperty() + */ + void Enable( bool enable = true ); + /** Call to enable or disable usage of common value (integer value that can be selected for properties instead of their normal values) for this @@ -1590,6 +1681,11 @@ public: return GetValueAsString(0); } + /** + Returns property's hint text (shown in empty value cell). + */ + inline wxString GetHintText() const; + /** Returns property grid where property lies. */ wxPropertyGrid* GetGrid() const; @@ -1611,7 +1707,7 @@ public: /** Returns true if property has editable wxTextCtrl when selected. @remarks - Altough disabled properties do not displayed editor, they still + Although disabled properties do not displayed editor, they still return True here as being disabled is considered a temporary condition (unlike being read-only or having limited editing enabled). */ @@ -1622,7 +1718,12 @@ public: return m_value.IsNull(); } - FlagType HasFlag( FlagType flag ) const + /** + Returns non-zero if property has given flag set. + + @see propgrid_propflags + */ + FlagType HasFlag( wxPGPropertyFlags flag ) const { return ( m_flags & flag ); } @@ -1638,6 +1739,9 @@ public: */ wxVariant GetAttributesAsList() const; + /** + Returns property flags. + */ FlagType GetFlags() const { return m_flags; @@ -1791,7 +1895,7 @@ public: By default changes are applied recursively. Set this paramter wxPG_DONT_RECURSE to prevent this. */ - inline bool Hide( bool hide, int flags = wxPG_RECURSE ); + bool Hide( bool hide, int flags = wxPG_RECURSE ); bool IsExpanded() const { return (!(m_flags & wxPG_PROP_COLLAPSED) && GetChildCount()); } @@ -1821,18 +1925,34 @@ public: void SetAttributes( const wxPGAttributeStorage& attributes ); + /** + Set if user can change the property's value to unspecified by + modifying the value of the editor control (usually by clearing + it). Currently, this can work with following properties: + wxIntProperty, wxUIntProperty, wxFloatProperty, wxEditEnumProperty. + + @param enable + Whether to enable or disable this behaviour (it is disabled by + default). + */ + void SetAutoUnspecified( bool enable = true ) + { + ChangeFlag(wxPG_PROP_AUTO_UNSPECIFIED, enable); + } + /** Sets property's background colour. @param colour Background colour to use. - @param recursively - If @true, children are affected recursively, and any categories - are not. + @param flags + Default is wxPG_RECURSE which causes colour to be set recursively. + Omit this flag to only set colour for the property in question + and not any of its children. */ void SetBackgroundColour( const wxColour& colour, - bool recursively = false ); + int flags = wxPG_RECURSE ); /** Sets property's text colour. @@ -1840,12 +1960,13 @@ public: @param colour Text colour to use. - @param recursively - If @true, children are affected recursively, and any categories - are not. + @param flags + Default is wxPG_RECURSE which causes colour to be set recursively. + Omit this flag to only set colour for the property in question + and not any of its children. */ void SetTextColour( const wxColour& colour, - bool recursively = false ); + int flags = wxPG_RECURSE ); /** Set default value of a property. Synonymous to @@ -1855,7 +1976,6 @@ public: */ void SetDefaultValue( wxVariant& value ); -#ifndef SWIG /** Sets editor for a property. @param editor @@ -1870,7 +1990,6 @@ public: { m_customEditor = editor; } -#endif /** Sets editor for a property. */ @@ -1952,14 +2071,16 @@ public: } /** - Sets given property flag(s). - */ - void SetFlag( FlagType flag ) { m_flags |= flag; } + Sets or clears given property flag. Mainly for internal use. - /** - Sets or clears given property flag(s). + @remarks Setting a property flag never has any side-effect, and is + intended almost exclusively for internal use. So, for + example, if you want to disable a property, call + Enable(false) instead of setting wxPG_PROP_DISABLED flag. + + @see HasFlag(), GetFlags() */ - void ChangeFlag( FlagType flag, bool set ) + void ChangeFlag( wxPGPropertyFlags flag, bool set ) { if ( set ) m_flags |= flag; @@ -1967,7 +2088,13 @@ public: m_flags &= ~flag; } - void SetFlagRecursively( FlagType flag, bool set ); + /** + Sets or clears given property flag, recursively. This function is + primarily intended for internal use. + + @see ChangeFlag() + */ + void SetFlagRecursively( wxPGPropertyFlags flag, bool set ); void SetHelpString( const wxString& helpString ) { @@ -1998,7 +2125,7 @@ public: void SetValueToUnspecified() { wxVariant val; // Create NULL variant - SetValue(val); + SetValue(val, NULL, wxPG_SETVAL_REFRESH_EDITOR); } // Helper function (for wxPython bindings and such) for settings protected @@ -2022,9 +2149,8 @@ public: return m_validator; return DoGetValidator(); } -#endif // #if wxUSE_VALIDATORS +#endif // wxUSE_VALIDATORS -#ifndef SWIG /** Returns client data (void*) of a property. */ void* GetClientData() const @@ -2052,14 +2178,14 @@ public: /** Sets managed client object of a property. */ wxClientData *GetClientObject() const { return m_clientObject; } -#endif - /** Sets new set of choices for property. + /** + Sets new set of choices for the property. - @remarks - This operation clears the property value. + @remarks This operation deselects the property and clears its + value. */ - bool SetChoices( wxPGChoices& choices ); + bool SetChoices( const wxPGChoices& choices ); /** Set max length of text in text editor. */ @@ -2079,8 +2205,6 @@ public: return m_helpString; } - void ClearFlag( FlagType flag ) { m_flags &= ~(flag); } - // Use, for example, to detect if item is inside collapsed section. bool IsSomeParent( wxPGProperty* candidate_parent ) const; @@ -2150,16 +2274,12 @@ public: */ int GetImageOffset( int imageWidth ) const; -#ifndef SWIG // Returns wxPropertyGridPageState in which this property resides. wxPropertyGridPageState* GetParentState() const { return m_parentState; } -#endif -#ifndef SWIG wxPGProperty* GetItemAtY( unsigned int y, unsigned int lh, unsigned int* nextItemY ) const; -#endif /** Returns property at given virtual y coordinate. */ @@ -2169,8 +2289,6 @@ public: */ wxPGProperty* GetPropertyByName( const wxString& name ) const; -#ifndef SWIG - // Returns various display-related information for given column void GetDisplayInfo( unsigned int column, int choiceIndex, @@ -2252,6 +2370,8 @@ protected: const wxVariantList* valueOverrides = NULL, wxPGHashMapS2S* childResults = NULL ) const; + bool DoHide( bool hide, int flags ); + void DoSetName(const wxString& str) { m_name = str; } /** Deletes all sub-properties. */ @@ -2267,14 +2387,37 @@ protected: void InitAfterAdded( wxPropertyGridPageState* pageState, wxPropertyGrid* propgrid ); + /** + Returns true if child property is selected. + */ + bool IsChildSelected( bool recursive = false ) const; + // Removes child property with given pointer. Does not delete it. void RemoveChild( wxPGProperty* p ); + void DoEnable( bool enable ); + void DoPreAddChild( int index, wxPGProperty* prop ); void SetParentState( wxPropertyGridPageState* pstate ) { m_parentState = pstate; } + void SetFlag( wxPGPropertyFlags flag ) + { + // + // NB: While using wxPGPropertyFlags here makes it difficult to + // combine different flags, it usefully prevents user from + // using incorrect flags (say, wxWindow styles). + m_flags |= flag; + } + + void ClearFlag( FlagType flag ) { m_flags &= ~(flag); } + + // Called when the property is being removed from the grid and/or + // page state (but *not* when it is also deleted). + void OnDetached(wxPropertyGridPageState* state, + wxPropertyGrid* propgrid); + // Call after fixed sub-properties added/removed after creation. // if oldSelInd >= 0 and < new max items, then selection is // moved to it. @@ -2338,7 +2481,6 @@ private: // Called in constructors. void Init(); void Init( const wxString& label, const wxString& name ); -#endif // #ifndef SWIG }; // ----------------------------------------------------------------------- @@ -2351,14 +2493,12 @@ private: #define WX_PG_DECLARE_DOGETEDITORCLASS \ virtual const wxPGEditor* DoGetEditorClass() const; -#ifndef SWIG +#ifndef WX_PG_DECLARE_PROPERTY_CLASS #define WX_PG_DECLARE_PROPERTY_CLASS(CLASSNAME) \ public: \ DECLARE_DYNAMIC_CLASS(CLASSNAME) \ WX_PG_DECLARE_DOGETEDITORCLASS \ private: -#else - #define WX_PG_DECLARE_PROPERTY_CLASS(CLASSNAME) #endif // Implements sans constructor function. Also, first arg is class name, not @@ -2371,8 +2511,6 @@ const wxPGEditor* PROPNAME::DoGetEditorClass() const \ // ----------------------------------------------------------------------- -#ifndef SWIG - /** @class wxPGRootProperty @ingroup classes Root parent property. @@ -2418,6 +2556,7 @@ public: int GetTextExtent( const wxWindow* wnd, const wxFont& font ) const; virtual wxString ValueToString( wxVariant& value, int argFlags ) const; + virtual wxString GetValueAsString( int argFlags = 0 ) const; protected: void SetTextColIndex( unsigned int colInd ) @@ -2434,8 +2573,6 @@ private: void Init(); }; -#endif // !SWIG - // ----------------------------------------------------------------------- #endif // wxUSE_PROPGRID