def icon_path(exe: path_type, name: str): id_file_name = f'{name}.png' id_path = p_join(this_dir, 'icons', id_file_name) if not p_exists(id_path): ico_x = GetSystemMetrics(SM_CXICON) try: large, small = ExtractIconEx(exe, 0) except error: return default_icon_path if not len(large): return default_icon_path if len(small): DestroyIcon(small[0]) hdc = CreateDCFromHandle(GetDC(0)) h_bmp = CreateBitmap() h_bmp.CreateCompatibleBitmap(hdc, ico_x, ico_x) hdc = hdc.CreateCompatibleDC() hdc.SelectObject(h_bmp) hdc.DrawIcon((0, 0), large[0]) bmp_str = h_bmp.GetBitmapBits(True) img = Image.frombuffer('RGBA', (32, 32), bmp_str, 'raw', 'BGRA', 0, 1) img.save(id_path) print(f'Icon of {exe} saved in {id_path}') return id_path
def windowshots(self, x1, y1, x2, y2): w, h = x2 - x1, y2 - y1 # wDC = GetDC(hwnd) # 根据窗口句柄获取窗口的设备上下文DC(Divice Context) # 获取桌面 hdesktop = GetDesktopWindow() wDC = GetWindowDC(hdesktop) # 根据窗口的DC获取dcObj dcObj = CreateDCFromHandle(wDC) # dcObj创建可兼容的DC cDC = dcObj.CreateCompatibleDC() # 创建bigmap准备保存图片 dataBitMap = CreateBitmap() # 为bitmap开辟空间 dataBitMap.CreateCompatibleBitmap(dcObj, w, h) # 高度cDC,将截图保存到dataBitMap中 cDC.SelectObject(dataBitMap) # 截取从左上角(0,0)长宽为(w,h)的图片 cDC.BitBlt((0, 0), (w, h), dcObj, (x1, y1), SRCCOPY) # 保存图像 # dataBitMap.SaveBitmapFile(cDC, 'test.jpg') signedIntsArray = dataBitMap.GetBitmapBits(True) # Free Resources # 释放资源 DeleteObject(dataBitMap.GetHandle()) cDC.DeleteDC() dcObj.DeleteDC() ReleaseDC(hdesktop, wDC) screen = np.frombuffer(signedIntsArray, dtype='uint8') screen.shape = (h, w, 4) screen = cv2.cvtColor(screen, cv2.COLOR_BGRA2BGR) return screen
def Screenshot(self): ######################## # Usadas en Screenshot # ######################## from time import sleep from win32gui import GetDesktopWindow, GetWindowDC from win32ui import CreateDCFromHandle, CreateBitmap from win32con import SRCCOPY, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN from win32api import GetSystemMetrics, GetUserName from time import strftime print "Tomando Pantallazo" # Toma 4 pantallazos # Cada pantallazo lo llama pantallazo1 , 2 ,3 o 4 # Lo hace cada 2 segundos t = strftime("%Y-%H%M%S") hwin = GetDesktopWindow() width = GetSystemMetrics(SM_CXVIRTUALSCREEN) height = GetSystemMetrics(SM_CYVIRTUALSCREEN) left = GetSystemMetrics(SM_XVIRTUALSCREEN) top = GetSystemMetrics(SM_YVIRTUALSCREEN) hwindc = GetWindowDC(hwin) srcdc = CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, width, height) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), SRCCOPY) bmp.SaveBitmapFile( memdc, "C:\\Users\\" + GetUserName() + "\\Downloads\\test\\screen" + t + ".bmp")
def screenshot(**kwargs): global client dimensions = GetWindowDC(client) handle = CreateDCFromHandle(dimensions) buff = handle.CreateCompatibleDC() screenshot = CreateBitmap() screenshot.CreateCompatibleBitmap(handle, kwargs['width'], kwargs['height']) buff.SelectObject(screenshot) buff.BitBlt((0, 0), (kwargs['width'], kwargs['height']), handle, (kwargs['left'], kwargs['top']), SRCCOPY) pixels = screenshot.GetBitmapBits(True) im = array( Image.frombuffer('RGB', (kwargs['width'], kwargs['height']), pixels, 'raw', 'BGRX', 0, 1)) if kwargs['cleaning'] == True: im = cleaning(kwargs['width'], kwargs['height'], im) handle.DeleteDC() buff.DeleteDC() ReleaseDC(client, dimensions) DeleteObject(screenshot.GetHandle()) return im
def hwd_screenshot(self): # 获取句柄窗口的大小信息 try: _left, _top, _right, _bot = self.get_window_rect() _width = _right - _left _height = _bot - _top # 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框 _hwnd_dc = GetWindowDC(self.hwnd) # 创建设备描述表 _mfc_dc = CreateDCFromHandle(_hwnd_dc) # 创建内存设备描述表 _save_dc = _mfc_dc.CreateCompatibleDC() # 创建位图对象准备保存图片 _save_bit_map = CreateBitmap() # 为bitmap开辟存储空间 _save_bit_map.CreateCompatibleBitmap(_mfc_dc, _width, _height) # 将截图保存到saveBitMap中 _save_dc.SelectObject(_save_bit_map) # 保存bitmap到内存设备描述表 _save_dc.BitBlt((0, 0), (_width, _height), _mfc_dc, (0, 0), win32con.SRCCOPY) # 如果要截图到打印设备: ###最后一个int参数:0-保存整个窗口,1-只保存客户区。如果PrintWindow成功函数返回值为1 # result = windll.user32.PrintWindow(hWnd,_save_dc.GetSafeHdc(),0) # print(result) #PrintWindow成功则输出1 # 保存图像 ##方法一:windows api保存 ###保存bitmap到文件 # _save_bit_map.SaveBitmapFile(_save_dc, "img_Winapi.bmp") ##方法二(第一部分):PIL保存 ###获取位图信息 # bmpinfo = _save_bit_map.GetInfo() # bmpstr = _save_bit_map.GetBitmapBits(True) ###生成图像 # im_PIL = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1) ##方法二(后续转第二部分) ##方法三(第一部分):opencv+numpy保存 ###获取位图信息 signed_ints_array = _save_bit_map.GetBitmapBits(True) return Image.get_img_opencv(signed_ints_array, _width, _height) ##方法三(后续转第二部分) finally: # 内存释放 DeleteObject(_save_bit_map.GetHandle()) _save_dc.DeleteDC() _mfc_dc.DeleteDC() ReleaseDC(self.hwnd, _hwnd_dc)
def _capture(self): # make sure the process is DPI aware, otherwise the image # is only a part of the full monitor content # (necessary only on Win 8.1+) old_awareness = self._dpi_aware() self._set_dpi_aware(True) # get width and height of current monitor width = GetSystemMetrics(SM_CXVIRTUALSCREEN) height = GetSystemMetrics(SM_CYVIRTUALSCREEN) # get 'desktop' window handle handle_desktop = GetDesktopWindow() # get window graphic context handle handle_context = GetWindowDC(handle_desktop) # create device context dev_ctx = CreateDCFromHandle(handle_context) # create destination for original device context dest_ctx = dev_ctx.CreateCompatibleDC() # create bitmap compatible with desktop window device bmp = CreateBitmap() bmp.CreateCompatibleBitmap(dev_ctx, width, height) # select bitmap into destination device dest_ctx.SelectObject(bmp) # populate selected bitmap in destination device dest_ctx.BitBlt( (0, 0), # start point (x, y) (width, height), # size of rectangle dev_ctx, ( # source device GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN) ), # source rectangle, can be different monitor SRCCOPY # copy directly without filters ) # save bitmap to file bmp.SaveBitmapFile(dest_ctx, self.file_path) # return to the original state self._set_dpi_aware(old_awareness)
def getBmp(box=None, handle=None, dcTuple=None): if handle is None: handle = getHandle() if dcTuple is None: localDC = True dcTuple = getDc(handle) else: localDC = False left, up, right, down = box if box else wgui.GetWindowRect(handle) height, width = down - up, right - left size = width, height bmp = CreateBitmap() bmp.CreateCompatibleBitmap(dcTuple[1], width, height) dcTuple[2].SelectObject(bmp) dcTuple[2].BitBlt((0, 0), size, dcTuple[1], (left, up), win32con.SRCCOPY) if localDC: dropDc(handle, dcTuple) return bmp
def ScreenShot(self): """ 截图 网上找的代码直接复制修改的 后面加了释放资源代码,网上找的 """ hwndDC = GetWindowDC(self.mHwnd) mfcDC = CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() saveBitMap = CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, self.mWindowWidth, self.mWindowHeight) saveDC.SelectObject(saveBitMap) saveDC.BitBlt((0, 0), (self.mWindowWidth, self.mWindowHeight), mfcDC, (0, 0), SRCCOPY) saveBitMap.SaveBitmapFile(saveDC, self.mScreenShotFileName) self.mImageSrc = aircv.imread(self.mScreenShotFileName) # release DeleteObject(saveBitMap.GetHandle()) mfcDC.DeleteDC() saveDC.DeleteDC() ReleaseDC(self.mHwnd, hwndDC)
def save_screenshot(): hwnd = GetDesktopWindow() width = GetSystemMetrics(SM_CXVIRTUALSCREEN) height = GetSystemMetrics(SM_CYVIRTUALSCREEN) x = GetSystemMetrics(SM_XVIRTUALSCREEN) y = GetSystemMetrics(SM_YVIRTUALSCREEN) hwnd_dc = GetWindowDC(hwnd) mfc_dc = CreateDCFromHandle(hwnd_dc) save_dc = mfc_dc.CreateCompatibleDC() save_bit_map = CreateBitmap() save_bit_map.CreateCompatibleBitmap(mfc_dc, width, height) save_dc.SelectObject(save_bit_map) save_dc.BitBlt((0, 0), (width, height), mfc_dc, (x, y), SRCCOPY) bmp_info = save_bit_map.GetInfo() bmp_str = save_bit_map.GetBitmapBits(True) image = Image.frombuffer('RGB', (bmp_info['bmWidth'], bmp_info['bmHeight']), bmp_str, 'raw', 'BGRX', 0, 1) time_str = str(ctime()).replace(' ', '_').replace(':', '_').lower() name_scr = 'screen_' + time_str + '.png' image.save(name_scr, format='png') log_record('сохранен скриншот: ' + name_scr) save_dc.DeleteDC() DeleteObject(save_bit_map.GetHandle())
def get_screenshot(): hdesktop = GetDesktopWindow() width = GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) height = GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) left = GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) top = GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) hdc = GetWindowDC(hdesktop) source_dc = CreateDCFromHandle(hdc) target_dc = source_dc.CreateCompatibleDC() bmp = CreateBitmap() bmp.CreateCompatibleBitmap(source_dc, width, height) target_dc.SelectObject(bmp) target_dc.BitBlt((0, 0), (width, height), source_dc, (left, top), win32con.SRCCOPY) tmp = tempfile.NamedTemporaryFile(suffix='.bmp') bmp.SaveBitmapFile(target_dc, tmp.name) return tmp
def __getIconFromProc(self, proc): path = proc.cmdline()[0] ico_size = GetSystemMetrics(SM_CXICON) large, _ = ExtractIconEx(path, 0) hdc = CreateDCFromHandle(GetDC(0)) hbmp = CreateBitmap() hbmp.CreateCompatibleBitmap(hdc, ico_size, ico_size) hdc = hdc.CreateCompatibleDC() hdc.SelectObject(hbmp) hdc.DrawIcon((0, 0), large[0]) bmpstr = hbmp.GetBitmapBits(True) image = Image.frombuffer('RGB', (ico_size, ico_size), bmpstr, 'raw', 'BGRX', 0, 1) self.__imageList.append(image)
def __init__(self): self.AHK = AHK() self.application = self.start_game() self.process_id = self.application.process self.process = Process(pid=self.process_id) self.dialog = self.get_window_dialog() self.handle = self.dialog.handle self.window = Window.from_pid(self.AHK, self.process_id) left, top, right, bot = GetClientRect(self.handle) w = right - left h = bot - top self.hwndDC = GetWindowDC(self.handle) self.mfcDC = CreateDCFromHandle(self.hwndDC) self.saveDC = self.mfcDC.CreateCompatibleDC() self.saveDC_handle = self.saveDC.GetSafeHdc() self.saveBitMap = CreateBitmap() self.saveBitMap.CreateCompatibleBitmap(self.mfcDC, w, h) self.bmpinfo = self.saveBitMap.GetInfo() self.saveDC.SelectObject(self.saveBitMap) self.navigate_main_menu() self.enter_avoidance() self.process.suspend() self.PREVIOUS_ACTION = 0 self.deathcount = self.get_game_deathcount() self.action_space = spaces.Discrete(6) self.elapsed_time = 0.0 self.observation_space = spaces.Dict({"window": spaces.Box(low=0, high=255, shape=self.get_observation_space_size(), dtype=np.uint8), "time": spaces.Box(low=0, high=900, shape=(1,))})
class SoullessEnv(gym.Env): metadata = {'render.modes': ['human']} user32 = WinDLL("user32") DEATHCOUNT_PATTERN = re.compile("(\d+)") KEYS = (KEYS.LEFT, KEYS.RIGHT, KEYS.DELETE) TRANSITION_TO_ACTION = {"10": "UP", "01": "DOWN", "00": False, "11": False} def __init__(self): self.AHK = AHK() self.application = self.start_game() self.process_id = self.application.process self.process = Process(pid=self.process_id) self.dialog = self.get_window_dialog() self.handle = self.dialog.handle self.window = Window.from_pid(self.AHK, self.process_id) left, top, right, bot = GetClientRect(self.handle) w = right - left h = bot - top self.hwndDC = GetWindowDC(self.handle) self.mfcDC = CreateDCFromHandle(self.hwndDC) self.saveDC = self.mfcDC.CreateCompatibleDC() self.saveDC_handle = self.saveDC.GetSafeHdc() self.saveBitMap = CreateBitmap() self.saveBitMap.CreateCompatibleBitmap(self.mfcDC, w, h) self.bmpinfo = self.saveBitMap.GetInfo() self.saveDC.SelectObject(self.saveBitMap) self.navigate_main_menu() self.enter_avoidance() self.process.suspend() self.PREVIOUS_ACTION = 0 self.deathcount = self.get_game_deathcount() self.action_space = spaces.Discrete(6) self.elapsed_time = 0.0 self.observation_space = spaces.Dict({"window": spaces.Box(low=0, high=255, shape=self.get_observation_space_size(), dtype=np.uint8), "time": spaces.Box(low=0, high=900, shape=(1,))}) def start_game(self): """starts the Soulless process""" app = Application().start( "D:/Users/david/PycharmProjects/reinforcement-learning/gym-soulless/Soulless 1.3HM/Soulless Hard Mode.exe") return app def get_window_dialog(self): """:returns the main dialog of the application, which is the entry-point for interacting with it""" return self._top_window() @try_loop(error_type=RuntimeError) def _top_window(self): return self.application.top_window() def navigate_main_menu(self): """from the title screen it navigates the menus until it enters the game""" self.window.send("{Shift}", blocking=False) sleep(3) self.window.send("{Shift}", blocking=False) def enter_avoidance(self): self.window.send("{Left down}", blocking=False) sleep(0.3) self.window.send("{Left up}", blocking=False) sleep(2) def capture_window(self): """:returns a np array image of the dialog cropped to exclude the margins for resizing the window https://stackoverflow.com/questions/19695214/python-screenshot-of-inactive-window-printwindow-win32gui""" SoullessEnv.user32.PrintWindow(HWND(self.handle), self.saveDC_handle, 3) bmpstr = self.saveBitMap.GetBitmapBits(True) im = Image.frombuffer( 'RGB', (self.bmpinfo['bmWidth'], self.bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1) return np.array(im, copy=False) def step(self, action: int): """expects the game to be in a suspended state""" is_done, obs, reward = self.step_and_track_elapsed_time(action) obs = {"window": obs, "time": np.array([self.elapsed_time], dtype=np.float)} return obs, reward, is_done, {} def step_and_track_elapsed_time(self, action): self.process.resume() step_start_time = perf_counter() is_done, obs = self._step(action) self.process.suspend() step_end_time = perf_counter() elapsed_time = step_end_time - step_start_time self.elapsed_time += elapsed_time return is_done, obs, elapsed_time def _step(self, action): self.perform_action(action) obs = self.capture_window() is_done = self.is_done() if is_done: self.update_env_deathcount() return is_done, obs def perform_action(self, action): keystrokes = self.get_action_transition(self.PREVIOUS_ACTION, action) self.send_input_to_game(keystrokes) self.PREVIOUS_ACTION = action def is_done(self): return self.get_game_deathcount() > self.deathcount def update_env_deathcount(self): self.deathcount = self.get_game_deathcount() def get_action_transition(self, old_action: int, new_action: int): """:param old_action is the action performed on the previous step, or no-op if this is the first step :param new_action is the action performed on this step :returns the input to the send function needed to transition from the old action to the new action""" old_action, new_action = bin(old_action)[2:].zfill(3), bin(new_action)[2:].zfill(3) actions = map(SoullessEnv.TRANSITION_TO_ACTION.get, map("".join, zip(old_action, new_action))) return "".join(getattr(key, action) for key, action in zip(SoullessEnv.KEYS, actions) if action) def send_input_to_game(self, keystrokes: str): """:param keystrokes is the input to the send_keys function""" self.window.send(keystrokes, blocking=False) def reset(self): self.process.resume() self.window.send("r", delay=150) self.process.suspend() self.elapsed_time = 0.0 return {"window": self.capture_window(), "time": np.array([self.elapsed_time], dtype=np.float)} def render(self, mode='human'): pass def close(self): DeleteObject(self.saveBitMap.GetHandle()) self.saveDC.DeleteDC() self.mfcDC.DeleteDC() ReleaseDC(self.handle, self.hwndDC) self.application.kill() def get_observation_space_size(self): return self.capture_window().shape def get_game_deathcount(self): """:returns the number of times the kid has died""" title = self.window.title.decode("utf8") return int(re.search(SoullessEnv.DEATHCOUNT_PATTERN, title)[0])