p/invoke 和 EnumDisplaySettingsEx 的困难

Posted

技术标签:

【中文标题】p/invoke 和 EnumDisplaySettingsEx 的困难【英文标题】:Difficulties with p/invoke and EnumDisplaySettingsEx 【发布时间】:2011-03-23 23:24:15 【问题描述】:

我正在尝试检索系统上存在的所有各种监视器(及其适配器)的信息。到目前为止,我使用EnumDisplayDevices 列出所有监视器的尝试效果很好——它找到了两个,第一个是"\\.\DISPLAY1\Monitor0"(第二个分别是 2 和 1,但这与这个问题无关)。无论如何,然后我尝试在其上调用EnumDisplaySettingsEx,如上所述传递监视器的名称,但它总是失败。使用空名称参数的调用成功,但返回的DEVMODE 结构表示dmDeviceName 是“cdd”,我非常怀疑这是否准确。我做错了什么?

哦,我尝试过使用 EnumDisplaySettings(非 Ex 之一),但它甚至不适用于 null 名称参数。

P/Invoke 签名(Ex 对 pinvoke.net 上的签名稍作修改,试图让它发挥作用):

[DllImport("user32.dll")]
public static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
public static extern bool EnumDisplaySettingsEx([MarshalAs(UnmanagedType.LPStr)]string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode, EdsDwFlags dwFlags);

DEVMODE 定义在http://www.pinvoke.net/default.aspx/Structures/DEVMODE.htmlEdsDwFlags 现在始终为零。 iModeNum 为 -1(当前设置)。

由于某种原因,StackOveflow 不允许我在这篇文章中附加 C# 标签。

【问题讨论】:

【参考方案1】:

我是个白痴,你应该给这个函数传递一个显示适配器,而不是一个监视器。只传递"\\.\DISPLAY1" 效果很好。

不过,我仍然会为 dmDeviceName 字段返回垃圾信息,因此,如果我有任何关于我是如何弄错的建议,我将不胜感激。

【讨论】:

我怀疑“cdd”代表“规范显示驱动程序”(Windows 中有一个名为 cdd.dll 的系统文件,它是规范显示驱动程序)。如果有人知道,请纠正我。 顺便说一句,根据DEVMODE.dmDeviceName 的文档,它应该代表与DISPLAY_DEVICE.DeviceName 相同的东西。您可以调用EnumDisplayDevices,传入"\\.\DISPLAY1" 并获取友好/显示名称。

以上是关于p/invoke 和 EnumDisplaySettingsEx 的困难的主要内容,如果未能解决你的问题,请参考以下文章

使用 P/Invoke 在托管和非托管回调链上引发异常

p/invoke 和 EnumDisplaySettingsEx 的困难

p/invoke 不平衡堆栈错误

与普通的 p/Invoke 调用相比,使用不安全的 P/Invoke 调用是不是有性能优势?

P/Invoke 和内存相关的间歇性崩溃

通过 P/Invoke 调用 GetGUIThreadInfo