From 56594c099e15e48d73209115f3723824fd749008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <101191390+HIllya51@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:55:06 +0800 Subject: [PATCH] fix Update settin.py --- .../LunaTranslator/LunaTranslator.py | 3 +- .../LunaTranslator/gui/attachprocessdialog.py | 2 +- .../LunaTranslator/gui/dialog_memory.py | 2 +- .../LunaTranslator/gui/dialog_savedgame.py | 2 +- LunaTranslator/LunaTranslator/gui/settin.py | 15 +- .../gui/settingpage_xianshishezhi.py | 14 +- .../LunaTranslator/gui/translatorUI.py | 5 +- .../LunaTranslator/gui/usefulwidget.py | 2 +- .../LunaTranslator/myutils/fullscreen.py | 3 +- LunaTranslator/LunaTranslator/myutils/hwnd.py | 104 ----------- .../LunaTranslator/textsource/texthook.py | 6 +- LunaTranslator/LunaTranslator/windows.py | 134 -------------- .../LunaTranslator/winsharedutils.py | 33 +++- .../files/defaultconfig/config.json | 1 + plugins/winsharedutils/CMakeLists.txt | 4 +- plugins/winsharedutils/define.h | 3 + plugins/winsharedutils/hwnd.cpp | 119 ++++++++++++ plugins/winsharedutils/theme.cpp | 173 ++++++++++++++++++ 18 files changed, 367 insertions(+), 258 deletions(-) create mode 100644 plugins/winsharedutils/hwnd.cpp create mode 100644 plugins/winsharedutils/theme.cpp diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index 98aeea60..7189f633 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -23,7 +23,7 @@ from myutils.utils import ( ) from myutils.wrapper import threader from gui.showword import searchwordW -from myutils.hwnd import pid_running, getpidexe, testprivilege, ListProcess +from myutils.hwnd import getpidexe, testprivilege, ListProcess from textsource.copyboard import copyboard from textsource.texthook import texthook from textsource.ocrtext import ocrtext @@ -42,6 +42,7 @@ import hmac, pytz, uuid import windows import re, gobject import winsharedutils +from winsharedutils import pid_running from myutils.post import POSTSOLVE from gui.usefulwidget import Prompt, getQMessageBox diff --git a/LunaTranslator/LunaTranslator/gui/attachprocessdialog.py b/LunaTranslator/LunaTranslator/gui/attachprocessdialog.py index 5b9b3ac8..093e882e 100644 --- a/LunaTranslator/LunaTranslator/gui/attachprocessdialog.py +++ b/LunaTranslator/LunaTranslator/gui/attachprocessdialog.py @@ -10,6 +10,7 @@ from PyQt5.QtWidgets import ( QApplication, QPushButton, ) +from winsharedutils import getpidhwndfirst from PyQt5.QtGui import QStandardItemModel, QStandardItem import functools from myutils.config import globalconfig, _TR @@ -21,7 +22,6 @@ from myutils.hwnd import ( ListProcess, mouseselectwindow, getExeIcon, - getpidhwndfirst, ) import qtawesome diff --git a/LunaTranslator/LunaTranslator/gui/dialog_memory.py b/LunaTranslator/LunaTranslator/gui/dialog_memory.py index bfe9efd9..25a17baa 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_memory.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_memory.py @@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt from myutils.config import _TR, globalconfig from gui.usefulwidget import saveposwindow from myutils.wrapper import Singleton_close -from myutils.hwnd import showintab +from winsharedutils import showintab @Singleton_close diff --git a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py index ff8b8300..f2094011 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py @@ -50,7 +50,7 @@ from gui.usefulwidget import ( ) from PyQt5.QtCore import QRect, QSize, Qt, pyqtSignal import os -from myutils.hwnd import showintab +from winsharedutils import showintab from PyQt5.QtGui import QStandardItem, QStandardItemModel from PyQt5.QtCore import Qt, QSize from myutils.config import savehook_new_list, savehook_new_data, vndbtagdata diff --git a/LunaTranslator/LunaTranslator/gui/settin.py b/LunaTranslator/LunaTranslator/gui/settin.py index a29cba43..60b30dcc 100644 --- a/LunaTranslator/LunaTranslator/gui/settin.py +++ b/LunaTranslator/LunaTranslator/gui/settin.py @@ -31,7 +31,6 @@ from gui.setting_proxy import setTab_proxy from gui.settingpage7 import setTab7, settab7direct from gui.settingpage_about import setTab_about, setTab_about_dicrect from gui.usefulwidget import closeashidewindow -from myutils.hwnd import darkchange class gridwidget(QWidget): @@ -257,17 +256,25 @@ class Settin(closeashidewindow): darklight = ["light", "dark"][dark] class WindowEventFilter(QObject): - def eventFilter(self, obj, event): + def eventFilter(_, obj, event): if event.type() == QEvent.Type.WinIdChange: + if obj == self.parent(): + return False hwnd = obj.winId() if hwnd: # window create/destroy,when destroy winId is None - darkchange(int(obj.winId()), dark) + winsharedutils.SetTheme( + int(obj.winId()), dark, globalconfig["WindowBackdrop"] + ) return False self.__filter = WindowEventFilter() # keep ref QApplication.instance().installEventFilter(self.__filter) for widget in QApplication.topLevelWidgets(): - darkchange(int(widget.winId()), dark) + if widget == self.parent(): + continue + winsharedutils.SetTheme( + int(widget.winId()), dark, globalconfig["WindowBackdrop"] + ) try: idx = globalconfig[darklight + "theme"] - int(not dark) diff --git a/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py b/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py index a8bdf8cc..faf74836 100644 --- a/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py +++ b/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py @@ -12,7 +12,7 @@ from gui.inputdialog import multicolorset from myutils.config import globalconfig, _TR, _TRL, magpie_config, static_data from myutils.wrapper import Singleton import qtawesome, gobject, json -from myutils.hwnd import showintab +from winsharedutils import showintab from gui.inputdialog import getsomepath1 from gui.usefulwidget import ( getsimplecombobox, @@ -527,6 +527,18 @@ def setTabThree_lazy(self): 5, ), ], + [ + ("WindowBackdrop", 6), + ( + getsimplecombobox( + ["Solid", "Acrylic", "Mica", "MicaAlt"], + globalconfig, + "WindowBackdrop", + callback=lambda _: self.setstylesheet(), + ), + 5, + ), + ], ] innermagpie = [ diff --git a/LunaTranslator/LunaTranslator/gui/translatorUI.py b/LunaTranslator/LunaTranslator/gui/translatorUI.py index 318b7183..db78769a 100644 --- a/LunaTranslator/LunaTranslator/gui/translatorUI.py +++ b/LunaTranslator/LunaTranslator/gui/translatorUI.py @@ -2,7 +2,6 @@ import time import functools import threading import os, sys -import winsharedutils from PyQt5.QtCore import QT_VERSION_STR import windows from traceback import print_exc @@ -17,7 +16,7 @@ import winsharedutils from myutils.config import globalconfig, saveallconfig, _TR, static_data from myutils.subproc import endsubprocs from myutils.ocrutil import ocr_run, imageCut -from myutils.hwnd import mouseselectwindow, showintab, grabwindow, getExeIcon +from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon from gui.dialog_savedgame import dialog_savedgame_new from gui.dialog_memory import dialog_memory from gui.textbrowser import Textbrowser @@ -25,7 +24,7 @@ from myutils.fullscreen import fullscreen from gui.rangeselect import moveresizegame, rangeselct_function from gui.usefulwidget import resizableframeless from gui.dialog_savedgame import browserdialog - +from winsharedutils import showintab class QUnFrameWindow(resizableframeless): displayres = pyqtSignal(dict) diff --git a/LunaTranslator/LunaTranslator/gui/usefulwidget.py b/LunaTranslator/LunaTranslator/gui/usefulwidget.py index 2240509a..d0b7e224 100644 --- a/LunaTranslator/LunaTranslator/gui/usefulwidget.py +++ b/LunaTranslator/LunaTranslator/gui/usefulwidget.py @@ -27,7 +27,7 @@ from PyQt5.QtWidgets import ( from traceback import print_exc import qtawesome, functools, gobject from myutils.wrapper import Singleton -from myutils.hwnd import showintab +from winsharedutils import showintab @Singleton diff --git a/LunaTranslator/LunaTranslator/myutils/fullscreen.py b/LunaTranslator/LunaTranslator/myutils/fullscreen.py index 5829df21..b8d51b33 100644 --- a/LunaTranslator/LunaTranslator/myutils/fullscreen.py +++ b/LunaTranslator/LunaTranslator/myutils/fullscreen.py @@ -1,7 +1,8 @@ import os, json import windows, winsharedutils +from winsharedutils import letfullscreen, recoverwindow from myutils.config import globalconfig, magpie_config -from myutils.hwnd import letfullscreen, recoverwindow, ListProcess, injectdll +from myutils.hwnd import ListProcess, injectdll from traceback import print_exc from myutils.subproc import subproc_w import time diff --git a/LunaTranslator/LunaTranslator/myutils/hwnd.py b/LunaTranslator/LunaTranslator/myutils/hwnd.py index 07bcd52a..2b91824f 100644 --- a/LunaTranslator/LunaTranslator/myutils/hwnd.py +++ b/LunaTranslator/LunaTranslator/myutils/hwnd.py @@ -8,20 +8,6 @@ import time, winrtutils, winsharedutils, hashlib from myutils.wrapper import threader -def pid_running(pid): - try: - process = windows.AutoHandle( - windows.OpenProcess(windows.SYNCHRONIZE, False, pid) - ) - if process == 0: - return False - ret = windows.WaitForSingleObject(process, 0) - return ret == windows.WAIT_TIMEOUT - - except: - return False - - @threader def grabwindow(): @@ -124,18 +110,6 @@ def getpidhwndfirst(pid): return 0 -def getwindowlist(): - windows_list = [] - pidlist = [] - windows.EnumWindows(lambda hWnd, param: windows_list.append(hWnd), 0) - for hwnd in windows_list: - try: - pid = windows.GetWindowThreadProcessId(hwnd) - pidlist.append(pid) - except: - pass - return list(set(pidlist)) - def getprocesslist(): @@ -286,81 +260,3 @@ def mouseselectwindow(callback): pass threading.Thread(target=_loop).start() - - -def letfullscreen(hwnd): - wpc = windows.GetWindowPlacement(hwnd, False) - HWNDStyle = windows.GetWindowLong(hwnd, windows.GWL_STYLE) - HWNDStyleEx = windows.GetWindowLong(hwnd, windows.GWL_EXSTYLE) - NewHWNDStyle = HWNDStyle - NewHWNDStyle &= ~windows.WS_BORDER - NewHWNDStyle &= ~windows.WS_DLGFRAME - NewHWNDStyle &= ~windows.WS_THICKFRAME - NewHWNDStyleEx = HWNDStyleEx - NewHWNDStyleEx &= ~windows.WS_EX_WINDOWEDGE - windows.SetWindowLong(hwnd, windows.GWL_STYLE, NewHWNDStyle | windows.WS_POPUP) - windows.SetWindowLong( - hwnd, windows.GWL_EXSTYLE, NewHWNDStyleEx | windows.WS_EX_TOPMOST - ) - windows.ShowWindow(hwnd, windows.SW_SHOWMAXIMIZED) - return (wpc, HWNDStyle, HWNDStyleEx) - - -def recoverwindow(hwnd, status): - wpc, HWNDStyle, HWNDStyleEx = status - windows.SetWindowLong(hwnd, windows.GWL_STYLE, HWNDStyle) - windows.SetWindowLong(hwnd, windows.GWL_EXSTYLE, HWNDStyleEx) - windows.ShowWindow(hwnd, windows.SW_SHOWNORMAL) - windows.SetWindowPlacement(hwnd, wpc) - - -def showintab(hwnd, show): - style_ex = windows.GetWindowLong(hwnd, windows.GWL_EXSTYLE) - if show: - style_ex |= windows.WS_EX_APPWINDOW - style_ex &= ~windows.WS_EX_TOOLWINDOW - else: - style_ex &= ~windows.WS_EX_APPWINDOW - style_ex |= windows.WS_EX_TOOLWINDOW - windows.SetWindowLong(hwnd, windows.GWL_EXSTYLE, style_ex) - - -def darkchange(hwnd, dark): - def ChangeDWMAttrib(hWnd: int, attrib: int, color) -> None: - try: - ctypes.windll.dwmapi.DwmSetWindowAttribute( - hWnd, attrib, ctypes.byref(color), ctypes.sizeof(ctypes.c_int) - ) - except: - pass - - def systemmenu(mode): - try: - # https://stackoverflow.com/questions/53501268/win10-dark-theme-how-to-use-in-winapi - # https://gist.github.com/rounk-ctrl/b04e5622e30e0d62956870d5c22b7017 - LoadLibrary = ctypes.windll.Kernel32.LoadLibraryW - LoadLibrary.argtypes = (ctypes.c_wchar_p,) - LoadLibrary.restype = ctypes.c_void_p - GetProcAddress = ctypes.windll.Kernel32.GetProcAddress - GetProcAddress.argtypes = ctypes.c_void_p, ctypes.c_void_p - GetProcAddress.restype = ctypes.c_void_p - uxtheme = LoadLibrary("uxtheme.dll") - SetPreferredAppMode = GetProcAddress(uxtheme, 135) - FlushMenuThemes = GetProcAddress(uxtheme, 136) - SetPreferredAppMode = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)( - SetPreferredAppMode - ) - FlushMenuThemes = ctypes.CFUNCTYPE(None)(FlushMenuThemes) - SetPreferredAppMode(mode) - FlushMenuThemes() - except: - pass - - if dark: - ChangeDWMAttrib(hwnd, 19, ctypes.c_int(1)) - ChangeDWMAttrib(hwnd, 20, ctypes.c_int(1)) - systemmenu(2) - else: - ChangeDWMAttrib(hwnd, 19, ctypes.c_int(0)) - ChangeDWMAttrib(hwnd, 20, ctypes.c_int(0)) - systemmenu(3) diff --git a/LunaTranslator/LunaTranslator/textsource/texthook.py b/LunaTranslator/LunaTranslator/textsource/texthook.py index 8c8dcb7b..c782e805 100644 --- a/LunaTranslator/LunaTranslator/textsource/texthook.py +++ b/LunaTranslator/LunaTranslator/textsource/texthook.py @@ -1,10 +1,10 @@ -import threading +import threading, windows from queue import Queue import re, os import time, gobject from collections import OrderedDict import codecs, functools -import windows +from winsharedutils import Is64bit from myutils.config import globalconfig, savehook_new_data, static_data from textsource.textsourcebase import basetext from myutils.utils import checkchaos @@ -99,7 +99,7 @@ class texthook(basetext): self.newline = Queue() self.newline_delaywait = Queue() - self.is64bit = windows.Is64bit(pids[0]) + self.is64bit = Is64bit(pids[0]) self.lock = threading.Lock() self.hookdatacollecter = OrderedDict() self.hooktypecollecter = OrderedDict() diff --git a/LunaTranslator/LunaTranslator/windows.py b/LunaTranslator/LunaTranslator/windows.py index 168330a3..8b5ff48a 100644 --- a/LunaTranslator/LunaTranslator/windows.py +++ b/LunaTranslator/LunaTranslator/windows.py @@ -345,7 +345,6 @@ def GetProcessFileName(hHandle): return v -_IsWow64Process = _kernel32.IsWow64Process _CreateProcessW = _kernel32.CreateProcessW _CreateProcessW.argtypes = ( c_wchar_p, @@ -391,12 +390,6 @@ def CreateProcess( return _pinfo -def IsWow64Process(phandle): - b = c_bool() - _IsWow64Process(phandle, byref(b)) - return b.value - - def GetClipboardOwner(): return _GetClipboardOwner() @@ -870,133 +863,6 @@ def ConnectNamedPipe(pipe, lpoverlap): return _ConnectNamedPipe(pipe, lpoverlap) -FILE_MAP_READ = 0x4 -_OpenFileMappingW = _kernel32.OpenFileMappingW -_OpenFileMappingW.argtypes = c_uint, c_bool, c_wchar_p - - -def OpenFileMapping(access, inherit, name): - map_handle = _OpenFileMappingW(access, inherit, name) - return map_handle - - -_MapViewOfFile = _kernel32.MapViewOfFile -_MapViewOfFile.argtypes = c_void_p, c_uint, c_uint, c_uint, c_uint -_MapViewOfFile.restype = c_void_p - - -def MapViewOfFile(fhandel, access, size): - return _MapViewOfFile(fhandel, access, 0, 0, size) - - -_CreateFileMappingW = _kernel32.CreateFileMappingW -_CreateFileMappingW.argtypes = c_void_p, c_void_p, c_uint, c_uint, c_uint, c_wchar_p -_CreateFileMappingW.restype = c_void_p - - -def CreateFileMapping(name, acc, size): - return _CreateFileMappingW( - -1, pointer(get_SECURITY_ATTRIBUTES()), acc, 0, size, name - ) - - -_MultiByteToWideChar = _kernel32.MultiByteToWideChar -_MultiByteToWideChar.argtypes = c_uint, c_uint, c_void_p, c_int, c_wchar_p, c_int - - -def MultiByteToWideChar(buff, length, codepage): - _w = create_unicode_buffer(length + 1) - l = _MultiByteToWideChar(codepage, 0, buff, length, _w, length) - if l == 0: - return None - return _w.value - - -class MEMORY_BASIC_INFORMATION32(Structure): - _fields_ = [ - ("BaseAddress", c_void_p), - ("AllocationBase", c_void_p), - ("AllocationProtect", c_uint), - ("RegionSize", c_void_p), - ("State", c_uint), - ("Protect", c_uint), - ("Type", c_uint), - ] - - -class MEMORY_BASIC_INFORMATION64(Structure): - _fields_ = [ - ("BaseAddress", c_void_p), - ("AllocationBase", c_void_p), - ("AllocationProtect", c_uint), - ("PartitionId", c_short), - ("RegionSize", c_void_p), - ("State", c_uint), - ("Protect", c_uint), - ("Type", c_uint), - ] - - -_VirtualQueryEx = _kernel32.VirtualQueryEx -_VirtualQueryEx.argtypes = c_void_p, c_void_p, c_void_p, c_int - - -def VirtualQueryEx(hprocess, address): - if sizeof(c_void_p) == 4: - MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION32 - else: - MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION64 - info = MEMORY_BASIC_INFORMATION() - _VirtualQueryEx(hprocess, address, pointer(info), sizeof(info)) - return info - - -_IsDBCSLeadByteEx = _kernel32.IsDBCSLeadByteEx -_IsDBCSLeadByteEx.argtypes = c_uint, c_byte - - -def IsDBCSLeadByteEx(codepage, char): - return _IsDBCSLeadByteEx(codepage, char) - - -_GetNativeSystemInfo = _kernel32.GetNativeSystemInfo -_GetNativeSystemInfo.argtypes = (c_void_p,) - - -class SYSTEM_INFO(Structure): - _fields_ = [ - ("wProcessorArchitecture", c_ushort), - ("wReserved", c_ushort), - ("dwPageSize", c_uint), - ("lpMinimumApplicationAddress", c_void_p), - ("lpMaximumApplicationAddress", c_void_p), - ("dwActiveProcessorMask", c_void_p), - ("dwNumberOfProcessors", c_uint), - ("dwProcessorType", c_uint), - ("dwAllocationGranularity", c_uint), - ("wProcessorLevel", c_ushort), - ("wProcessorRevision", c_ushort), - ] - - -def GetNativeSystemInfo(): - _SYSTEM_INFO = SYSTEM_INFO() - _GetNativeSystemInfo(pointer(_SYSTEM_INFO)) - return _SYSTEM_INFO - - -def Is64bit(pid): - sysinfo = GetNativeSystemInfo() - if sysinfo.wProcessorArchitecture == 9 or sysinfo.wProcessorArchitecture == 6: - hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)) - if hprocess == 0: - return False - res = not IsWow64Process(hprocess) - return res - else: - return False - - _MessageBoxW = _user32.MessageBoxW _MessageBoxW.argtypes = c_void_p, c_wchar_p, c_wchar_p, c_uint diff --git a/LunaTranslator/LunaTranslator/winsharedutils.py b/LunaTranslator/LunaTranslator/winsharedutils.py index 338d0459..bb925697 100644 --- a/LunaTranslator/LunaTranslator/winsharedutils.py +++ b/LunaTranslator/LunaTranslator/winsharedutils.py @@ -18,7 +18,8 @@ from ctypes import ( windll, c_char, ) -from ctypes.wintypes import WORD, HANDLE +from ctypes.wintypes import WORD, HANDLE, HWND, LONG, DWORD +from windows import WINDOWPLACEMENT import gobject utilsdll = CDLL(gobject.GetDllpath(("winsharedutils32.dll", "winsharedutils64.dll"))) @@ -313,3 +314,33 @@ def queryversion(exe): startdarklistener = utilsdll.startdarklistener startdarklistener.restype = HANDLE + +SetTheme = utilsdll._SetTheme +SetTheme.argtypes = HWND, c_bool, c_int + +showintab = utilsdll.showintab +showintab.argtypes = HWND, c_bool + + +class windowstatus(Structure): + _fields_ = [("wpc", WINDOWPLACEMENT), ("HWNDStyle", LONG), ("HWNDStyleEx", LONG)] + + +letfullscreen = utilsdll.letfullscreen +letfullscreen.argtypes = (HWND,) +letfullscreen.restype = windowstatus + +recoverwindow = utilsdll.recoverwindow +recoverwindow.argtypes = HWND, windowstatus + +pid_running = utilsdll.pid_running +pid_running.argtypes = (DWORD,) +pid_running.restype = c_bool + +getpidhwndfirst = utilsdll.getpidhwndfirst +getpidhwndfirst.argtypes = (DWORD,) +getpidhwndfirst.restype = HWND + +Is64bit = utilsdll.Is64bit +Is64bit.argtypes = (DWORD,) +Is64bit.restype = c_bool diff --git a/LunaTranslator/files/defaultconfig/config.json b/LunaTranslator/files/defaultconfig/config.json index 827cc676..d3e3c095 100644 --- a/LunaTranslator/files/defaultconfig/config.json +++ b/LunaTranslator/files/defaultconfig/config.json @@ -7,6 +7,7 @@ "only_from_exe": [], "showrangeafterrangeselect": true, "autodisappear": false, + "WindowBackdrop":0, "read_raw": true, "read_trans": false, "read_translator": 0, diff --git a/plugins/winsharedutils/CMakeLists.txt b/plugins/winsharedutils/CMakeLists.txt index 23979673..89c9be45 100644 --- a/plugins/winsharedutils/CMakeLists.txt +++ b/plugins/winsharedutils/CMakeLists.txt @@ -2,8 +2,8 @@ project(winsharedutils) -add_library(winsharedutils MODULE darklistener.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp) - +add_library(winsharedutils MODULE hwnd.cpp darklistener.cpp theme.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp) +target_link_libraries(winsharedutils dwmapi) if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64") else() diff --git a/plugins/winsharedutils/define.h b/plugins/winsharedutils/define.h index ec907a71..954a1f34 100644 --- a/plugins/winsharedutils/define.h +++ b/plugins/winsharedutils/define.h @@ -1,7 +1,10 @@ #pragma once #include +#define DECLARE extern "C" __declspec(dllexport) extern "C" { + __declspec(dllexport) bool _SetTheme(HWND _hWnd, bool dark, int backdrop); + __declspec(dllexport) HANDLE startdarklistener(); __declspec(dllexport) bool queryversion(const wchar_t *exe, WORD *_1, WORD *_2, WORD *_3, WORD *_4); diff --git a/plugins/winsharedutils/hwnd.cpp b/plugins/winsharedutils/hwnd.cpp new file mode 100644 index 00000000..d0fb5972 --- /dev/null +++ b/plugins/winsharedutils/hwnd.cpp @@ -0,0 +1,119 @@ +#include +#include "define.h" + +DECLARE void showintab(HWND hwnd, bool show) +{ + auto style_ex = GetWindowLong(hwnd, GWL_EXSTYLE); + if (show) + { + style_ex |= WS_EX_APPWINDOW; + style_ex &= ~WS_EX_TOOLWINDOW; + } + else + { + style_ex &= ~WS_EX_APPWINDOW; + style_ex |= WS_EX_TOOLWINDOW; + } + SetWindowLong(hwnd, GWL_EXSTYLE, style_ex); +} + +struct windowstatus +{ + WINDOWPLACEMENT wpc; + LONG HWNDStyle, HWNDStyleEx; +}; + +DECLARE windowstatus letfullscreen(HWND hwnd) +{ + WINDOWPLACEMENT wpc; + GetWindowPlacement(hwnd, &wpc); + auto HWNDStyle = GetWindowLong(hwnd, GWL_STYLE); + auto HWNDStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE); + auto NewHWNDStyle = HWNDStyle; + NewHWNDStyle &= ~WS_BORDER; + NewHWNDStyle &= ~WS_DLGFRAME; + NewHWNDStyle &= ~WS_THICKFRAME; + auto NewHWNDStyleEx = HWNDStyleEx; + NewHWNDStyleEx &= ~WS_EX_WINDOWEDGE; + SetWindowLong(hwnd, GWL_STYLE, NewHWNDStyle | WS_POPUP); + SetWindowLong( + hwnd, GWL_EXSTYLE, NewHWNDStyleEx | WS_EX_TOPMOST); + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + return {wpc, HWNDStyle, HWNDStyleEx}; +} + +DECLARE void recoverwindow(HWND hwnd, windowstatus status) +{ + SetWindowLong(hwnd, GWL_STYLE, status.HWNDStyle); + SetWindowLong(hwnd, GWL_EXSTYLE, status.HWNDStyleEx); + ShowWindow(hwnd, SW_SHOWNORMAL); + SetWindowPlacement(hwnd, &status.wpc); +} +struct AutoHandle +{ + HANDLE _handle; + AutoHandle(HANDLE handle) : _handle(handle){}; + ~AutoHandle() + { + CloseHandle(_handle); + } + operator HANDLE() + { + return _handle; + } + operator bool() + { + return _handle == INVALID_HANDLE_VALUE; + } +}; +DECLARE bool pid_running(DWORD pid) +{ + DWORD code; + GetExitCodeProcess(AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)), &code); + return code == STILL_ACTIVE; + // auto process = AutoHandle(OpenProcess(SYNCHRONIZE, FALSE, pid)); + // DWORD ret = WaitForSingleObject(process, 0); + // return ret == WAIT_TIMEOUT; +} + +struct __EnumWindowsProc +{ + DWORD pid; + HWND hwnd; +}; +BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + if (IsWindow(hwnd) && IsWindowEnabled(hwnd) & IsWindowVisible(hwnd)) + { + auto info = (__EnumWindowsProc *)lParam; + + DWORD processId; + GetWindowThreadProcessId(hwnd, &processId); + if (info->pid == processId && info->hwnd == 0) + { + info->hwnd = hwnd; + } + } + return TRUE; +} +DECLARE HWND getpidhwndfirst(DWORD pid) +{ + __EnumWindowsProc info = {pid, 0}; + EnumWindows(EnumWindowsProc, (LPARAM)&info); + return info.hwnd; +} + +DECLARE bool Is64bit(DWORD pid) +{ + SYSTEM_INFO sysinfo; + GetNativeSystemInfo(&sysinfo); + if (sysinfo.wProcessorArchitecture == 9 || sysinfo.wProcessorArchitecture == 6) + { + auto hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)); + BOOL b; + IsWow64Process(hprocess, &b); + return !b; + } + else + return false; +} \ No newline at end of file diff --git a/plugins/winsharedutils/theme.cpp b/plugins/winsharedutils/theme.cpp new file mode 100644 index 00000000..1d2973ec --- /dev/null +++ b/plugins/winsharedutils/theme.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include "define.h" +// https://github.com/Blinue/Xaml-Islands-Cpp/blob/main/src/XamlIslandsCpp/XamlWindow.h + +enum WindowBackdrop : int32_t +{ + SolidColor = 0, + Acrylic = 1, + Mica = 2, + MicaAlt = 3, +}; + +static uint32_t GetOSBuild() noexcept +{ + HMODULE hNtDll = GetModuleHandle(L"ntdll.dll"); + if (!hNtDll) + { + return 0; + } + + auto rtlGetVersion = (LONG(WINAPI *)(PRTL_OSVERSIONINFOW))GetProcAddress(hNtDll, "RtlGetVersion"); + if (rtlGetVersion == nullptr) + { + // assert(false); + return 0; + } + + RTL_OSVERSIONINFOW version{}; + version.dwOSVersionInfoSize = sizeof(version); + rtlGetVersion(&version); + + return version.dwBuildNumber; +} + +struct Win32Helper +{ + struct OSVersion + { + constexpr OSVersion(uint32_t build) : _build(build) {} + + bool Is20H1OrNewer() const noexcept + { + return _build >= 19041; + } + + // 下面为 Win11 + // 不考虑代号相同的 Win10 + + bool IsWin11() const noexcept + { + return Is21H2OrNewer(); + } + + bool Is21H2OrNewer() const noexcept + { + return _build >= 22000; + } + + bool Is22H2OrNewer() const noexcept + { + return _build >= 22621; + } + + private: + uint32_t _build = 0; + }; + + static OSVersion GetOSVersion() noexcept; +}; +Win32Helper::OSVersion Win32Helper::GetOSVersion() noexcept +{ + static OSVersion version = GetOSBuild(); + return version; +} + +enum class PreferredAppMode +{ + Default, + AllowDark, + ForceDark, + ForceLight, + Max +}; + +using fnSetPreferredAppMode = PreferredAppMode(WINAPI *)(PreferredAppMode appMode); +using fnAllowDarkModeForWindow = bool(WINAPI *)(HWND hWnd, bool allow); +using fnRefreshImmersiveColorPolicyState = void(WINAPI *)(); +using fnFlushMenuThemes = void(WINAPI *)(); +// using fnDwmSetWindowAttribute=HRESULT (WINAPI*)(HWND,DWORD,LPCVOID,DWORD); + +static fnSetPreferredAppMode SetPreferredAppMode = nullptr; +static fnAllowDarkModeForWindow AllowDarkModeForWindow = nullptr; +static fnRefreshImmersiveColorPolicyState RefreshImmersiveColorPolicyState = nullptr; +static fnFlushMenuThemes FlushMenuThemes = nullptr; +// static fnDwmSetWindowAttribute DwmSetWindowAttribute=nullptr; +static bool initok() +{ + return SetPreferredAppMode && AllowDarkModeForWindow && RefreshImmersiveColorPolicyState && FlushMenuThemes; //&&DwmSetWindowAttribute; +} +static bool InitApis() noexcept +{ + if (initok()) + return true; + + HMODULE hUxtheme = LoadLibrary(L"uxtheme.dll"); + // assert(hUxtheme); + + SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)); + AllowDarkModeForWindow = (fnAllowDarkModeForWindow)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)); + RefreshImmersiveColorPolicyState = (fnRefreshImmersiveColorPolicyState)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)); + FlushMenuThemes = (fnFlushMenuThemes)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)); + + // HMODULE hdwmapi = LoadLibrary(L"dwmapi.dll"); + + // DwmSetWindowAttribute = (fnDwmSetWindowAttribute)GetProcAddress(hdwmapi, "DwmSetWindowAttribute"); + return initok(); +} + +static void SetWindowTheme(HWND hWnd, bool darkBorder, bool darkMenu) noexcept +{ + if (!InitApis()) + return; + + SetPreferredAppMode(darkMenu ? PreferredAppMode::ForceDark : PreferredAppMode::ForceLight); + AllowDarkModeForWindow(hWnd, darkMenu); + + // 使标题栏适应黑暗模式 + // build 18985 之前 DWMWA_USE_IMMERSIVE_DARK_MODE 的值不同 + // https://github.com/MicrosoftDocs/sdk-api/pull/966/files + constexpr const DWORD DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19; + BOOL value = darkBorder; + DwmSetWindowAttribute( + hWnd, + Win32Helper::GetOSVersion().Is20H1OrNewer() ? DWMWA_USE_IMMERSIVE_DARK_MODE : DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, + &value, + sizeof(value)); + + RefreshImmersiveColorPolicyState(); + FlushMenuThemes(); +} +bool _SetTheme( + HWND _hWnd, + bool dark, + int backdrop) +{ + auto _isBackgroundSolidColor = backdrop == WindowBackdrop::SolidColor; + if (Win32Helper::GetOSVersion().Is22H2OrNewer() && + _isBackgroundSolidColor != (backdrop == WindowBackdrop::SolidColor)) + { + return true; + } + + // Win10 中即使在亮色主题下我们也使用暗色边框,这也是 UWP 窗口的行为 + SetWindowTheme( + _hWnd, + Win32Helper::GetOSVersion().IsWin11() ? dark : true, + dark); + + if (!Win32Helper::GetOSVersion().Is22H2OrNewer()) + { + return false; + } + + // 设置背景 + static const DWM_SYSTEMBACKDROP_TYPE BACKDROP_MAP[] = { + DWMSBT_AUTO, DWMSBT_TRANSIENTWINDOW, DWMSBT_MAINWINDOW, DWMSBT_TABBEDWINDOW}; + DWM_SYSTEMBACKDROP_TYPE value = BACKDROP_MAP[(int)backdrop]; + DwmSetWindowAttribute(_hWnd, DWMWA_SYSTEMBACKDROP_TYPE, &value, sizeof(value)); + + return false; +} \ No newline at end of file