Sexy system trac icon instead of ugly console, Total received/sent stat, List all site peer, Dont sent passive peers over pex, Dont store passive peers on trackers, Dont monkey patch thread at all, Allow main command plugins
This commit is contained in:
parent
804fed2659
commit
30281c8fb5
14 changed files with 1170 additions and 207 deletions
0
plugins/Trayicon/lib/__init__.py
Normal file
0
plugins/Trayicon/lib/__init__.py
Normal file
800
plugins/Trayicon/lib/notificationicon.py
Normal file
800
plugins/Trayicon/lib/notificationicon.py
Normal file
|
@ -0,0 +1,800 @@
|
|||
# Pure ctypes windows taskbar notification icon
|
||||
# via https://gist.github.com/jasonbot/5759510
|
||||
# Modified for ZeroNet
|
||||
|
||||
import ctypes
|
||||
import ctypes.wintypes
|
||||
import os
|
||||
#import threading
|
||||
#import Queue
|
||||
import uuid
|
||||
import time
|
||||
import gevent
|
||||
|
||||
__all__ = ['NotificationIcon']
|
||||
|
||||
# Create popup menu
|
||||
|
||||
CreatePopupMenu = ctypes.windll.user32.CreatePopupMenu
|
||||
CreatePopupMenu.restype = ctypes.wintypes.HMENU
|
||||
CreatePopupMenu.argtypes = []
|
||||
|
||||
MF_BYCOMMAND = 0x0
|
||||
MF_BYPOSITION = 0x400
|
||||
|
||||
MF_BITMAP = 0x4
|
||||
MF_CHECKED = 0x8
|
||||
MF_DISABLED = 0x2
|
||||
MF_ENABLED = 0x0
|
||||
MF_GRAYED = 0x1
|
||||
MF_MENUBARBREAK = 0x20
|
||||
MF_MENUBREAK = 0x40
|
||||
MF_OWNERDRAW = 0x100
|
||||
MF_POPUP = 0x10
|
||||
MF_SEPARATOR = 0x800
|
||||
MF_STRING = 0x0
|
||||
MF_UNCHECKED = 0x0
|
||||
|
||||
InsertMenu = ctypes.windll.user32.InsertMenuW
|
||||
InsertMenu.restype = ctypes.wintypes.BOOL
|
||||
InsertMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.LPCWSTR]
|
||||
|
||||
AppendMenu = ctypes.windll.user32.AppendMenuW
|
||||
AppendMenu.restype = ctypes.wintypes.BOOL
|
||||
AppendMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT, ctypes.wintypes.LPCWSTR]
|
||||
|
||||
SetMenuDefaultItem = ctypes.windll.user32.SetMenuDefaultItem
|
||||
SetMenuDefaultItem.restype = ctypes.wintypes.BOOL
|
||||
SetMenuDefaultItem.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.wintypes.UINT]
|
||||
|
||||
#class MENUITEMINFO(ctypes.Structure):
|
||||
# UINT cbSize;
|
||||
# UINT fMask;
|
||||
# UINT fType;
|
||||
# UINT fState;
|
||||
# UINT wID;
|
||||
# HMENU hSubMenu;
|
||||
# HBITMAP hbmpChecked;
|
||||
# HBITMAP hbmpUnchecked;
|
||||
# ULONG_PTR dwItemData;
|
||||
# LPTSTR dwTypeData;
|
||||
# UINT cch;
|
||||
# HBITMAP hbmpItem;
|
||||
#
|
||||
#BOOL WINAPI InsertMenuItem(
|
||||
# __in HMENU hMenu,
|
||||
# __in UINT uItem,
|
||||
# __in BOOL fByPosition,
|
||||
# __in LPCMENUITEMINFO lpmii
|
||||
#);
|
||||
#
|
||||
|
||||
class POINT(ctypes.Structure):
|
||||
_fields_ = [ ('x', ctypes.wintypes.LONG),
|
||||
('y', ctypes.wintypes.LONG)]
|
||||
|
||||
GetCursorPos = ctypes.windll.user32.GetCursorPos
|
||||
GetCursorPos.argtypes = [ctypes.POINTER(POINT)]
|
||||
|
||||
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow
|
||||
SetForegroundWindow.argtypes = [ctypes.wintypes.HWND]
|
||||
|
||||
TPM_LEFTALIGN = 0x0
|
||||
TPM_CENTERALIGN = 0x4
|
||||
TPM_RIGHTALIGN = 0x8
|
||||
|
||||
TPM_TOPALIGN = 0x0
|
||||
TPM_VCENTERALIGN = 0x10
|
||||
TPM_BOTTOMALIGN = 0x20
|
||||
|
||||
TPM_NONOTIFY = 0x80
|
||||
TPM_RETURNCMD = 0x100
|
||||
|
||||
TPM_LEFTBUTTON = 0x0
|
||||
TPM_RIGHTBUTTON = 0x2
|
||||
|
||||
TPM_HORNEGANIMATION = 0x800
|
||||
TPM_HORPOSANIMATION = 0x400
|
||||
TPM_NOANIMATION = 0x4000
|
||||
TPM_VERNEGANIMATION = 0x2000
|
||||
TPM_VERPOSANIMATION = 0x1000
|
||||
|
||||
TrackPopupMenu = ctypes.windll.user32.TrackPopupMenu
|
||||
TrackPopupMenu.restype = ctypes.wintypes.BOOL
|
||||
TrackPopupMenu.argtypes = [ctypes.wintypes.HMENU, ctypes.wintypes.UINT, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.wintypes.HWND, ctypes.c_void_p]
|
||||
|
||||
PostMessage = ctypes.windll.user32.PostMessageW
|
||||
PostMessage.restype = ctypes.wintypes.BOOL
|
||||
PostMessage.argtypes = [ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM]
|
||||
|
||||
DestroyMenu = ctypes.windll.user32.DestroyMenu
|
||||
DestroyMenu.restype = ctypes.wintypes.BOOL
|
||||
DestroyMenu.argtypes = [ctypes.wintypes.HMENU]
|
||||
|
||||
# Create notification icon
|
||||
|
||||
GUID = ctypes.c_ubyte * 16
|
||||
|
||||
class TimeoutVersionUnion(ctypes.Union):
|
||||
_fields_ = [('uTimeout', ctypes.wintypes.UINT),
|
||||
('uVersion', ctypes.wintypes.UINT),]
|
||||
|
||||
NIS_HIDDEN = 0x1
|
||||
NIS_SHAREDICON = 0x2
|
||||
|
||||
class NOTIFYICONDATA(ctypes.Structure):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(NOTIFYICONDATA, self).__init__(*args, **kwargs)
|
||||
self.cbSize = ctypes.sizeof(self)
|
||||
_fields_ = [
|
||||
('cbSize', ctypes.wintypes.DWORD),
|
||||
('hWnd', ctypes.wintypes.HWND),
|
||||
('uID', ctypes.wintypes.UINT),
|
||||
('uFlags', ctypes.wintypes.UINT),
|
||||
('uCallbackMessage', ctypes.wintypes.UINT),
|
||||
('hIcon', ctypes.wintypes.HICON),
|
||||
('szTip', ctypes.wintypes.WCHAR * 64),
|
||||
('dwState', ctypes.wintypes.DWORD),
|
||||
('dwStateMask', ctypes.wintypes.DWORD),
|
||||
('szInfo', ctypes.wintypes.WCHAR * 256),
|
||||
('union', TimeoutVersionUnion),
|
||||
('szInfoTitle', ctypes.wintypes.WCHAR * 64),
|
||||
('dwInfoFlags', ctypes.wintypes.DWORD),
|
||||
('guidItem', GUID),
|
||||
('hBalloonIcon', ctypes.wintypes.HICON),
|
||||
]
|
||||
|
||||
NIM_ADD = 0
|
||||
NIM_MODIFY = 1
|
||||
NIM_DELETE = 2
|
||||
NIM_SETFOCUS = 3
|
||||
NIM_SETVERSION = 4
|
||||
|
||||
NIF_MESSAGE = 1
|
||||
NIF_ICON = 2
|
||||
NIF_TIP = 4
|
||||
NIF_STATE = 8
|
||||
NIF_INFO = 16
|
||||
NIF_GUID = 32
|
||||
NIF_REALTIME = 64
|
||||
NIF_SHOWTIP = 128
|
||||
|
||||
NIIF_NONE = 0
|
||||
NIIF_INFO = 1
|
||||
NIIF_WARNING = 2
|
||||
NIIF_ERROR = 3
|
||||
NIIF_USER = 4
|
||||
|
||||
NOTIFYICON_VERSION = 3
|
||||
NOTIFYICON_VERSION_4 = 4
|
||||
|
||||
Shell_NotifyIcon = ctypes.windll.shell32.Shell_NotifyIconW
|
||||
Shell_NotifyIcon.restype = ctypes.wintypes.BOOL
|
||||
Shell_NotifyIcon.argtypes = [ctypes.wintypes.DWORD, ctypes.POINTER(NOTIFYICONDATA)]
|
||||
|
||||
# Load icon/image
|
||||
|
||||
IMAGE_BITMAP = 0
|
||||
IMAGE_ICON = 1
|
||||
IMAGE_CURSOR = 2
|
||||
|
||||
LR_CREATEDIBSECTION = 0x00002000
|
||||
LR_DEFAULTCOLOR = 0x00000000
|
||||
LR_DEFAULTSIZE = 0x00000040
|
||||
LR_LOADFROMFILE = 0x00000010
|
||||
LR_LOADMAP3DCOLORS = 0x00001000
|
||||
LR_LOADTRANSPARENT = 0x00000020
|
||||
LR_MONOCHROME = 0x00000001
|
||||
LR_SHARED = 0x00008000
|
||||
LR_VGACOLOR = 0x00000080
|
||||
|
||||
OIC_SAMPLE = 32512
|
||||
OIC_HAND = 32513
|
||||
OIC_QUES = 32514
|
||||
OIC_BANG = 32515
|
||||
OIC_NOTE = 32516
|
||||
OIC_WINLOGO = 32517
|
||||
OIC_WARNING = OIC_BANG
|
||||
OIC_ERROR = OIC_HAND
|
||||
OIC_INFORMATION = OIC_NOTE
|
||||
|
||||
LoadImage = ctypes.windll.user32.LoadImageW
|
||||
LoadImage.restype = ctypes.wintypes.HANDLE
|
||||
LoadImage.argtypes = [ctypes.wintypes.HINSTANCE, ctypes.wintypes.LPCWSTR, ctypes.wintypes.UINT, ctypes.c_int, ctypes.c_int, ctypes.wintypes.UINT]
|
||||
|
||||
# CreateWindow call
|
||||
|
||||
WNDPROC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.wintypes.HWND, ctypes.c_uint, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
|
||||
DefWindowProc = ctypes.windll.user32.DefWindowProcW
|
||||
DefWindowProc.restype = ctypes.c_int
|
||||
DefWindowProc.argtypes = [ctypes.wintypes.HWND, ctypes.c_uint, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM]
|
||||
|
||||
WS_OVERLAPPED = 0x00000000L
|
||||
WS_POPUP = 0x80000000L
|
||||
WS_CHILD = 0x40000000L
|
||||
WS_MINIMIZE = 0x20000000L
|
||||
WS_VISIBLE = 0x10000000L
|
||||
WS_DISABLED = 0x08000000L
|
||||
WS_CLIPSIBLINGS = 0x04000000L
|
||||
WS_CLIPCHILDREN = 0x02000000L
|
||||
WS_MAXIMIZE = 0x01000000L
|
||||
WS_CAPTION = 0x00C00000L
|
||||
WS_BORDER = 0x00800000L
|
||||
WS_DLGFRAME = 0x00400000L
|
||||
WS_VSCROLL = 0x00200000L
|
||||
WS_HSCROLL = 0x00100000L
|
||||
WS_SYSMENU = 0x00080000L
|
||||
WS_THICKFRAME = 0x00040000L
|
||||
WS_GROUP = 0x00020000L
|
||||
WS_TABSTOP = 0x00010000L
|
||||
|
||||
WS_MINIMIZEBOX = 0x00020000L
|
||||
WS_MAXIMIZEBOX = 0x00010000L
|
||||
|
||||
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |
|
||||
WS_CAPTION |
|
||||
WS_SYSMENU |
|
||||
WS_THICKFRAME |
|
||||
WS_MINIMIZEBOX |
|
||||
WS_MAXIMIZEBOX)
|
||||
|
||||
SM_XVIRTUALSCREEN = 76
|
||||
SM_YVIRTUALSCREEN = 77
|
||||
SM_CXVIRTUALSCREEN = 78
|
||||
SM_CYVIRTUALSCREEN = 79
|
||||
SM_CMONITORS = 80
|
||||
SM_SAMEDISPLAYFORMAT = 81
|
||||
|
||||
WM_NULL = 0x0000
|
||||
WM_CREATE = 0x0001
|
||||
WM_DESTROY = 0x0002
|
||||
WM_MOVE = 0x0003
|
||||
WM_SIZE = 0x0005
|
||||
WM_ACTIVATE = 0x0006
|
||||
WM_SETFOCUS = 0x0007
|
||||
WM_KILLFOCUS = 0x0008
|
||||
WM_ENABLE = 0x000A
|
||||
WM_SETREDRAW = 0x000B
|
||||
WM_SETTEXT = 0x000C
|
||||
WM_GETTEXT = 0x000D
|
||||
WM_GETTEXTLENGTH = 0x000E
|
||||
WM_PAINT = 0x000F
|
||||
WM_CLOSE = 0x0010
|
||||
WM_QUERYENDSESSION = 0x0011
|
||||
WM_QUIT = 0x0012
|
||||
WM_QUERYOPEN = 0x0013
|
||||
WM_ERASEBKGND = 0x0014
|
||||
WM_SYSCOLORCHANGE = 0x0015
|
||||
WM_ENDSESSION = 0x0016
|
||||
WM_SHOWWINDOW = 0x0018
|
||||
WM_CTLCOLOR = 0x0019
|
||||
WM_WININICHANGE = 0x001A
|
||||
WM_SETTINGCHANGE = 0x001A
|
||||
WM_DEVMODECHANGE = 0x001B
|
||||
WM_ACTIVATEAPP = 0x001C
|
||||
WM_FONTCHANGE = 0x001D
|
||||
WM_TIMECHANGE = 0x001E
|
||||
WM_CANCELMODE = 0x001F
|
||||
WM_SETCURSOR = 0x0020
|
||||
WM_MOUSEACTIVATE = 0x0021
|
||||
WM_CHILDACTIVATE = 0x0022
|
||||
WM_QUEUESYNC = 0x0023
|
||||
WM_GETMINMAXINFO = 0x0024
|
||||
WM_PAINTICON = 0x0026
|
||||
WM_ICONERASEBKGND = 0x0027
|
||||
WM_NEXTDLGCTL = 0x0028
|
||||
WM_SPOOLERSTATUS = 0x002A
|
||||
WM_DRAWITEM = 0x002B
|
||||
WM_MEASUREITEM = 0x002C
|
||||
WM_DELETEITEM = 0x002D
|
||||
WM_VKEYTOITEM = 0x002E
|
||||
WM_CHARTOITEM = 0x002F
|
||||
WM_SETFONT = 0x0030
|
||||
WM_GETFONT = 0x0031
|
||||
WM_SETHOTKEY = 0x0032
|
||||
WM_GETHOTKEY = 0x0033
|
||||
WM_QUERYDRAGICON = 0x0037
|
||||
WM_COMPAREITEM = 0x0039
|
||||
WM_GETOBJECT = 0x003D
|
||||
WM_COMPACTING = 0x0041
|
||||
WM_COMMNOTIFY = 0x0044
|
||||
WM_WINDOWPOSCHANGING = 0x0046
|
||||
WM_WINDOWPOSCHANGED = 0x0047
|
||||
WM_POWER = 0x0048
|
||||
WM_COPYDATA = 0x004A
|
||||
WM_CANCELJOURNAL = 0x004B
|
||||
WM_NOTIFY = 0x004E
|
||||
WM_INPUTLANGCHANGEREQUEST = 0x0050
|
||||
WM_INPUTLANGCHANGE = 0x0051
|
||||
WM_TCARD = 0x0052
|
||||
WM_HELP = 0x0053
|
||||
WM_USERCHANGED = 0x0054
|
||||
WM_NOTIFYFORMAT = 0x0055
|
||||
WM_CONTEXTMENU = 0x007B
|
||||
WM_STYLECHANGING = 0x007C
|
||||
WM_STYLECHANGED = 0x007D
|
||||
WM_DISPLAYCHANGE = 0x007E
|
||||
WM_GETICON = 0x007F
|
||||
WM_SETICON = 0x0080
|
||||
WM_NCCREATE = 0x0081
|
||||
WM_NCDESTROY = 0x0082
|
||||
WM_NCCALCSIZE = 0x0083
|
||||
WM_NCHITTEST = 0x0084
|
||||
WM_NCPAINT = 0x0085
|
||||
WM_NCACTIVATE = 0x0086
|
||||
WM_GETDLGCODE = 0x0087
|
||||
WM_SYNCPAINT = 0x0088
|
||||
WM_NCMOUSEMOVE = 0x00A0
|
||||
WM_NCLBUTTONDOWN = 0x00A1
|
||||
WM_NCLBUTTONUP = 0x00A2
|
||||
WM_NCLBUTTONDBLCLK = 0x00A3
|
||||
WM_NCRBUTTONDOWN = 0x00A4
|
||||
WM_NCRBUTTONUP = 0x00A5
|
||||
WM_NCRBUTTONDBLCLK = 0x00A6
|
||||
WM_NCMBUTTONDOWN = 0x00A7
|
||||
WM_NCMBUTTONUP = 0x00A8
|
||||
WM_NCMBUTTONDBLCLK = 0x00A9
|
||||
WM_KEYDOWN = 0x0100
|
||||
WM_KEYUP = 0x0101
|
||||
WM_CHAR = 0x0102
|
||||
WM_DEADCHAR = 0x0103
|
||||
WM_SYSKEYDOWN = 0x0104
|
||||
WM_SYSKEYUP = 0x0105
|
||||
WM_SYSCHAR = 0x0106
|
||||
WM_SYSDEADCHAR = 0x0107
|
||||
WM_KEYLAST = 0x0108
|
||||
WM_IME_STARTCOMPOSITION = 0x010D
|
||||
WM_IME_ENDCOMPOSITION = 0x010E
|
||||
WM_IME_COMPOSITION = 0x010F
|
||||
WM_IME_KEYLAST = 0x010F
|
||||
WM_INITDIALOG = 0x0110
|
||||
WM_COMMAND = 0x0111
|
||||
WM_SYSCOMMAND = 0x0112
|
||||
WM_TIMER = 0x0113
|
||||
WM_HSCROLL = 0x0114
|
||||
WM_VSCROLL = 0x0115
|
||||
WM_INITMENU = 0x0116
|
||||
WM_INITMENUPOPUP = 0x0117
|
||||
WM_MENUSELECT = 0x011F
|
||||
WM_MENUCHAR = 0x0120
|
||||
WM_ENTERIDLE = 0x0121
|
||||
WM_MENURBUTTONUP = 0x0122
|
||||
WM_MENUDRAG = 0x0123
|
||||
WM_MENUGETOBJECT = 0x0124
|
||||
WM_UNINITMENUPOPUP = 0x0125
|
||||
WM_MENUCOMMAND = 0x0126
|
||||
WM_CTLCOLORMSGBOX = 0x0132
|
||||
WM_CTLCOLOREDIT = 0x0133
|
||||
WM_CTLCOLORLISTBOX = 0x0134
|
||||
WM_CTLCOLORBTN = 0x0135
|
||||
WM_CTLCOLORDLG = 0x0136
|
||||
WM_CTLCOLORSCROLLBAR = 0x0137
|
||||
WM_CTLCOLORSTATIC = 0x0138
|
||||
WM_MOUSEMOVE = 0x0200
|
||||
WM_LBUTTONDOWN = 0x0201
|
||||
WM_LBUTTONUP = 0x0202
|
||||
WM_LBUTTONDBLCLK = 0x0203
|
||||
WM_RBUTTONDOWN = 0x0204
|
||||
WM_RBUTTONUP = 0x0205
|
||||
WM_RBUTTONDBLCLK = 0x0206
|
||||
WM_MBUTTONDOWN = 0x0207
|
||||
WM_MBUTTONUP = 0x0208
|
||||
WM_MBUTTONDBLCLK = 0x0209
|
||||
WM_MOUSEWHEEL = 0x020A
|
||||
WM_PARENTNOTIFY = 0x0210
|
||||
WM_ENTERMENULOOP = 0x0211
|
||||
WM_EXITMENULOOP = 0x0212
|
||||
WM_NEXTMENU = 0x0213
|
||||
WM_SIZING = 0x0214
|
||||
WM_CAPTURECHANGED = 0x0215
|
||||
WM_MOVING = 0x0216
|
||||
WM_DEVICECHANGE = 0x0219
|
||||
WM_MDICREATE = 0x0220
|
||||
WM_MDIDESTROY = 0x0221
|
||||
WM_MDIACTIVATE = 0x0222
|
||||
WM_MDIRESTORE = 0x0223
|
||||
WM_MDINEXT = 0x0224
|
||||
WM_MDIMAXIMIZE = 0x0225
|
||||
WM_MDITILE = 0x0226
|
||||
WM_MDICASCADE = 0x0227
|
||||
WM_MDIICONARRANGE = 0x0228
|
||||
WM_MDIGETACTIVE = 0x0229
|
||||
WM_MDISETMENU = 0x0230
|
||||
WM_ENTERSIZEMOVE = 0x0231
|
||||
WM_EXITSIZEMOVE = 0x0232
|
||||
WM_DROPFILES = 0x0233
|
||||
WM_MDIREFRESHMENU = 0x0234
|
||||
WM_IME_SETCONTEXT = 0x0281
|
||||
WM_IME_NOTIFY = 0x0282
|
||||
WM_IME_CONTROL = 0x0283
|
||||
WM_IME_COMPOSITIONFULL = 0x0284
|
||||
WM_IME_SELECT = 0x0285
|
||||
WM_IME_CHAR = 0x0286
|
||||
WM_IME_REQUEST = 0x0288
|
||||
WM_IME_KEYDOWN = 0x0290
|
||||
WM_IME_KEYUP = 0x0291
|
||||
WM_MOUSEHOVER = 0x02A1
|
||||
WM_MOUSELEAVE = 0x02A3
|
||||
WM_CUT = 0x0300
|
||||
WM_COPY = 0x0301
|
||||
WM_PASTE = 0x0302
|
||||
WM_CLEAR = 0x0303
|
||||
WM_UNDO = 0x0304
|
||||
WM_RENDERFORMAT = 0x0305
|
||||
WM_RENDERALLFORMATS = 0x0306
|
||||
WM_DESTROYCLIPBOARD = 0x0307
|
||||
WM_DRAWCLIPBOARD = 0x0308
|
||||
WM_PAINTCLIPBOARD = 0x0309
|
||||
WM_VSCROLLCLIPBOARD = 0x030A
|
||||
WM_SIZECLIPBOARD = 0x030B
|
||||
WM_ASKCBFORMATNAME = 0x030C
|
||||
WM_CHANGECBCHAIN = 0x030D
|
||||
WM_HSCROLLCLIPBOARD = 0x030E
|
||||
WM_QUERYNEWPALETTE = 0x030F
|
||||
WM_PALETTEISCHANGING = 0x0310
|
||||
WM_PALETTECHANGED = 0x0311
|
||||
WM_HOTKEY = 0x0312
|
||||
WM_PRINT = 0x0317
|
||||
WM_PRINTCLIENT = 0x0318
|
||||
WM_HANDHELDFIRST = 0x0358
|
||||
WM_HANDHELDLAST = 0x035F
|
||||
WM_AFXFIRST = 0x0360
|
||||
WM_AFXLAST = 0x037F
|
||||
WM_PENWINFIRST = 0x0380
|
||||
WM_PENWINLAST = 0x038F
|
||||
WM_APP = 0x8000
|
||||
WM_USER = 0x0400
|
||||
WM_REFLECT = WM_USER + 0x1c00
|
||||
|
||||
class WNDCLASSEX(ctypes.Structure):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WNDCLASSEX, self).__init__(*args, **kwargs)
|
||||
self.cbSize = ctypes.sizeof(self)
|
||||
_fields_ = [("cbSize", ctypes.c_uint),
|
||||
("style", ctypes.c_uint),
|
||||
("lpfnWndProc", WNDPROC),
|
||||
("cbClsExtra", ctypes.c_int),
|
||||
("cbWndExtra", ctypes.c_int),
|
||||
("hInstance", ctypes.wintypes.HANDLE),
|
||||
("hIcon", ctypes.wintypes.HANDLE),
|
||||
("hCursor", ctypes.wintypes.HANDLE),
|
||||
("hBrush", ctypes.wintypes.HANDLE),
|
||||
("lpszMenuName", ctypes.wintypes.LPCWSTR),
|
||||
("lpszClassName", ctypes.wintypes.LPCWSTR),
|
||||
("hIconSm", ctypes.wintypes.HANDLE)]
|
||||
|
||||
UpdateWindow = ctypes.windll.user32.UpdateWindow
|
||||
UpdateWindow.argtypes = [ctypes.wintypes.HWND]
|
||||
|
||||
SW_HIDE = 0
|
||||
SW_SHOWNORMAL = 1
|
||||
SW_SHOW = 5
|
||||
|
||||
ShowWindow = ctypes.windll.user32.ShowWindow
|
||||
ShowWindow.argtypes = [ctypes.wintypes.HWND, ctypes.c_int]
|
||||
|
||||
CS_VREDRAW = 0x0001
|
||||
CS_HREDRAW = 0x0002
|
||||
CS_KEYCVTWINDOW = 0x0004
|
||||
CS_DBLCLKS = 0x0008
|
||||
CS_OWNDC = 0x0020
|
||||
CS_CLASSDC = 0x0040
|
||||
CS_PARENTDC = 0x0080
|
||||
CS_NOKEYCVT = 0x0100
|
||||
CS_NOCLOSE = 0x0200
|
||||
CS_SAVEBITS = 0x0800
|
||||
CS_BYTEALIGNCLIENT = 0x1000
|
||||
CS_BYTEALIGNWINDOW = 0x2000
|
||||
CS_GLOBALCLASS = 0x4000
|
||||
|
||||
COLOR_SCROLLBAR = 0
|
||||
COLOR_BACKGROUND = 1
|
||||
COLOR_ACTIVECAPTION = 2
|
||||
COLOR_INACTIVECAPTION = 3
|
||||
COLOR_MENU = 4
|
||||
COLOR_WINDOW = 5
|
||||
COLOR_WINDOWFRAME = 6
|
||||
COLOR_MENUTEXT = 7
|
||||
COLOR_WINDOWTEXT = 8
|
||||
COLOR_CAPTIONTEXT = 9
|
||||
COLOR_ACTIVEBORDER = 10
|
||||
COLOR_INACTIVEBORDER = 11
|
||||
COLOR_APPWORKSPACE = 12
|
||||
COLOR_HIGHLIGHT = 13
|
||||
COLOR_HIGHLIGHTTEXT = 14
|
||||
COLOR_BTNFACE = 15
|
||||
COLOR_BTNSHADOW = 16
|
||||
COLOR_GRAYTEXT = 17
|
||||
COLOR_BTNTEXT = 18
|
||||
COLOR_INACTIVECAPTIONTEXT = 19
|
||||
COLOR_BTNHIGHLIGHT = 20
|
||||
|
||||
LoadCursor = ctypes.windll.user32.LoadCursorW
|
||||
|
||||
def GenerateDummyWindow(callback, uid):
|
||||
newclass = WNDCLASSEX()
|
||||
newclass.lpfnWndProc = callback
|
||||
newclass.style = CS_VREDRAW | CS_HREDRAW
|
||||
newclass.lpszClassName = uid.replace("-", "")
|
||||
newclass.hBrush = COLOR_BACKGROUND
|
||||
newclass.hCursor = LoadCursor(0, 32512)
|
||||
ATOM = ctypes.windll.user32.RegisterClassExW(ctypes.byref(newclass))
|
||||
#print "ATOM", ATOM
|
||||
#print "CLASS", newclass.lpszClassName
|
||||
hwnd = ctypes.windll.user32.CreateWindowExW(0,
|
||||
newclass.lpszClassName,
|
||||
u"Dummy Window",
|
||||
WS_OVERLAPPEDWINDOW | WS_SYSMENU,
|
||||
ctypes.windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
||||
ctypes.windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN),
|
||||
800, 600, 0, 0, 0, 0)
|
||||
ShowWindow(hwnd, SW_SHOW)
|
||||
UpdateWindow(hwnd)
|
||||
ShowWindow(hwnd, SW_HIDE)
|
||||
return hwnd
|
||||
|
||||
# Message loop calls
|
||||
|
||||
TIMERCALLBACK = ctypes.WINFUNCTYPE(None,
|
||||
ctypes.wintypes.HWND,
|
||||
ctypes.wintypes.UINT,
|
||||
ctypes.POINTER(ctypes.wintypes.UINT),
|
||||
ctypes.wintypes.DWORD)
|
||||
|
||||
SetTimer = ctypes.windll.user32.SetTimer
|
||||
SetTimer.restype = ctypes.POINTER(ctypes.wintypes.UINT)
|
||||
SetTimer.argtypes = [ctypes.wintypes.HWND,
|
||||
ctypes.POINTER(ctypes.wintypes.UINT),
|
||||
ctypes.wintypes.UINT,
|
||||
TIMERCALLBACK]
|
||||
|
||||
KillTimer = ctypes.windll.user32.KillTimer
|
||||
KillTimer.restype = ctypes.wintypes.BOOL
|
||||
KillTimer.argtypes = [ctypes.wintypes.HWND,
|
||||
ctypes.POINTER(ctypes.wintypes.UINT)]
|
||||
|
||||
class MSG(ctypes.Structure):
|
||||
_fields_ = [ ('HWND', ctypes.wintypes.HWND),
|
||||
('message', ctypes.wintypes.UINT),
|
||||
('wParam', ctypes.wintypes.WPARAM),
|
||||
('lParam', ctypes.wintypes.LPARAM),
|
||||
('time', ctypes.wintypes.DWORD),
|
||||
('pt', POINT)]
|
||||
|
||||
GetMessage = ctypes.windll.user32.GetMessageW
|
||||
GetMessage.restype = ctypes.wintypes.BOOL
|
||||
GetMessage.argtypes = [ctypes.POINTER(MSG), ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.UINT]
|
||||
|
||||
TranslateMessage = ctypes.windll.user32.TranslateMessage
|
||||
TranslateMessage.restype = ctypes.wintypes.ULONG
|
||||
TranslateMessage.argtypes = [ctypes.POINTER(MSG)]
|
||||
|
||||
DispatchMessage = ctypes.windll.user32.DispatchMessageW
|
||||
DispatchMessage.restype = ctypes.wintypes.ULONG
|
||||
DispatchMessage.argtypes = [ctypes.POINTER(MSG)]
|
||||
|
||||
def LoadIcon(iconfilename, small=False):
|
||||
return LoadImage(0,
|
||||
unicode(iconfilename),
|
||||
IMAGE_ICON,
|
||||
16 if small else 0,
|
||||
16 if small else 0,
|
||||
LR_LOADFROMFILE)
|
||||
|
||||
|
||||
class NotificationIcon(object):
|
||||
def __init__(self, iconfilename, tooltip=None):
|
||||
assert os.path.isfile(unicode(iconfilename)), "{} doesn't exist".format(iconfilename)
|
||||
self._iconfile = unicode(iconfilename)
|
||||
self._hicon = LoadIcon(self._iconfile, True)
|
||||
assert self._hicon, "Failed to load {}".format(iconfilename)
|
||||
#self._pumpqueue = Queue.Queue()
|
||||
self._die = False
|
||||
self._timerid = None
|
||||
self._uid = uuid.uuid4()
|
||||
self._tooltip = unicode(tooltip) if tooltip else u''
|
||||
#self._thread = threading.Thread(target=self._run)
|
||||
#self._thread.start()
|
||||
self._info_bubble = None
|
||||
self.items = []
|
||||
|
||||
|
||||
def _bubble(self, iconinfo):
|
||||
if self._info_bubble:
|
||||
info_bubble = self._info_bubble
|
||||
self._info_bubble = None
|
||||
message = unicode(self._info_bubble)
|
||||
iconinfo.uFlags |= NIF_INFO
|
||||
iconinfo.szInfo = message
|
||||
iconinfo.szInfoTitle = message
|
||||
iconinfo.dwInfoFlags = NIIF_INFO
|
||||
iconinfo.union.uTimeout = 10000
|
||||
Shell_NotifyIcon(NIM_MODIFY, ctypes.pointer(iconinfo))
|
||||
|
||||
|
||||
def _run(self):
|
||||
self._windowproc = WNDPROC(self._callback)
|
||||
self._hwnd = GenerateDummyWindow(self._windowproc, str(self._uid))
|
||||
|
||||
iconinfo = NOTIFYICONDATA()
|
||||
iconinfo.hWnd = self._hwnd
|
||||
iconinfo.uID = 100
|
||||
iconinfo.uFlags = NIF_ICON | NIF_SHOWTIP | NIF_MESSAGE | (NIF_TIP if self._tooltip else 0)
|
||||
iconinfo.uCallbackMessage = WM_MENUCOMMAND
|
||||
iconinfo.hIcon = self._hicon
|
||||
iconinfo.szTip = self._tooltip
|
||||
iconinfo.dwState = NIS_SHAREDICON
|
||||
iconinfo.dwInfoFlags = NIIF_INFO
|
||||
# iconinfo.dwStateMask = NIS_SHAREDICON
|
||||
iconinfo.szInfo = "Application Title"
|
||||
iconinfo.union.uTimeout = 5000
|
||||
|
||||
Shell_NotifyIcon(NIM_ADD, ctypes.pointer(iconinfo))
|
||||
|
||||
iconinfo.union.uVersion = NOTIFYICON_VERSION
|
||||
self.iconinfo = iconinfo
|
||||
|
||||
Shell_NotifyIcon(NIM_SETVERSION, ctypes.pointer(iconinfo))
|
||||
|
||||
PostMessage(self._hwnd, WM_NULL, 0, 0)
|
||||
|
||||
#self._timerid = SetTimer(self._hwnd, self._timerid, 25, TIMERCALLBACK())
|
||||
message = MSG()
|
||||
last_time = -1
|
||||
ret = None
|
||||
while not self._die:
|
||||
ret = GetMessage(ctypes.pointer(message), 0, 0, 0)
|
||||
TranslateMessage(ctypes.pointer(message))
|
||||
DispatchMessage(ctypes.pointer(message))
|
||||
time.sleep(0.125)
|
||||
#KillTimer(self._hwnd, self._timerid)
|
||||
|
||||
Shell_NotifyIcon(NIM_DELETE, ctypes.pointer(iconinfo))
|
||||
ctypes.windll.user32.DestroyWindow(self._hwnd)
|
||||
ctypes.windll.user32.DestroyIcon(self._hicon)
|
||||
|
||||
|
||||
def _menu(self):
|
||||
if not hasattr(self, 'items'):
|
||||
return
|
||||
|
||||
menu = CreatePopupMenu()
|
||||
func = None
|
||||
|
||||
try:
|
||||
iidx = 1000
|
||||
defaultitem = -1
|
||||
item_map = {}
|
||||
for fs in self.items:
|
||||
iidx += 1
|
||||
if isinstance(fs, basestring):
|
||||
if fs and not fs.strip('-_='):
|
||||
AppendMenu(menu, MF_SEPARATOR, iidx, fs)
|
||||
else:
|
||||
AppendMenu(menu, MF_STRING | MF_GRAYED, iidx, fs)
|
||||
elif isinstance(fs, tuple):
|
||||
if callable(fs[0]):
|
||||
itemstring = fs[0]()
|
||||
else:
|
||||
itemstring = unicode(fs[0])
|
||||
flags = MF_STRING
|
||||
if itemstring.startswith("!"):
|
||||
itemstring = itemstring[1:]
|
||||
defaultitem = iidx
|
||||
if itemstring.startswith("+"):
|
||||
itemstring = itemstring[1:]
|
||||
flags = flags | MF_CHECKED
|
||||
itemcallable = fs[1]
|
||||
item_map[iidx] = itemcallable
|
||||
if itemcallable is False:
|
||||
flags = flags | MF_DISABLED
|
||||
elif not callable(itemcallable):
|
||||
flags = flags | MF_GRAYED
|
||||
AppendMenu(menu, flags, iidx, itemstring)
|
||||
|
||||
if defaultitem != -1:
|
||||
SetMenuDefaultItem(menu, defaultitem, 0)
|
||||
|
||||
pos = POINT()
|
||||
GetCursorPos(ctypes.pointer(pos))
|
||||
|
||||
PostMessage(self._hwnd, WM_NULL, 0, 0)
|
||||
|
||||
SetForegroundWindow(self._hwnd)
|
||||
|
||||
ti = TrackPopupMenu(menu, TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, pos.x, pos.y, 0, self._hwnd, None)
|
||||
|
||||
if ti in item_map:
|
||||
func = item_map[ti]
|
||||
|
||||
PostMessage(self._hwnd, WM_NULL, 0, 0)
|
||||
finally:
|
||||
DestroyMenu(menu)
|
||||
if func: func()
|
||||
|
||||
|
||||
def clicked(self):
|
||||
self._menu()
|
||||
|
||||
|
||||
|
||||
def _callback(self, hWnd, msg, wParam, lParam):
|
||||
# Check if the main thread is still alive
|
||||
if msg == WM_TIMER:
|
||||
if not any(thread.getName() == 'MainThread' and thread.isAlive()
|
||||
for thread in threading.enumerate()):
|
||||
self._die = True
|
||||
elif msg == WM_MENUCOMMAND and lParam == WM_LBUTTONUP:
|
||||
self.clicked()
|
||||
elif msg == WM_MENUCOMMAND and lParam == WM_RBUTTONUP:
|
||||
self._menu()
|
||||
else:
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam)
|
||||
return 1
|
||||
|
||||
|
||||
def die(self):
|
||||
try:
|
||||
Shell_NotifyIcon(NIM_DELETE, ctypes.pointer(self.iconinfo))
|
||||
except:
|
||||
pass
|
||||
ctypes.windll.user32.DestroyWindow(self._hwnd)
|
||||
ctypes.windll.user32.DestroyIcon(self._hicon)
|
||||
self._die = True
|
||||
|
||||
|
||||
def pump(self):
|
||||
try:
|
||||
while not self._pumpqueue.empty():
|
||||
callable = self._pumpqueue.get(False)
|
||||
callable()
|
||||
except Queue.Empty:
|
||||
pass
|
||||
|
||||
|
||||
def announce(self, text):
|
||||
self._info_bubble = text
|
||||
|
||||
|
||||
def hideConsole():
|
||||
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
|
||||
|
||||
def showConsole():
|
||||
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
def greet():
|
||||
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
|
||||
print "Hello"
|
||||
def quit():
|
||||
ni._die = True
|
||||
#sys.exit()
|
||||
def announce():
|
||||
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 1)
|
||||
ni.announce("Hello there")
|
||||
|
||||
def clicked():
|
||||
ni.announce("Hello")
|
||||
|
||||
def dynamicTitle():
|
||||
return "!The time is: %s" % time.time()
|
||||
|
||||
ni = NotificationIcon(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../trayicon.ico'), "ZeroNet 0.2.9")
|
||||
ni.items = [
|
||||
(dynamicTitle, False),
|
||||
('Hello', greet),
|
||||
('Title', False),
|
||||
('!Default', greet),
|
||||
('+Popup bubble', announce),
|
||||
'Nothing',
|
||||
'--',
|
||||
('Quit', quit)
|
||||
]
|
||||
ni.clicked = clicked
|
||||
import atexit
|
||||
@atexit.register
|
||||
def goodbye():
|
||||
print "You are now leaving the Python sector."
|
||||
|
||||
ni._run()
|
48
plugins/Trayicon/lib/winfolders.py
Normal file
48
plugins/Trayicon/lib/winfolders.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
''' Get windows special folders without pythonwin
|
||||
Example:
|
||||
import specialfolders
|
||||
start_programs = specialfolders.get(specialfolders.PROGRAMS)
|
||||
|
||||
Code is public domain, do with it what you will.
|
||||
|
||||
Luke Pinner - Environment.gov.au, 2010 February 10
|
||||
'''
|
||||
|
||||
#Imports use _syntax to mask them from autocomplete IDE's
|
||||
import ctypes as _ctypes
|
||||
from ctypes.wintypes import HWND as _HWND, HANDLE as _HANDLE,DWORD as _DWORD,LPCWSTR as _LPCWSTR,MAX_PATH as _MAX_PATH, create_unicode_buffer as _cub
|
||||
_SHGetFolderPath = _ctypes.windll.shell32.SHGetFolderPathW
|
||||
|
||||
#public special folder constants
|
||||
DESKTOP= 0
|
||||
PROGRAMS= 2
|
||||
MYDOCUMENTS= 5
|
||||
FAVORITES= 6
|
||||
STARTUP= 7
|
||||
RECENT= 8
|
||||
SENDTO= 9
|
||||
STARTMENU= 11
|
||||
MYMUSIC= 13
|
||||
MYVIDEOS= 14
|
||||
NETHOOD= 19
|
||||
FONTS= 20
|
||||
TEMPLATES= 21
|
||||
ALLUSERSSTARTMENU= 22
|
||||
ALLUSERSPROGRAMS= 23
|
||||
ALLUSERSSTARTUP= 24
|
||||
ALLUSERSDESKTOP= 25
|
||||
APPLICATIONDATA= 26
|
||||
PRINTHOOD= 27
|
||||
LOCALSETTINGSAPPLICATIONDATA= 28
|
||||
ALLUSERSFAVORITES= 31
|
||||
LOCALSETTINGSTEMPORARYINTERNETFILES=32
|
||||
COOKIES= 33
|
||||
LOCALSETTINGSHISTORY= 34
|
||||
ALLUSERSAPPLICATIONDATA= 35
|
||||
|
||||
def get(intFolder):
|
||||
_SHGetFolderPath.argtypes = [_HWND, _ctypes.c_int, _HANDLE, _DWORD, _LPCWSTR]
|
||||
auPathBuffer = _cub(_MAX_PATH)
|
||||
exit_code=_SHGetFolderPath(0, intFolder, 0, 0, auPathBuffer)
|
||||
return auPathBuffer.value
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue