go - 如何在go中调用user32.dll的EnumDisplaySettingsA

标签 go winapi user32

我正在尝试通过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)
    
    它应该都可以正常工作。

    关于go - 如何在go中调用user32.dll的EnumDisplaySettingsA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63570600/

    相关文章:

    c++ - TerminateProcess 上的 ERROR_INVALID_HANDLE (VS C++)

    c# - 当外部应用程序的窗口移动时移动窗口

    powershell - 如何使用 Register-ObjectEvent 检测 PowerShell 中进程的 MainWindowTitle 的更改?

    docker - 如何在 Golang 中模拟 docker ApiClient?

    json - 使用 Go 解析 .Net JSON 日期

    json - 你如何在 Golang 中修改这个结构来接受两个不同的结果?

    c# - 使用我的 C# 应用程序从谷歌浏览器中获取文本

    amazon-web-services - 可以从 SQS url 获取 AWS 区域吗?

    c++ - 如何使用 C++ 迭代器调用 Win32 API 函数 `WriteFile()`?

    c++ - 从 VS2013 构建 XP 驱动程序