[Python] 纯文本查看 复制代码
import sys
import os
import json
import ctypes
from ctypes import wintypes
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QRubberBand,
QDialog, QVBoxLayout, QComboBox, QPushButton,
QHBoxLayout, QFileDialog)
from PyQt5.QtCore import Qt, QRect, QPoint, QTimer
from PyQt5.QtGui import QMovie, QPainterPath, QRegion, QFont, QCursor, QIcon
# ================= 资源路径自动解析 (兼容打包) =================
def get_resource_path(relative_path):
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base_path, relative_path)
GIF_DIR = get_resource_path("")
CONFIG_FILE = "moyu_config.json"
# ================= Windows API 结构体与常量 =================
DWM_TNP_VISIBLE = 0x8
DWM_TNP_RECTDESTINATION = 0x1
DWM_TNP_OPACITY = 0x4
SWP_NOZORDER = 0x0004
SWP_NOSIZE = 0x0001
SWP_NOACTIVATE = 0x0010
WM_SIZING = 0x0214
WMSZ_LEFT = 1
WMSZ_RIGHT = 2
WMSZ_TOP = 3
WMSZ_TOPLEFT = 4
WMSZ_TOPRIGHT = 5
WMSZ_BOTTOM = 6
WMSZ_BOTTOMLEFT = 7
WMSZ_BOTTOMRIGHT = 8
WM_LBUTTONDOWN = 0x0201
WM_LBUTTONUP = 0x0202
WM_MOUSEMOVE = 0x0200
WM_MOUSEWHEEL = 0x020A
MK_LBUTTON = 0x0001
GWL_EXSTYLE = -20
WS_EX_APPWINDOW = 0x00040000
WS_EX_TOOLWINDOW = 0x00000080
WS_EX_LAYERED = 0x00080000
LWA_ALPHA = 0x00000002
GW_OWNER = 4
DWMWA_CLOAKED = 14
class DWM_THUMBNAIL_PROPERTIES(ctypes.Structure):
_fields_ = [
("dwFlags", wintypes.DWORD),
("rcDestination", wintypes.RECT),
("rcSource", wintypes.RECT),
("opacity", wintypes.BYTE),
("fVisible", wintypes.BOOL),
("fSourceClientAreaOnly", wintypes.BOOL),
]
class POINT(ctypes.Structure):
_fields_ = [("x", wintypes.LONG), ("y", wintypes.LONG)]
class WINDOWPLACEMENT(ctypes.Structure):
_fields_ = [
("length", wintypes.UINT),
("flags", wintypes.UINT),
("showCmd", wintypes.UINT),
("ptMinPosition", POINT),
("ptMaxPosition", POINT),
("rcNormalPosition", wintypes.RECT)
]
dwmapi = ctypes.windll.dwmapi
user32 = ctypes.windll.user32
# ================= 辅助函数 =================
def load_config():
default_config = {
"gif_name": "1.gif",
"target_window_title": ""
}
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
default_config.update(data)
except:
pass
return default_config
def save_config(config):
try:
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=4)
except Exception as e:
print(f"保存配置失败: {e}")
def get_visible_windows():
taskbar_windows = []
tray_windows = []
blacklist = [
"mord", "Program Manager", "",
"Windows 输入体验", "Realtek Audio Console", "设置", "Settings",
"Microsoft Text Input Application", "Microsoft Store"
]
def enum_windows_proc(hwnd, lParam):
if user32.IsWindowVisible(hwnd) and user32.GetWindowTextLengthW(hwnd) > 0:
length = user32.GetWindowTextLengthW(hwnd)
buf = ctypes.create_unicode_buffer(length + 1)
user32.GetWindowTextW(hwnd, buf, length + 1)
title = buf.value
if title in blacklist:
return True
is_cloaked = ctypes.c_int(0)
dwmapi.DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, ctypes.byref(is_cloaked), ctypes.sizeof(is_cloaked))
if is_cloaked.value != 0:
return True
ex_style = user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
owner = user32.GetWindow(hwnd, GW_OWNER)
is_taskbar = False
if not (ex_style & WS_EX_TOOLWINDOW):
if owner == 0 or (ex_style & WS_EX_APPWINDOW):
is_taskbar = True
if is_taskbar:
taskbar_windows.append((hwnd, title))
else:
tray_windows.append((hwnd, title))
return True
user32.EnumWindows(ctypes.WINFUNCTYPE(ctypes.c_bool, wintypes.HWND, wintypes.LPARAM)(enum_windows_proc), 0)
return taskbar_windows, tray_windows
# ================= iOS 极简风设置面板 (精简版) =================
class SettingsDialog(QDialog):
def __init__(self, parent=None, config=None):
super().__init__(parent)
self.setWindowTitle("设置")
self.setWindowIcon(QIcon(get_resource_path("mord.ico")))
self.resize(300, 200)
self.action_type = "confirm"
self.selected_hwnd = None
self.config = config
self.setup_ui()
self.apply_ios_theme()
def setup_ui(self):
layout = QVBoxLayout(self)
layout.setSpacing(12)
layout.setContentsMargins(15, 20, 15, 15)
layout.addWidget(QLabel("底图 GIF"))
self.gif_combo = QComboBox()
current_gif = self.config.get("gif_name", "1.gif")
# 这里的范围改为了 1 到 7,也就是会添加 1.gif 到 6.gif
for i in range(1, 7): self.gif_combo.addItem(f"{i}.gif")
existing_items = [self.gif_combo.itemText(i) for i in range(self.gif_combo.count())]
if current_gif not in existing_items:
self.gif_combo.insertItem(0, current_gif)
self.gif_combo.addItem("自定义本地文件...")
self.gif_combo.setCurrentText(current_gif)
self.gif_combo.activated.connect(self.on_gif_activated)
layout.addWidget(self.gif_combo)
layout.addWidget(QLabel("隐藏并克隆的目标窗口"))
self.hwnd_combo = QComboBox()
self.taskbar_windows, self.tray_windows = get_visible_windows()
self.tray_expanded = False
self.populate_hwnd_combo()
self.hwnd_combo.activated.connect(self.on_hwnd_activated)
layout.addWidget(self.hwnd_combo)
layout.addSpacing(15)
btn_layout = QHBoxLayout()
rb = QPushButton("重绘")
rb.setObjectName("btn_redraw")
rb.clicked.connect(self.on_redraw)
ok = QPushButton("完成")
ok.setObjectName("btn_confirm")
ok.clicked.connect(self.on_confirm)
ex = QPushButton("退出")
ex.setObjectName("btn_exit")
ex.clicked.connect(self.on_exit)
btn_layout.addWidget(rb)
btn_layout.addWidget(ok)
btn_layout.addWidget(ex)
layout.addLayout(btn_layout)
layout.addStretch()
info_label = QLabel("mord v1.0.3 | 作者: ALiang")
info_label.setAlignment(Qt.AlignCenter)
info_label.setStyleSheet("color: #A1A1A6; font-size: 10px; margin-top: 5px;")
layout.addWidget(info_label)
def populate_hwnd_combo(self):
self.hwnd_combo.clear()
saved_title = self.config.get("target_window_title", "")
if not self.tray_expanded:
for hwnd, title in self.tray_windows:
if title == saved_title:
self.tray_expanded = True
break
index_to_select = -1
for hwnd, title in self.taskbar_windows:
self.hwnd_combo.addItem(title, hwnd)
if title == saved_title:
index_to_select = self.hwnd_combo.count() - 1
if self.tray_expanded:
for hwnd, title in self.tray_windows:
self.hwnd_combo.addItem(f"[后台/托盘] {title}", hwnd)
if title == saved_title:
index_to_select = self.hwnd_combo.count() - 1
else:
self.hwnd_combo.addItem("--- 点击展开后台与托盘工具 ---", None)
if index_to_select >= 0:
self.hwnd_combo.setCurrentIndex(index_to_select)
elif self.hwnd_combo.count() > 0:
self.hwnd_combo.setCurrentIndex(0)
def on_hwnd_activated(self, index):
data = self.hwnd_combo.itemData(index)
if data is None and not self.tray_expanded:
self.tray_expanded = True
self.populate_hwnd_combo()
self.hwnd_combo.showPopup()
def apply_ios_theme(self):
self.setStyleSheet("""
QDialog {
background-color: #F2F2F7;
font-family: -apple-system, "Segoe UI", "Microsoft YaHei";
}
QLabel {
color: #6E6E73;
font-size: 11px;
font-weight: 500;
margin-top: 2px;
}
QComboBox {
background-color: #FFFFFF;
border: none;
border-radius: 8px;
padding: 6px 10px;
color: #1D1D1F;
font-size: 13px;
}
QComboBox::drop-down { border: none; }
QPushButton {
border-radius: 8px;
padding: 7px;
font-size: 13px;
font-weight: bold;
}
QPushButton#btn_confirm { background-color: #007AFF; color: white; }
QPushButton#btn_confirm:hover { background-color: #0066CC; }
QPushButton#btn_redraw { background-color: #E5E5EA; color: #007AFF; }
QPushButton#btn_redraw:hover { background-color: #D1D1D6; }
QPushButton#btn_exit { background-color: #E5E5EA; color: #FF3B30; }
QPushButton#btn_exit:hover { background-color: #D1D1D6; }
""")
def on_gif_activated(self, index):
if self.gif_combo.itemText(index) == "自定义本地文件...":
path, _ = QFileDialog.getOpenFileName(self, "选择本地 GIF", "", "GIF 动画 (*.gif)")
if path:
self.gif_combo.insertItem(0, path)
self.gif_combo.setCurrentIndex(0)
else:
self.gif_combo.setCurrentText(self.config.get("gif_name", "1.gif"))
def on_confirm(self):
self.selected_hwnd = self.hwnd_combo.currentData()
if self.selected_hwnd:
raw_title = self.hwnd_combo.currentText().replace("[后台/托盘] ", "")
self.config["target_window_title"] = raw_title
self.action_type = "confirm"
self.accept()
def on_redraw(self):
self.action_type = "redraw"
self.accept()
def on_exit(self):
self.action_type = "exit"
self.accept()
# ================= 主窗口 =================
class mord(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowTitle("mord")
self.setWindowIcon(QIcon(get_resource_path("mord.ico")))
self.setMouseTracking(True)
self.config = load_config()
self.state = "INIT"
self.video_rect = QRect()
self.thumb_handle = ctypes.c_void_p(0)
self.target_hwnd = None
self.drag_pos = None
self.is_interacting = False
self.aspect_ratio = 1.0
self.current_movie = None
self.saved_placement = None
self.original_ex_style = None
self.init_ui()
QTimer.singleShot(50, lambda: self.load_specified_gif(self.config["gif_name"]))
def init_ui(self):
self.bg_label = QLabel(self)
self.bg_label.setScaledContents(True)
self.bg_label.setStyleSheet("background-color: transparent; border-radius: 12px;")
self.bg_label.setMouseTracking(True)
self.hint_label = QLabel(self)
self.hint_label.setAlignment(Qt.AlignCenter)
self.hint_label.setStyleSheet(
"background-color: rgba(0, 0, 0, 160); color: white; padding: 10px 16px; border-radius: 16px;")
self.hint_label.setFont(QFont("-apple-system", 9, QFont.Medium))
self.hint_label.hide()
self.settings_btn = QPushButton("", self)
self.settings_btn.resize(30, 30)
self.settings_btn.setToolTip("设置 (点击修改窗口或重绘)")
self.settings_btn.clicked.connect(self.open_settings)
self.settings_btn.setStyleSheet("""
QPushButton { background: transparent; border: none; }
QPushButton:hover { background: rgba(255, 255, 255, 40); border-radius: 10px; }
""")
self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
def move_to_bottom_right(self):
screen = QApplication.screenAt(self.geometry().center())
if not screen:
screen = QApplication.primaryScreen()
screen_geo = screen.availableGeometry()
margin = 20
target_x = screen_geo.x() + screen_geo.width() - self.width() - margin
target_y = screen_geo.y() + screen_geo.height() - self.height() - margin
self.move(target_x, target_y)
def show_hint(self, text):
self.hint_label.setText(text)
self.hint_label.adjustSize()
self.hint_label.move((self.width() - self.hint_label.width()) // 2,
(self.height() - self.hint_label.height()) // 2)
self.hint_label.show()
def hide_original_window(self, hwnd):
if not hwnd: return
self.saved_placement = WINDOWPLACEMENT()
self.saved_placement.length = ctypes.sizeof(WINDOWPLACEMENT)
user32.GetWindowPlacement(hwnd, ctypes.byref(self.saved_placement))
self.original_ex_style = user32.GetWindowLongW(hwnd, GWL_EXSTYLE)
user32.SetWindowLongW(hwnd, GWL_EXSTYLE, self.original_ex_style | WS_EX_LAYERED)
user32.SetLayeredWindowAttributes(hwnd, 0, 0, LWA_ALPHA)
if self.saved_placement.showCmd != 2:
user32.ShowWindow(hwnd, 7)
user32.ShowWindow(hwnd, 9)
user32.SetWindowPos(hwnd, 0, -30000, -30000, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE)
user32.SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA)
def restore_original_window(self):
if self.target_hwnd:
if self.original_ex_style is not None:
user32.SetWindowLongW(self.target_hwnd, GWL_EXSTYLE, self.original_ex_style)
if self.saved_placement:
user32.SetWindowPlacement(self.target_hwnd, ctypes.byref(self.saved_placement))
else:
user32.SetWindowPos(self.target_hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER | SWP_NOSIZE)
def register_thumbnail(self, hwnd):
if self.thumb_handle:
dwmapi.DwmUnregisterThumbnail(self.thumb_handle)
self.thumb_handle = ctypes.c_void_p(0)
self.target_hwnd = hwnd
self.hide_original_window(hwnd)
bg_rect = wintypes.RECT()
user32.GetWindowRect(hwnd, ctypes.byref(bg_rect))
orig_w = bg_rect.right - bg_rect.left
orig_h = bg_rect.bottom - bg_rect.top
if orig_w > 0 and orig_h > 0 and not self.video_rect.isEmpty():
target_ratio = orig_w / orig_h
box_w = self.video_rect.width()
box_h = self.video_rect.height()
box_ratio = box_w / box_h
if box_ratio > target_ratio:
final_h = box_h
final_w = int(final_h * target_ratio)
final_x = self.video_rect.left() + (box_w - final_w) // 2
final_y = self.video_rect.top()
else:
final_w = box_w
final_h = int(final_w / target_ratio)
final_x = self.video_rect.left()
final_y = self.video_rect.top() + (box_h - final_h) // 2
self.video_rect = QRect(final_x, final_y, final_w, final_h)
self.original_video_rect = QRect(self.video_rect)
res = dwmapi.DwmRegisterThumbnail(int(self.winId()), hwnd, ctypes.byref(self.thumb_handle))
if res == 0:
self.update_thumbnail_rect(visible=False)
self.state = "PLAYING"
self.hint_label.hide()
def update_thumbnail_rect(self, visible=True):
if not self.thumb_handle or self.video_rect.isEmpty(): return
ratio = self.devicePixelRatioF()
props = DWM_THUMBNAIL_PROPERTIES()
props.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY
props.fVisible = visible
props.opacity = 255
left = int(self.video_rect.x() * ratio)
top = int(self.video_rect.y() * ratio)
right = int((self.video_rect.x() + self.video_rect.width()) * ratio)
bottom = int((self.video_rect.y() + self.video_rect.height()) * ratio)
props.rcDestination = wintypes.RECT(left, top, right, bottom)
dwmapi.DwmUpdateThumbnailProperties(self.thumb_handle, ctypes.byref(props))
def load_specified_gif(self, gif_name_or_path):
if os.path.isabs(gif_name_or_path):
path = gif_name_or_path
else:
path = os.path.join(GIF_DIR, gif_name_or_path)
if not os.path.exists(path): return
self.current_movie = QMovie(path)
self.bg_label.setMovie(self.current_movie)
self.current_movie.start()
sz = self.current_movie.currentImage().size()
if sz.width() > 0 and sz.height() > 0:
screen = QApplication.screenAt(self.geometry().center())
if not screen:
screen = QApplication.primaryScreen()
screen_h = screen.availableGeometry().height()
target_h = screen_h // 3
self.aspect_ratio = sz.width() / sz.height()
target_w = int(target_h * self.aspect_ratio)
self.resize(target_w, target_h)
self.move_to_bottom_right()
self.show_hint("按住鼠标中键 拖拽框选游戏区")
def open_settings(self):
dialog = SettingsDialog(self, self.config)
if dialog.exec_() == QDialog.Accepted:
if dialog.action_type == "exit":
self.close()
elif dialog.action_type == "redraw":
self.trigger_redraw()
elif dialog.action_type == "confirm":
new_gif = dialog.gif_combo.currentText()
if new_gif != self.config.get("gif_name") and new_gif != "自定义本地文件...":
self.config["gif_name"] = new_gif
self.trigger_redraw()
self.load_specified_gif(new_gif)
dialog.selected_hwnd = None
save_config(self.config)
if dialog.selected_hwnd:
self.register_thumbnail(dialog.selected_hwnd)
def trigger_redraw(self):
if self.thumb_handle:
dwmapi.DwmUnregisterThumbnail(self.thumb_handle)
self.thumb_handle = ctypes.c_void_p(0)
self.restore_original_window()
self.state = "INIT"
self.video_rect = QRect()
self.show_hint("按住鼠标中键 拖拽框选游戏区")
def enterEvent(self, e):
if self.state == "PLAYING": self.update_thumbnail_rect(True)
def leaveEvent(self, e):
if self.state == "PLAYING": self.update_thumbnail_rect(False)
def map_and_send_mouse_event(self, pos, msg_type, wparam=0):
if not self.target_hwnd: return
bg_rect = wintypes.RECT()
user32.GetWindowRect(self.target_hwnd, ctypes.byref(bg_rect))
orig_w = bg_rect.right - bg_rect.left
orig_h = bg_rect.bottom - bg_rect.top
if orig_w <= 0 or orig_h <= 0: return
rel_x = pos.x() - self.video_rect.left()
rel_y = pos.y() - self.video_rect.top()
target_x = int((rel_x / self.video_rect.width()) * orig_w)
target_y = int((rel_y / self.video_rect.height()) * orig_h)
lparam = (target_y << 16) | (target_x & 0xFFFF)
user32.PostMessageW(self.target_hwnd, msg_type, wparam, lparam)
def mousePressEvent(self, event):
if self.state == "PLAYING" and event.button() == Qt.LeftButton and self.video_rect.contains(event.pos()):
self.map_and_send_mouse_event(event.pos(), WM_LBUTTONDOWN, MK_LBUTTON)
self.is_interacting = True
return
if event.button() == Qt.MiddleButton and self.state == "INIT":
self.origin_point = event.pos()
self.rubber_band.setGeometry(QRect(self.origin_point, QPoint()))
self.rubber_band.show()
self.state = "SELECTING"
elif event.button() == Qt.LeftButton:
self.drag_pos = event.globalPos() - self.frameGeometry().topLeft()
def mouseMoveEvent(self, event):
if self.state == "PLAYING" and event.buttons() == Qt.NoButton:
if self.video_rect.contains(event.pos()):
self.map_and_send_mouse_event(event.pos(), WM_MOUSEMOVE, 0)
return
if self.is_interacting:
self.map_and_send_mouse_event(event.pos(), WM_MOUSEMOVE, MK_LBUTTON)
return
if self.state == "SELECTING":
self.rubber_band.setGeometry(QRect(self.origin_point, event.pos()).normalized())
elif self.drag_pos:
self.move(event.globalPos() - self.drag_pos)
def mouseReleaseEvent(self, event):
if self.is_interacting and event.button() == Qt.LeftButton:
self.map_and_send_mouse_event(event.pos(), WM_LBUTTONUP, 0)
self.is_interacting = False
return
if event.button() == Qt.MiddleButton and self.state == "SELECTING":
self.video_rect = self.rubber_band.geometry()
self.original_video_rect = QRect(self.video_rect)
self.original_size = self.size()
if self.size().height() > 0:
self.aspect_ratio = self.size().width() / self.size().height()
self.rubber_band.hide()
self.state = "READY"
self.open_settings()
elif event.button() == Qt.LeftButton:
self.drag_pos = None
def wheelEvent(self, event):
if self.state == "PLAYING" and self.video_rect.contains(event.pos()):
if not self.target_hwnd: return
bg_rect = wintypes.RECT()
user32.GetWindowRect(self.target_hwnd, ctypes.byref(bg_rect))
orig_w = bg_rect.right - bg_rect.left
orig_h = bg_rect.bottom - bg_rect.top
if orig_w <= 0 or orig_h <= 0: return
rel_x = event.pos().x() - self.video_rect.left()
rel_y = event.pos().y() - self.video_rect.top()
target_win_x = int((rel_x / self.video_rect.width()) * orig_w)
target_win_y = int((rel_y / self.video_rect.height()) * orig_h)
screen_x = bg_rect.left + target_win_x
screen_y = bg_rect.top + target_win_y
z_delta = event.angleDelta().y()
wparam = ((z_delta & 0xFFFF) << 16) | 0
lparam = ((screen_y & 0xFFFF) << 16) | (screen_x & 0xFFFF)
user32.PostMessageW(self.target_hwnd, WM_MOUSEWHEEL, wparam, lparam)
def nativeEvent(self, eventType, message):
if not message or eventType not in [b'windows_generic_MSG', b'windows_dispatcher_MSG']:
return super().nativeEvent(eventType, message)
try:
msg = wintypes.MSG.from_address(int(message))
if msg.message == WM_SIZING and hasattr(self, 'aspect_ratio'):
rect = ctypes.cast(msg.lParam, ctypes.POINTER(wintypes.RECT)).contents
edge = msg.wParam
w = rect.right - rect.left
h = rect.bottom - rect.top
if edge in (WMSZ_LEFT, WMSZ_RIGHT):
rect.bottom = rect.top + int(w / self.aspect_ratio)
elif edge in (WMSZ_TOP, WMSZ_BOTTOM):
rect.right = rect.left + int(h * self.aspect_ratio)
elif edge in (WMSZ_TOPLEFT, WMSZ_TOPRIGHT, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT):
if edge in (WMSZ_TOPLEFT, WMSZ_TOPRIGHT):
rect.top = rect.bottom - int(w / self.aspect_ratio)
else:
rect.bottom = rect.top + int(w / self.aspect_ratio)
return True, 1
if msg.message == 0x0084:
pos = self.mapFromGlobal(QCursor.pos())
w, h, m = self.width(), self.height(), 12
if pos.x() < m and pos.y() < m: return True, 13
if pos.x() > w - m and pos.y() < m: return True, 14
if pos.x() < m and pos.y() > h - m: return True, 16
if pos.x() > w - m and pos.y() > h - m: return True, 17
if pos.y() < m: return True, 12
if pos.y() > h - m: return True, 15
if pos.x() < m: return True, 10
if pos.x() > w - m: return True, 11
except:
pass
return super().nativeEvent(eventType, message)
def resizeEvent(self, event):
self.bg_label.resize(self.size())
self.settings_btn.move(self.width() - 36, self.height() - 36)
path = QPainterPath()
path.addRoundedRect(0, 0, self.width(), self.height(), 12, 12)
self.setMask(QRegion(path.toFillPolygon().toPolygon()))
if self.state in ["PLAYING", "READY"] and hasattr(self, 'original_video_rect'):
wr, hr = self.width() / self.original_size.width(), self.height() / self.original_size.height()
self.video_rect = QRect(
int(self.original_video_rect.left() * wr), int(self.original_video_rect.top() * hr),
int(self.original_video_rect.width() * wr), int(self.original_video_rect.height() * hr)
)
self.update_thumbnail_rect(True)
super().resizeEvent(event)
def closeEvent(self, e):
self.restore_original_window()
super().closeEvent(e)
if __name__ == "__main__":
if hasattr(Qt, 'AA_EnableHighDpiScaling'):
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
app = QApplication(sys.argv)
window = mord()
window.show()
sys.exit(app.exec_())