PyQt5 / PyQt

PyQt Examples(PyQt各种测试和例子) PyQt4 PyQt5

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NativeEvent - Maximize window issue

shironori66 opened this issue · comments

Environment : / 环境

  • OS: Win 10
  • Python 3.9 X64
  • PyQt5 e.g. 5.15.1

Hi. I am trying your NativeEvent.py demo. I have trouble maximize the window. This sample worked perfectly but after I added WS_CAPTION in SetWindowLong() for a window animation, I encountered an issue. When i maximize the window, the part mentioned in line ~80 does not work. But if i change that line to "self._rect.height() - 1", it works again but as you can see the window height is not fit to the screen. There is a 1px space and i don't know why the window has to be a bit smaller than the available space.

commented
#!/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 | win32con.WS_CAPTION)

        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
                print(info.ptMaxPosition.x, info.ptMaxPosition.y, info.ptMaxSize.x, info.ptMaxSize.y)
            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_())

win32gui.SetWindowLong(
int(self.winId()), win32con.GWL_STYLE, style | win32con.WS_THICKFRAME | win32con.WS_CAPTION)

print(info.ptMaxPosition.x, info.ptMaxPosition.y, info.ptMaxSize.x, info.ptMaxSize.y)

0, 0, 1920, 1040

Thank you so much. that Chinese site was very helpful.