123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- # coding=utf-8
- # pystray
- # Copyright (C) 2016-2020 Moses Palmér
- #
- # This program is free software: you can redistribute it and/or modify it under
- # the terms of the GNU Lesser General Public License as published by the Free
- # Software Foundation, either version 3 of the License, or (at your option) any
- # later version.
- #
- # This program is distributed in the hope that it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- # details.
- #
- # You should have received a copy of the GNU Lesser General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- import ctypes
- from ctypes import wintypes
- windll = ctypes.LibraryLoader(ctypes.WinDLL)
- WM_CREATE = 0x0001
- WM_NCCREATE = 0x0081
- WM_LBUTTONUP = 0x0202
- WM_RBUTTONUP = 0x0205
- WM_USER = 0x400
- WM_STOP = WM_USER + 10
- WM_NOTIFY = WM_USER + 11
- LR_DEFAULTSIZE = 0x00000040
- LR_LOADFROMFILE = 0x00000010
- MFS_CHECKED = 0x00000008
- MFS_DEFAULT = 0x00001000
- MFS_DISABLED = 0x00000003
- MFS_ENABLED = 0x00000000
- MFS_GRAYED = 0x00000003
- MFS_HILITE = 0x00000080
- MFS_UNCHECKED = 0x00000000
- MFS_UNHILITE = 0x00000000
- MFT_BITMAP = 0x00000004
- MFT_MENUBARBREAK = 0x00000020
- MFT_MENUBREAK = 0x00000040
- MFT_OWNERDRAW = 0x00000100
- MFT_RADIOCHECK = 0x00000200
- MFT_RIGHTJUSTIFY = 0x00004000
- MFT_RIGHTORDER = 0x00002000
- MFT_SEPARATOR = 0x00000800
- MFT_STRING = 0x00000000
- MIIM_BITMAP = 0x00000080
- MIIM_CHECKMARKS = 0x00000008
- MIIM_DATA = 0x00000020
- MIIM_FTYPE = 0x00000100
- MIIM_ID = 0x00000002
- MIIM_STATE = 0x00000001
- MIIM_STRING = 0x00000040
- MIIM_SUBMENU = 0x00000004
- MIIM_TYPE = 0x00000010
- MSGFLT_ALLOW = 1
- MSGFLT_DISALLOW = 2
- MSGFLT_RESET = 0
- NIF_MESSAGE = 0x00000001
- NIF_ICON = 0x00000002
- NIF_TIP = 0x00000004
- NIF_STATE = 0x00000008
- NIF_INFO = 0x00000010
- NIF_GUID = 0x00000020
- NIF_REALTIME = 0x00000040
- NIF_SHOWTIP = 0x00000080
- NIM_ADD = 0x00000000
- NIM_MODIFY = 0x00000001
- NIM_DELETE = 0x00000002
- NIM_SETFOCUS = 0x00000003
- NIM_SETVERSION = 0x00000004
- TPM_CENTERALIGN = 0x0004
- TPM_LEFTALIGN = 0x0000
- TPM_RIGHTALIGN = 0x0008
- TPM_BOTTOMALIGN = 0x0020
- TPM_TOPALIGN = 0x0000
- TPM_VCENTERALIGN = 0x0010
- TPM_NONOTIFY = 0x0080
- TPM_RETURNCMD = 0x0100
- TPM_LEFTBUTTON = 0x0000
- TPM_RIGHTBUTTON = 0x0002
- TPM_HORNEGANIMATION = 0x0800
- TPM_HORPOSANIMATION = 0x0400
- TPM_NOANIMATION = 0x4000
- TPM_VERNEGANIMATION = 0x2000
- TPM_VERPOSANIMATION = 0x1000
- TPM_HORIZONTAL = 0x0000
- TPM_VERTICAL = 0x0040
- WS_POPUP = 0x80000000
- PM_NOREMOVE = 0
- COLOR_WINDOW = 5
- HWND_MESSAGE = -3
- IMAGE_ICON = 1
- LPMSG = ctypes.POINTER(wintypes.MSG)
- LPPOINT = ctypes.POINTER(wintypes.POINT)
- WNDPROC = ctypes.WINFUNCTYPE(
- ctypes.HRESULT,
- wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
- class MENUITEMINFO(ctypes.Structure):
- _fields_ = [
- ('cbSize', wintypes.UINT),
- ('fMask', wintypes.UINT),
- ('fType', wintypes.UINT),
- ('fState', wintypes.UINT),
- ('wID', wintypes.UINT),
- ('hSubMenu', wintypes.HMENU),
- ('hbmpChecked', wintypes.HBITMAP),
- ('hbmpUnchecked', wintypes.HBITMAP),
- ('dwItemData', wintypes.LPVOID),
- ('dwTypeData', wintypes.LPCWSTR),
- ('cch', wintypes.UINT),
- ('hbmpItem', wintypes.HBITMAP)]
- LPMENUITEMINFO = ctypes.POINTER(MENUITEMINFO)
- class NOTIFYICONDATAW(ctypes.Structure):
- class VERSION_OR_TIMEOUT(ctypes.Union):
- _fields_ = [
- ('uTimeout', wintypes.UINT),
- ('uVersion', wintypes.UINT)]
- class GUID(ctypes.Structure):
- _fields_ = [
- ('Data1', wintypes.ULONG),
- ('Data2', wintypes.WORD),
- ('Data3', wintypes.WORD),
- ('Data4', wintypes.BYTE * 8)]
- _fields_ = [
- ('cbSize', wintypes.DWORD),
- ('hWnd', wintypes.HWND),
- ('uID', wintypes.UINT),
- ('uFlags', wintypes.UINT),
- ('uCallbackMessage', wintypes.UINT),
- ('hIcon', wintypes.HICON),
- ('szTip', wintypes.WCHAR * 128),
- ('dwState', wintypes.DWORD),
- ('dwStateMask', wintypes.DWORD),
- ('szInfo', wintypes.WCHAR * 256),
- ('version_or_timeout', VERSION_OR_TIMEOUT),
- ('szInfoTitle', wintypes.WCHAR * 64),
- ('dwInfoFlags', wintypes.DWORD),
- ('guidItem', GUID),
- ('hBalloonIcon', wintypes.HICON)]
- _anonymous_ = [
- 'version_or_timeout']
- LPNOTIFYICONDATAW = ctypes.POINTER(NOTIFYICONDATAW)
- class TPMPARAMS(ctypes.Structure):
- _fields_ = [
- ('cbSize', wintypes.UINT),
- ('rcExclude', wintypes.RECT)]
- LPTPMPARAMS = ctypes.POINTER(TPMPARAMS)
- class WNDCLASSEX(ctypes.Structure):
- _fields_ = [
- ('cbSize', wintypes.UINT),
- ('style', wintypes.UINT),
- ('lpfnWndProc', WNDPROC),
- ('cbClsExtra', wintypes.INT),
- ('cbWndExtra', wintypes.INT),
- ('hInstance', wintypes.HANDLE),
- ('hIcon', wintypes.HICON),
- ('hCursor', wintypes.HANDLE),
- ('hbrBackground', wintypes.HBRUSH),
- ('lpszMenuName', wintypes.LPCWSTR),
- ('lpszClassName', wintypes.LPCWSTR),
- ('hIconSm', wintypes.HICON)]
- def _err(result, func, arguments):
- """A *ctypes* ``errchecker`` that ensures truthy values.
- """
- if not result:
- raise ctypes.WinError()
- else:
- return result
- LPWNDCLASSEX = ctypes.POINTER(WNDCLASSEX)
- CreatePopupMenu = windll.user32.CreatePopupMenu
- CreatePopupMenu.argtypes = ()
- CreatePopupMenu.restype = wintypes.HMENU
- CreatePopupMenu.errcheck = _err
- CreateWindowEx = windll.user32.CreateWindowExW
- CreateWindowEx.argtypes = (
- wintypes.DWORD, wintypes.ATOM, wintypes.LPCWSTR, wintypes.DWORD,
- wintypes.INT, wintypes.INT, wintypes.INT, wintypes.INT, wintypes.HWND,
- wintypes.HMENU, wintypes.HINSTANCE, wintypes.LPVOID)
- CreateWindowEx.restype = wintypes.HWND
- CreateWindowEx.errcheck = _err
- DefWindowProc = windll.user32.DefWindowProcW
- DefWindowProc.argtypes = (
- wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
- DefWindowProc.restype = wintypes.DWORD
- DestroyIcon = windll.user32.DestroyIcon
- DestroyIcon.argtypes = (
- wintypes.HICON,)
- DestroyIcon.restype = wintypes.BOOL
- DestroyIcon.errcheck = _err
- DestroyMenu = windll.user32.DestroyMenu
- DestroyMenu.argtypes = (
- wintypes.HMENU,)
- DestroyMenu.restype = wintypes.BOOL
- DestroyMenu.errcheck = _err
- DestroyWindow = windll.user32.DestroyWindow
- DestroyWindow.argtypes = (
- wintypes.HWND,)
- DestroyWindow.restype = wintypes.BOOL
- DestroyWindow.errcheck = _err
- DispatchMessage = windll.user32.DispatchMessageW
- DispatchMessage.argtypes = (
- LPMSG,)
- DispatchMessage.restype = wintypes.DWORD
- GetCursorPos = windll.user32.GetCursorPos
- GetCursorPos.argtypes = (
- LPPOINT,)
- GetCursorPos.restype = wintypes.BOOL
- GetCursorPos.errcheck = _err
- GetMessage = windll.user32.GetMessageW
- GetMessage.argtypes = (
- LPMSG, wintypes.HWND, wintypes.UINT, wintypes.UINT)
- GetMessage.restype = wintypes.BOOL
- GetModuleHandle = windll.kernel32.GetModuleHandleW
- GetModuleHandle.argtypes = (
- wintypes.LPCWSTR,)
- GetModuleHandle.restype = wintypes.HMODULE
- GetModuleHandle.errcheck = _err
- InsertMenuItem = windll.user32.InsertMenuItemW
- InsertMenuItem.argtypes = (
- wintypes.HMENU, wintypes.UINT, wintypes.BOOL, LPMENUITEMINFO)
- InsertMenuItem.restype = wintypes.BOOL
- InsertMenuItem.errcheck = _err
- LoadImage = windll.user32.LoadImageW
- LoadImage.argtypes = (
- wintypes.HINSTANCE, wintypes.LPCWSTR, wintypes.UINT, wintypes.INT,
- wintypes.INT, wintypes.UINT)
- LoadImage.restype = wintypes.HANDLE
- LoadImage.errcheck = _err
- PeekMessage = windll.user32.PeekMessageW
- PeekMessage.argtypes = (
- LPMSG, wintypes.HWND, wintypes.UINT, wintypes.UINT, wintypes.UINT)
- PeekMessage.restype = wintypes.BOOL
- PostMessage = windll.user32.PostMessageW
- PostMessage.argtypes = (
- wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
- PostMessage.restype = wintypes.BOOL
- PostMessage.restype = wintypes.BOOL
- PostQuitMessage = windll.user32.PostQuitMessage
- PostQuitMessage.argtypes = (
- wintypes.INT,)
- RegisterClassEx = windll.user32.RegisterClassExW
- RegisterClassEx.argtypes = (
- LPWNDCLASSEX,)
- RegisterClassEx.restype = wintypes.ATOM
- RegisterClassEx.errcheck = _err
- SetForegroundWindow = windll.user32.SetForegroundWindow
- SetForegroundWindow.argtypes = (
- wintypes.HWND,)
- SetForegroundWindow.restype = wintypes.BOOL
- Shell_NotifyIcon = windll.shell32.Shell_NotifyIconW
- Shell_NotifyIcon.argtypes = (
- wintypes.DWORD, LPNOTIFYICONDATAW)
- Shell_NotifyIcon.restype = wintypes.BOOL
- TranslateMessage = windll.user32.TranslateMessage
- TranslateMessage.argtypes = (
- LPMSG,)
- TranslateMessage.restype = wintypes.BOOL
- TrackPopupMenuEx = windll.user32.TrackPopupMenuEx
- TrackPopupMenuEx.argtypes = (
- wintypes.HMENU, wintypes.UINT, wintypes.INT, wintypes.INT, wintypes.HWND,
- LPTPMPARAMS)
- UnregisterClass = windll.user32.UnregisterClassW
- UnregisterClass.argtypes = (
- wintypes.ATOM, wintypes.HINSTANCE)
- UnregisterClass.restype = wintypes.BOOL
- UnregisterClass.errcheck = _err
- RegisterWindowMessage = windll.user32.RegisterWindowMessageW
- RegisterWindowMessage.argtypes = (
- wintypes.LPCWSTR,)
- RegisterWindowMessage.restype = wintypes.UINT
- RegisterWindowMessage.errcheck = _err
- #: The message broadcast to top-level windows on Explorer restart
- WM_TASKBARCREATED = RegisterWindowMessage('TaskbarCreated')
- # Ensure that we receive WM_TASKBARCREATED even when running with elevated
- # privileges
- try:
- ChangeWindowMessageFilterEx = windll.user32.ChangeWindowMessageFilterEx
- ChangeWindowMessageFilterEx.argtypes = (
- wintypes.HWND, wintypes.UINT, wintypes.DWORD, wintypes.LPVOID)
- ChangeWindowMessageFilterEx.restype = wintypes.BOOL
- ChangeWindowMessageFilterEx.errcheck = _err
- except KeyError:
- def ChangeWindowMessageFilterEx(
- hWnd, message, action, pCHangeFilterStruct):
- """A dummy implementation of ``ChangeWindowMessageFilterEx`` always
- returning ``TRUE``.
- This is used on version of *Windows* prior to *Windows Vista*.
- """
- return True
|