#1 - 2022-9-22 11:14
冈崎羽未鹰原汐 (二阶堂芽爱 小河坂青空)
解决方案:
        from win32 import win32api, win32gui, win32print
        import win32con  # 为了得到两个常量,可以不导入
        # 获取所有逻辑屏幕的信息,得到虚拟分辨率和逻辑监视器句柄 hMonitor
        # 逻辑监视器信息(tuple): (hMonitor句柄, hdcMonitor没卵用, PyRECT包围盒)
        scInfos = win32api.EnumDisplayMonitors()
        for index, sc in enumerate(scInfos):
            # 获取设备信息字典,得到设备名称 Device
            # 物理设备信息(dict) = GetMonitorInfo(hMonitor)
            info = win32api.GetMonitorInfo(sc[0])
            # 为显示设备创建设备上下文,得到物理设备句柄 hDC
            # 设备句柄(int) = CreateDC (设备名称, 设备名称 , None )
            hDC = win32gui.CreateDC(info['Device'], info['Device'], None)
            w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
            h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)

            print(f'第{index}号屏幕:')
            print(f'设备名称:{info["Device"]}')
            print(f'物理分辨率 w: {w}   h: {h}')
            print(f'逻辑分辨率 w: {sc[2][2]-sc[2][0]}   h: {sc[2][3]-sc[2][1]}')
            print(f'逻辑坐标系 x: {sc[2][0]}   y: {sc[2][1]}')
            print()


==================== 坑点 =============================

设备名称一定要用 GetMonitorInfo 获取。用 EnumDisplayDevices 得到的设备名称是错的(或者说,index对应的不是正在使用的物理显示器)!
# 获取第二块屏幕的名称
index = 1 # 第二块屏幕

device = win32api.EnumDisplayDevices(DevNum=index)   #  错!!
print(f'设备名称:{device.DeviceName}') # 这个DeviceName是不能被CreateDC识别的!

info = win32api.GetMonitorInfo( win32api.EnumDisplayMonitors()[index][0] )  # 对!
print(f'设备名称:{info["Device"]}')           # 这个Device才能被CreateDC识别!

==================== 以下原帖 =============================

我正在写一个选区截图模块,目标之一是能适配多屏幕。

我的思路是获取整块虚拟屏幕(所有屏幕拼起来的画面)的完整截图。然后创造一个置顶的无边框窗口,窗口的左上角设为虚拟屏幕的左上角,窗口的宽高设为虚拟屏幕的宽高,然后在窗口上显示完整截图。这样,截图的位置就能与每个显示器的位置相对应。最后,监听鼠标拖拽来获取截图选区。

目前,我的代码在单块屏幕或多块同缩放比例的屏幕上工作良好。(缩放比例即为windows的更改文本、应用等项目的大小)。但是,当其中一块屏幕的缩放比例与其他不同时,我的程序会出现显示错位的情况;原因是  EnumDisplayMonitors() 只能获取每块屏幕的逻辑分辨率(缩放后)。也许需要获取物理分辨率或缩放系数来配合调整。

用这一段代码可以获得主屏幕的物理分辨率,但是似乎没办法获取其他屏幕。将 EnumDisplayMonitors 得到的第二屏幕的句柄填入 GetDC 或 GetDeviceCaps 似乎也不起作用。
hDC = win32gui.GetDC(0)
w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)


所以求个助,有什么办法可以获取多屏幕的物理分辨率 or 缩放系数呢?或者说我截图模块的设计思路不对,有更好的思路呢?
#2 - 2022-9-22 11:45
(V1046-R MAHORO)
#2-1 - 2022-9-22 17:25
冈崎羽未鹰原汐
感谢,顺着这条线索一路找下去,找到解决方案了(bgm89)见主楼
#2-2 - 2022-9-22 22:13
烈之斩
冈崎羽未鹰原汐 说: 感谢,顺着这条线索一路找下去,找到解决方案了见主楼
记得考虑一下各种奇葩的摆放方式,比如我这种(

第0号屏幕:453059800
设备名称:\\.\DISPLAY1
物理分辨率 w: 1920   h: 1080
逻辑分辨率 w: 1920   h: 1080
逻辑坐标系 x: 0   y: 0

第1号屏幕:-654236552
设备名称:\\.\DISPLAY2
物理分辨率 w: 1080   h: 1920
逻辑分辨率 w: 1080   h: 1920
逻辑坐标系 x: -1080   y: -527
#2-3 - 2022-9-24 12:54
冈崎羽未鹰原汐
烈之斩 说: 记得考虑一下各种奇葩的摆放方式,比如我这种(

第0号屏幕:453059800
设备名称:\\.\DISPLAY1
物理分辨率 w: 1920   h: 1080
逻辑分辨率 w:...
第二块屏幕在左上角?可真是够奇葩的,不卡鼠标么(bgm38)

只要两块屏幕的缩放比例相同(比如你这都是100%),我的截屏都能完美匹配。头疼的是不同缩放比的屏幕组合(bgm39)