Skip to content

Commit add2957

Browse files
committedMay 1, 2021
Added return in list_window_names()
1 parent c9fadbd commit add2957

File tree

1 file changed

+53
-11
lines changed

1 file changed

+53
-11
lines changed
 

‎windowcapture.py

+53-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
from threading import Lock, Thread
2+
13
import numpy as np
2-
import win32gui, win32ui, win32con
4+
import win32con
5+
import win32gui
6+
import win32ui
37

48

59
class WindowCapture:
610

11+
# threading properties
12+
stopped = True
13+
lock = None
14+
screenshot = None
715
# properties
816
w = 0
917
h = 0
@@ -14,24 +22,27 @@ class WindowCapture:
1422
offset_y = 0
1523

1624
# constructor
17-
def __init__(self, window_name=None):
25+
def __init__(self, window_name=None, cut_window=1):
26+
# create a thread lock object
27+
self.lock = Lock()
28+
1829
# find the handle for the window we want to capture.
1930
# if no window name is given, capture the entire screen
2031
if window_name is None:
2132
self.hwnd = win32gui.GetDesktopWindow()
2233
else:
2334
self.hwnd = win32gui.FindWindow(None, window_name)
2435
if not self.hwnd:
25-
raise Exception('Window not found: {}'.format(window_name))
36+
raise Exception("Window not found: {}".format(window_name))
2637

2738
# get the window size
2839
window_rect = win32gui.GetWindowRect(self.hwnd)
2940
self.w = window_rect[2] - window_rect[0]
3041
self.h = window_rect[3] - window_rect[1]
3142

3243
# account for the window border and titlebar and cut them off
33-
border_pixels = 8
34-
titlebar_pixels = 30
44+
border_pixels = 8 * cut_window
45+
titlebar_pixels = 30 * cut_window
3546
self.w = self.w - (border_pixels * 2)
3647
self.h = self.h - titlebar_pixels - border_pixels
3748
self.cropped_x = border_pixels
@@ -51,12 +62,18 @@ def get_screenshot(self):
5162
dataBitMap = win32ui.CreateBitmap()
5263
dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
5364
cDC.SelectObject(dataBitMap)
54-
cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)
65+
cDC.BitBlt(
66+
(0, 0),
67+
(self.w, self.h),
68+
dcObj,
69+
(self.cropped_x, self.cropped_y),
70+
win32con.SRCCOPY,
71+
)
5572

5673
# convert the raw data into a format opencv can read
57-
#dataBitMap.SaveBitmapFile(cDC, 'debug.bmp')
74+
# dataBitMap.SaveBitmapFile(cDC, 'debug.bmp')
5875
signedIntsArray = dataBitMap.GetBitmapBits(True)
59-
img = np.fromstring(signedIntsArray, dtype='uint8')
76+
img = np.fromstring(signedIntsArray, dtype="uint8")
6077
img.shape = (self.h, self.w, 4)
6178

6279
# free resources
@@ -66,9 +83,9 @@ def get_screenshot(self):
6683
win32gui.DeleteObject(dataBitMap.GetHandle())
6784

6885
# drop the alpha channel, or cv.matchTemplate() will throw an error like:
69-
# error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type()
86+
# error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type()
7087
# && _img.dims() <= 2 in function 'cv::matchTemplate'
71-
img = img[...,:3]
88+
img = img[..., :3]
7289

7390
# make image C_CONTIGUOUS to avoid errors that look like:
7491
# File ... in draw_rectangles
@@ -84,15 +101,40 @@ def get_screenshot(self):
84101
# https://stackoverflow.com/questions/55547940/how-to-get-a-list-of-the-name-of-every-open-window
85102
@staticmethod
86103
def list_window_names():
104+
window_list = []
105+
87106
def winEnumHandler(hwnd, ctx):
88107
if win32gui.IsWindowVisible(hwnd):
89108
print(hex(hwnd), win32gui.GetWindowText(hwnd))
109+
window_list.append(win32gui.GetWindowText(hwnd))
110+
90111
win32gui.EnumWindows(winEnumHandler, None)
112+
return window_list
91113

92114
# translate a pixel position on a screenshot image to a pixel position on the screen.
93115
# pos = (x, y)
94116
# WARNING: if you move the window being captured after execution is started, this will
95117
# return incorrect coordinates, because the window position is only calculated in
96118
# the __init__ constructor.
97119
def get_screen_position(self, pos):
98-
return (pos[0] + self.offset_x, pos[1] + self.offset_y)
120+
return (pos[0] + self.offset_x, pos[1] + self.offset_y)
121+
122+
# threading methods
123+
124+
def start(self):
125+
self.stopped = False
126+
t = Thread(target=self.run)
127+
t.start()
128+
129+
def stop(self):
130+
self.stopped = True
131+
132+
def run(self):
133+
# TODO: you can write your own time/iterations calculation to determine how fast this is
134+
while not self.stopped:
135+
# get an updated image of the game
136+
screenshot = self.get_screenshot()
137+
# lock the thread while updating the results
138+
self.lock.acquire()
139+
self.screenshot = screenshot
140+
self.lock.release()

0 commit comments

Comments
 (0)
Please sign in to comment.