PyQt/Demo/NativeEvent.py
2021-07-13 14:52:26 +08:00

128 lines
4.5 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Created on 2018年8月2日
author: Irony
site: https://pyqt.site , https://github.com/PyQt5
email: 892768447@qq.com
file: win无边框调整大小
description:
"""
import ctypes.wintypes
from ctypes.wintypes import POINT
import win32api
import win32con
import win32gui
try:
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtWinExtras import QtWin
except ImportError:
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QWidget, QPushButton, QApplication
from PySide2.QtWinExtras import QtWin
class MINMAXINFO(ctypes.Structure):
_fields_ = [
("ptReserved", POINT),
("ptMaxSize", POINT),
("ptMaxPosition", POINT),
("ptMinTrackSize", POINT),
("ptMaxTrackSize", POINT),
]
class Window(QWidget):
BorderWidth = 5
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
# 主屏幕的可用大小(去掉任务栏)
self._rect = QApplication.instance().desktop().availableGeometry(self)
self.resize(800, 600)
self.setWindowFlags(Qt.Window
| Qt.FramelessWindowHint
| Qt.WindowSystemMenuHint
| Qt.WindowMinimizeButtonHint
| Qt.WindowMaximizeButtonHint
| Qt.WindowCloseButtonHint)
# 增加薄边框
style = win32gui.GetWindowLong(int(self.winId()), win32con.GWL_STYLE)
win32gui.SetWindowLong(
int(self.winId()), win32con.GWL_STYLE, style | win32con.WS_THICKFRAME)
if QtWin.isCompositionEnabled():
# 加上 Aero 边框阴影
QtWin.extendFrameIntoClientArea(self, -1, -1, -1, -1)
else:
QtWin.resetExtendedFrame(self)
def nativeEvent(self, eventType, message):
retval, result = super(Window, self).nativeEvent(eventType, message)
if eventType == "windows_generic_MSG":
msg = ctypes.wintypes.MSG.from_address(message.__int__())
# 获取鼠标移动经过时的坐标
x = win32api.LOWORD(msg.lParam) - self.frameGeometry().x()
y = win32api.HIWORD(msg.lParam) - self.frameGeometry().y()
# 判断鼠标位置是否有其它控件
if self.childAt(x, y) != None:
return retval, result
if msg.message == win32con.WM_NCCALCSIZE:
# 拦截不显示顶部的系统自带的边框
return True, 0
if msg.message == win32con.WM_GETMINMAXINFO:
# 当窗口位置改变或者大小改变时会触发该消息
info = ctypes.cast(
msg.lParam, ctypes.POINTER(MINMAXINFO)).contents
# 修改最大化的窗口大小为主屏幕的可用大小
info.ptMaxSize.x = self._rect.width()
info.ptMaxSize.y = self._rect.height()
# 修改放置点的x,y坐标为0,0
info.ptMaxPosition.x, info.ptMaxPosition.y = 0, 0
if msg.message == win32con.WM_NCHITTEST:
w, h = self.width(), self.height()
lx = x < self.BorderWidth
rx = x > w - self.BorderWidth
ty = y < self.BorderWidth
by = y > h - self.BorderWidth
# 左上角
if (lx and ty):
return True, win32con.HTTOPLEFT
# 右下角
if (rx and by):
return True, win32con.HTBOTTOMRIGHT
# 右上角
if (rx and ty):
return True, win32con.HTTOPRIGHT
# 左下角
if (lx and by):
return True, win32con.HTBOTTOMLEFT
# 上
if ty:
return True, win32con.HTTOP
# 下
if by:
return True, win32con.HTBOTTOM
# 左
if lx:
return True, win32con.HTLEFT
# 右
if rx:
return True, win32con.HTRIGHT
# 标题
return True, win32con.HTCAPTION
return retval, result
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Window()
btn = QPushButton('exit', w, clicked=app.quit)
btn.setGeometry(10, 10, 100, 40)
w.show()
sys.exit(app.exec_())