go - 如何在 go 中调用 user32.dll 的 EnumDisplaySettingsA
问题描述
我正在尝试通过 Win32 API 获取显示信息。到目前为止,我已经很好地管理了 EnumDisplayDevicesA,但是 EnumDisplaySettingsA 给我带来了麻烦。
无论我如何设置前两个变量,该函数都返回零(表示失败),没有关于失败原因的额外信息。
这是我的代码的简化版本,其中仅包含有问题的功能;
package main
import (
"fmt"
"syscall"
"unsafe"
)
var (
dll = syscall.MustLoadDLL("user32.dll")
enumDisplaySettings = dll.MustFindProc("EnumDisplaySettingsA")
)
type devMode struct {
dmDeviceName [32]uint16
dmSpecVersion uint16
dmDriverVersion uint16
dmSize uint16
dmDriverExtra uint16
dmFields uint32
dmOrientation int16
dmPaperSize int16
dmPaperLength int16
dmPaperWidth int16
dmScale int16
dmCopies int16
dmDefaultSource int16
dmPrintQuality int16
dmColor int16
dmDuplex int16
dmYResolution int16
dmTTOption int16
dmCollate int16
dmFormName [32]uint16
dmLogPixels uint16
dmBitsPerPel uint32
dmPelsWidth uint32
dmPelsHeight uint32
dmDisplayFlags uint32
dmDisplayFrequency uint32
dmICMMethod uint32
dmICMIntent uint32
dmMediaType uint32
dmDitherType uint32
dmReserved1 uint32
dmReserved2 uint32
dmPanningWidth uint32
dmPanningHeight uint32
}
func queryDisplaySettings() devMode {
out := devMode{}
out.dmSize = uint16(unsafe.Sizeof(out))
outptr := uintptr(unsafe.Pointer(&out))
namePtr := uintptr(unsafe.Pointer(nil))
var iModeNum uint32 = 4294967295
enumCurrentSettings := uintptr(unsafe.Pointer(&iModeNum))
ret, _, _ := enumDisplaySettings.Call(namePtr, enumCurrentSettings, outptr)
if ret == 0 {
fmt.Printf("Failed EnumDisplaySettings")
}
return out
}
func main() {
settings := queryDisplaySettings()
fmt.Printf("\n%v\n", settings.dmPelsWidth)
fmt.Printf("%v\n", settings.dmPelsHeight)
fmt.Printf("%v\n\n", settings.dmDisplayFrequency)
}
我的来源:
- https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaysettingsw
- https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodea
- https://github.com/JamesHovious/w32/blob/74b38b9b07b520e0f84a5eec5daada6c7b6a2471/typedef.go#L363
- https://docs.rs/winapi/0.2.0/i686-pc-windows-msvc/winapi/constant.ENUM_CURRENT_SETTINGS.html
解决方案
这里的代码存在多个问题。
首先,您的 devMode 类型定义是针对 DEVMODEW 的,但您正在调用 EnumDisplaySettingsA。但是,您不应该首先调用它(它是 ANSI 版本),所以请改用 EnumDisplaySettingsW(UNICODE)。
接下来,EnumDisplaySettingsA/EnumDisplaySettingsW 的第二个参数是一个 DWORD (uint32),但是不是传递值,而是传递地址给它。
所以更换
var iModeNum uint32 = 4294967295
enumCurrentSettings := uintptr(unsafe.Pointer(&iModeNum))
只需
iModeNum := uintptr(4294967295)
这一切都应该正常工作。
推荐阅读
- java - 如果还有其他有效的八位位组,我不确定如何列出无效的八位位组
- python - 如何刮取 NBA 首发阵容并创建 Pandas DataFrame?
- c# - “ValidateExecutableReferences”任务意外失败
- typescript - 对条件类型参数的混淆;为什么不编译?
- node.js - MongoDB:findOne 没有按预期工作?
- python - 由于 ModuleNotFoundError,pytest 在 AWS SAM 项目中失败
- python - 根据多个条件过滤像素
- javascript - 在firebase 9中访问文档中的集合
- python - 遍历 XLSX 工作簿并将唯一值保存在从数据框到单个工作表的卷中
- postgresql - 多个 Postgres Docker 服务