Currently, my property handler provides properties that can be displayed in Windows Explorer columns of type String
. My goal is to extend the handler by a property of (display) type Icon, that can be added as a column to the details view of Windows Explorer. In this column, an icon should be displayed for each file item, e. g. the icon could represent a specific state of the file out of several possible states.
However, I did not manage to assemble the necessary parts of creating a property with these characteristics on the base of the Windows Property System correctly.
The first step of my approach is to specify the XML for the property in a .propdesc file and then go through the usual PSRegisterPropertySchema
registration process. This runs always successfully and the property is listed in the Windows Property System.
<propertyDescription name="myprop.icon" formatID="{c5f47221-1053-4a75-aadc-0bfbac1c3e9c}" propID="444">
<typeInfo type="???" isInnate="true" isViewable="true"/>
<labelInfo label="MyProp-Icon"/>
<displayInfo defaultColumnWidth="25" alignment="Center">
<drawControl control="IconList"/>
</displayInfo>
</propertyDescription>
The existence of <drawControl>
(drawControl) with a control
attribute of type "IconList"
within the <displayInfo>
tag makes me feel that my idea could be feasible.
But how to set the corresponding type
in the <typeInfo>
tag (typeInfo)? Depending on the concept of control="IconList"
this could be an integer as an index
into somewhat like an imagelist. Or is it a "Buffer"
, "Blob"
or "Stream"
representing the image itself?
Last, in the GetValue()
method of the Property Handler shell extension the PROPVARIANT
has to be initialized according to the property description of the .propdesc file:
HRESULT PropertyHandler::GetValue (REFPROPERTYKEY key, PROPVARIANT *pPropVar)
{
HRESULT hr = ERROR_NOT_FOUND;
if (key.pid == 444)
{
// How to initialize pPropVar in case of control="IconList"?
}
else
{
// String example
hr = InitPropVariantFromString (L"Some Text", pPropVar);
}
return hr;
}
Again, how to do this for "IconList"
properties?
Each attempt to find a correct match between the XML specification and the PROPVARIANT initialization leaves the corresponding column in Windows Explorer blank.
Does anybody already implemented a property with a <drawControl>
of type IconList
?
There is WINDOWSPROPERTYDESCRIPTIONS resource inside propsys.dll. This resource describes all system props. Some of properties have drawcontrol equal to IconList. Example:
<propertyDescription name="System.StorageProviderUIStatus" formatID="{E77E90DF-6271-4F5B-834F-2DD1F245DDA4}" propID="2">
<searchInfo reIndexPatterns="" processReIndexPatternsImmediately="true" inInvertedIndex="false" isColumn="false">
</searchInfo>
<typeInfo type="Blob" isInnate="true" isViewable="true">
</typeInfo>
<labelInfo label="@propsys.dll,-42289">
</labelInfo>
<displayInfo defaultColumnWidth="10">
<drawControl control="IconList">
</drawControl>
</displayInfo>
</propertyDescription>
ALL of such props have type equal to "Blob". So Blob is answer.
Update
My little investigation.
The only known (by me) handler that shows icons is OneDrive. Screenshot:
I got value of System.StorageProviderUIStatus property of one of OneDrive files. Value dump:
As you see this is not image or icon. This is Property Store Binary File described in [MS-PROPSTORE]. Decoded form:
System.PropList.StatusIcons = prop:System.StorageProviderState;System.StorageProviderCustomStates
System.PropList.StatusIconsDisplayFlag = 3
StorageProviderState = 2
StorageProviderCustomStates = (binary data)
Binary data in embedded Property Store Binary File. Its decoded form:
StorageProviderFullyQualifiedId = OneDrive!S-1-5-21-782054983-1121033576-3753986437-1001!Personal|79D9464945C2A3B2!331
Everything looks quite hard for simple icon description. And maybe I`am wrong and Blob type is not the only answer.
SOLUTION
Content of propdesc file:
<propertyDescription name="DummyUIState" formatID="{8A560909-320E-4E6A-A6C4-A95C50B77084}" propID="5001">
<searchInfo columnIndexType="NotIndexed"/>
<labelInfo label="DummyUIState"/>
<typeInfo type="Blob" isInnate="true" isViewable="true"/>
<displayInfo defaultColumnWidth="10">
<drawControl control="IconList"/>
</displayInfo>
</propertyDescription>
<propertyDescription name="DummyState" formatID="{8A560909-320E-4E6A-A6C4-A95C50B77084}" propID="5000">
<searchInfo columnIndexType="NotIndexed"/>
<labelInfo label="DummyState"/>
<typeInfo type="UInt32" isInnate="true" isViewable="true"/>
<displayInfo displayType="Enumerated">
<enumeratedList>
<enum name="None" value="0" text="@propsys.dll,-42290"/>
<enum name="Sparse" value="1" text="@propsys.dll,-42291">
<image res="%systemroot%\system32\imageres.dll,-1404"/>
</enum>
<enum name="InSync" value="2" text="@propsys.dll,-42292">
<image res="%systemroot%\system32\imageres.dll,-1400"/>
</enum>
<enum name="Pinned" value="3" text="@propsys.dll,-42293">
<image res="%systemroot%\system32\imageres.dll,-1405"/>
</enum>
<enum name="PendingUpload" value="4" text="@propsys.dll,-42294">
<image res="%systemroot%\system32\imageres.dll,-1401"/>
</enum>
<enum name="PendingDownload" value="5" text="@propsys.dll,-42303">
<image res="%systemroot%\system32\imageres.dll,-1401"/>
</enum>
<enum name="Transferring" value="6" text="@propsys.dll,-42296">
<image res="%systemroot%\system32\imageres.dll,-1401"/>
</enum>
<enum name="Error" value="7" text="@propsys.dll,-42315">
<image res="%systemroot%\system32\imageres.dll,-1402"/>
</enum>
<enum name="Warning" value="8" text="@propsys.dll,-42316">
<image res="%systemroot%\system32\imageres.dll,-1403"/>
</enum>
<enum name="Excluded" value="9" text="@propsys.dll,-42319"/>
<enum name="Pending" value="10" text="@propsys.dll,-42324">
<image res="%systemroot%\system32\imageres.dll,-1401"/>
</enum>
</enumeratedList>
</displayInfo>
</propertyDescription>
When shell request DummyUIState you must create blob with Property Store Binary File. Property Store Binary File must contain the following data:
That's all. Tested on Windows 10. Screenshot: