问题描述
我正在制作一个可以做很多事情的实用程序脚本.我想做的一件事是旋转显示器;我有多个显示器,我希望主显示器旋转.我知道这种事情通常通过 win32api
起作用,我发现其中的一些功能似乎很有帮助,但我正在努力实现.
此行和下一行之间的所有内容都已过时,请参阅下面的第二行以获取对解决方案尝试的最新描述
在将我的脸埋在文档中之后,恐怕我仍然没有太多关于如何前进的想法,除了它可能涉及 win32api.ChangeDisplaySettingsEx()
.我知道我需要给那个函数一个指向 DEVMODE
对象的指针(甚至不确定如何在 python 中做 C 指针),我想我可以从 win32api.EnumDisplaySettingsEx()代码>.所以如果我尝试,
我应该得到一些涉及 DEVMODE
指针或其他什么的东西,但我得到了
我不知道该怎么做,但我认为 这是结构
那么,我如何获得可以提供给 ChangeDisplaySettingsEx()
的 DEVMODE
对象,以便我可以旋转我的一个显示器?提前致谢.
我在 Windows 7 上运行 Python 2.7
如果我使用正确的功能,它仍然不起作用.这可能是 Python 模块不完整吗?
>>>a = win32.EnumDisplaySettings()>>>类型(一)<输入'PyDEVMODEA'>>>>尺寸回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 'PyDEVMODEA' 对象没有属性 'dmSize'>>>a.dmScale回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 'PyDEVMODEA' 对象没有属性 'dmScale'>>>a.dmDisplayOrientation回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中AttributeError: 'PyDEVMODEA' 对象没有属性 'dmDisplayOrientation'现在,我注意到这给了我一个 DEVMODEA
对象而不是 DEVMODE
,但是 这个页面 说它们是一样的.这可能是什么问题?
现在我使用了正确的属性名称,我可以获得一个有效的 DEVMODEA
对象:
并改变对象的方向:
>>>a.DisplayOrientation = 90L>>>a.显示方向90L然后我可以通过将这个 DEVMODEA
对象提供给 ChangeDisplaySettingsEx()
我发现 -5L
返回值表示一个错误的参数.具体来说,它对第一个字段感到愤怒.如果我用 DISPLAY_DEVICE.DeviceName
替换它,我会得到 -2L
结果.这对应于坏模式(无论是什么).即使我给 ChangeDisplaySettingsEx()
提供了 EnumDisplaySettings()
输出的内容,也会发生这种情况.
到目前为止我的进展:
>>>将 win32api 导入为 win32>>>导入 win32con>>>a = win32.EnumDisplaySettings()>>>a.显示方向0升>>>a.DisplayOrientation = win32con.DMDO_90>>>a.显示方向1L>>>a.PelsWidth, a.PelsHeight = a.PelsHeight, a.PelsWidth>>>a.Fields = a.Fields &win32con.DM_DISPLAYORIENTATION>>>name = win32.EnumDisplayDevices().DeviceName>>>姓名'\\\\.\\DISPLAY1'>>>win32.ChangeDisplaySettingsEx(name, a)-2L最近的尝试(美国东部时间 6 月 4 日上午 10:50)
Python 2.7.6(默认,2013 年 11 月 10 日,19:24:18)[MSC v.1500 32 位(英特尔)] on win32输入帮助"、版权"、信用"或许可"以获取更多信息.>>>将 win32api 导入为 win32>>>导入 win32con>>>>>>device = win32.EnumDisplayDevices(None, 1)>>>打印旋转设备 {} ({})".format(device.DeviceString, device.DeviceName)旋转设备 Intel(R) HD Graphics 4000 (\\.\DISPLAY2)>>>>>>dm = win32.EnumDisplaySettings(device.DeviceName, win32con.ENUM_CURRENT_SETTINGS)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中pywintypes.error: (0, 'EnumDisplaySettings', '没有可用的错误信息')>>>>>>dm = win32.EnumDisplaySettings(device.DeviceName)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中pywintypes.error: (123, 'EnumDisplaySettings', '文件名、目录名或卷标语法不正确.')>>>>>>dm = win32.EnumDisplaySettings(device.DeviceName, win32con.ENUM_CURRENT_SETTINGS)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中pywintypes.error: (123, 'EnumDisplaySettings', '文件名、目录名或卷标语法不正确.')>>>
注意创建 dm
的第一次和第三次尝试如何失败尽管代码相同,但出现不同的错误.
您正在调用返回 PDISPLAY_DEVICE 的 EnumDisplayDevices
API.(请参阅 http://msdn.microsoft.com/en-us/library/windows/desktop/dd162609(v=vs.85).aspx)
您可以通过两种方式获取对象:
1) 来自 EnumDisplayDevicesEx
>>>导入 win32api>>>win32api.EnumDisplaySettingsEx()<0x00512E78处的PyDEVMODEA对象>2) 或创建它(它将是空的)
>>>导入pywintypes;>>>dmode = pywintypes.DEVMODEType()>>>类型(dmode)<输入'PyDEVMODEA'>对象公开的属性不命名为win32"版本:例如dmSize
变成Size
完整列表可以在 PyDEVMODEA
对象上使用 dir(dmode)
命令可以看到.
可以使用 PyDEVMODEA
对象上的 help(dmode)
命令读取字段的描述.
完整的详细映射参考pywin32源代码分发内的PyDEVMODE.cpp
旋转显示器的步骤是:
获取开发模式
获取显示名称
设置旋转
使用 a.Fields = a.Fields & 配置标志win32con.DM_DISPLAYORIENTATION
调用 ChangeDisplaySettingsEx
在您的脚本中,您缺少 3-5 步.(字段也用作二进制掩码,因此必须相应处理).
您可以在 msdn 站点上看到有关 api 使用(C 语言)的完整示例:http://msdn.microsoft.com/en-us/library/ms812499.aspx
编辑 3在设置旋转"期间,您还必须交换宽度和高度,否则您要求的屏幕模式是不可能的:
(dmode.PelsWidth,dmode.PelsHeight) = (dmode.PelsHeight,dmode.PelsWidth)
EDIT4一个完整的例子(没有错误检查):
导入win32api为win32导入 win32condef printAllScreen():我 = 0为真:尝试:device = win32.EnumDisplayDevices(None,i);print("[%d] %s (%s)"%(i,device.DeviceString,device.DeviceName));i = i+1;除了:休息;返回我screen_count=printAllScreen()x = int(input("\n请输入一个显示数字 [0-%d]: "%screen_count-1))device = win32.EnumDisplayDevices(None,x);print("旋转设备 %s (%s)"%(device.DeviceString,device.DeviceName));dm = win32.EnumDisplaySettings(device.DeviceName,win32con.ENUM_CURRENT_SETTINGS)dm.DisplayOrientation = win32con.DMDO_90dm.PelsWidth, dm.PelsHeight = dm.PelsHeight, dm.PelsWidthdm.Fields = dm.Fields &win32con.DM_DISPLAYORIENTATIONwin32.ChangeDisplaySettingsEx(device.DeviceName,dm)
I'm working on making a utility script that does a whole bunch of things. One of the things I want to do is to rotate a display; I have multiple monitors, and I want the main one to rotate. I know this sort of thing usually works through win32api
and I found a few functions there that seem helpful, but I'm struggling with the implementation.
Everything between this line and the next is out of date, see below second line for up to date description of solution attempts
After burying my face in the docs, I'm afraid I still don't have much of an idea on how to move forward aside from that it will likely involve win32api.ChangeDisplaySettingsEx()
. I know I need to give that function a pointer to a DEVMODE
object (not even sure how to do C pointers in python), which I think I can get from win32api.EnumDisplaySettingsEx()
. So if I try,
>>> import win32api as win32
>>> a = win32.EnumDisplayDevices()
>>> type(a)
I should get something that involves DEVMODE
pointer or whatever, but instead I get
>>> type(a)
<type 'PyDISPLAY_DEVICE'>
And I have no idea what to do with that, but I think this is the structure
So, how do I get a DEVMODE
ojbect I can give to ChangeDisplaySettingsEx()
so that I can rotate one of my displays? Thanks in advance.
I'm running Python 2.7 on Windows 7
EDIT: If I acutally use the correct function, it still doesn't work. Could this be the Python module be not complete?
>>> a = win32.EnumDisplaySettings()
>>> type(a)
<type 'PyDEVMODEA'>
>>> a.dmSize
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'PyDEVMODEA' object has no attribute 'dmSize'
>>> a.dmScale
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'PyDEVMODEA' object has no attribute 'dmScale'
>>> a.dmDisplayOrientation
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'PyDEVMODEA' object has no attribute 'dmDisplayOrientation'
Now, I noticed that this is giving me a DEVMODEA
object instead of DEVMODE
, but this page says they're the same. What could be the issue here?
EDIT: Now that I'm using the correct attribute names, I can get a valid DEVMODEA
object:
>>> a = win32.EnumDisplaySettings()
>>> a.Size
124L
>>> a.DisplayOrientation
0L
And change the orientation in the object:
>>> a.DisplayOrientation = 90L
>>> a.DisplayOrientation
90L
I can then attempt to "apply" these changes by giving this DEVMODEA
object to ChangeDisplaySettingsEx()
>>> win32.ChangeDisplaySettingsEx(a.DeviceName, a, 0)
-5L
I've worked out that -5L
return value indicates a bad parameter. Specifically, its angry at the first field. If I replace that with DISPLAY_DEVICE.DeviceName
, I get a -2L
result. This corresponds to a bad mode (whatever that is). This happens even if I give ChangeDisplaySettingsEx()
exactly what EnumDisplaySettings()
puts out.
So my progress so far:
>>> import win32api as win32
>>> import win32con
>>> a = win32.EnumDisplaySettings()
>>> a.DisplayOrientation
0L
>>> a.DisplayOrientation = win32con.DMDO_90
>>> a.DisplayOrientation
1L
>>> a.PelsWidth, a.PelsHeight = a.PelsHeight, a.PelsWidth
>>> a.Fields = a.Fields & win32con.DM_DISPLAYORIENTATION
>>> name = win32.EnumDisplayDevices().DeviceName
>>> name
'\\\\.\\DISPLAY1'
>>> win32.ChangeDisplaySettingsEx(name, a)
-2L
Most recent attempt (6/4, 10:50am EST)
Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32api as win32
>>> import win32con
>>>
>>> device = win32.EnumDisplayDevices(None, 1)
>>> print "Rotate device {} ({})".format(device.DeviceString, device.DeviceName)
Rotate device Intel(R) HD Graphics 4000 (\\.\DISPLAY2)
>>>
>>> dm = win32.EnumDisplaySettings(device.DeviceName, win32con.ENUM_CURRENT_SETTINGS)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
pywintypes.error: (0, 'EnumDisplaySettings', 'No error message is available')
>>>
>>> dm = win32.EnumDisplaySettings(device.DeviceName)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
pywintypes.error: (123, 'EnumDisplaySettings', 'The filename, directory name, or volume label syntax is incorrect.')
>>>
>>> dm = win32.EnumDisplaySettings(device.DeviceName, win32con.ENUM_CURRENT_SETTINGS)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
pywintypes.error: (123, 'EnumDisplaySettings', 'The filename, directory name, or volume label syntax is incorrect.')
>>>
Notice how the first and third attempt to create dm
fail with different errors despite being the same code.
You are calling the EnumDisplayDevices
API that returns a PDISPLAY_DEVICE.(see http://msdn.microsoft.com/en-us/library/windows/desktop/dd162609(v=vs.85).aspx)
You can obtain the object in two way:
1) From EnumDisplayDevicesEx
>>> import win32api
>>> win32api.EnumDisplaySettingsEx()
<PyDEVMODEA object at 0x00512E78>
2) or creating it (it will be empty)
>>> import pywintypes;
>>> dmode = pywintypes.DEVMODEType()
>>> type(dmode)
<type 'PyDEVMODEA'>
EDIT:
the property exposed by the object are not named like the "win32" version: for example dmSize
becomes Size
the full list can be seen with dir(dmode)
command on PyDEVMODEA
object.
The description of the fields can be read with the help(dmode)
command on a PyDEVMODEA
object.
For a full detailed mapping refer to PyDEVMODE.cpp
inside the pywin32 source distribution
EDIT2:The procedure to rotate the monitor is:
Get Devmode
Get DisplayName
Set Rotation
Configure the flags with a.Fields = a.Fields & win32con.DM_DISPLAYORIENTATION
Invoke ChangeDisplaySettingsEx
In your script you are missing steps from 3-5. (also Fields is used as a binary mask so must handled corrispondly).
You can see a complete example about the api usage (in C) on the msdn site:http://msdn.microsoft.com/en-us/library/ms812499.aspx
Edit3During "Set Rotation" you must also need to swap width and height, otherwise you are asking an screen mode that is not possible:
(dmode.PelsWidth,dmode.PelsHeight) = (dmode.PelsHeight,dmode.PelsWidth)
EDIT4A complete example (with no error checking):
import win32api as win32
import win32con
def printAllScreen():
i = 0
while True:
try:
device = win32.EnumDisplayDevices(None,i);
print("[%d] %s (%s)"%(i,device.DeviceString,device.DeviceName));
i = i+1;
except:
break;
return i
screen_count=printAllScreen()
x = int(input("\nEnter a display number [0-%d]: "%screen_count-1))
device = win32.EnumDisplayDevices(None,x);
print("Rotate device %s (%s)"%(device.DeviceString,device.DeviceName));
dm = win32.EnumDisplaySettings(device.DeviceName,win32con.ENUM_CURRENT_SETTINGS)
dm.DisplayOrientation = win32con.DMDO_90
dm.PelsWidth, dm.PelsHeight = dm.PelsHeight, dm.PelsWidth
dm.Fields = dm.Fields & win32con.DM_DISPLAYORIENTATION
win32.ChangeDisplaySettingsEx(device.DeviceName,dm)
这篇关于以编程方式旋转监视器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!