Some time ago, we saw how the
IBindCtx
parameter to
IShellFolder::
can be used to modify how the parse takes place.
More generally, the
IBindCtx
parameter to a function is a
catch-all miscellaneous options parameter.
The interesting part of the bind context is all the stuff
that has been added to it via
the
IBindCtx::
method.
You can attach arbitrary objects to the bind context,
using a string to identify each one.
Some bind context parameters are like Boolean parameters
that simply change some default behavior of the operation.
For these operations, the object that is associated with the
bind context string is not important;
the important thing is that there is something associated
with it.
Traditionally, you just connect a dummy object that
implements just IUnknown
.
In the most general case, the object associated with a bind
context string implements some operation-specific interface.
For example,
the
STR_
bind context string
expects you to associate an object that implements
the
ICreateObject
interface,
because the whole point of the
STR_
bind context string is to say,
"Hey, I want to create objects in a nonstandard way,"
so you need to tell it what that nonstandard way is.
At the other extreme, you may have a chunk of data that you want
to associate with the bind context string.
Since bind contexts want to associate objects,
you need to wrap the data inside a COM object.
We saw this earlier when
we had to create an object that
implemented the
IFileSystemBindData
interface
in order to babysit a
WIN32_
structure.
Rather than having to create a separate interface for
each data type
(hello,
IObjectWithFolderEnumMode
),
and rather than going to the opposite extreme and just
using IStream
to pass arbitrary unstructured
data,
the shell folks decided to take a middle-ground approach:
Use a common interface that still has a modicum of type safety,
namely,
IPropertyBag
.
Other nice things about this approach is that
there are a lot of pre-existing
helper functions for property bags and property variants.
Also, you need to attach only one object instead of a whole
bunch of tiny little ones.
Under this new regime (which took hold in Windows 8), the bind context has an associated property bag, and you put your data in that property bag.
In pictures:
IBindCtx:: | IPropertyBag:: | |||||
IBindCtx | → | Boolean parameter | IUnknown | |||
Interface parameter | object with custom interface | |||||
STR_ | IPropertyBag | → | Property bag DWORD parameter | VT_UI4 | ||
Property bag string parameter | VT_BSTR | |||||
Property bag Boolean parameter | VT_BOOL |
If you want a
Boolean-style parameter to be true
,
then set it in the bind context with a dummy object that implements
IUnknown
.
If you want a
Boolean-style parameter to false
,
then omit it from the bind context entirely.
To set an interface-style parameter, set it in the bind context with an object that implements the desired interface.
To set a property bag-based parameter, set it in the property bag with the appropriate variant type.
Here are the bind context strings defined up through Windows 8.1 and the way you set them into the bind context.
Bind context string | Model | Operation |
---|---|---|
STR_ | Boolean | Binding |
STR_ | Interface ICreateObject | Binding |
STR_ | Interface IObjectWithFolderEnumMode | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Binding |
STR_ | Boolean | Parsing |
STR_ | Boolean | Binding |
STR_ | Property bag: VT_ | Binding for enumeration |
STR_ | Interface IFileSysBindData or IFileSysBindData2 | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | GetUIObjectOf |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IPropertyStore |
STR_ | Boolean | Binding for IFilter |
STR_ | Boolean | Binding for IFilter |
STR_ | Boolean | Loading history |
STR_ | Boolean | Parsing |
STR_ | Interface IBindCtx | Parsing and initiailzing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Parsing |
STR_ | Interface IParseAndCreateItem | Parsing |
STR_ | Boolean | Parsing |
STR_ | Property bag: VT_BOOL | Parsing |
STR_ | Interface IShellItem | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Parsing |
STR_ | Interface IPropertyBag | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Parsing |
STR_ | Boolean | Parsing |
STR_ | Property bag: VT_BSTR | Parsing |
STR_ | Property bag: VT_BSTR | Parsing |
STR_ | Interface IPropertyStore | Parsing |
STR_ | Interface IPropertyBag | holds property bag parameters |
STR_ | Interface IPersist | Parsing and binding |
There are some oddities in the above table.
- All of the
STR_
values would be more conveniently expressed as a singleGPS_* VT_UI4
property bag-based value. (Exercise: Why isn't it?) - The
STR_
bind context parameter is itself another bind context! The idea here is that you, the caller, are enabling caching during the parse, and the inner bind context acts as the cache.ITEM_ CACHE_ CONTEXT - The
STR_
value is unusual in that it is something set by the parser and passed back to the caller.PARSE_ EXPLICIT_ ASSOCIATION_ SUCCESSFUL - As we have been discussing,
STR_
is a bind context string that doesn't mean anything on its own. Rather, it provides a property bag into which more parameters can be stored.PROPERTYBAG_ PARAM
Next time, I'll write some helper functions to make all this slightly more manageable.