0

I have a working Python script that captures the width and height of the work area of my primary monitor by the following code.

# First, install library win32api by executing as administrator
# the command "pip install pywin32" in PowerShell. Then,

from win32api import MonitorFromPoint, GetMonitorInfo
handle_for_primary_monitor = MonitorFromPoint((0,0))
monitor_info = GetMonitorInfo(handle_for_primary_monitor)
work_area_info = monitor_info.get("Work")
width_of_work_area = work_area_info[2]
height_of_work_area = work_area_info[3]

Visual Studio Code erroneously throws the following two errors:

Error_in_Automatic_Debugging_of_Python_Script_in_VSCode

How do I get Visual Studio Code to recognize that class MonitorFromPoint and method GetMonitorInfo actually are in the win32api library?

Tom Lever
  • 321
  • 3
  • 16

2 Answers2

1

This error is due to Pylint.

In fact, Pylint does not run Python code during analysis, so most of non-standard (non-inferable) constructs have to be supported by writing custom code.

Refer: Why is pylint unable to find this package's module(s)?

There are two ways to solve this problem:

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • Thank you for your suggestions, Strive Sun. I believe I'm running the latest version of pylint. Reading the comments in the answer associated with your link, "Why is pylint unable to find this package's module(s)?", it seems that I could use a version of pylint or astroid from a GitHub repository or edit pylint source code. Do you have any idea how this could be set up? – Tom Lever Jan 22 '20 at 17:18
  • @TomLever Have you tried `# pylint: disable-msg=E0611`? If you don't know how to add, please refer [this](https://stackoverflow.com/a/29562085/11128312). – Strive Sun Jan 23 '20 at 08:01
  • Hi Strive Sun. My instinct is to not disable messages, as I'm not sure what useful information would be disabled in the future. Thanks for the resource. – Tom Lever Jan 27 '20 at 02:52
1

As a workaround, you can use the ctypes.windll:

import ctypes
from ctypes.wintypes import tagPOINT
from ctypes import *
class RECT(Structure):
    _fields_ = [
        ("left", c_long),
        ("top", c_long),
        ("right", c_long),
        ("bottom", c_long),
    ]
class MONITORINFOEXA(Structure):
    _fields_ = [
        ("cbSize", c_ulong),
        ("rcMonitor", RECT),
        ("rcWork", RECT),
        ("dwFlags", c_ulong),
        ("szDevice", c_char*32),
    ]
class MONITORINFOEXW(Structure):
    _fields_ = [
        ("cbSize", c_ulong),
        ("rcMonitor", RECT),
        ("rcWork", RECT),
        ("dwFlags", c_ulong),
        ("szDevice", c_wchar*32),
    ]
point = tagPOINT(0,0)
handle_for_primary_monitor = ctypes.windll.user32.MonitorFromPoint(point,0)
print(handle_for_primary_monitor)
monitorinfo = MONITORINFOEXW()
#monitorinfo.cbSize = 72 #sizeof(MONITORINFOEXA) = 72 ;sizeof(MONITORINFOEXW) = 104
monitorinfo.cbSize = 104
monitorinfo.dwFlags = 0x01 #MONITORINFOF_PRIMARY
#ctypes.windll.user32.GetMonitorInfoW(handle_for_primary_monitor,byref(monitorinfo))
ctypes.windll.user32.GetMonitorInfoW(handle_for_primary_monitor,byref(monitorinfo))
Monitor_width =  monitorinfo.rcMonitor.right - monitorinfo.rcMonitor.left
Monitor_height =  monitorinfo.rcMonitor.bottom - monitorinfo.rcMonitor.top
Work_width = monitorinfo.rcWork.right - monitorinfo.rcWork.left
Work_height = monitorinfo.rcWork.bottom - monitorinfo.rcWork.top
print(monitorinfo.szDevice)
print(Monitor_width)
print(Monitor_height)
print(Work_width)
print(Work_height)
Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • Would you describe how to define the MONITORINFOEX struct? – Tom Lever Jan 30 '20 at 18:09
  • Please see my update, and feel free to tell me if you have any other problems. – Drake Wu Jan 31 '20 at 02:35
  • Does the solution help to you? – Drake Wu Feb 03 '20 at 07:11
  • Thanks for checking in. I'm getting the byte array b'\\\\.\\DISPLAY1' for monitorinfo.szDevice. I see how your defining the upper left corner of the first monitor, defining a handle, creating a MONITORINFOEXA object and its cbSize property. What does GetMonitorInfoA do? – Tom Lever Feb 03 '20 at 17:58
  • GetMonitorInfo[[A](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmonitorinfoa)]/[[W](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmonitorinfow)] are the multibyte and unicode version, specify the member `szDevice` is a `char` or `wchar_t` array. – Drake Wu Feb 04 '20 at 01:10
  • Hi Drake. If I print(monitorinfo.szDevice.decode("utf-8")), I get a string reading "\\\\.\\DISPLAY1". If I use GetMonitorInfoW, I get an empty byte array / string. How do I get a tuple of integers indicating the width and height of my primary monitor? – Tom Lever Feb 07 '20 at 18:35
  • @TomLever For `GetMonitorInfoW`, you need to define a `MONITORINFOEXW` struct. For width and height, just need to use `monitorinfo.rcMonitor.right - monitorinfo.rcMonitor.left` and `monitorinfo.rcMonitor.bottom - monitorinfo.rcMonitor.top`, if you want to get the width/height of the work area, use `monitorinfo.rcWork.right - monitorinfo.rcWork.left` and `monitorinfo.rcWork.bottom - monitorinfo.rcWork.top`. See the update. – Drake Wu Feb 10 '20 at 01:19
  • Hi Drake. Sorry for the delayed response. Your solution works perfectly, though in production I would probably import only some components from the ctypes library. Thank you for sticking with me, checking in, and helping me find an alternative. I learned about Cython, too. I gave you a thumbs-up. – Tom Lever Mar 09 '20 at 01:25
  • @TomLever And please feel free to [accept](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) this answer for the people with the same issue – Drake Wu Mar 10 '20 at 02:31