From 625856c31c871559bf02f4f64c0617c54fcad711 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Tue, 11 Jun 2024 11:36:43 -0400 Subject: [PATCH] [1805] Apply More Pywin32 --- EDMarketConnector.py | 4 +-- monitor.py | 8 ++--- prefs.py | 11 +++---- protocol.py | 75 ++++++++++++-------------------------------- stats.py | 2 +- theme.py | 15 +++------ 6 files changed, 34 insertions(+), 81 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 0cd34486..ecc84e1b 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -263,8 +263,6 @@ if __name__ == '__main__': # noqa: C901 import win32con GetProcessHandleFromHwnd = windll.oleacc.GetProcessHandleFromHwnd # noqa: N806 - - ShowWindow = windll.user32.ShowWindow # noqa: N806 ShowWindowAsync = windll.user32.ShowWindowAsync # noqa: N806 COINIT_MULTITHREADED = 0 # noqa: N806,F841 @@ -308,7 +306,7 @@ if __name__ == '__main__': # noqa: C901 if len(sys.argv) > 1 and sys.argv[1].startswith(protocolhandler_redirect): CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) # Wait for it to be responsive to avoid ShellExecute recursing - ShowWindow(window_handle, win32con.SW_RESTORE) + win32gui.ShowWindow(window_handle, win32con.SW_RESTORE) win32api.ShellExecute(0, None, sys.argv[1], None, None, win32con.SW_RESTORE) else: diff --git a/monitor.py b/monitor.py index 2f508bf9..8b55a2b9 100644 --- a/monitor.py +++ b/monitor.py @@ -36,17 +36,15 @@ MAX_FCMATERIALS_DISCREPANCY = 5 # Timestamp difference in seconds if sys.platform == 'win32': import ctypes - from ctypes.wintypes import BOOL, HWND, LPARAM, HANDLE + from ctypes.wintypes import BOOL, HWND, LPARAM import win32gui + import win32api from watchdog.events import FileSystemEventHandler, FileSystemEvent from watchdog.observers import Observer from watchdog.observers.api import BaseObserver EnumWindowsProc = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM) - CloseHandle = ctypes.windll.kernel32.CloseHandle - CloseHandle.argtypes = [HANDLE] - CloseHandle.restype = BOOL GetProcessHandleFromHwnd = ctypes.windll.oleacc.GetProcessHandleFromHwnd else: @@ -2136,7 +2134,7 @@ class EDLogs(FileSystemEventHandler): if name and name.startswith('Elite - Dangerous'): handle = GetProcessHandleFromHwnd(hWnd) if handle: # If GetProcessHandleFromHwnd succeeds then the app is already running as this user - CloseHandle(handle) + win32api.CloseHandle(handle) return False # stop enumeration return True diff --git a/prefs.py b/prefs.py index 89e107fb..7e4465d1 100644 --- a/prefs.py +++ b/prefs.py @@ -188,8 +188,9 @@ class AutoInc(contextlib.AbstractContextManager): if sys.platform == 'win32': import ctypes import winreg - from ctypes.wintypes import HINSTANCE, LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT, BOOL + from ctypes.wintypes import LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT, BOOL import win32gui + import win32api is_wine = False try: WINE_REGISTRY_KEY = r'HKEY_LOCAL_MACHINE\Software\Wine' @@ -225,10 +226,6 @@ if sys.platform == 'win32': SHGetLocalizedName = ctypes.windll.shell32.SHGetLocalizedName SHGetLocalizedName.argtypes = [LPCWSTR, LPWSTR, UINT, ctypes.POINTER(ctypes.c_int)] - LoadString = ctypes.windll.user32.LoadStringW - LoadString.argtypes = [HINSTANCE, UINT, LPWSTR, ctypes.c_int] - LoadString.restype = ctypes.c_int - class PreferencesDialog(tk.Toplevel): """The EDMC preferences dialog.""" @@ -313,7 +310,7 @@ class PreferencesDialog(tk.Toplevel): # Ensure fully on-screen if sys.platform == 'win32' and CalculatePopupWindowPosition: position = RECT() - win32gui.GetWindowRect(win32gui.GetParent(self.winfo_id()), position) + win32gui.GetWindowRect(win32gui.GetParent(self.winfo_id())) if CalculatePopupWindowPosition( POINT(parent.winfo_rootx(), parent.winfo_rooty()), SIZE(position.right - position.left, position.bottom - position.top), # type: ignore @@ -1093,7 +1090,7 @@ class PreferencesDialog(tk.Toplevel): for i in range(start, len(components)): try: if (not SHGetLocalizedName('\\'.join(components[:i+1]), buf, MAX_PATH, ctypes.byref(pidsRes)) and - LoadString(ctypes.WinDLL(expandvars(buf.value))._handle, pidsRes.value, buf, MAX_PATH)): + win32api.LoadString(ctypes.WinDLL(expandvars(buf.value))._handle, pidsRes.value, buf, MAX_PATH)): display.append(buf.value) else: diff --git a/protocol.py b/protocol.py index eed14b44..a0f02f15 100644 --- a/protocol.py +++ b/protocol.py @@ -69,16 +69,16 @@ if (config.auth_force_edmc_protocol # noqa: C901 # This could be false if you use auth_force_edmc_protocol, but then you get to keep the pieces assert sys.platform == 'win32' # spell-checker: words HBRUSH HICON WPARAM wstring WNDCLASS HMENU HGLOBAL - from ctypes import ( # type: ignore - windll, POINTER, WINFUNCTYPE, Structure, byref, c_long, c_void_p, create_unicode_buffer, wstring_at + from ctypes import ( + windll, WINFUNCTYPE, Structure, byref, c_long, c_void_p, create_unicode_buffer, wstring_at ) from ctypes.wintypes import ( - ATOM, BOOL, DWORD, HBRUSH, HGLOBAL, HICON, HINSTANCE, HMENU, HWND, INT, LPARAM, LPCWSTR, LPMSG, LPVOID, LPWSTR, + ATOM, HBRUSH, HICON, HINSTANCE, HWND, INT, LPARAM, LPCWSTR, LPWSTR, MSG, UINT, WPARAM ) - from win32con import CW_USEDEFAULT import win32gui import win32con + import win32api class WNDCLASS(Structure): """ @@ -101,37 +101,7 @@ if (config.auth_force_edmc_protocol # noqa: C901 ('lpszClassName', LPCWSTR) ] - - CreateWindowExW = windll.user32.CreateWindowExW - CreateWindowExW.argtypes = [DWORD, LPCWSTR, LPCWSTR, DWORD, INT, INT, INT, INT, HWND, HMENU, HINSTANCE, LPVOID] - CreateWindowExW.restype = HWND - RegisterClassW = windll.user32.RegisterClassW - RegisterClassW.argtypes = [POINTER(WNDCLASS)] - # DefWindowProcW - # Ref: - # LRESULT DefWindowProcW([in] HWND hWnd,[in] UINT Msg,[in] WPARAM wParam,[in] LPARAM lParam); - # As per example at - - prototype = WINFUNCTYPE(c_long, HWND, UINT, WPARAM, LPARAM) - paramflags = (1, "hWnd"), (1, "Msg"), (1, "wParam"), (1, "lParam") - DefWindowProcW = prototype(("DefWindowProcW", windll.user32), paramflags) - - SetForegroundWindow = windll.user32.SetForegroundWindow - - # - # NB: Despite 'BOOL' return type, it *can* be >0, 0 or -1, so is actually - # c_long - prototype = WINFUNCTYPE(c_long, LPMSG, HWND, UINT, UINT) - paramflags = (1, "lpMsg"), (1, "hWnd"), (1, "wMsgFilterMin"), (1, "wMsgFilterMax") - GetMessageW = prototype(("GetMessageW", windll.user32), paramflags) - TranslateMessage = windll.user32.TranslateMessage - DispatchMessageW = windll.user32.DispatchMessageW - PostThreadMessageW = windll.user32.PostThreadMessageW - SendMessageW = windll.user32.SendMessageW - SendMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] - PostMessageW = windll.user32.PostMessageW - PostMessageW.argtypes = [HWND, UINT, WPARAM, LPARAM] # https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-dde-initiate WM_DDE_INITIATE = 0x03E0 @@ -148,12 +118,6 @@ if (config.auth_force_edmc_protocol # noqa: C901 GlobalGetAtomNameW = windll.kernel32.GlobalGetAtomNameW GlobalGetAtomNameW.argtypes = [ATOM, LPWSTR, INT] GlobalGetAtomNameW.restype = UINT - GlobalLock = windll.kernel32.GlobalLock - GlobalLock.argtypes = [HGLOBAL] - GlobalLock.restype = LPVOID - GlobalUnlock = windll.kernel32.GlobalUnlock - GlobalUnlock.argtypes = [HGLOBAL] - GlobalUnlock.restype = BOOL # Windows Message handler stuff (IPC) # https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633573(v=vs.85) @@ -171,7 +135,7 @@ if (config.auth_force_edmc_protocol # noqa: C901 if message != WM_DDE_INITIATE: # Not a DDE init message, bail and tell windows to do the default # https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca?redirectedfrom=MSDN - return DefWindowProcW(hwnd, message, wParam, lParam) + return win32gui.DefWindowProc(hwnd, message, wParam, lParam) service = create_unicode_buffer(256) topic = create_unicode_buffer(256) @@ -196,7 +160,7 @@ if (config.auth_force_edmc_protocol # noqa: C901 if target_is_valid and topic_is_valid: # if everything is happy, send an acknowledgement of the DDE request - SendMessageW( + win32gui.SendMessage( wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, GlobalAddAtomW(appname), GlobalAddAtomW('System')) ) @@ -229,7 +193,7 @@ if (config.auth_force_edmc_protocol # noqa: C901 thread = self.thread if thread: self.thread = None - PostThreadMessageW(thread.ident, win32con.WM_QUIT, 0, 0) + win32api.PostThreadMessage(thread.ident, win32con.WM_QUIT, 0, 0) thread.join() # Wait for it to quit def worker(self) -> None: @@ -239,24 +203,25 @@ if (config.auth_force_edmc_protocol # noqa: C901 wndclass.lpfnWndProc = WndProc wndclass.cbClsExtra = 0 wndclass.cbWndExtra = 0 - wndclass.hInstance = windll.kernel32.GetModuleHandleW(0) + wndclass.hInstance = win32gui.GetModuleHandle(0) wndclass.hIcon = None wndclass.hCursor = None wndclass.hbrBackground = None wndclass.lpszMenuName = None wndclass.lpszClassName = 'DDEServer' - if not RegisterClassW(byref(wndclass)): + if not win32gui.RegisterClass(byref(wndclass)): print('Failed to register Dynamic Data Exchange for cAPI') return # https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw - hwnd = CreateWindowExW( + hwnd = win32gui.CreateWindowEx( 0, # dwExStyle wndclass.lpszClassName, # lpClassName "DDE Server", # lpWindowName 0, # dwStyle - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, # X, Y, nWidth, nHeight + # X, Y, nWidth, nHeight + win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, self.master.winfo_id(), # hWndParent # Don't use HWND_MESSAGE since the window won't get DDE broadcasts None, # hMenu wndclass.hInstance, # hInstance @@ -276,13 +241,13 @@ if (config.auth_force_edmc_protocol # noqa: C901 # # But it does actually work. Either getting a non-0 value and # entering the loop, or getting 0 and exiting it. - while GetMessageW(byref(msg), None, 0, 0) != 0: + while win32gui.GetMessage(byref(msg), None, 0, 0) != 0: logger.trace_if('frontier-auth.windows', f'DDE message of type: {msg.message}') if msg.message == WM_DDE_EXECUTE: # GlobalLock does some sort of "please dont move this?" # https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globallock - args = wstring_at(GlobalLock(msg.lParam)).strip() - GlobalUnlock(msg.lParam) # Unlocks the GlobalLock-ed object + args = wstring_at(win32gui.GlobalLock(msg.lParam)).strip() + win32gui.GlobalUnlock(msg.lParam) # Unlocks the GlobalLock-ed object if args.lower().startswith('open("') and args.endswith('")'): logger.trace_if('frontier-auth.windows', f'args are: {args}') @@ -291,20 +256,20 @@ if (config.auth_force_edmc_protocol # noqa: C901 logger.debug(f'Message starts with {self.redirect}') self.event(url) - SetForegroundWindow(win32gui.GetParent(self.master.winfo_id())) # raise app window + win32gui.SetForegroundWindow(win32gui.GetParent(self.master.winfo_id())) # raise app window # Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE - PostMessageW(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0x80, msg.lParam)) + win32gui.PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0x80, msg.lParam)) else: # Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE - PostMessageW(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0, msg.lParam)) + win32gui.PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0, msg.lParam)) elif msg.message == WM_DDE_TERMINATE: - PostMessageW(msg.wParam, WM_DDE_TERMINATE, hwnd, 0) + win32gui.PostMessage(msg.wParam, WM_DDE_TERMINATE, hwnd, 0) else: TranslateMessage(byref(msg)) # "Translates virtual key messages into character messages" ??? - DispatchMessageW(byref(msg)) + win32gui.DispatchMessage(byref(msg)) else: # Linux / Run from source diff --git a/stats.py b/stats.py index b8a6531a..b0ba34b3 100644 --- a/stats.py +++ b/stats.py @@ -420,7 +420,7 @@ class StatsResults(tk.Toplevel): # Ensure fully on-screen if sys.platform == 'win32' and CalculatePopupWindowPosition: position = RECT() - win32gui.GetWindowRect(win32gui.GetParent(self.winfo_id()), position) + win32gui.GetWindowRect(win32gui.GetParent(self.winfo_id())) if CalculatePopupWindowPosition( POINT(parent.winfo_rootx(), parent.winfo_rooty()), # - is evidently supported on the C side diff --git a/theme.py b/theme.py index 121bcb60..6024bf4f 100644 --- a/theme.py +++ b/theme.py @@ -422,12 +422,7 @@ class _Theme: self.active = theme if sys.platform == 'win32': - GWL_STYLE = -16 # noqa: N806 # ctypes - WS_MAXIMIZEBOX = 0x00010000 # noqa: N806 # ctypes - # tk8.5.9/win/tkWinWm.c:342 - GWL_EXSTYLE = -20 # noqa: N806 # ctypes - WS_EX_APPWINDOW = 0x00040000 # noqa: N806 # ctypes - WS_EX_LAYERED = 0x00080000 # noqa: N806 # ctypes + import win32con # FIXME: Lose the "treat this like a boolean" bullshit if theme == self.THEME_DEFAULT: @@ -445,14 +440,14 @@ class _Theme: root.withdraw() root.update_idletasks() # Size and windows styles get recalculated here hwnd = win32gui.GetParent(root.winfo_id()) - win32gui.SetWindowLong(hwnd, GWL_STYLE, - win32gui.GetWindowLong(hwnd, GWL_STYLE) & ~WS_MAXIMIZEBOX) # disable maximize + win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, + win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) & ~win32con.WS_MAXIMIZEBOX) # disable maximize if theme == self.THEME_TRANSPARENT: - win32gui.SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYERED) # Add to taskbar + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32con.WS_EX_APPWINDOW | win32con.WS_EX_LAYERED) # Add to taskbar else: - win32gui.SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW) # Add to taskbar + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32con.WS_EX_APPWINDOW) # Add to taskbar root.deiconify() root.wait_visibility() # need main window to be displayed before returning