fork download
  1. import win32gui
  2. import win32ui
  3. from ctypes import windll
  4. from contextlib import contextmanager
  5. from collections import namedtuple
  6.  
  7.  
  8. class NoSuchWindowError(Exception):
  9. "ウィンドウが見つからなかった場合に投げる例外"
  10.  
  11.  
  12. class PrintScreenError(Exception):
  13. "PrintScreenが失敗した場合に投げる例外"
  14.  
  15.  
  16. class WindowChapter():
  17. def __init__(self):
  18. self.hwnd_dc = None
  19. self.mem_dc = None
  20. self.src_dc = None
  21. self.bmp = None
  22.  
  23. def __del__(self):
  24. if self.src_dc is not None:
  25. self.src_dc.DeleteDC()
  26. self.src_dc = None
  27. if self.mem_dc is not None:
  28. self.mem_dc.DeleteDC()
  29. self.mem_dc = None
  30. if self.bmp is not None:
  31. win32gui.DeleteObject(self.bmp.GetHandle())
  32. self.bmp = None
  33. if self.hwnd_dc is not None:
  34. win32gui.ReleaseDC(self.hwnd, self.hwnd_dc)
  35. self.hwnd_dc = None
  36.  
  37. @contextmanager
  38. def capture_window(self, window_name):
  39. self.hwnd = win32gui.FindWindow(None, window_name)
  40. if self.hwnd == 0:
  41. raise NoSuchWindowError
  42.  
  43. # ウィンドウサイズを取得
  44. left, top, right, bottom = win32gui.GetWindowRect(self.hwnd)
  45. width = right - left
  46. height = bottom - top
  47.  
  48. # デバイスコンテキストを取得
  49. self.hwnd_dc = win32gui.GetWindowDC(self.hwnd)
  50. self.src_dc = win32ui.CreateDCFromHandle(self.hwnd_dc)
  51. self.mem_dc = self.src_dc.CreateCompatibleDC()
  52.  
  53. # ビットマップを作成
  54. self.bmp = win32ui.CreateBitmap()
  55. self.bmp.CreateCompatibleBitmap(self.src_dc, width, height)
  56.  
  57. # ビットマップをデバイスコンテキストに関連付け
  58. self.mem_dc.SelectObject(self.bmp)
  59. result = windll.user32.PrintWindow(
  60. self.hwnd, self.mem_dc.GetSafeHdc(), 0)
  61. if result == 0:
  62. raise PrintScreenError
  63.  
  64. buf = self.bmp.GetBitmapBits(True)
  65. Bitmap = namedtuple('Bitmap', ['data', 'width', 'height'])
  66. yield Bitmap(buf, width, height)
  67.  
  68.  
  69. def main():
  70. wc = WindowChapter()
  71.  
  72. with wc.capture_window('NoxPlayer') as bmp:
  73. # PILを使う場合
  74. from PIL import Image
  75. im = Image.frombuffer(
  76. 'RGB', (bmp.width, bmp.height), bmp.data, 'raw', 'BGRX', 0, 1)
  77. im.save("test.png")
  78.  
  79. # Numpyを使う場合(OpenCVはこっち)
  80. import numpy as np
  81. import matplotlib.pyplot as plt
  82. data = np.frombuffer(bmp.data, dtype=np.uint8)
  83. data = data.reshape(bmp.height, bmp.width, 4)
  84. data = data[:, :, [2, 1, 0, 3]] # BGR->RGB
  85. plt.imshow(data)
  86. plt.show()
  87.  
  88.  
  89. if __name__ == "__main__":
  90. main()
  91.  
Runtime error #stdin #stdout #stderr 0.01s 7136KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Traceback (most recent call last):
  File "prog.py", line 1, in <module>
ImportError: No module named win32gui