This commit is contained in:
恍兮惚兮 2025-01-07 20:18:35 +08:00
parent 364bed7a07
commit 10ba876bcd
7 changed files with 126 additions and 188 deletions

View File

@ -16,20 +16,18 @@ DECLARE_API void *wcocr_init(const wchar_t *wexe, const wchar_t *wwcdir)
}
}
DECLARE_API void wcocr_destroy(void *pobj)
DECLARE_API void wcocr_destroy(CWeChatOCR *pobj)
{
if (!pobj)
return;
auto obj = reinterpret_cast<CWeChatOCR *>(pobj);
delete obj;
delete pobj;
}
DECLARE_API bool wcocr_ocr(void *pobj, const char *u8path, void (*cb)(int, int, int, int, LPCSTR))
DECLARE_API bool wcocr_ocr(CWeChatOCR *pobj, const char *u8path, void (*cb)(int, int, int, int, LPCSTR))
{
if (!pobj)
return false;
auto obj = reinterpret_cast<CWeChatOCR *>(pobj);
CWeChatOCR::result_t res;
if (!obj->doOCR(u8path, &res))
if (!pobj->doOCR(u8path, &res))
return false;
for (auto &blk : res.ocr_response)
{

View File

@ -201,18 +201,16 @@ DECLARE_API void *html_new(HWND parent)
return s_pWebBrowser;
}
DECLARE_API void html_navigate(void *web, wchar_t *path)
DECLARE_API void html_navigate(MWebBrowserEx *ww, wchar_t *path)
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->Navigate2(path);
}
DECLARE_API void html_resize(void *web, int x, int y, int w, int h)
DECLARE_API void html_resize(MWebBrowserEx *ww, int x, int y, int w, int h)
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
RECT r;
r.left = x;
r.top = y;
@ -220,37 +218,33 @@ DECLARE_API void html_resize(void *web, int x, int y, int w, int h)
r.bottom = y + h;
ww->MoveWindow(r);
}
DECLARE_API void html_release(void *web)
DECLARE_API void html_release(MWebBrowserEx *ww)
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->Destroy();
// ww->Release(); Destroy减少引用计数自动del
}
DECLARE_API void html_get_current_url(void *web, void (*cb)(LPCWSTR))
DECLARE_API void html_get_current_url(MWebBrowserEx *ww, void (*cb)(LPCWSTR))
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
CComBSTR _u;
CHECK_FAILURE_NORET(ww->get_LocationURL(&_u));
cb(_u);
}
DECLARE_API void html_set_html(void *web, wchar_t *html)
DECLARE_API void html_set_html(MWebBrowserEx *ww, wchar_t *html)
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->SetHtml(html);
}
DECLARE_API void html_add_menu(void *web, int index, const wchar_t *label, void (*callback)(const wchar_t *))
DECLARE_API void html_add_menu(MWebBrowserEx *ww, int index, const wchar_t *label, void (*callback)(const wchar_t *))
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
std::optional<std::wstring> _label;
if (label)
_label = label;
@ -259,37 +253,33 @@ DECLARE_API void html_add_menu(void *web, int index, const wchar_t *label, void
ww->menuitems.insert(ptr, {_label, command});
ww->menucallbacks[command] = callback;
}
DECLARE_API void html_get_select_text(void *web, void (*cb)(LPCWSTR))
DECLARE_API void html_get_select_text(MWebBrowserEx *ww, void (*cb)(LPCWSTR))
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
CComBSTR selectedText;
CHECK_FAILURE_NORET(ww->getselectedtext(&selectedText));
cb(selectedText);
}
DECLARE_API void html_bind_function(void *web, const wchar_t *name, void (*function)(wchar_t **, int))
DECLARE_API void html_bind_function(MWebBrowserEx *ww, const wchar_t *name, void (*function)(wchar_t **, int))
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->jsobj->bindfunction(name, function);
}
DECLARE_API bool html_check_ctrlc(void *web)
DECLARE_API bool html_check_ctrlc(MWebBrowserEx *ww)
{
if (!web)
if (!ww)
return false;
auto ww = static_cast<MWebBrowserEx *>(web);
return GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(67) && (ww->GetIEServerWindow() == GetFocus());
}
DECLARE_API void html_eval(void *web, const wchar_t *js)
DECLARE_API void html_eval(MWebBrowserEx *ww, const wchar_t *js)
{
if (!web)
if (!ww)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
CComPtr<IHTMLDocument2> pDocument;
CHECK_FAILURE_NORET(ww->GetIHTMLDocument2(&pDocument));
CComPtr<IDispatch> scriptDispatch;
@ -319,3 +309,17 @@ DECLARE_API void html_eval(void *web, const wchar_t *js)
dispid, IID_NULL, 0, DISPATCH_METHOD,
&params, &result, &excepInfo, &nArgErr);
}
DECLARE_API void html_get_html(MWebBrowserEx *ww, void (*cb)(LPCWSTR))
{
if (!ww)
return;
CComPtr<IHTMLDocument2> pDocument;
CHECK_FAILURE_NORET(ww->GetIHTMLDocument2(&pDocument));
CComPtr<IHTMLDocument3> pDocument3;
CHECK_FAILURE_NORET(pDocument.QueryInterface(&pDocument3));
CComPtr<IHTMLElement> ele;
CHECK_FAILURE_NORET(pDocument3->get_documentElement(&ele));
CComBSTR data;
CHECK_FAILURE_NORET(ele->get_outerHTML(&data));
cb(data);
}

View File

@ -10,13 +10,14 @@ using namespace Microsoft::WRL;
#else
typedef int COREWEBVIEW2_PREFERRED_COLOR_SCHEME;
typedef int EventRegistrationToken;
typedef int ICoreWebView2Controller;
#endif
DECLARE_API void set_transparent_background(void *m_host)
DECLARE_API void set_transparent_background(ICoreWebView2Controller *m_host)
{
#ifndef WINXP
COREWEBVIEW2_COLOR color;
ZeroMemory(&color, sizeof(color));
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2Controller2> coreWebView2 =
m_controller.try_query<ICoreWebView2Controller2>();
if (coreWebView2)
@ -26,10 +27,10 @@ DECLARE_API void set_transparent_background(void *m_host)
#endif
}
DECLARE_API void put_PreferredColorScheme(void *m_host, COREWEBVIEW2_PREFERRED_COLOR_SCHEME scheme)
DECLARE_API void put_PreferredColorScheme(ICoreWebView2Controller *m_host, COREWEBVIEW2_PREFERRED_COLOR_SCHEME scheme)
{
#ifndef WINXP
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2> coreWebView2;
[&]()
{
@ -45,13 +46,13 @@ DECLARE_API void put_PreferredColorScheme(void *m_host, COREWEBVIEW2_PREFERRED_C
}();
#endif
}
DECLARE_API void *add_ZoomFactorChanged(void *m_host, void (*signal)(double))
DECLARE_API void *add_ZoomFactorChanged(ICoreWebView2Controller *m_host, void (*signal)(double))
{
#ifndef WINXP
EventRegistrationToken *m_zoomFactorChangedToken = new EventRegistrationToken;
// Register a handler for the ZoomFactorChanged event.
// This handler just announces the new level of zoom on the window's title bar.
reinterpret_cast<ICoreWebView2Controller *>(m_host)->add_ZoomFactorChanged(
m_host->add_ZoomFactorChanged(
Callback<ICoreWebView2ZoomFactorChangedEventHandler>(
[signal](ICoreWebView2Controller *sender, IUnknown *args) -> HRESULT
{
@ -70,34 +71,34 @@ DECLARE_API void *add_ZoomFactorChanged(void *m_host, void (*signal)(double))
return NULL;
#endif
}
DECLARE_API void remove_ZoomFactorChanged(void *m_host, EventRegistrationToken *token)
DECLARE_API void remove_ZoomFactorChanged(ICoreWebView2Controller *m_host, EventRegistrationToken *token)
{
#ifndef WINXP
reinterpret_cast<ICoreWebView2Controller *>(m_host)->remove_ZoomFactorChanged(*token);
m_host->remove_ZoomFactorChanged(*token);
delete token;
#endif
}
DECLARE_API double get_ZoomFactor(void *m_host)
DECLARE_API double get_ZoomFactor(ICoreWebView2Controller *m_host)
{
#ifndef WINXP
double zoomFactor;
reinterpret_cast<ICoreWebView2Controller *>(m_host)->get_ZoomFactor(&zoomFactor);
m_host->get_ZoomFactor(&zoomFactor);
return zoomFactor;
#else
return 1;
#endif
}
DECLARE_API void put_ZoomFactor(void *m_host, double zoomFactor)
DECLARE_API void put_ZoomFactor(ICoreWebView2Controller *m_host, double zoomFactor)
{
#ifndef WINXP
reinterpret_cast<ICoreWebView2Controller *>(m_host)->put_ZoomFactor(zoomFactor);
m_host->put_ZoomFactor(zoomFactor);
#endif
}
// https://github.com/MicrosoftEdge/WebView2Feedback/blob/main/specs/WebMessageObjects.md
DECLARE_API void remove_WebMessageReceived(void *m_host, EventRegistrationToken *token)
DECLARE_API void remove_WebMessageReceived(ICoreWebView2Controller *m_host, EventRegistrationToken *token)
{
#ifndef WINXP
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2> m_webView;
[&]()
{
@ -109,10 +110,10 @@ DECLARE_API void remove_WebMessageReceived(void *m_host, EventRegistrationToken
#endif
}
DECLARE_API void *add_WebMessageReceived(void *m_host, void (*callback)(const wchar_t *))
DECLARE_API void *add_WebMessageReceived(ICoreWebView2Controller *m_host, void (*callback)(const wchar_t *))
{
#ifndef WINXP
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2Controller4> coreWebView4 =
m_controller.try_query<ICoreWebView2Controller4>();
if (coreWebView4)
@ -188,20 +189,19 @@ struct contextcallbackdatas
};
// https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/how-to/context-menus?tabs=cpp
// https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2_11?view=webview2-1.0.2849.39
DECLARE_API void add_menu_list(void *ptr, int index, const wchar_t *label, void (*callback)(const wchar_t *))
DECLARE_API void add_menu_list(contextcallbackdatas *ptr, int index, const wchar_t *label, void (*callback)(const wchar_t *))
{
if (!ptr)
return;
auto token = reinterpret_cast<contextcallbackdatas *>(ptr);
token->menus.insert(token->menus.begin() + index, std::make_pair(label, callback));
ptr->menus.insert(ptr->menus.begin() + index, std::make_pair(label, callback));
}
DECLARE_API void *add_ContextMenuRequested(void *m_host)
DECLARE_API void *add_ContextMenuRequested(ICoreWebView2Controller *m_host)
{
#ifndef WINXP
contextcallbackdatas *data = new contextcallbackdatas;
[=]()
{
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2> m_webView;
CHECK_FAILURE(m_controller->get_CoreWebView2(&m_webView));
auto m_webView2_11 = m_webView.try_query<ICoreWebView2_11>();
@ -280,10 +280,10 @@ DECLARE_API void *add_ContextMenuRequested(void *m_host)
return NULL;
#endif
}
DECLARE_API void remove_ContextMenuRequested(void *m_host, contextcallbackdatas *data)
DECLARE_API void remove_ContextMenuRequested(ICoreWebView2Controller *m_host, contextcallbackdatas *data)
{
#ifndef WINXP
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2> m_webView;
[&]()
{
@ -297,3 +297,20 @@ DECLARE_API void remove_ContextMenuRequested(void *m_host, contextcallbackdatas
delete data;
#endif
}
DECLARE_API void get_root_html(ICoreWebView2Controller *m_host, void (*cb)(LPCWSTR))
{
#ifndef WINXP
wil::com_ptr<ICoreWebView2Controller> m_controller(m_host);
wil::com_ptr<ICoreWebView2> m_webView;
CHECK_FAILURE_NORET(m_controller->get_CoreWebView2(&m_webView));
CHECK_FAILURE_NORET(m_webView->ExecuteScript(L"document.documentElement.outerHTML", Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
[=](HRESULT errorCode,
LPCWSTR resultObjectAsJson)
{
cb(resultObjectAsJson);
return S_OK;
})
.Get()));
#endif
}

View File

@ -1063,67 +1063,15 @@ class showdiction(QWidget):
class showwordfastwebview(auto_select_webview):
def reloaddata(self):
if isinstance(self.internal, mshtmlWidget):
super().reloaddata()
def _maybecreate_internal(self):
self.needreset = True
super()._maybecreate_internal()
if isinstance(self.internal, WebivewWidget):
if self.lastaction:
super().reloaddata()
else:
self.setframework()
def __init__(self, parent, dyna=False):
self.needreset = False
super().__init__(parent, dyna)
self.on_load.connect(self.checkurlchange)
def setframework(self, html=None):
path = os.path.join(os.path.dirname(__file__), "showwordfast.html")
if html:
with open(path, "r", encoding="utf8") as ff:
html = ff.read().replace(
'<div id="luna_root_div"></div>',
'<div id="luna_root_div">{}</div>'.format(html),
)
md5 = hashlib.md5(html.encode("utf8", errors="ignore")).hexdigest()
path = gobject.gettempdir(md5 + ".html")
with open(path, "w", encoding="utf8") as ff:
ff.write(html)
self.internal.navigate(os.path.abspath(path))
def checkurlchange(self, url: str):
if url == "about:blank":
pass
elif not url.startswith("file:"):
self.needreset = True
def setHtml(self, html):
# webview2 sethtml谜之很慢navigate和eval比较快
if isinstance(self.internal, mshtmlWidget):
super().setHtml(html)
elif isinstance(self.internal, WebivewWidget):
self.lastaction = 1, html
self.internal.set_zoom(self.internalsavedzoom)
if self.needreset:
self.needreset = False
self.setframework(html)
else:
self.internal.eval("_clear_all()")
self.internal.eval("_set_extra_html('{}')".format(quote(html)))
def clear(self):
if isinstance(self.internal, mshtmlWidget):
super().clear()
elif isinstance(self.internal, WebivewWidget):
self.lastaction = None
if self.needreset:
self.needreset = False
self.setframework()
self.internal.eval("_clear_all()")
def _createwebview(self):
web = super()._createwebview()
if isinstance(web, WebivewWidget):
web.html_limit = 1
return web
class searchwordW(closeashidewindow):

View File

@ -1,47 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<style>
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
}
body {
background-color: rgb(44, 44, 44);
color: white;
}
}
</style>
</head>
<div id="luna_root_div"></div>
<script>
const rootdivid = 'luna_root_div';
function _clear_all() {
document.getElementById(rootdivid).innerHTML = "";
}
function _runScript(script) {
let newScript = document.createElement('script');
newScript.innerHTML = script.innerHTML;
let src = script.getAttribute('src');
if (src) newScript.setAttribute('src', src);
document.head.appendChild(newScript);
document.head.removeChild(newScript);
}
function _setHTMLWithScript(container, rawHTML) {
container.innerHTML = rawHTML;
let scripts = container.querySelectorAll('script');
for (let script of scripts) {
_runScript(script);
}
}
function _set_extra_html(htmlx) {
_setHTMLWithScript(document.getElementById(rootdivid), decodeURIComponent(htmlx))
}
</script>
</html>

View File

@ -1,7 +1,7 @@
from qtsymbols import *
import os, re, functools, hashlib, json, math, csv, io, pickle
from traceback import print_exc
import windows, qtawesome, winsharedutils, gobject
import windows, qtawesome, winsharedutils, gobject, threading
from webviewpy import webview_native_handle_kind_t, Webview
from myutils.config import _TR, globalconfig
from myutils.wrapper import Singleton_close, tryprint
@ -1100,6 +1100,9 @@ class abstractwebview(QWidget):
html_limit = 2 * 1024 * 1024
# 必须的接口
def getHtml(self, callback):
return
def setHtml(self, html):
pass
@ -1181,6 +1184,14 @@ class WebivewWidget(abstractwebview):
# https://github.com/MicrosoftEdge/WebView2Feedback/issues/1355#issuecomment-1384161283
dropfilecallback = pyqtSignal(str)
def getHtml(self, callback):
def __(html):
callback(json.loads(html))
cb = winsharedutils.html_get_select_text_cb(__)
winsharedutils.get_root_html(self.get_controller(), cb)
self.callbacks.append(cb)
def __del__(self):
if not self.webview:
return
@ -1392,6 +1403,10 @@ class QWebWrap(abstractwebview):
class mshtmlWidget(abstractwebview):
def getHtml(self, callback):
cb = winsharedutils.html_get_select_text_cb(callback)
winsharedutils.html_get_html(self.browser, cb)
self.callbacks.append(cb)
def eval(self, js):
winsharedutils.html_eval(self.browser, js)
@ -1505,7 +1520,6 @@ class auto_select_webview(QWidget):
def eval(self, js):
self.internal.eval(js)
self.evals.append(js)
def bind(self, funcname, function):
self.bindinfo.append((funcname, function))
@ -1516,16 +1530,13 @@ class auto_select_webview(QWidget):
self.internal.add_menu(index, label, callback)
def clear(self):
self.lastaction = None
self.internal.setHtml(self.internal.parsehtml("")) # 夜间
def navigate(self, url):
self.lastaction = 0, url
self.internal.set_zoom(self.internalsavedzoom)
self.internal.navigate(url)
def setHtml(self, html):
self.lastaction = 1, html
self.internal.set_zoom(self.internalsavedzoom)
html = self.internal.parsehtml(html)
if len(html) < self.internal.html_limit:
@ -1547,15 +1558,14 @@ class auto_select_webview(QWidget):
def __init__(self, parent, dyna=False) -> None:
super().__init__(parent)
self.addmenuinfo = []
self.evals = []
self.bindinfo = []
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.internal = None
self.saveurl = None
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(layout)
self.internalsavedzoom = 1
self.lastaction = None
self._maybecreate_internal()
if dyna:
switchtypes.append(self)
@ -1569,31 +1579,36 @@ class auto_select_webview(QWidget):
self.internalsavedzoom = zoom
self.on_ZoomFactorChanged.emit(zoom)
def _maybecreate_internal(self):
if self.internal:
def _gethtmlcallback(self, html):
self.layout().removeWidget(self.internal)
self._createinternal()
self.internal.setHtml(html)
def _on_load(self, url):
self.saveurl = url
self.on_load.emit(url)
def _createinternal(self):
self.internal = self._createwebview()
self.internal.set_zoom(self.internalsavedzoom)
self.internal.on_load.connect(self.on_load)
self.internal.on_load.connect(self._on_load)
self.internal.on_ZoomFactorChanged.connect(self.internalzoomchanged)
self.layout().addWidget(self.internal)
for _ in self.addmenuinfo:
self.internal.add_menu(*_)
for _ in self.bindinfo:
self.internal.bind(*_)
for _ in self.evals:
self.internal.eval(_)
self.reloaddata()
def reloaddata(self):
if self.lastaction:
action, arg = self.lastaction
if action == 0:
self.navigate(arg)
elif action == 1:
self.setHtml(arg)
def _maybecreate_internal(self):
if self.internal:
if self.saveurl and self.saveurl != "about:blank":
self.layout().removeWidget(self.internal)
self._createinternal()
self.internal.navigate(self.saveurl)
else:
self.clear()
self.internal.getHtml(self._gethtmlcallback)
return
self._createinternal()
def _createwebview(self):
contex = globalconfig["usewebview"]

View File

@ -105,7 +105,8 @@ html_get_select_text = utilsdll.html_get_select_text
html_get_select_text_cb = CFUNCTYPE(None, c_wchar_p)
html_get_select_text.argtypes = (c_void_p, c_void_p)
html_get_html = utilsdll.html_get_html
html_get_html.argtypes = (c_void_p, c_void_p)
html_bind_function_FT = CFUNCTYPE(None, POINTER(c_wchar_p), c_int)
html_bind_function = utilsdll.html_bind_function
html_bind_function.argtypes = c_void_p, c_wchar_p, html_bind_function_FT
@ -285,6 +286,8 @@ remove_ContextMenuRequested = utilsdll.remove_ContextMenuRequested
remove_ContextMenuRequested.argtypes = c_void_p, c_void_p
add_menu_list = utilsdll.add_menu_list
add_menu_list.argtypes = (c_void_p, c_int, c_wchar_p, add_ContextMenuRequested_cb)
get_root_html = utilsdll.get_root_html
get_root_html.argtypes = c_void_p, c_void_p
StartCaptureAsync_cb = CFUNCTYPE(None, c_void_p, c_size_t)
StartCaptureAsync = utilsdll.StartCaptureAsync
StartCaptureAsync.argtypes = (StartCaptureAsync_cb,)