winapi - 从 C#/F# 使用 IColumnManager 获取/设置列
问题描述
我想在详细信息视图中获取和设置可见列。我有一个 shell 扩展(使用 3rd 方库实现),当用户右键单击文件夹背景时,我将一个菜单项添加到上下文菜单中。通过将 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 中找到的顺序相匹配。
推荐阅读
- android - 向所有安装了我的应用程序的用户发送 FCM 通知
- sql - 将年数转换为日期名称?
- java - 使用递归在迷宫中找到最短路径?
- c++ - 按字母顺序对双向链表进行排序
- javascript - 油脂猴 - 加载 html 和 css 时运行脚本
- laravel - Laravel API ResourceCollection - 调用未定义的方法 Illuminate\Database\Eloquent\Builder::mapInto()
- javascript - 如何删除 JQuery 的 Ui-Datepicker-Year 选择箭头
- ruby-on-rails - 将 devise_security_extension 与 Rails 3 应用程序一起使用
- python - 在 Python 中安装软件包时出现问题:python setup.py egg_info" failed with error code 1
- php - 为什么我的 ibase_query 结果乱序