全局热键

This commit is contained in:
Irony 2017-12-12 00:47:29 +08:00
parent 9f90499259
commit 9ccad8c431
19 changed files with 271 additions and 3 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
tmp
tmp/*
*.pyc

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>PyQtGithub</name>
<name>PyQt</name>
<comment></comment>
<projects>
</projects>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python35</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/${PROJECT_DIR_NAME}</path>
</pydev_pathproperty>

View file

@ -25,4 +25,6 @@
### 11.<a href="浏览器获取Cookie">浏览器获取Cookie</a><br />
### 12.<a href="截图画矩形">截图画矩形</a><br />
### 12.<a href="截图画矩形">截图画矩形</a><br />
### 13.<a href="全局热键">全局热键</a><br />

110
全局热键/HotKey.py Normal file
View file

@ -0,0 +1,110 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2017年12月11日
@author: Irony."[讽刺]
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
@email: 892768447@qq.com
@file: HotKey
@description:
'''
import ctypes # @UnusedImport
import ctypes.wintypes
from datetime import datetime
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout,\
QMessageBox, QTextBrowser, QPushButton
# 参考
# https://github.com/wujunwei/python-cookbook/blob/6e550d1a2b2b045cb07e56dd0198ccf01a2f3ea1/HotKey.py
# https://github.com/chenyijie4238215/notebook/blob/ba11fcc43cf8d623d1d1a722c261ddc20ad6b941/global_hotkey/GlobalHotKey.py
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
__Version__ = "Version 1.0"
WM_HOTKEY = 0x0312
MOD_ALT = 0x0001
MOD_NONE = 0x000
MOD_CONTROL = 0x0002
MOD_SHIFT = 0x0004
MOD_WIN = 0x0008
Modifier = {
"None": MOD_NONE,
"Ctrl": MOD_CONTROL,
"Alt": MOD_ALT,
"Shift": MOD_SHIFT,
"Win": MOD_WIN
}
class Window(QWidget):
KeyIds = {}
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
self.logView = QTextBrowser(self)
self.logView.append("点击右上角关闭按钮会隐藏窗口,通过热键Alt+S来显示")
self.logView.append("等待热键中")
layout.addWidget(QPushButton("退出整个程序", self, clicked=self.onQuit))
layout.addWidget(self.logView)
def unregisterHotKey(self, kid):
ctypes.windll.user32.UnregisterHotKey(ctypes.c_int(self.winId()), kid)
def registerHotKey(self, kid, modifier, key):
key = str(key).upper()
_modifier = Modifier.get(modifier, None)
if not _modifier:
return QMessageBox.critical(self, "错误", "modifier key {0}未找到".format(modifier))
success = ctypes.windll.user32.RegisterHotKey(
ctypes.c_int(self.winId()), kid, _modifier, ord(key))
if success:
self.KeyIds[kid] = modifier + "+" + key
self.logView.append("热键:{0}+{1}注册{2}".format(modifier, key, "成功"))
else:
self.logView.append("热键:{0}+{1}注册{2}".format(modifier, key, "失败"))
def onQuit(self):
# 退出程序
for kid in self.KeyIds:
self.unregisterHotKey(kid)
QApplication.instance().quit()
def closeEvent(self, event):
# 忽略关闭窗口,直接隐藏
self.hide()
return event.ignore()
# 能监听热键,但是有个问题就是其它程序无法接受到事件
# 比如Ctrl+S,在记事本里随便输入内容按下Ctrl+S发现无法保存
def nativeEvent(self, eventType, message):
if eventType == "windows_generic_MSG" or eventType == "windows_dispatcher_MSG":
msg = ctypes.wintypes.MSG.from_address(message.__int__())
# 这段代码无法运行
# if ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0,
# 0) != 0:
if msg.message == WM_HOTKEY:
if msg.wParam == 1: # Alt+S
self.show()
self.logView.append("id:{0}, {1} at time:{2}".format(
msg.wParam, self.KeyIds.get(msg.wParam, None), datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
return True, 0
return super(Window, self).nativeEvent(eventType, message)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Window()
w.show()
w.registerHotKey(1, "Alt", "S")
w.registerHotKey(2, "Ctrl", "S")
w.registerHotKey(3, "Shift", "S")
w.registerHotKey(4, "Win", "S")
w.registerHotKey(5, "Win", "Z")
sys.exit(app.exec_())

9
全局热键/README.md Normal file
View file

@ -0,0 +1,9 @@
# PyQt全局热键 For Windows Test
能监听热键,但是有个问题就是其它程序无法接受到事件<br/>
比如Ctrl+S,在记事本里随便输入内容按下Ctrl+S发现无法保存<br/>
这里还有个比较好的例子<a href="https://github.com/yeejlan/py-stock-watcher/blob/87a7b7cfdeb01b44058fac6906c9cce5fd19cac0/modules/hotkey.py">hotkey.py</a>
# 截图
<img src="ScreenShot/1.png" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

6
自动更新/README.md Normal file
View file

@ -0,0 +1,6 @@
# 自动更新
1.dist/mylibs1.zip 为版本一的文件
2.dist/mylibs2.zip 为版本二的文件
运行演示后再次演示。需要把mylibs1.zip中的文件解压出来替换

BIN
自动更新/dist/mylibs vendored Normal file

Binary file not shown.

BIN
自动更新/dist/mylibs1.zip vendored Normal file

Binary file not shown.

BIN
自动更新/dist/mylibs2.zip vendored Normal file

Binary file not shown.

BIN
自动更新/dist/test.exe vendored Normal file

Binary file not shown.

View file

View file

@ -0,0 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2017年5月7日
@author: Irony."[讽刺]
@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in
@email: 892768447@qq.com
@file: 自动更新.mylibs.testlibs
@description:
'''
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
__Version__ = "Version 1.0"
def version():
return "0.0.1"
def test():
print("version: 0.0.1")

Binary file not shown.

Binary file not shown.

57
自动更新/setup.py Normal file
View file

@ -0,0 +1,57 @@
from distutils.core import setup
import glob
import os
import py_compile
import site
import sys
from zipfile import ZipFile, ZIP_DEFLATED
import py2exe # @UnusedImport
sys.argv.append("py2exe")
sitepackages = site.getsitepackages()[1]
py2exe_options = {
"includes": [],
"excludes": ["mylibs"], # 不打包这个
"dll_excludes": ["MSVCP90.dll", "MSVCR90.dll"],
"compressed": 1, # compressed 值为1则压缩为0不压缩默认为0
"optimize": 2, # optimize - 合法值是字符串('','O','OO')或者整型数字 (0, 1, or 2)
"bundle_files": 1
}
setup(
name="test",
version="0.0.1",
console=[
{"script": "test.py"}
], # 括号中更改为你要打包的代码文件名
zipfile=None,
options={'py2exe': py2exe_options},
data_files=[
# ("","./icon.ico"),
]
)
cores = glob.glob(os.path.join("mylibs", "*.py"))
for core in cores:
py_compile.compile(
core, cfile="pyos\\" + core + "o", doraise=True, optimize=2)
print("compile core module ok")
# 添加到压缩文件
zpfd = ZipFile("dist\\mylibs", "w", ZIP_DEFLATED)
zpfd.write("mylibs")
for core in cores:
zpfd.write("pyos\\" + core + "o", core + "o")
zpfd.close()
print("zip core file ok")
# D:\soft\Python34\python setup.py py2exe
# windows
# console

55
自动更新/test.py Normal file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2017年5月7日
@author: Irony."[讽刺]
@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in
@email: 892768447@qq.com
@file: 自动更新.test
@description:
'''
import sys
sys.path.append("mylibs")
import os
from time import sleep
from zipfile import ZipFile
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
__Version__ = "Version 1.0"
def update():
# 更新
from mylibs import testlibs # @UnresolvedImport
v1 = testlibs.version() # 获取本地模块版本
v2 = "0.0.2" # 模拟新版本(也可以从网络中检测)
if v1 != v2: # 需要更新
print("发现新版本0.0.2")
# 模拟从网络中下载更新包并解压(也可以包含图片等其它文件)
with ZipFile("mylibs2.zip", "r") as zf:
zf.extractall(os.path.dirname(sys.executable)) # 解压到当前目录
return 1
return 0
def main():
from mylibs import testlibs # @UnresolvedImport
testlibs.test()
print("当前版本:", testlibs.version())
if update():
print("更新完毕,即将重启")
import platform
if platform.system() == "Windows":
import ctypes
ctypes.windll.user32.MessageBoxW(
0, "更新完毕,关闭对话框即将重启", "提示", 0x0000030)
sleep(0.5)
os.startfile(sys.executable) # 重启
sys.exit() # 退出本身
if __name__ == "__main__":
main()
input("press any key exit")

3
自动更新/编译.bat Normal file
View file

@ -0,0 +1,3 @@
cd %~dp0
py -3.4 setup.py py2exe
pause