Обновить Windows Balloon Tip из темы Python
Я использую модуль для всплывающих уведомлений в системном трее, когда пользователь получает новое сообщение. (используя Python 3.3 и Kivy 1.8. Я развертываю на Windows 7.)
Я полагаю, что оригинальный код исходит от этого github.
Это модуль, как я изменил его:
from win32api import *
from win32gui import *
import win32con
import sys, os
import struct
import threading
import time
print ("Importing pypops")
class WindowsBalloonTip:
def __init__(self, title, msg):
message_map = {
win32con.WM_DESTROY: self.OnDestroy,
# win32con.WM_CLOSE: self.onClose
}
# Register the Window class.
wc = WNDCLASS()
hinst = wc.hInstance = GetModuleHandle(None)
wc.lpszClassName = "PythonTaskbar"
wc.lpfnWndProc = message_map # could also specify a wndproc.
classAtom = RegisterClass(wc)
# Create the Window.
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
self.hwnd = CreateWindow( classAtom, "Taskbar", style, \
0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \
0, 0, hinst, None)
UpdateWindow(self.hwnd)
iconPathName = os.path.abspath(os.path.join( sys.path[0], "balloontip.ico" ))
icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
try:
hicon = LoadImage(hinst, iconPathName, \
win32con.IMAGE_ICON, 0, 0, icon_flags)
except:
hicon = LoadIcon(0, win32con.IDI_APPLICATION)
flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "tooltip")
#Notify
Shell_NotifyIcon(NIM_ADD, nid)
Shell_NotifyIcon(NIM_MODIFY, \
(self.hwnd, 0, NIF_INFO, win32con.WM_USER+20,\
hicon, "Balloon tooltip",msg,400,title))
### from original code
# time.sleep(10) #cannot use this. it kills the whole app
# DestroyWindow(self.hwnd)
# classAtom = UnregisterClass(classAtom, hinst)
def onClose(self, hwnd): #to be called from thread as a method of the class instance
DestroyWindow(hwnd)
classAtom = UnregisterClass(classAtom, hinst)
return True
def OnDestroy(self, hwnd, msg, wparam, lparam):
nid = (self.hwnd, 0)
Shell_NotifyIcon(NIM_DELETE, nid)
PostQuitMessage(0) # Terminate the app.
Я инстанцирую WindowsBalloonTip
Класс в потоке, если и только если приходит новое сообщение. После создания экземпляра класса, если последующий поток обнаруживает другое новое сообщение, я пытался вызвать onClose
в качестве метода класса pypops и получения
pywintypes.error: (1400, 'DestroyWindow', 'Неверный дескриптор окна.').
Я знаю из других источников, что это потому, что поток, который создает окно, должен использоваться для его уничтожения. Как обойти это?
time.sleep
Решение, закомментированное в моем коде, неосуществимо по крайней мере по следующим причинам:
- Мне нужно окно, чтобы остаться в живых, пока а) пользователь не нажмет или б) не появится новое сообщение
time.sleep()
убивает все мое приложение, предотвращает ввод пользователя, перерисовки и т. д.
Я исследовал: Обработка недействительных оконных дескрипторов и многие другие.
Как я могу уничтожить окно и динамически отменить регистрацию класса в потоке или обновить окно Text
?
Когда я пытаюсь DestroyWindow
как последовательный --init--
шаг, все работает отлично. логирование 'hwnd'
дает целое число Тем не менее, когда я пытаюсь позвонить onClose
, Я получаю ошибку 1400, хотя ведение журнала 'hwnd'
в этом случае дает то же самое точное значение, что и другие 'hwnd'
другими словами, параметр, который я передаю DestroyWindow
такое же значение, будь то DestroyWindow
происходит в --init--
этап, или как часть метода, который я вызову позже. Что говорит об ошибке в последнем случае?
Я очень хорошо знаком с Python и становлюсь лучше с Kivy. Тем не менее, это мой первый набег в любую совместимость с графическим интерфейсом и интерфейсом Windows.
Спасибо за любые ответы, предложения, критику, ведет!
"Ведет? Ведет, да, конечно. Я просто посоветуюсь с ребятами в Криминальной лаборатории. У них есть еще четыре детектива, работающие над делом. Они заставляют нас работать посменно".