Reputation: 303
Posting because the posts where this has been fixed are dead and the people maintaining the code haven't replied in months.
Traceback (most recent call last):
File "c:\Users\Combined_180222_desktop_version .py", line 510, in <module>
detection()
File "c:\Users\Combined_180222_desktop_version .py", line 464, in detection
r,g,b = py.pixel(x, y)
File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\pyscreeze\__init__.py", line 614, in pixel
return (r, g, b)
File "C:\Users\AppData\Local\Programs\Python\Python39\lib\contextlib.py", line 135, in __exit__
self.gen.throw(type, value, traceback)
File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\pyscreeze\__init__.py", line 123, in __win32_openDC
raise WindowsError("windll.user32.ReleaseDC failed : return 0")
OSError: windll.user32.ReleaseDC failed : return 0
I'm just trying to check the rgb
value of a pixel.
import pyautogui as py
x, y = 1742, 979
r, g, b = py.pixel(x, y)
if b == 106:
do_something()
When this stopped working I swapped to try
and except
as described here which worked for about two months but now the error is back.
import pyautogui as py
x, y = 1742, 979
r, g, b = py.pixel(x, y)
try:
if b == 106:
do_something()
except:
if b == 106:
do_somethinge()
I could link another half dozen posts all around the same error. There's a lot of information here about the route of the issue being pixel
and pyscreeze
being the route of the issue and in this stack Pyautogui and pyscreeze crash with windll.user32.ReleaseDC failed one of the pyscreeze
maintainers claims it was fixed back in 0.1.28
yet it's not fixed and I can't seem to find anyone who's doing anything other than talking about it not being fixed.
pip show pyscreeze
confirms I'm running 0.1.28
which is meant to contain the fix. Does anyone know how to fix this error?
It might be relevant so I'm posting this next section anyway but may remove it if not relevant to the answer. I am using windll.user32.ReleaseDC
elsewhere in a separate class:
import numpy as np
import win32gui, win32ui, win32con
class WindowCapture:
# properties
w = 0
h = 0
hwnd = None
cropped_x = 0
cropped_y = 0
offset_x = 0
offset_y = 0
# constructor
def __init__(self, window_name=None):
# find the handle for the window we want to capture.
# if no window name is given, capture the entire screen
if window_name is None:
self.hwnd = win32gui.GetDesktopWindow()
else:
self.hwnd = win32gui.FindWindow(None, window_name)
if not self.hwnd:
raise Exception('Window not found: {}'.format(window_name))
# get the window size
window_rect = win32gui.GetWindowRect(self.hwnd)
self.w = window_rect[2] - window_rect[0]
self.h = window_rect[3] - window_rect[1]
# account for the window border and titlebar and cut them off
border_pixels = 0
titlebar_pixels = 0
self.w = self.w - (border_pixels * 2)
self.h = self.h - titlebar_pixels - border_pixels
self.cropped_x = border_pixels
self.cropped_y = titlebar_pixels
# set the cropped coordinates offset so we can translate screenshot
# images into actual screen positions
self.offset_x = window_rect[0] + self.cropped_x
self.offset_y = window_rect[1] + self.cropped_y
def get_haystack(self):
# get the window image data
wDC = win32gui.GetWindowDC(self.hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)
# convert the raw data into a format opencv can read
# dataBitMap.SaveBitmapFile(cDC, 'debug.bmp')
signedIntsArray = dataBitMap.GetBitmapBits(True)
img = np.fromstring(signedIntsArray, dtype='uint8')
img.shape = (self.h, self.w, 4)
# free resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(self.hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
img = img[...,:3]
img = np.ascontiguousarray(img)
return img
@staticmethod
def list_window_names():
def winEnumHandler(hwnd, ctx):
if win32gui.IsWindowVisible(hwnd):
print(hex(hwnd), win32gui.GetWindowText(hwnd))
win32gui.EnumWindows(winEnumHandler, None)
# translate a pixel position on a screenshot image to a pixel position on the screen.
# pos = (x, y)
def get_screen_position(self, pos):
return (pos[0] + self.offset_x, pos[1] + self.offset_y)
Upvotes: 1
Views: 277