【问题标题】:ctypes: passing and reading an enum pointerctypes:传递和读取枚举指针
【发布时间】:2014-12-06 13:01:17
【问题描述】:

This page 说:

未实现枚举类型。你自己就可以轻松搞定 使用 c_int 作为基类。

如果很简单,为什么还没有实现?例如,我如何get the current color temperature of my monitor

BOOL GetMonitorColorTemperature(
  _In_   HANDLE hMonitor,
  _Out_  LPMC_COLOR_TEMPERATURE pctCurrentColorTemperature
);

Parameters

hMonitor [in]

    Handle to a physical monitor. To get the monitor handle, call GetPhysicalMonitorsFromHMONITOR or GetPhysicalMonitorsFromIDirect3DDevice9.
pctCurrentColorTemperature [out]

    Receives the monitor's current color temperature, specified as a member of the MC_COLOR_TEMPERATURE enumeration.

Return value

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call GetLastError.

这是我能得到的最接近的:

from ctypes import *

import win32api  # http://sourceforge.net/projects/pywin32/files/pywin32/

for idx, (hMon, hDC, (left, top, right, bottom)) in enumerate(win32api.EnumDisplayMonitors(None, None)):
    print(hMon.handle)  # or int(hMon)

class MyEnum(c_int):
    MC_COLOR_TEMPERATURE_UNKNOWN = 0
    MC_COLOR_TEMPERATURE_4000K = 1
    MC_COLOR_TEMPERATURE_5000K = 2
    MC_COLOR_TEMPERATURE_6500K = 3
    MC_COLOR_TEMPERATURE_7500K = 4
    MC_COLOR_TEMPERATURE_8200K = 5
    MC_COLOR_TEMPERATURE_9300K = 6
    MC_COLOR_TEMPERATURE_10000K = 7
    MC_COLOR_TEMPERATURE_11500K = 8

o = MyEnum()
print(o)
po = pointer(o)
t = windll.dxva2.GetMonitorColorTemperature(hMon.handle, po)  #byref(o))
#print(dir(o))
print(o)
print(po.contents)
print(t)
print(windll.kernel32.GetLastError())  # ERROR_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = -1071241844 # Variable c_long '-0x03fd9da74'

...返回这个:

65537
65539
<MyEnum object at 0x006F6DA0>
<MyEnum object at 0x006F6DA0>
<MyEnum object at 0x0234FAD0>
0
-1071241844

这两个监视器句柄都是一样的。我做错了什么?

【问题讨论】:

    标签: python enums ctypes pywin32


    【解决方案1】:

    使用this answer,我不知何故发现它使用None 作为物理监视器句柄:

    from ctypes import *
    from ctypes.wintypes import BOOL, HMONITOR, HDC, RECT, LPARAM, DWORD, BYTE, WCHAR, HANDLE
    
    import win32api  # http://sourceforge.net/projects/pywin32/files/pywin32/
    
    _MONITORENUMPROC = WINFUNCTYPE(BOOL, HMONITOR, HDC, POINTER(RECT), LPARAM)
    
    class _PHYSICAL_MONITOR(Structure):
        _fields_ = [('handle', HANDLE),
                    ('description', WCHAR * 128)]
    
    
    def _iter_physical_monitors(close_handles=True):
        """Iterates physical monitors.
    
        The handles are closed automatically whenever the iterator is advanced.
        This means that the iterator should always be fully exhausted!
    
        If you want to keep handles e.g. because you need to store all of them and
        use them later, set `close_handles` to False and close them manually."""
    
        def callback(hmonitor, hdc, lprect, lparam):
            monitors.append(hmonitor)
            return True
    
        monitors = []
        if not windll.user32.EnumDisplayMonitors(None, None, _MONITORENUMPROC(callback), None):
            raise WinError('EnumDisplayMonitors failed')
    
        for monitor in monitors:
            # Get physical monitor count
            count = DWORD()
            if not windll.dxva2.GetNumberOfPhysicalMonitorsFromHMONITOR(monitor, byref(count)):
                raise WinError()
            # Get physical monitor handles
            physical_array = (_PHYSICAL_MONITOR * count.value)()
            if not windll.dxva2.GetPhysicalMonitorsFromHMONITOR(monitor, count.value, physical_array):
                raise WinError()
            for physical in physical_array:
                yield physical.handle
                if close_handles:
                    if not windll.dxva2.DestroyPhysicalMonitor(physical.handle):
                        raise WinError()
    
    mons = [m for m in _iter_physical_monitors(False)]
    
    #for idx, (hMon, hDC, (left, top, right, bottom)) in enumerate(win32api.EnumDisplayMonitors(None, None)):
    #   print(hMon.handle)  # or int(hMon)
    
    temps = (
        'UNKNOWN',
        '4000K',
        '5000K',
        '6500K',
        '7500K',
        '8200K',
        '9300K',
        '10000K',
        '11500K'
    )
    class MyEnum(c_int):
        MC_COLOR_TEMPERATURE_UNKNOWN = 0
        MC_COLOR_TEMPERATURE_4000K = 1
        MC_COLOR_TEMPERATURE_5000K = 2
        MC_COLOR_TEMPERATURE_6500K = 3
        MC_COLOR_TEMPERATURE_7500K = 4
        MC_COLOR_TEMPERATURE_8200K = 5
        MC_COLOR_TEMPERATURE_9300K = 6
        MC_COLOR_TEMPERATURE_10000K = 7
        MC_COLOR_TEMPERATURE_11500K = 8
    
    o = MyEnum()
    print(o)
    po = pointer(o)
    
    pm = mons[0]
    print("physical %r" % pm)
    t = windll.dxva2.GetMonitorColorTemperature(pm, po)  #byref(o))
    if t:
        #print(o)
        #print(dir(po.contents))
        print(temps[po.contents.value])
    
    else:
        print("Err: %s" % windll.kernel32.GetLastError())  # ERROR_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = -1071241844 # Variable c_long '-0x03fd9da74'
    

    结果:

    <MyEnum object at 0x005D6120>
    physical None
    6500K
    

    【讨论】:

      猜你喜欢
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 2011-05-11
      相关资源
      最近更新 更多