@@ -68,28 +68,19 @@ class BITMAPINFO(ctypes.Structure):
6868class MSS (MSSMixin ):
6969 """ Multiple ScreenShots implementation for Microsoft Windows. """
7070
71- __slots__ = {
72- "_bbox" ,
73- "_bmi" ,
74- "_bmp" ,
75- "_data" ,
76- "_memdc" ,
77- "_srcdc" ,
78- "gdi32" ,
79- "monitorenumproc" ,
80- "user32" ,
81- }
71+ __slots__ = {"_bbox" , "_bmi" , "_data" , "gdi32" , "monitorenumproc" , "user32" }
72+
73+ # Class attributes instancied one time to prevent resource leaks.
74+ bmp = None
75+ memdc = None
76+ srcdc = None
8277
8378 def __init__ (self , ** _ ):
8479 # type: (Any) -> None
8580 """ Windows initialisations. """
8681
8782 super ().__init__ ()
8883
89- self ._bbox = {"height" : 0 , "width" : 0 }
90- self ._bmp = None
91- self ._data = ctypes .create_string_buffer (0 ) # type: ctypes.Array[ctypes.c_char]
92-
9384 self .monitorenumproc = ctypes .WINFUNCTYPE (
9485 INT , DWORD , DWORD , ctypes .POINTER (RECT ), DOUBLE
9586 )
@@ -99,8 +90,12 @@ def __init__(self, **_):
9990 self ._set_cfunctions ()
10091 self ._set_dpi_awareness ()
10192
102- self ._srcdc = self .user32 .GetWindowDC (0 )
103- self ._memdc = self .gdi32 .CreateCompatibleDC (self ._srcdc )
93+ self ._bbox = {"height" : 0 , "width" : 0 }
94+ self ._data = ctypes .create_string_buffer (0 ) # type: ctypes.Array[ctypes.c_char]
95+
96+ if not MSS .srcdc or not MSS .memdc :
97+ MSS .srcdc = self .user32 .GetWindowDC (0 )
98+ MSS .memdc = self .gdi32 .CreateCompatibleDC (MSS .srcdc )
10499
105100 bmi = BITMAPINFO ()
106101 bmi .bmiHeader .biSize = ctypes .sizeof (BITMAPINFOHEADER )
@@ -129,17 +124,13 @@ def _set_cfunctions(self):
129124 self ._cfactory (
130125 attr = self .user32 , func = "GetWindowDC" , argtypes = [HWND ], restype = HDC
131126 )
132- self ._cfactory (
133- attr = self .user32 , func = "ReleaseDC" , argtypes = [HWND , HGDIOBJ ], restype = INT
134- )
135127
136128 self ._cfactory (
137129 attr = self .gdi32 , func = "GetDeviceCaps" , argtypes = [HWND , INT ], restype = INT
138130 )
139131 self ._cfactory (
140132 attr = self .gdi32 , func = "CreateCompatibleDC" , argtypes = [HDC ], restype = HDC
141133 )
142- self ._cfactory (attr = self .gdi32 , func = "DeleteDC" , argtypes = [HDC ], restype = BOOL )
143134 self ._cfactory (
144135 attr = self .gdi32 ,
145136 func = "CreateCompatibleBitmap" ,
@@ -168,32 +159,10 @@ def _set_cfunctions(self):
168159 restype = BOOL ,
169160 )
170161
171- def close (self ):
172- # type: () -> None
173- """ Close GDI handles and free DCs. """
174-
175- try :
176- self .gdi32 .DeleteObject (self ._bmp )
177- del self ._bmp
178- except AttributeError :
179- pass
180-
181- try :
182- self .gdi32 .DeleteDC (self ._memdc )
183- del self ._memdc
184- except (OSError , AttributeError ):
185- pass
186-
187- try :
188- self .user32 .ReleaseDC (0 , self ._srcdc )
189- del self ._srcdc
190- except AttributeError :
191- pass
192-
193162 def _set_dpi_awareness (self ):
194163 """ Set DPI aware to capture full screen on Hi-DPI monitors. """
195164
196- version = sys .getwindowsversion ()[:2 ]
165+ version = sys .getwindowsversion ()[:2 ] # pylint: disable=no-member
197166 if version >= (6 , 3 ):
198167 # Windows 8.1+
199168 # Here 2 = PROCESS_PER_MONITOR_DPI_AWARE, which means:
@@ -288,29 +257,32 @@ def grab(self, monitor):
288257 "height" : monitor [3 ] - monitor [1 ],
289258 }
290259
260+ srcdc , memdc = MSS .srcdc , MSS .memdc
291261 width , height = monitor ["width" ], monitor ["height" ]
292262
293263 if (self ._bbox ["height" ], self ._bbox ["width" ]) != (height , width ):
294264 self ._bbox = monitor
295265 self ._bmi .bmiHeader .biWidth = width
296266 self ._bmi .bmiHeader .biHeight = - height # Why minus? [1]
297267 self ._data = ctypes .create_string_buffer (width * height * 4 ) # [2]
298- self ._bmp = self .gdi32 .CreateCompatibleBitmap (self ._srcdc , width , height )
299- self .gdi32 .SelectObject (self ._memdc , self ._bmp )
268+ if MSS .bmp :
269+ self .gdi32 .DeleteObject (MSS .bmp )
270+ MSS .bmp = self .gdi32 .CreateCompatibleBitmap (srcdc , width , height )
271+ self .gdi32 .SelectObject (memdc , MSS .bmp )
300272
301273 self .gdi32 .BitBlt (
302- self . _memdc ,
274+ memdc ,
303275 0 ,
304276 0 ,
305277 width ,
306278 height ,
307- self . _srcdc ,
279+ srcdc ,
308280 monitor ["left" ],
309281 monitor ["top" ],
310282 SRCCOPY | CAPTUREBLT ,
311283 )
312284 bits = self .gdi32 .GetDIBits (
313- self . _memdc , self . _bmp , 0 , height , self ._data , self ._bmi , DIB_RGB_COLORS
285+ memdc , MSS . bmp , 0 , height , self ._data , self ._bmi , DIB_RGB_COLORS
314286 )
315287 if bits != height :
316288 raise ScreenShotError ("gdi32.GetDIBits() failed." )
0 commit comments