Enhancement: Ability to customize window properties to look for when win32 api searching for d2r window (#563)
This commit is contained in:
@@ -250,4 +250,8 @@ settings_backup_key=f8
|
||||
auto_settings_key=f9
|
||||
graphic_debugger_key=f10
|
||||
resume_key=f11
|
||||
exit_key=f12
|
||||
exit_key=f12
|
||||
hwnd_window_title=
|
||||
hwnd_window_process=D2R\.exe
|
||||
;If you want to control Hyper-V window from host use 0,51 here
|
||||
window_client_area_offset=0,0
|
||||
|
||||
@@ -8,6 +8,8 @@ from logger import Logger
|
||||
|
||||
config_lock = threading.Lock()
|
||||
|
||||
def _default_iff(value, iff, default = None):
|
||||
return default if value == iff else value
|
||||
|
||||
@dataclass
|
||||
class ItemProps:
|
||||
@@ -312,6 +314,9 @@ class Config:
|
||||
"restore_settings_from_backup_key": Config._select_val("advanced_options", "restore_settings_from_backup_key"),
|
||||
"settings_backup_key": Config._select_val("advanced_options", "settings_backup_key"),
|
||||
"graphic_debugger_key": Config._select_val("advanced_options", "graphic_debugger_key"),
|
||||
"hwnd_window_title": _default_iff(Config._select_val("advanced_options", "hwnd_window_title"), ''),
|
||||
"hwnd_window_process": _default_iff(Config._select_val("advanced_options", "hwnd_window_process"), ''),
|
||||
"window_client_area_offset": tuple(map(int, Config._select_val("advanced_options", "window_client_area_offset").split(",")))
|
||||
}
|
||||
|
||||
Config.items = {}
|
||||
|
||||
@@ -5,7 +5,7 @@ import time
|
||||
from logger import Logger
|
||||
from typing import Tuple
|
||||
from config import Config
|
||||
from utils.misc import find_d2r_window
|
||||
from utils.misc import WindowSpec, find_d2r_window
|
||||
import os
|
||||
|
||||
|
||||
@@ -22,8 +22,12 @@ class Screen:
|
||||
# Find d2r screen offsets and monitor idx
|
||||
self.found_offsets = False
|
||||
position = None
|
||||
Logger.debug("Using WinAPI to search for window under D2R.exe process")
|
||||
position = find_d2r_window()
|
||||
find_window = WindowSpec(
|
||||
title_regex=Config.advanced_options["hwnd_window_title"],
|
||||
process_name_regex=Config.advanced_options["hwnd_window_process"],
|
||||
)
|
||||
Logger.debug(f"Using WinAPI to search for window: {find_window}")
|
||||
position = find_d2r_window(find_window, offset=Config.advanced_options["window_client_area_offset"])
|
||||
if position is not None:
|
||||
self._set_window_position(*position)
|
||||
else:
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
from dataclasses import dataclass
|
||||
from decimal import InvalidOperation
|
||||
from re import RegexFlag
|
||||
import time
|
||||
import random
|
||||
import ctypes
|
||||
import numpy as np
|
||||
from copy import deepcopy
|
||||
|
||||
from pyparsing import Regex
|
||||
|
||||
from logger import Logger
|
||||
import cv2
|
||||
from typing import List, Tuple
|
||||
from typing import List, Tuple, Union
|
||||
import os
|
||||
from math import cos, sin, dist
|
||||
import subprocess
|
||||
@@ -20,15 +25,34 @@ import psutil
|
||||
def close_down_d2():
|
||||
subprocess.call(["taskkill","/F","/IM","D2R.exe"], stderr=subprocess.DEVNULL)
|
||||
|
||||
def find_d2r_window() -> tuple[int, int]:
|
||||
@dataclass
|
||||
class WindowSpec:
|
||||
title_regex: 'Union[str, None]' = None
|
||||
process_name_regex: 'Union[str, None]' = None
|
||||
|
||||
def match(self, hwnd) -> bool:
|
||||
result = True
|
||||
if self.title_regex is not None:
|
||||
result = result and Regex(self.title_regex).matches(GetWindowText(hwnd))
|
||||
if self.process_name_regex is not None:
|
||||
_, process_id = GetWindowThreadProcessId(hwnd)
|
||||
result = result and Regex(self.process_name_regex).matches(psutil.Process(process_id).name())
|
||||
if self.title_regex is None and self.process_name_regex is None:
|
||||
result = False
|
||||
return result
|
||||
|
||||
|
||||
def find_d2r_window(spec: WindowSpec, offset = (0, 0)) -> tuple[int, int]:
|
||||
offset_x, offset_y = offset
|
||||
|
||||
if os.name == 'nt':
|
||||
window_list = []
|
||||
EnumWindows(lambda w, l: l.append((w, *GetWindowThreadProcessId(w))), window_list)
|
||||
for (hwnd, _, process_id) in window_list:
|
||||
if psutil.Process(process_id).name() == "D2R.exe":
|
||||
EnumWindows(lambda w, l: l.append(w), window_list)
|
||||
for hwnd in window_list:
|
||||
if spec.match(hwnd):
|
||||
left, top, right, bottom = GetClientRect(hwnd)
|
||||
(left, top), (right, bottom) = ClientToScreen(hwnd, (left, top)), ClientToScreen(hwnd, (right, bottom))
|
||||
return (left, top)
|
||||
return (left + offset_x, top + offset_y)
|
||||
return None
|
||||
|
||||
def set_d2r_always_on_top():
|
||||
@@ -187,3 +211,10 @@ def rotate_vec(vec: np.ndarray, deg: float) -> np.ndarray:
|
||||
|
||||
def unit_vector(vec: np.ndarray) -> np.ndarray:
|
||||
return vec / dist(vec, (0, 0))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
spec1 = WindowSpec(title_regex="D2R1 on .+")
|
||||
spec2 = WindowSpec(process_name_regex="D2R.exe")
|
||||
print(find_d2r_window(spec1))
|
||||
print(find_d2r_window(spec2))
|
||||
Reference in New Issue
Block a user