使用Windows发送DDC/CI命令以在Windows上进行监视吗? [英] Sending DDC/CI commands to monitor on Windows using Python?

查看:782
本文介绍了使用Windows发送DDC/CI命令以在Windows上进行监视吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望从Windows控制我的监视器(诸如更改输入源之类的简单操作),但是找不到从Python发送DDC/CI命令的方法...

I would like to have my monitors controlled from Windows (simple stuff such as changing the input source), but cannot find a way of sending DDC/CI commands from Python...

关于库或方法的任何线索可以在这里提供帮助吗?

Any clue about a library or method that could help here?

推荐答案

使用 ctypes 调用它们并不难.

This is easily possible using the windows monitor API. I don't think there are any Python bindings out there and pywin32 doesn't contain those functions. However, using ctypes to call them is not that hard.

这里有一个示例,它可以将显示器先关闭然后再打开;它应该很容易适应更改输入源等的情况.唯一复杂的部分毕竟是获取物理监视器的手柄:

Here's an example that switches the monitor to soft-off and then back on; it should be pretty easy to adapt it to changing the input source etc. The only complicated part is getting the handles for the physical monitors after all:

from ctypes import windll, byref, Structure, WinError, POINTER, WINFUNCTYPE
from ctypes.wintypes import BOOL, HMONITOR, HDC, RECT, LPARAM, DWORD, BYTE, WCHAR, HANDLE


_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(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()


def set_vcp_feature(monitor, code, value):
    """Sends a DDC command to the specified monitor.

    See this link for a list of commands:
    ftp://ftp.cis.nctu.edu.tw/pub/csie/Software/X11/private/VeSaSpEcS/VESA_Document_Center_Monitor_Interface/mccsV3.pdf
    """
    if not windll.dxva2.SetVCPFeature(HANDLE(monitor), BYTE(code), DWORD(value)):
        raise WinError()


# Switch to SOFT-OFF, wait for the user to press return and then back to ON
for handle in _iter_physical_monitors():
    set_vcp_feature(handle, 0xd6, 0x04)
    raw_input()
    set_vcp_feature(handle, 0xd6, 0x01)

这篇关于使用Windows发送DDC/CI命令以在Windows上进行监视吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆