From e05c29e2053f291791dd0dd7c9c0ec0b30ac4b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Sun, 1 Dec 2024 12:32:35 +0800 Subject: [PATCH] . --- cpp/winsharedutils/screenshot.cpp | 69 ------------------------------- py/LunaTranslator/myutils/hwnd.py | 43 +++++++++---------- py/LunaTranslator/windows.py | 21 ++++++++++ 3 files changed, 41 insertions(+), 92 deletions(-) diff --git a/cpp/winsharedutils/screenshot.cpp b/cpp/winsharedutils/screenshot.cpp index 68b3b643..1361a38c 100644 --- a/cpp/winsharedutils/screenshot.cpp +++ b/cpp/winsharedutils/screenshot.cpp @@ -1,6 +1,5 @@  - void GetVirtualDesktopRect(RECT &rect) { // 获取虚拟桌面的尺寸和位置 @@ -31,72 +30,6 @@ HBITMAP GetBitmap(RECT &rect, HDC hDC) return hBitmap; } -int SaveBitmapToFile(HBITMAP hBitmap, LPCWSTR lpFileName) -{ - WORD wBitCount; // 位图中每个像素所占字节数 - // 定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数 - DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten; - BITMAP Bitmap; // 位图属性结构 - BITMAPFILEHEADER bmfHdr; // 位图文件头结构 - BITMAPINFOHEADER bi; // 位图信息头结构 - HANDLE fh; // 定义文件,分配内存句柄,调色板句柄 - LPSTR lpbk, lpmem; - - wBitCount = 32; - // 设置位图信息头结构 - GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); - bi.biSize = sizeof(BITMAPINFOHEADER); - bi.biWidth = Bitmap.bmWidth; - bi.biHeight = Bitmap.bmHeight; // 为负,正向的位图;为正,倒向的位图 - bi.biPlanes = 1; - bi.biBitCount = wBitCount; - bi.biCompression = BI_RGB; - bi.biSizeImage = 0; - bi.biXPelsPerMeter = 0; - bi.biYPelsPerMeter = 0; - bi.biClrUsed = 0; - bi.biClrImportant = 0; - dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; - - // 创建位图文件 - fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if (fh == INVALID_HANDLE_VALUE) - return FALSE; - // 设置位图文件头 - bmfHdr.bfType = 0x4D42; // "BM" - dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize; - bmfHdr.bfSize = dwDIBSize; - bmfHdr.bfReserved1 = 0; - bmfHdr.bfReserved2 = 0; - bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); - - // 写入位图文件头 - WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); - // 写入位图信息头 - WriteFile(fh, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL); - - // 获取位图阵列 - lpmem = new char[dwBmBitsSize]; - lpbk = (LPSTR) new char[dwBmBitsSize]; - GetBitmapBits(hBitmap, dwBmBitsSize, lpmem); // 正向的内存图象数据 - - // 转化为倒向数据(仅在bmHeight为正时需要) - for (int i = 0; i < Bitmap.bmHeight; i++) - { - memcpy(lpbk + Bitmap.bmWidth * i * 4, lpmem + Bitmap.bmWidth * (Bitmap.bmHeight - i - 1) * 4, Bitmap.bmWidth * 4); - } - // 写位图数据 - WriteFile(fh, lpbk, dwBmBitsSize, &dwWritten, NULL); - - // 清除 - delete[] lpbk; - delete[] lpmem; - - CloseHandle(fh); - return TRUE; -} - std::vector SaveBitmapToBuffer(HBITMAP hBitmap) { WORD wBitCount; // 位图中每个像素所占字节数 @@ -167,8 +100,6 @@ DECLARE_API void gdi_screenshot(HWND hwnd, RECT rect, void (*cb)(byte *, size_t) if (!hdc) return; auto bm = GetBitmap(rect, hdc); - // SaveBitmapToFile(bm, LR"(.\2.bmp)"); - size_t size; auto bf = std::move(SaveBitmapToBuffer(bm)); if (bf.size()) cb(bf.data(), bf.size()); diff --git a/py/LunaTranslator/myutils/hwnd.py b/py/LunaTranslator/myutils/hwnd.py index 2b9c77ff..e61c3c30 100644 --- a/py/LunaTranslator/myutils/hwnd.py +++ b/py/LunaTranslator/myutils/hwnd.py @@ -23,11 +23,12 @@ def clipboard_set_image(p: QImage): @threader def grabwindow(app="PNG", callback_origin=None, tocliponly=False): + tmsp = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) if tocliponly: fname = "" uid = None elif callback_origin or tocliponly: - fname = gobject.gettempdir(time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())) + fname = gobject.gettempdir(tmsp) uid = None else: @@ -36,29 +37,26 @@ def grabwindow(app="PNG", callback_origin=None, tocliponly=False): hwndx = windows.GetForegroundWindow() hwndx = windows.GetAncestor(hwndx) gamepath = getpidexe(windows.GetWindowThreadProcessId(hwndx)) - exename = os.path.basename(gamepath).replace( - "." + os.path.basename(gamepath).split(".")[-1], "" - ) + exename = os.path.splitext(os.path.basename(gamepath))[0] uid = gobject.baseobject.gameuid screenshot_savepath: str = globalconfig.get("screenshot_savepath", "") - fnamef = lambda: gobject.getcachedir( - "screenshot/" - + exename - + "/" - + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()), - abspath=False, - ) - if screenshot_savepath: - try: - dirname = screenshot_savepath.format(exename=exename) - os.makedirs(dirname, exist_ok=True) - fname = os.path.join( - dirname, time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) - ) - except: - fname = fnamef() - else: - fname = fnamef() + + try: + if not screenshot_savepath: + raise + dirname = screenshot_savepath.format(exename=exename) + os.makedirs(dirname, exist_ok=True) + fname = os.path.join(dirname, tmsp) + except: + fnamebase = "cache/screenshot" + if not os.path.exists(fnamebase): + fnamebase = windows.SHGetFolderPathW(windows.CSIDL_MYPICTURES) + if not (fnamebase and os.path.exists(fnamebase)): + fnamebase = "cache/screenshot" + else: + fnamebase = os.path.join(fnamebase, "LunaTranslator") + fname = os.path.join(fnamebase, exename, tmsp) + os.makedirs(os.path.join(fnamebase, exename), exist_ok=True) def callback_1(callback_origin, uid, tocliponly, p: QPixmap, fn): if p.isNull(): @@ -80,7 +78,6 @@ def grabwindow(app="PNG", callback_origin=None, tocliponly=False): hwnd = windows.GetAncestor(hwnd) _ = windows.GetClientRect(hwnd) p = gdi_screenshot(0, 0, _[2], _[3], hwnd) - callback(p, fname + "_gdi." + app) isshit = (not callback_origin) and (not tocliponly) if p.isNull() or isshit: diff --git a/py/LunaTranslator/windows.py b/py/LunaTranslator/windows.py index 213a6fff..a18b7191 100644 --- a/py/LunaTranslator/windows.py +++ b/py/LunaTranslator/windows.py @@ -53,6 +53,7 @@ from ctypes.wintypes import ( USHORT, ) +HRESULT = LONG HWINEVENTHOOK = HANDLE LRESULT = LPLONG WAIT_TIMEOUT = 258 @@ -962,3 +963,23 @@ SetWinEventHook.argtypes = DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DW PathFileExists = windll.Shlwapi.PathFileExistsW PathFileExists.argtypes = (LPCWSTR,) PathFileExists.restype = BOOL + +_SHGetFolderPathW = _shell32.SHGetFolderPathW +_SHGetFolderPathW.argtypes = ( + HWND, + c_int, + HANDLE, + DWORD, + LPWSTR, +) +_SHGetFolderPathW.restype = HRESULT +CSIDL_MYPICTURES = 0x27 +SHGFP_TYPE_CURRENT = 0 +S_OK = 0 + + +def SHGetFolderPathW(csidl): + buff = create_unicode_buffer(MAX_PATH + 100) + if _SHGetFolderPathW(None, csidl, None, SHGFP_TYPE_CURRENT, buff) != S_OK: + return None + return buff.value