我想在详细信息视图中获取并设置可见列。我有一个shell扩展(用第三方库实现),当用户右键单击文件夹背景时,我在上下文菜单中添加一个菜单项。通过将IObjectWithSite添加到我的扩展,我已经能够获得IColumnManager的接口。
在www.pinvoke.net上没有IColumnManager的声明,并且我在.NET中找到的唯一一个调用它的例子是BExplorer的一个已经不存在的分支。基于此,我得到了GetColumnCount()。
let mutable colCount = 0u;
columnManager.GetColumnCount (CM_ENUM_FLAGS.CM_ENUM_VISIBLE, &colCount)
(我在F#工作。但是现在我用C#来声明接口和结构)。
看起来我的下一步是通过调用GetColumns()来获取PROPERTYKEY数组。这被定义为
HRESULT ( STDMETHODCALLTYPE *GetColumns )(
__RPC__in IColumnManager * This,
/* [in] */ CM_ENUM_FLAGS dwFlags,
/* [size_is][out] */ __RPC__out_ecount_full(cColumns) PROPERTYKEY *rgkeyOrder,
/* [in] */ UINT cColumns);
以下是从C ++开始的一个例子,取自http://blogs3805.rssing.com/chan-16291381/all_p568.html:
PROPERTYKEY *columns = new PROPERTYKEY[nColumns];
hr = pColumnManager->GetColumns(CM_ENUM_VISIBLE,
columns,
nColumns);
BExplorer为GetColumns提供此功能:
void GetColumns(CM_ENUM_FLAGS dwFlags, [Out] [MarshalAs(UnmanagedType.LPArray)] PropertyKey[] rgkeyOrder, uint cColumns);
但在我看来,这里需要SizeParamIndex,因为我正在编组一个数组。所以我也试过了
void GetColumns([In] CM_ENUM_FLAGS dwFlags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] PROPERTYKEY[] columns, [In] uint colCount);
两者都不起作用。当我这样做
let columns = Array.init (int colCount) (fun i -> PROPERTYKEY())
columnManager.GetColumns (CM_ENUM_FLAGS.CM_ENUM_VISIBLE, columns, colCount)
我得到一个带有HResult = 0x80004003的System.AccessViolationException。
我的问题是,在使用IColumnManager的C#接口声明烦躁时,我改变了两个函数的顺序。函数的顺序必须与运行时在vtable中找到的顺序相匹配。