mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-27 15:44:12 +08:00
...
This commit is contained in:
parent
7f6518bad8
commit
707644cdfa
@ -12,6 +12,7 @@ from myutils.config import (
|
||||
extradatas,
|
||||
globalconfig,
|
||||
)
|
||||
from myutils.hwnd import clipboard_set_image
|
||||
from myutils.utils import str2rgba, get_time_stamp, loopbackrecorder
|
||||
from myutils.audioplayer import playonce
|
||||
from gui.inputdialog import autoinitdialog
|
||||
@ -468,7 +469,10 @@ class viewpixmap_x(QWidget):
|
||||
self.pathview.resize(e.size().width(), self.pathview.height())
|
||||
self.infoview.resize(e.size().width(), self.infoview.height())
|
||||
self.leftclick.setGeometry(
|
||||
0, e.size().height() // 10, e.size().width() // 5, 7 * e.size().height() // 10
|
||||
0,
|
||||
e.size().height() // 10,
|
||||
e.size().width() // 5,
|
||||
7 * e.size().height() // 10,
|
||||
)
|
||||
self.bottombtn.setGeometry(
|
||||
e.size().width() // 5,
|
||||
@ -581,12 +585,14 @@ class pixwrapper(QWidget):
|
||||
else:
|
||||
seticon = LAction(("设为图标"))
|
||||
deleteimage = LAction(("删除图片"))
|
||||
copyimage = LAction(("复制图片"))
|
||||
deleteimage_x = LAction(("删除图片文件"))
|
||||
hualang = LAction(("画廊"))
|
||||
pos = LAction(("位置"))
|
||||
|
||||
menu.addAction(setimage)
|
||||
menu.addAction(seticon)
|
||||
menu.addAction(copyimage)
|
||||
menu.addAction(deleteimage)
|
||||
menu.addAction(deleteimage_x)
|
||||
menu.addAction(hualang)
|
||||
@ -596,6 +602,8 @@ class pixwrapper(QWidget):
|
||||
action = menu.exec(QCursor.pos())
|
||||
if action == deleteimage:
|
||||
self.removecurrent(False)
|
||||
elif copyimage == action:
|
||||
clipboard_set_image(curr)
|
||||
elif action == deleteimage_x:
|
||||
self.removecurrent(True)
|
||||
elif action == pos:
|
||||
|
@ -626,7 +626,7 @@ class TranslatorWindow(resizableframeless):
|
||||
),
|
||||
("searchwordW", lambda: gobject.baseobject.searchwordW.showsignal.emit()),
|
||||
("fullscreen", self._fullsgame, lambda: self.isletgamefullscreened, None),
|
||||
("grabwindow", grabwindow),
|
||||
("grabwindow", grabwindow, None, None, lambda: grabwindow(tocliponly=True)),
|
||||
(
|
||||
"muteprocess",
|
||||
self.muteprocessfuntion,
|
||||
|
@ -5,12 +5,25 @@ import gobject
|
||||
import os, subprocess, functools
|
||||
import time, winrtutils, winsharedutils, hashlib
|
||||
from myutils.config import savehook_new_data, globalconfig
|
||||
from myutils.wrapper import threader
|
||||
from myutils.wrapper import threader, tryprint
|
||||
from myutils.utils import qimage2binary
|
||||
|
||||
|
||||
def clipboard_set_image(p: QImage):
|
||||
if isinstance(p, str):
|
||||
qimg = QImage()
|
||||
qimg.load(p)
|
||||
p = qimg
|
||||
if p.isNull():
|
||||
return
|
||||
winsharedutils.clipboard_set_image(qimage2binary(p))
|
||||
|
||||
|
||||
@threader
|
||||
def grabwindow(app="PNG", callback_origin=None):
|
||||
if callback_origin:
|
||||
def grabwindow(app="PNG", callback_origin=None, tocliponly=False):
|
||||
if tocliponly:
|
||||
pass
|
||||
elif callback_origin or tocliponly:
|
||||
fname = gobject.gettempdir(time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()))
|
||||
uid = None
|
||||
else:
|
||||
@ -42,50 +55,54 @@ def grabwindow(app="PNG", callback_origin=None):
|
||||
else:
|
||||
fname = fnamef()
|
||||
|
||||
def callback_1(callback, uid, fn):
|
||||
if not os.path.exists(fn):
|
||||
def callback_1(callback_origin, uid, tocliponly, p: QPixmap, fn):
|
||||
if p.isNull():
|
||||
return
|
||||
if callback:
|
||||
callback(os.path.abspath(fn))
|
||||
if tocliponly:
|
||||
clipboard_set_image(p)
|
||||
return
|
||||
p.save(fn)
|
||||
if callback_origin:
|
||||
callback_origin(os.path.abspath(fn))
|
||||
if uid:
|
||||
savehook_new_data[uid]["imagepath_all"].append(fn)
|
||||
|
||||
callback = functools.partial(callback_1, callback_origin, uid)
|
||||
hwnd = windows.FindWindow(
|
||||
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
|
||||
)
|
||||
if hwnd:
|
||||
|
||||
@threader
|
||||
def _():
|
||||
winrtutils._winrt_capture_window(fname + "_winrt_magpie." + app, hwnd)
|
||||
callback(fname + "_winrt_magpie." + app)
|
||||
|
||||
_()
|
||||
callback = functools.partial(callback_1, callback_origin, uid, tocliponly)
|
||||
|
||||
hwnd = gobject.baseobject.hwnd
|
||||
if not hwnd:
|
||||
hwnd = windows.GetForegroundWindow()
|
||||
hwnd = windows.GetAncestor(hwnd)
|
||||
_ = windows.GetClientRect(hwnd)
|
||||
p = screenshot(0, 0, _[2], _[3], hwnd).toImage()
|
||||
if not p.allGray():
|
||||
p.save(fname + "_gdi." + app)
|
||||
callback(fname + "_gdi." + app)
|
||||
p = gdi_screenshot(0, 0, _[2], _[3], hwnd)
|
||||
|
||||
if not callback_origin:
|
||||
callback(p, fname + "_gdi." + app)
|
||||
isshit = (not callback_origin) and (not tocliponly)
|
||||
if (not p.isNull()) or isshit:
|
||||
|
||||
@threader
|
||||
def _():
|
||||
p = winrt_capture_window(hwnd)
|
||||
callback(p, fname + "_winrt." + app)
|
||||
|
||||
_()
|
||||
|
||||
if isshit:
|
||||
gobject.baseobject.translation_ui.displaystatus.emit(
|
||||
"saved to " + fname, False, True
|
||||
)
|
||||
|
||||
@threader
|
||||
def _():
|
||||
winrtutils._winrt_capture_window(fname + "_winrt." + app, hwnd)
|
||||
callback(fname + "_winrt." + app)
|
||||
hwnd = windows.FindWindow(
|
||||
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
|
||||
)
|
||||
if hwnd:
|
||||
|
||||
if p.allGray() or (not callback_origin):
|
||||
_()
|
||||
@threader
|
||||
def _():
|
||||
p = winrt_capture_window(hwnd)
|
||||
callback(p, fname + "_winrt_magpie." + app)
|
||||
|
||||
_()
|
||||
|
||||
|
||||
def getpidexe(pid):
|
||||
@ -238,13 +255,27 @@ def mouseselectwindow(callback):
|
||||
threading.Thread(target=_loop).start()
|
||||
|
||||
|
||||
def screenshot(x1, y1, x2, y2, hwnd=None):
|
||||
def safepixmap(bs):
|
||||
if not bs:
|
||||
return QPixmap()
|
||||
pixmap = QPixmap()
|
||||
pixmap.loadFromData(bs)
|
||||
if pixmap.isNull():
|
||||
return QPixmap()
|
||||
if pixmap.toImage().allGray():
|
||||
return QPixmap()
|
||||
return pixmap
|
||||
|
||||
|
||||
def gdi_screenshot(x1, y1, x2, y2, hwnd=None):
|
||||
if hwnd:
|
||||
_r = QApplication.instance().devicePixelRatio()
|
||||
_dpi = windows.GetDpiForWindow(hwnd)
|
||||
x1, y1, x2, y2 = (int(_ * _dpi / 96 / _r) for _ in (x1, y1, x2, y2))
|
||||
bs = winsharedutils.gdi_screenshot(x1, y1, x2, y2, hwnd)
|
||||
pixmap = QPixmap()
|
||||
if bs:
|
||||
pixmap.loadFromData(bs)
|
||||
return pixmap
|
||||
return safepixmap(bs)
|
||||
|
||||
|
||||
def winrt_capture_window(hwnd):
|
||||
bs = winrtutils.winrt_capture_window(hwnd)
|
||||
return safepixmap(bs)
|
||||
|
@ -3,21 +3,12 @@ import os, importlib
|
||||
from myutils.config import globalconfig, _TR
|
||||
from qtsymbols import *
|
||||
from myutils.commonbase import ArgsEmptyExc
|
||||
from myutils.hwnd import screenshot
|
||||
from myutils.utils import stringfyerror
|
||||
from myutils.hwnd import gdi_screenshot
|
||||
from myutils.utils import stringfyerror, qimage2binary
|
||||
from traceback import print_exc
|
||||
import threading, gobject
|
||||
|
||||
|
||||
def qimage2binary(qimage: QImage, fmt="BMP"):
|
||||
byte_array = QByteArray()
|
||||
buffer = QBuffer(byte_array)
|
||||
buffer.open(QBuffer.WriteOnly)
|
||||
qimage.save(buffer, fmt)
|
||||
buffer.close()
|
||||
image_data = byte_array.data()
|
||||
return image_data
|
||||
|
||||
|
||||
def binary2qimage(binary):
|
||||
image = QImage()
|
||||
@ -44,14 +35,14 @@ def imageCut(hwnd, x1, y1, x2, y2) -> QImage:
|
||||
QRect(_x1, _y1, _x2 - _x1, _y2 - _y1)
|
||||
):
|
||||
continue
|
||||
pix = screenshot(_x1, _y1, _x2, _y2, hwnd)
|
||||
if pix.toImage().allGray():
|
||||
pix = gdi_screenshot(_x1, _y1, _x2, _y2, hwnd)
|
||||
if pix.isNull():
|
||||
continue
|
||||
break
|
||||
except:
|
||||
print_exc()
|
||||
else:
|
||||
pix = screenshot(x1, y1, x2, y2)
|
||||
pix = gdi_screenshot(x1, y1, x2, y2)
|
||||
|
||||
image = pix.toImage()
|
||||
gobject.baseobject.maybesetimage(image)
|
||||
|
@ -23,6 +23,16 @@ import re, heapq, winsharedutils
|
||||
from myutils.wrapper import tryprint, threader
|
||||
|
||||
|
||||
def qimage2binary(qimage: QImage, fmt="BMP"):
|
||||
byte_array = QByteArray()
|
||||
buffer = QBuffer(byte_array)
|
||||
buffer.open(QBuffer.OpenModeFlag.WriteOnly)
|
||||
qimage.save(buffer, fmt)
|
||||
buffer.close()
|
||||
image_data = byte_array.data()
|
||||
return image_data
|
||||
|
||||
|
||||
def checkisusingwine():
|
||||
iswine = True
|
||||
try:
|
||||
|
@ -6,6 +6,9 @@ from ctypes import (
|
||||
c_size_t,
|
||||
CFUNCTYPE,
|
||||
c_void_p,
|
||||
cast,
|
||||
POINTER,
|
||||
c_char,
|
||||
)
|
||||
import platform, gobject
|
||||
|
||||
@ -50,4 +53,15 @@ if winrtutilsdll:
|
||||
return ret
|
||||
|
||||
_winrt_capture_window = winrtutilsdll.winrt_capture_window
|
||||
_winrt_capture_window.argtypes = c_wchar_p, c_void_p
|
||||
_winrt_capture_window.argtypes = c_void_p, c_void_p
|
||||
|
||||
def winrt_capture_window(hwnd):
|
||||
ret = []
|
||||
|
||||
def cb(ptr, size):
|
||||
ret.append(cast(ptr, POINTER(c_char))[:size])
|
||||
|
||||
_winrt_capture_window(hwnd, CFUNCTYPE(None, c_void_p, c_size_t)(cb))
|
||||
if len(ret):
|
||||
return ret[0]
|
||||
return None
|
||||
|
@ -61,10 +61,10 @@ _clipboard_get = utilsdll.clipboard_get
|
||||
_clipboard_get.argtypes = (c_void_p,)
|
||||
_clipboard_get.restype = c_bool
|
||||
_clipboard_set = utilsdll.clipboard_set
|
||||
_clipboard_set.argtypes = (
|
||||
c_void_p,
|
||||
c_wchar_p,
|
||||
)
|
||||
_clipboard_set.argtypes = (HWND, c_wchar_p)
|
||||
_clipboard_set_image = utilsdll.clipboard_set_image
|
||||
_clipboard_set_image.argtypes = (HWND, c_void_p, c_size_t)
|
||||
_clipboard_set_image.restype = c_bool
|
||||
|
||||
|
||||
def SAPI_List(v):
|
||||
@ -86,9 +86,8 @@ def SAPI_Speak(content, v, voiceid, rate, volume):
|
||||
return ret[0]
|
||||
|
||||
|
||||
def distance(
|
||||
s1, s2
|
||||
): # 词典更适合用编辑距离,因为就一两个字符,相似度会很小,预翻译适合用相似度
|
||||
def distance(s1, s2):
|
||||
# 词典更适合用编辑距离,因为就一两个字符,相似度会很小,预翻译适合用相似度
|
||||
return _levenshtein_distance(len(s1), s1, len(s2), s2)
|
||||
|
||||
|
||||
@ -101,10 +100,14 @@ clphwnd = windll.user32.CreateWindowExW(0, "STATIC", 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
def clipboard_set(text):
|
||||
global clphwnd
|
||||
# _set_clip_board_queue.put(text)
|
||||
return _clipboard_set(clphwnd, text)
|
||||
|
||||
|
||||
def clipboard_set_image(bytes_):
|
||||
global clphwnd
|
||||
return _clipboard_set_image(clphwnd, bytes_, len(bytes_))
|
||||
|
||||
|
||||
def clipboard_get():
|
||||
ret = []
|
||||
if not _clipboard_get(CFUNCTYPE(None, c_wchar_p)(ret.append)):
|
||||
|
@ -56,6 +56,7 @@
|
||||
var htmltabbuttons = ''
|
||||
var htmlcontents = ''
|
||||
var scriptElementss = []
|
||||
var scriptElementsssrc = []
|
||||
for (var iiii = 0; iiii < dictionaryInfo.length; iiii++) {
|
||||
htmltabbuttons += '<button type="button" onclick="onclickbtn(\'' + dictionaryInfo[iiii]['dict'] + '\')" id="luna_dict_btn_' + dictionaryInfo[iiii]['dict'] + '" class="tab-button">' + dictionaryInfo[iiii]['name'] + '</button>'
|
||||
|
||||
@ -72,12 +73,18 @@
|
||||
|
||||
for (var jjjj = 0; jjjj < scriptElements.length; jjjj++) {
|
||||
scriptElementss.push(scriptElements[jjjj].textContent)
|
||||
scriptElementsssrc.push(scriptElements[jjjj].src)
|
||||
}
|
||||
}
|
||||
document.getElementById('tab_buttons').innerHTML = htmltabbuttons
|
||||
document.getElementById('tab_contents').innerHTML = htmlcontents
|
||||
for (var iiii = 0; iiii < scriptElementss.length; iiii++) {
|
||||
eval(scriptElementss[iiii])
|
||||
let newScript = document.createElement('script')
|
||||
if (scriptElementsssrc[iiii]) {
|
||||
newScript.src = scriptElementsssrc[iiii];
|
||||
document.head.appendChild(newScript);
|
||||
}
|
||||
}
|
||||
if (dictionaryInfo.length > 0) {
|
||||
onclickbtn(dictionaryInfo[0]['dict'])
|
||||
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "تصفية أو اقتطاع حسب عدد الكلمات",
|
||||
"按行数过滤或截断": "تصفية أو اقتطاع حسب عدد الصفوف",
|
||||
"超过最大字数时截断而非过滤": "اقتطاع عند تجاوز الحد الأقصى لعدد الكلمات بدلا من تصفية",
|
||||
"超过最大行数时截断而非过滤": "البتر عند تجاوز الحد الأقصى لعدد الصفوف بدلا من الترشيح"
|
||||
"超过最大行数时截断而非过滤": "البتر عند تجاوز الحد الأقصى لعدد الصفوف بدلا من الترشيح",
|
||||
"复制图片": "نسخ الصور"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "按字數過濾或截斷",
|
||||
"按行数过滤或截断": "按行數過濾或截斷",
|
||||
"超过最大字数时截断而非过滤": "超過最大字數時截斷而非過濾",
|
||||
"超过最大行数时截断而非过滤": "超過最大行數時截斷而非過濾"
|
||||
"超过最大行数时截断而非过滤": "超過最大行數時截斷而非過濾",
|
||||
"复制图片": "複製圖片"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtrovat nebo zkrátit podle počtu slov",
|
||||
"按行数过滤或截断": "Filtrovat nebo zkrátit podle počtu řádků",
|
||||
"超过最大字数时截断而非过滤": "Při překročení maximálního počtu slov zkrátit místo filtrování",
|
||||
"超过最大行数时截断而非过滤": "Při překročení maximálního počtu řádků zkrátit namísto filtrování"
|
||||
"超过最大行数时截断而非过滤": "Při překročení maximálního počtu řádků zkrátit namísto filtrování",
|
||||
"复制图片": "Kopírovat obrázek"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Nach Wortanzahl filtern oder kürzen",
|
||||
"按行数过滤或截断": "Nach Zeilenanzahl filtern oder kürzen",
|
||||
"超过最大字数时截断而非过滤": "Kürzen statt Filtern, wenn die maximale Wortanzahl überschritten wird",
|
||||
"超过最大行数时截断而非过滤": "Kürzen statt Filtern, wenn die maximale Anzahl von Zeilen überschritten wird"
|
||||
"超过最大行数时截断而非过滤": "Kürzen statt Filtern, wenn die maximale Anzahl von Zeilen überschritten wird",
|
||||
"复制图片": "Bild kopieren"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filter or truncate by word count",
|
||||
"按行数过滤或截断": "Filter or truncate by row count",
|
||||
"超过最大字数时截断而非过滤": "Truncate instead of filtering when exceeding the maximum word count",
|
||||
"超过最大行数时截断而非过滤": "Truncate instead of filtering when the maximum number of rows is exceeded"
|
||||
"超过最大行数时截断而非过滤": "Truncate instead of filtering when the maximum number of rows is exceeded",
|
||||
"复制图片": "Copy image"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtrar o truncar por número de palabras",
|
||||
"按行数过滤或截断": "Filtrar o truncar por número de líneas",
|
||||
"超过最大字数时截断而非过滤": "Cortar en lugar de filtrar cuando se supera el número máximo de palabras",
|
||||
"超过最大行数时截断而非过滤": "Cortar en lugar de filtrar cuando se supera el número máximo de líneas"
|
||||
"超过最大行数时截断而非过滤": "Cortar en lugar de filtrar cuando se supera el número máximo de líneas",
|
||||
"复制图片": "Copiar imagen"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtrer ou tronquer par nombre de mots",
|
||||
"按行数过滤或截断": "Filtrer ou tronquer par nombre de lignes",
|
||||
"超过最大字数时截断而非过滤": "Tronquer au lieu de filtrer lorsque le nombre maximal de mots est dépassé",
|
||||
"超过最大行数时截断而非过滤": "Tronquer au lieu de filtrer lorsque le nombre maximal de lignes est dépassé"
|
||||
"超过最大行数时截断而非过滤": "Tronquer au lieu de filtrer lorsque le nombre maximal de lignes est dépassé",
|
||||
"复制图片": "Copier l'image"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtra o tronca per numero di parole",
|
||||
"按行数过滤或截断": "Filtra o tronca per numero di righe",
|
||||
"超过最大字数时截断而非过滤": "Truncare invece di filtrare quando si supera il numero massimo di parole",
|
||||
"超过最大行数时截断而非过滤": "Truncare invece di filtrare quando viene superato il numero massimo di righe"
|
||||
"超过最大行数时截断而非过滤": "Truncare invece di filtrare quando viene superato il numero massimo di righe",
|
||||
"复制图片": "Copia immagine"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "文字数によるフィルタまたは切り捨て",
|
||||
"按行数过滤或截断": "行数によるフィルタまたは切り捨て",
|
||||
"超过最大字数时截断而非过滤": "最大文字数を超えるとフィルタではなく切り捨て",
|
||||
"超过最大行数时截断而非过滤": "最大行数を超えるとフィルタではなくトランケートされます"
|
||||
"超过最大行数时截断而非过滤": "最大行数を超えるとフィルタではなくトランケートされます",
|
||||
"复制图片": "画像をコピー"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "단어 수로 필터링 또는 자르기",
|
||||
"按行数过滤或截断": "행 수로 필터링 또는 자르기",
|
||||
"超过最大字数时截断而非过滤": "최대 단어 수 초과 시 필터링 대신 절단",
|
||||
"超过最大行数时截断而非过滤": "최대 행 수를 초과할 경우 필터링 대신 잘림"
|
||||
"超过最大行数时截断而非过滤": "최대 행 수를 초과할 경우 필터링 대신 잘림",
|
||||
"复制图片": "사진 복사"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filteren of inkorten op woordaantal",
|
||||
"按行数过滤或截断": "Filteren of inkorten op rijaantal",
|
||||
"超过最大字数时截断而非过滤": "Afsnijden in plaats van filteren bij overschrijding van het maximale aantal woorden",
|
||||
"超过最大行数时截断而非过滤": "Afsnijden in plaats van filteren wanneer het maximale aantal rijen wordt overschreden"
|
||||
"超过最大行数时截断而非过滤": "Afsnijden in plaats van filteren wanneer het maximale aantal rijen wordt overschreden",
|
||||
"复制图片": "Afbeelding kopiëren"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtruj lub skróć według liczby słów",
|
||||
"按行数过滤或截断": "Filtruj lub skróć według liczby wierszy",
|
||||
"超过最大字数时截断而非过滤": "Przycięcie zamiast filtrowania przy przekroczeniu maksymalnej liczby słów",
|
||||
"超过最大行数时截断而非过滤": "Przycięcie zamiast filtrowania przy przekroczeniu maksymalnej liczby wierszy"
|
||||
"超过最大行数时截断而非过滤": "Przycięcie zamiast filtrowania przy przekroczeniu maksymalnej liczby wierszy",
|
||||
"复制图片": "Kopiuj obrazek"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtrar ou truncar por contagem de palavras",
|
||||
"按行数过滤或截断": "Filtrar ou truncar por contagem de linhas",
|
||||
"超过最大字数时截断而非过滤": "Truncar em vez de filtrar quando exceder a contagem máxima de palavras",
|
||||
"超过最大行数时截断而非过滤": "Truncar em vez de filtrar quando o número máximo de linhas for excedido"
|
||||
"超过最大行数时截断而非过滤": "Truncar em vez de filtrar quando o número máximo de linhas for excedido",
|
||||
"复制图片": "Copiar a imagem"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Фильтрация или отсечение по количеству слов",
|
||||
"按行数过滤或截断": "Фильтрация или отсечение по числу строк",
|
||||
"超过最大字数时截断而非过滤": "Преодоление максимального количества слов вместо фильтрации",
|
||||
"超过最大行数时截断而非过滤": "Преодоление максимального числа строк вместо фильтрации"
|
||||
"超过最大行数时截断而非过滤": "Преодоление максимального числа строк вместо фильтрации",
|
||||
"复制图片": "Копировать изображение"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Filtrera eller förkorta efter ordräkning",
|
||||
"按行数过滤或截断": "Filtrera eller förkorta efter radantal",
|
||||
"超过最大字数时截断而非过滤": "Trunkera istället för filtrering när det maximala ordantalet överskrids",
|
||||
"超过最大行数时截断而非过滤": "Trunkera istället för filtrering när det maximala antalet rader överskrids"
|
||||
"超过最大行数时截断而非过滤": "Trunkera istället för filtrering när det maximala antalet rader överskrids",
|
||||
"复制图片": "Kopiera bild"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "กรองหรือตัดตามจำนวนคำ",
|
||||
"按行数过滤或截断": "กรองหรือตัดตามจำนวนแถว",
|
||||
"超过最大字数时截断而非过滤": "ตัดแทนการกรองเมื่อเกินจำนวนคำสูงสุด",
|
||||
"超过最大行数时截断而非过滤": "ตัดแทนการกรองเมื่อเกินจำนวนแถวสูงสุด"
|
||||
"超过最大行数时截断而非过滤": "ตัดแทนการกรองเมื่อเกินจำนวนแถวสูงสุด",
|
||||
"复制图片": "คัดลอกรูปภาพ"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Kelime sayıyla sil ya da küçük",
|
||||
"按行数过滤或截断": "Sırada sayıyla sil ya da küçük",
|
||||
"超过最大字数时截断而非过滤": "Maksimum kelime sayısından fazladığında filtreleme yerine küçük",
|
||||
"超过最大行数时截断而非过滤": "Azamik satır sayısını aştığında filtrelemek yerine küçük"
|
||||
"超过最大行数时截断而非过滤": "Azamik satır sayısını aştığında filtrelemek yerine küçük",
|
||||
"复制图片": "Görüntü kopyala"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Фільтрувати або скоротити за кількістю слів",
|
||||
"按行数过滤或截断": "Фільтрувати або вирізати за кількістю рядків",
|
||||
"超过最大字数时截断而非过滤": "Вирізати замість фільтрування, якщо перевищує максимальну кількість слів",
|
||||
"超过最大行数时截断而非过滤": "Вирізати замість фільтрування, якщо перевищено максимальну кількість рядків"
|
||||
"超过最大行数时截断而非过滤": "Вирізати замість фільтрування, якщо перевищено максимальну кількість рядків",
|
||||
"复制图片": "Копіювати зображення"
|
||||
}
|
@ -825,5 +825,6 @@
|
||||
"按字数过滤或截断": "Lọc hoặc cắt ngắn theo số lượng từ",
|
||||
"按行数过滤或截断": "Lọc hoặc cắt ngắn theo số dòng",
|
||||
"超过最大字数时截断而非过滤": "Cắt ngắn thay vì lọc khi vượt quá số từ tối đa",
|
||||
"超过最大行数时截断而非过滤": "Cắt ngắn thay vì lọc khi vượt quá số dòng tối đa"
|
||||
"超过最大行数时截断而非过滤": "Cắt ngắn thay vì lọc khi vượt quá số dòng tối đa",
|
||||
"复制图片": "Sao chép ảnh"
|
||||
}
|
@ -825,5 +825,9 @@
|
||||
"按字数过滤或截断": "",
|
||||
"按行数过滤或截断": "",
|
||||
"超过最大字数时截断而非过滤": "",
|
||||
"超过最大行数时截断而非过滤": ""
|
||||
"超过最大行数时截断而非过滤": "",
|
||||
"复制图片": "",
|
||||
"旭光のマリアージュ": "",
|
||||
"俺たちに翼はない ―――under the innocent sky.": "",
|
||||
"卡片模板「modelofluna」中的「内容模板 1」存在错误。<br>内容模板正面应有字段替换。": ""
|
||||
}
|
@ -88,7 +88,8 @@ Some buttons have two icons to indicate two different states. Some buttons only
|
||||
You can scale the game window (HOOK linked game/clipboard, OCR bound window) with one click (default uses the built-in Magpie, or you can set it to use your own downloaded Magpie, etc.).<br>
|
||||
1. #### <i class="fa fa-camera"></i> <i class="fa fa-icon fa-rotate-right"></i> Window Screenshot
|
||||
You can take a screenshot of the bound window (it will take two screenshots by default, GDI and Winrt, both of which have a certain probability of failure). The best part is that if you are currently using Magpie for scaling, it will also take a screenshot of the enlarged window.<br>
|
||||
See [Useful Features](/zh/usefulsmalltools.md?id=Window Screenshot & Gallery & Recording, Capture Every Wonderful Moment)
|
||||
When left clicked, the screenshot will be saved to a file, and when right clicked, the screenshot will be saved to the clipboard.
|
||||
|
||||
1. #### <i class="fa fa-volume-off"></i> <i class="btnstatus2 fa fa-volume-up"></i> Game Mute
|
||||
After binding the game window (not just in HOOK mode, OCR or clipboard mode can also, as long as the game window is bound), you can mute the game with one click, saving the trouble of muting the game in the system volume mixer.
|
||||
1. #### <i class="fa fa-eye"></i> <i class="btnstatus2 fa fa-eye-slash"></i> Show/Hide Original Text
|
||||
|
@ -99,7 +99,7 @@
|
||||
|
||||
1. #### <i class="fa fa-camera"></i> <i class="fa fa-icon fa-rotate-right"></i> Снимок окна
|
||||
Можно сделать снимок привязанного окна (по умолчанию делает два снимка, GDI и Winrt, оба имеют некоторую вероятность сбоя). Лучшее место, если в настоящее время используется Magpie для масштабирования, также будет делать снимок увеличенного окна.<br>
|
||||
Подробнее в разделе [Полезные функции](/ru/usefulsmalltools.md?id=Снимок_окна&галерея&запись_звука,_захват_каждого_яркого_момента)
|
||||
Снимок экрана будет сохранен в файле при щелчке левой кнопкой мыши, а снимок экрана будет сохранен в буфере обмена при щелчке правой кнопкой мыши.
|
||||
|
||||
1. #### <i class="fa fa-volume-off"></i> <i class="btnstatus2 fa fa-volume-up"></i> Выключение звука игры
|
||||
После привязки окна игры (не только в режиме HOOK, но и в режиме OCR или буфера обмена, если только окно игры привязано), можно одним нажатием выключить звук игры, избавившись от необходимости отключать звук игры в системном микшере.
|
||||
|
@ -88,7 +88,7 @@
|
||||
可以一键对游戏窗口(HOOK链接游戏/剪贴板、OCR绑定窗口)进行缩放(默认使用内置的Magpie,也可以设置使用自己下载的Magpie等)。<br>
|
||||
1. #### <i class="fa fa-camera"></i> <i class="fa fa-icon fa-rotate-right"></i> 窗口截图
|
||||
可以对绑定的窗口进行截图,(默认会截两张图,GDI和Winrt,两者均有一定概率会失败)。最好的地方是,如果当前正在使用Magpie进行缩放,还会对放大的窗口进行截图。<br>
|
||||
详见[实用功能](/zh/usefulsmalltools.md?id=窗口截图amp画廊amp录音,捕捉每个精彩瞬间)
|
||||
左键点击时会把截图保存到文件,右键点击时截图会保存到剪贴板。
|
||||
1. #### <i class="fa fa-volume-off"></i> <i class="btnstatus2 fa fa-volume-up"></i> 游戏静音
|
||||
当绑定游戏窗口后(不只是hook模式,ocr或剪贴板模式都可以,只要绑定了游戏窗口),可以一键对游戏进行静音,省去了在系统音量合成器进行游戏静音的麻烦。
|
||||
1. #### <i class="fa fa-eye"></i> <i class="btnstatus2 fa fa-eye-slash"></i> 显示/隐藏原文
|
||||
|
@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
|
||||
include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 5)
|
||||
set(VERSION_MINOR 40)
|
||||
set(VERSION_PATCH 3)
|
||||
set(VERSION_MINOR 41)
|
||||
set(VERSION_PATCH 0)
|
||||
|
||||
add_library(pch pch.cpp)
|
||||
target_precompile_headers(pch PUBLIC pch.h)
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllexport) void winrt_capture_window(wchar_t *savepath, HWND hwnd);
|
||||
__declspec(dllexport) void winrt_capture_window(HWND hwnd, void (*cb)(byte *, size_t));
|
||||
|
||||
__declspec(dllexport) bool check_language_valid(wchar_t *);
|
||||
__declspec(dllexport) void getlanguagelist(void (*cb)(LPCWSTR));
|
||||
|
@ -56,9 +56,11 @@ int GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
|
||||
free(pImageCodecInfo);
|
||||
return -1; // Failure
|
||||
}
|
||||
void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
void capture_window(HWND window_handle, void (*cb)(byte *, size_t))
|
||||
{
|
||||
HMODULE hModule = LoadLibrary(TEXT("d3d11.dll"));
|
||||
HMODULE hModule = GetModuleHandle(TEXT("d3d11.dll"));
|
||||
if (!hModule)
|
||||
hModule = LoadLibrary(TEXT("d3d11.dll"));
|
||||
HRESULT typedef(_stdcall * CreateDirect3D11DeviceFromDXGIDevice_t)(
|
||||
_In_ IDXGIDevice * dxgiDevice,
|
||||
_COM_Outptr_ IInspectable * *graphicsDevice);
|
||||
@ -88,7 +90,7 @@ void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
winrt::check_hresult(idxgi_device2->GetParent(winrt::guid_of<IDXGIAdapter>(), adapter.put_void()));
|
||||
winrt::com_ptr<IDXGIFactory2> factory;
|
||||
winrt::check_hresult(adapter->GetParent(winrt::guid_of<IDXGIFactory2>(), factory.put_void()));
|
||||
|
||||
|
||||
winrt::com_ptr<ID3D11DeviceContext> d3d_context;
|
||||
d3d_device->GetImmediateContext(d3d_context.put());
|
||||
|
||||
@ -132,7 +134,6 @@ void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
access->GetInterface(winrt::guid_of<ID3D11Texture2D>(), texture.put_void());
|
||||
is_frame_arrived = true;
|
||||
return; });
|
||||
|
||||
session.StartCapture();
|
||||
|
||||
// Message pump
|
||||
@ -146,7 +147,6 @@ void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
}
|
||||
|
||||
session.Close();
|
||||
//??
|
||||
|
||||
D3D11_TEXTURE2D_DESC captured_texture_desc;
|
||||
texture->GetDesc(&captured_texture_desc);
|
||||
@ -160,7 +160,6 @@ void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
winrt::check_hresult(d3d_device->CreateTexture2D(&captured_texture_desc, nullptr, user_texture.put()));
|
||||
|
||||
d3d_context->CopyResource(user_texture.get(), texture.get());
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE resource;
|
||||
winrt::check_hresult(d3d_context->Map(user_texture.get(), NULL, D3D11_MAP_READ, 0, &resource));
|
||||
|
||||
@ -189,45 +188,23 @@ void capture_window(HWND window_handle, const std::wstring &output_file_path)
|
||||
sptr += resource.RowPitch;
|
||||
dptr -= l_bmp_row_pitch;
|
||||
}
|
||||
d3d_context->Unmap(user_texture.get(), NULL);
|
||||
BITMAPFILEHEADER bmfh;
|
||||
memset(&bmfh, 0, sizeof(BITMAPFILEHEADER));
|
||||
bmfh.bfType = 0x4D42; // 'BM'
|
||||
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + l_bmp_info.bmiHeader.biSizeImage;
|
||||
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
|
||||
// FILE* lfile = nullptr;
|
||||
|
||||
// if (auto lerr = _wfopen_s(&lfile, output_file_path.c_str(), L"wb"); lerr != 0)
|
||||
//{
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (lfile != nullptr)
|
||||
//{
|
||||
// BITMAPFILEHEADER bmp_file_header;
|
||||
|
||||
// bmp_file_header.bfReserved1 = 0;
|
||||
// bmp_file_header.bfReserved2 = 0;
|
||||
// bmp_file_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + l_bmp_info.bmiHeader.biSizeImage;
|
||||
// bmp_file_header.bfType = 'MB';
|
||||
// bmp_file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
|
||||
// fwrite(&bmp_file_header, sizeof(BITMAPFILEHEADER), 1, lfile);
|
||||
// fwrite(&l_bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, lfile);
|
||||
// fwrite(p_buf.get(), l_bmp_info.bmiHeader.biSizeImage, 1, lfile);
|
||||
|
||||
// fclose(lfile);
|
||||
|
||||
// //convert_image_encoding(output_file_path, L"png");
|
||||
//}
|
||||
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
|
||||
ULONG_PTR gdiplusToken;
|
||||
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
Gdiplus::Bitmap *image = Gdiplus::Bitmap::FromBITMAPINFO(&l_bmp_info, p_buf.get());
|
||||
|
||||
CLSID encoderClsid;
|
||||
GetEncoderClsid(L"image/png", &encoderClsid);
|
||||
|
||||
image->Save(output_file_path.c_str(), &encoderClsid, NULL);
|
||||
delete image;
|
||||
Gdiplus::GdiplusShutdown(gdiplusToken);
|
||||
auto p_buf2 = std::make_unique<BYTE[]>(bmfh.bfSize);
|
||||
auto ptr = p_buf2.get();
|
||||
memcpy(ptr, &bmfh, sizeof(BITMAPFILEHEADER));
|
||||
ptr += sizeof(BITMAPFILEHEADER);
|
||||
memcpy(ptr, (char *)&l_bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER));
|
||||
ptr += sizeof(BITMAPINFOHEADER);
|
||||
memcpy(ptr, p_buf.get(), l_bmp_info.bmiHeader.biSizeImage);
|
||||
cb(p_buf2.get(), bmfh.bfSize);
|
||||
}
|
||||
void winrt_capture_window(wchar_t *savepath, HWND hwnd)
|
||||
void winrt_capture_window(HWND hwnd, void (*cb)(byte *, size_t))
|
||||
{
|
||||
// auto hwnd = GetForegroundWindow();// FindWindow(L"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", 0);
|
||||
auto style_ex = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
@ -241,7 +218,7 @@ void winrt_capture_window(wchar_t *savepath, HWND hwnd)
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, style_ex);
|
||||
}
|
||||
|
||||
capture_window(hwnd, savepath);
|
||||
capture_window(hwnd, cb);
|
||||
if (needset)
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, style_ex_save);
|
||||
}
|
||||
|
@ -63,11 +63,18 @@ bool clipboard_set(HWND hwnd, wchar_t *text)
|
||||
break;
|
||||
auto pchData = (wchar_t *)GlobalLock(hClipboardData);
|
||||
if (pchData == 0)
|
||||
{
|
||||
GlobalFree(hClipboardData);
|
||||
break;
|
||||
}
|
||||
wcscpy_s(pchData, len, text);
|
||||
GlobalUnlock(hClipboardData);
|
||||
SetClipboardData(CF_UNICODETEXT, hClipboardData);
|
||||
success = true;
|
||||
if (SetClipboardData(CF_UNICODETEXT, hClipboardData))
|
||||
success = true;
|
||||
else
|
||||
{
|
||||
GlobalFree(hClipboardData);
|
||||
}
|
||||
|
||||
} while (false);
|
||||
CloseClipboard();
|
||||
@ -137,3 +144,29 @@ DECLARE void clipboard_callback_stop(HWND hwnd)
|
||||
RemoveClipboardFormatListener(hwnd);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
DECLARE bool clipboard_set_image(HWND hwnd, void *ptr, size_t size)
|
||||
{
|
||||
size -= sizeof(BITMAPFILEHEADER);
|
||||
HGLOBAL hDib = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||
if (!hDib)
|
||||
return false;
|
||||
void *pDib = GlobalLock(hDib);
|
||||
if (!pDib)
|
||||
{
|
||||
GlobalFree(hDib);
|
||||
return false;
|
||||
}
|
||||
memcpy((char *)pDib, (char *)ptr + sizeof(BITMAPFILEHEADER), size);
|
||||
if (tryopenclipboard(hwnd) == false)
|
||||
return false;
|
||||
EmptyClipboard();
|
||||
if (!SetClipboardData(CF_DIB, hDib))
|
||||
{
|
||||
GlobalFree(hDib);
|
||||
CloseClipboard();
|
||||
return false;
|
||||
}
|
||||
CloseClipboard();
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user