This commit is contained in:
恍兮惚兮 2024-12-29 15:35:27 +08:00
parent a4edf162fd
commit 905fe2b819
9 changed files with 124 additions and 241 deletions

View File

@ -1,5 +1,6 @@
#include "python.h" #include "python.h"
#include <dwrite.h> #include <dwrite.h>
#include <atlbase.h>
extern "C" __declspec(dllexport) const wchar_t *luna_internal_renpy_call_host(const wchar_t *text, int split) extern "C" __declspec(dllexport) const wchar_t *luna_internal_renpy_call_host(const wchar_t *text, int split)
{ {
return text; return text;
@ -139,23 +140,17 @@ namespace
_COM_Outptr_ IUnknown **factory); _COM_Outptr_ IUnknown **factory);
std::list<WCHAR *> get_fonts_path(LPCWSTR family_name, BOOL is_bold, BOOL is_italic, BYTE charset) std::list<WCHAR *> get_fonts_path(LPCWSTR family_name, BOOL is_bold, BOOL is_italic, BYTE charset)
{ {
std::list<WCHAR *> fonts_filename_list;
HRESULT hr; HRESULT hr;
IDWriteFactory *dwrite_factory; CComPtr<IDWriteFactory> dwrite_factory;
hr = fnDWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory)); hr = fnDWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(&dwrite_factory));
if (FAILED(hr)) if (FAILED(hr))
{ return {};
return fonts_filename_list;
}
IDWriteGdiInterop *gdi_interop; CComPtr<IDWriteGdiInterop> gdi_interop;
hr = dwrite_factory->GetGdiInterop(&gdi_interop); hr = dwrite_factory->GetGdiInterop(&gdi_interop);
if (FAILED(hr)) if (FAILED(hr))
{ return {};
dwrite_factory->Release();
return fonts_filename_list;
}
LOGFONT lf; LOGFONT lf;
memset(&lf, 0, sizeof(lf)); memset(&lf, 0, sizeof(lf));
@ -172,98 +167,57 @@ namespace
HDC hdc = CreateCompatibleDC(NULL); HDC hdc = CreateCompatibleDC(NULL);
HFONT hOldFont = SelectFont(hdc, hFont); HFONT hOldFont = SelectFont(hdc, hFont);
IDWriteFontFace *font_face; CComPtr<IDWriteFontFace> font_face;
hr = gdi_interop->CreateFontFaceFromHdc(hdc, &font_face); hr = gdi_interop->CreateFontFaceFromHdc(hdc, &font_face);
if (FAILED(hr)) if (FAILED(hr))
{ return {};
gdi_interop->Release();
dwrite_factory->Release();
return fonts_filename_list;
}
UINT file_count; UINT file_count;
hr = font_face->GetFiles(&file_count, NULL); hr = font_face->GetFiles(&file_count, NULL);
if (FAILED(hr)) if (FAILED(hr))
{ return {};
font_face->Release();
gdi_interop->Release();
dwrite_factory->Release();
return fonts_filename_list;
}
IDWriteFontFile **font_files = new IDWriteFontFile *[file_count]; auto font_files_1 = std::make_unique<IDWriteFontFile *[]>(file_count);
hr = font_face->GetFiles(&file_count, font_files); hr = font_face->GetFiles(&file_count, font_files_1.get());
if (FAILED(hr)) if (FAILED(hr))
{ return {};
font_face->Release(); auto font_files = std::make_unique<CComPtr<IDWriteFontFile>[]>(file_count);
gdi_interop->Release(); for (auto i = 0; i < file_count; i++)
dwrite_factory->Release(); font_files[i].Attach(font_files_1[i]);
return fonts_filename_list; std::list<WCHAR *> fonts_filename_list;
}
for (int i = 0; i < file_count; i++) for (int i = 0; i < file_count; i++)
{ {
LPCVOID font_file_reference_key; LPCVOID font_file_reference_key;
UINT font_file_reference_key_size; UINT font_file_reference_key_size;
hr = font_files[i]->GetReferenceKey(&font_file_reference_key, &font_file_reference_key_size); hr = font_files[i]->GetReferenceKey(&font_file_reference_key, &font_file_reference_key_size);
if (FAILED(hr)) if (FAILED(hr))
{
font_files[i]->Release();
continue; continue;
}
IDWriteFontFileLoader *loader; CComPtr<IDWriteFontFileLoader> loader;
hr = font_files[i]->GetLoader(&loader); hr = font_files[i]->GetLoader(&loader);
if (FAILED(hr)) if (FAILED(hr))
{
font_files[i]->Release();
continue; continue;
}
IDWriteLocalFontFileLoader *local_loader; CComPtr<IDWriteLocalFontFileLoader> local_loader;
hr = loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader), (void **)&local_loader); hr = loader.QueryInterface(&local_loader);
if (FAILED(hr)) if (FAILED(hr))
{
loader->Release();
font_files[i]->Release();
continue; continue;
}
UINT32 path_length; UINT32 path_length;
hr = local_loader->GetFilePathLengthFromKey(font_file_reference_key, font_file_reference_key_size, &path_length); hr = local_loader->GetFilePathLengthFromKey(font_file_reference_key, font_file_reference_key_size, &path_length);
if (FAILED(hr)) if (FAILED(hr))
{
local_loader->Release();
loader->Release();
font_files[i]->Release();
continue; continue;
}
WCHAR *path = new WCHAR[path_length + 1]; WCHAR *path = new WCHAR[path_length + 1];
hr = local_loader->GetFilePathFromKey(font_file_reference_key, font_file_reference_key_size, path, path_length + 1); hr = local_loader->GetFilePathFromKey(font_file_reference_key, font_file_reference_key_size, path, path_length + 1);
if (FAILED(hr)) if (FAILED(hr))
{
local_loader->Release();
loader->Release();
font_files[i]->Release();
continue; continue;
}
fonts_filename_list.push_back(path); fonts_filename_list.push_back(path);
local_loader->Release();
loader->Release();
font_files[i]->Release();
} }
font_face->Release();
gdi_interop->Release();
SelectObject(hdc, hOldFont); SelectObject(hdc, hOldFont);
ReleaseDC(NULL, hdc); ReleaseDC(NULL, hdc);
DeleteObject(hFont); DeleteObject(hFont);
dwrite_factory->Release();
return fonts_filename_list; return fonts_filename_list;
} }

View File

@ -1,9 +1,9 @@
std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *token, int voiceid, int rate, int volume) std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *token, int voiceid, int rate, int volume)
{ {
ISpVoice *pVoice = NULL;
if (FAILED(::CoInitialize(NULL))) if (FAILED(::CoInitialize(NULL)))
return {}; return {};
CComPtr<ISpVoice> pVoice = NULL;
std::optional<std::vector<byte>> ret = {}; std::optional<std::vector<byte>> ret = {};
do do
{ {
@ -13,7 +13,7 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
ret = {}; ret = {};
break; break;
} }
IEnumSpObjectTokens *pSpEnumTokens = NULL; CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL;
if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens))) if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens)))
{ {
ULONG ulTokensNumber = 0; ULONG ulTokensNumber = 0;
@ -60,9 +60,6 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
} }
pVoice->SetOutput(cpWavStream, TRUE); pVoice->SetOutput(cpWavStream, TRUE);
pVoice->Speak(Content.c_str(), SPF_IS_XML, NULL); pVoice->Speak(Content.c_str(), SPF_IS_XML, NULL);
pVoice->Release();
pSpEnumTokens->Release();
pVoice = NULL;
/*To verify that the data has been written correctly, uncomment this, you should hear the voice. /*To verify that the data has been written correctly, uncomment this, you should hear the voice.
cpVoice->SetOutput(NULL, FALSE); cpVoice->SetOutput(NULL, FALSE);
@ -74,7 +71,7 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
hr = cpWavStream->Seek(a, STREAM_SEEK_SET, NULL); hr = cpWavStream->Seek(a, STREAM_SEEK_SET, NULL);
// get the base istream from the ispstream // get the base istream from the ispstream
IStream *pIstream; CComPtr<IStream> pIstream;
cpWavStream->GetBaseStream(&pIstream); cpWavStream->GetBaseStream(&pIstream);
// calculate the size that is to be read // calculate the size that is to be read
@ -131,7 +128,6 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
cout << endl; cout << endl;
*/ */
ret = std::move(datas); ret = std::move(datas);
pIstream->Release();
} }
} while (0); } while (0);
@ -144,9 +140,9 @@ std::vector<std::wstring> _List(const wchar_t *token)
{ {
if (FAILED(::CoInitialize(NULL))) if (FAILED(::CoInitialize(NULL)))
return {}; return {};
ISpVoice *pSpVoice = NULL; CComPtr<ISpVoice> pSpVoice = NULL;
std::vector<std::wstring> ret; std::vector<std::wstring> ret;
IEnumSpObjectTokens *pSpEnumTokens = NULL; CComPtr<IEnumSpObjectTokens> pSpEnumTokens = NULL;
if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pSpVoice))) if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pSpVoice)))
{ {
return {}; return {};
@ -155,7 +151,7 @@ std::vector<std::wstring> _List(const wchar_t *token)
{ {
ULONG ulTokensNumber = 0; ULONG ulTokensNumber = 0;
pSpEnumTokens->GetCount(&ulTokensNumber); pSpEnumTokens->GetCount(&ulTokensNumber);
ISpObjectToken *m_pISpObjectToken; CComPtr<ISpObjectToken> m_pISpObjectToken;
for (ULONG i = 0; i < ulTokensNumber; i++) for (ULONG i = 0; i < ulTokensNumber; i++)
{ {
pSpEnumTokens->Item(i, &m_pISpObjectToken); pSpEnumTokens->Item(i, &m_pISpObjectToken);
@ -168,15 +164,10 @@ std::vector<std::wstring> _List(const wchar_t *token)
ret.emplace_back(pszVoiceName); ret.emplace_back(pszVoiceName);
CoTaskMemFree(pszVoiceName); CoTaskMemFree(pszVoiceName);
} }
CoTaskMemFree(pszVoiceId); CoTaskMemFree(pszVoiceId);
} }
} }
m_pISpObjectToken->Release();
pSpEnumTokens->Release();
} }
pSpVoice->Release();
::CoUninitialize(); ::CoUninitialize();
return ret; return ret;
} }

View File

@ -133,14 +133,12 @@ MWebBrowser::MWebBrowser(HWND hwndParent) : m_nRefCount(0),
m_hr = CreateBrowser(hwndParent); m_hr = CreateBrowser(hwndParent);
htmlSource = L""; htmlSource = L"";
IConnectionPointContainer *container = nullptr; CComPtr<IConnectionPointContainer> container = nullptr;
m_web_browser2->QueryInterface(IID_IConnectionPointContainer, (void **)&container); m_web_browser2.QueryInterface(&container);
container->FindConnectionPoint(__uuidof(DWebBrowserEvents2), &callback); container->FindConnectionPoint(__uuidof(DWebBrowserEvents2), &callback);
IUnknown *punk = nullptr; CComPtr<IUnknown> punk = nullptr;
QueryInterface(IID_IUnknown, (void **)&punk); QueryInterface(IID_IUnknown, (void **)&punk);
callback->Advise(punk, &eventCookie); callback->Advise(punk, &eventCookie);
punk->Release();
container->Release();
jsobj = new JSObject(); jsobj = new JSObject();
jsobj->AddRef(); jsobj->AddRef();
} }
@ -152,26 +150,6 @@ BOOL MWebBrowser::IsCreated() const
MWebBrowser::~MWebBrowser() MWebBrowser::~MWebBrowser()
{ {
if (m_pDocHostUIHandler)
{
m_pDocHostUIHandler->Release();
m_pDocHostUIHandler = NULL;
}
if (m_ole_object)
{
m_ole_object->Release();
m_ole_object = NULL;
}
if (m_ole_inplace_object)
{
m_ole_inplace_object->Release();
m_ole_inplace_object = NULL;
}
if (m_web_browser2)
{
m_web_browser2->Release();
m_web_browser2 = NULL;
}
if (jsobj) if (jsobj)
{ {
jsobj->Release(); jsobj->Release();
@ -242,12 +220,7 @@ HRESULT MWebBrowser::CreateBrowser(HWND hwndParent)
return hr; return hr;
} }
if (m_pDocHostUIHandler) m_ole_object.QueryInterface(&m_pDocHostUIHandler);
{
m_pDocHostUIHandler->Release();
m_pDocHostUIHandler = NULL;
}
m_ole_object->QueryInterface(&m_pDocHostUIHandler);
hr = m_ole_object->SetClientSite(this); hr = m_ole_object->SetClientSite(this);
if (FAILED(hr)) if (FAILED(hr))
@ -273,7 +246,7 @@ HRESULT MWebBrowser::CreateBrowser(HWND hwndParent)
return hr; return hr;
} }
hr = m_ole_object->QueryInterface(&m_web_browser2); hr = m_ole_object.QueryInterface(&m_web_browser2);
if (FAILED(hr)) if (FAILED(hr))
{ {
assert(0); assert(0);
@ -361,19 +334,17 @@ void MWebBrowser::StopDownload()
if (!m_web_browser2) if (!m_web_browser2)
return; return;
IDispatch *pDisp; CComPtr<IDispatch> pDisp;
m_web_browser2->get_Document(&pDisp); m_web_browser2->get_Document(&pDisp);
if (pDisp) if (pDisp)
{ {
IOleCommandTarget *pCmdTarget = NULL; CComPtr<IOleCommandTarget> pCmdTarget = NULL;
pDisp->QueryInterface(&pCmdTarget); pDisp.QueryInterface(&pCmdTarget);
if (pCmdTarget) if (pCmdTarget)
{ {
OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER; OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER;
pCmdTarget->Exec(NULL, OLECMDID_STOPDOWNLOAD, option, NULL, NULL); pCmdTarget->Exec(NULL, OLECMDID_STOPDOWNLOAD, option, NULL, NULL);
pCmdTarget->Release();
} }
pDisp->Release();
} }
} }
@ -430,12 +401,12 @@ void MWebBrowser::Print(BOOL bBang)
if (!m_web_browser2) if (!m_web_browser2)
return; return;
IDispatch *pDisp; CComPtr<IDispatch> pDisp;
m_web_browser2->get_Document(&pDisp); m_web_browser2->get_Document(&pDisp);
if (pDisp) if (pDisp)
{ {
IOleCommandTarget *pCmdTarget = NULL; CComPtr<IOleCommandTarget> pCmdTarget = NULL;
pDisp->QueryInterface(&pCmdTarget); pDisp.QueryInterface(&pCmdTarget);
if (pCmdTarget) if (pCmdTarget)
{ {
OLECMDEXECOPT option; OLECMDEXECOPT option;
@ -444,9 +415,7 @@ void MWebBrowser::Print(BOOL bBang)
else else
option = OLECMDEXECOPT_PROMPTUSER; option = OLECMDEXECOPT_PROMPTUSER;
pCmdTarget->Exec(NULL, OLECMDID_PRINT, option, NULL, NULL); pCmdTarget->Exec(NULL, OLECMDID_PRINT, option, NULL, NULL);
pCmdTarget->Release();
} }
pDisp->Release();
} }
} }
@ -455,19 +424,17 @@ void MWebBrowser::PrintPreview()
if (!m_web_browser2) if (!m_web_browser2)
return; return;
IDispatch *pDisp; CComPtr<IDispatch> pDisp;
m_web_browser2->get_Document(&pDisp); m_web_browser2->get_Document(&pDisp);
if (pDisp) if (pDisp)
{ {
IOleCommandTarget *pCmdTarget = NULL; CComPtr<IOleCommandTarget> pCmdTarget = NULL;
pDisp->QueryInterface(&pCmdTarget); pDisp.QueryInterface(&pCmdTarget);
if (pCmdTarget) if (pCmdTarget)
{ {
OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER; OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER;
pCmdTarget->Exec(NULL, OLECMDID_PRINTPREVIEW, option, NULL, NULL); pCmdTarget->Exec(NULL, OLECMDID_PRINTPREVIEW, option, NULL, NULL);
pCmdTarget->Release();
} }
pDisp->Release();
} }
} }
@ -476,19 +443,17 @@ void MWebBrowser::PageSetup()
if (!m_web_browser2) if (!m_web_browser2)
return; return;
IDispatch *pDisp; CComPtr<IDispatch> pDisp;
m_web_browser2->get_Document(&pDisp); m_web_browser2->get_Document(&pDisp);
if (pDisp) if (pDisp)
{ {
IOleCommandTarget *pCmdTarget = NULL; CComPtr<IOleCommandTarget> pCmdTarget;
pDisp->QueryInterface(&pCmdTarget); pDisp.QueryInterface(&pCmdTarget);
if (pCmdTarget) if (pCmdTarget)
{ {
OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER; OLECMDEXECOPT option = OLECMDEXECOPT_DONTPROMPTUSER;
pCmdTarget->Exec(NULL, OLECMDID_PAGESETUP, option, NULL, NULL); pCmdTarget->Exec(NULL, OLECMDID_PAGESETUP, option, NULL, NULL);
pCmdTarget->Release();
} }
pDisp->Release();
} }
} }
@ -497,12 +462,11 @@ BOOL MWebBrowser::TranslateAccelerator(LPMSG pMsg)
if (!m_web_browser2) if (!m_web_browser2)
return FALSE; return FALSE;
IOleInPlaceActiveObject *pOIPAO = NULL; CComPtr<IOleInPlaceActiveObject> pOIPAO = NULL;
HRESULT hr = m_web_browser2->QueryInterface(&pOIPAO); HRESULT hr = m_web_browser2.QueryInterface(&pOIPAO);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = pOIPAO->TranslateAccelerator(pMsg); hr = pOIPAO->TranslateAccelerator(pMsg);
pOIPAO->Release();
return hr == S_OK; return hr == S_OK;
} }
return FALSE; return FALSE;
@ -519,27 +483,6 @@ HRESULT MWebBrowser::get_LocationURL(BSTR *bstrURL) const
return m_web_browser2->get_LocationURL(bstrURL); return m_web_browser2->get_LocationURL(bstrURL);
} }
HRESULT MWebBrowser::get_mimeType(BSTR *bstrMIME) const
{
if (!m_web_browser2)
{
*bstrMIME = NULL;
return E_FAIL;
}
HRESULT hr = E_FAIL;
IDispatch *pDisp;
m_web_browser2->get_Document(&pDisp);
if (pDisp)
{
IHTMLDocument2 *pDocument = static_cast<IHTMLDocument2 *>(pDisp);
hr = pDocument->get_mimeType(bstrMIME);
pDisp->Release();
}
return hr;
}
BOOL MWebBrowser::is_busy() const BOOL MWebBrowser::is_busy() const
{ {
if (!m_web_browser2) if (!m_web_browser2)
@ -704,7 +647,7 @@ STDMETHODIMP MWebBrowser::CanInPlaceActivate()
STDMETHODIMP MWebBrowser::OnInPlaceActivate() STDMETHODIMP MWebBrowser::OnInPlaceActivate()
{ {
::OleLockRunning(m_ole_object, TRUE, FALSE); ::OleLockRunning(m_ole_object, TRUE, FALSE);
m_ole_object->QueryInterface(&m_ole_inplace_object); m_ole_object.QueryInterface(&m_ole_inplace_object);
m_ole_inplace_object->SetObjectRects(&m_rc, &m_rc); m_ole_inplace_object->SetObjectRects(&m_rc, &m_rc);
return S_OK; return S_OK;
} }
@ -957,24 +900,7 @@ STDMETHODIMP MWebBrowser::GetWindow(REFGUID rguidReason, HWND *phwnd)
STDMETHODIMP MWebBrowser::OnSecurityProblem(DWORD dwProblem) STDMETHODIMP MWebBrowser::OnSecurityProblem(DWORD dwProblem)
{ {
printf("MWebBrowser::OnSecurityProblem\n"); return S_OK;
BSTR url = NULL;
get_LocationURL(&url);
if (url)
{
SysFreeString(url);
}
{
return S_OK;
}
{
return S_OK;
}
return E_ABORT;
} }
// IDocHostUIHandler interface // IDocHostUIHandler interface
@ -1105,45 +1031,29 @@ HRESULT MWebBrowser::GetTypeInfoCount(UINT *pctinfo) { return E_FAIL; }
HRESULT MWebBrowser::GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_FAIL; } HRESULT MWebBrowser::GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_FAIL; }
HRESULT MWebBrowser::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_FAIL; } HRESULT MWebBrowser::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_FAIL; }
void AddCustomObject(IHTMLDocument2 *doc, IDispatch *custObj, std::string name) void AddCustomObject(IHTMLDocument2 *doc, IDispatch *custObj, std::wstring name)
{ {
CComPtr<IHTMLDocument2> _doc = doc;
if (doc == NULL) if (doc == NULL)
{
return; return;
}
IHTMLWindow2 *win = NULL; CComPtr<IHTMLWindow2> win = NULL;
doc->get_parentWindow(&win); _doc->get_parentWindow(&win);
doc->Release();
if (win == NULL) if (!win)
{
return; return;
}
IDispatchEx *winEx; CComPtr<IDispatchEx> winEx;
win->QueryInterface(&winEx); HRESULT hr = win.QueryInterface(&winEx);
win->Release();
if (winEx == NULL) if (FAILED(hr) || !winEx)
{
return; return;
}
int lenW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name.c_str(), -1, NULL, 0);
BSTR objName = SysAllocStringLen(0, lenW);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name.c_str(), -1, objName, lenW);
DISPID dispid; DISPID dispid;
HRESULT hr = winEx->GetDispID(objName, fdexNameEnsure, &dispid); hr = winEx->GetDispID(name.data(), fdexNameEnsure, &dispid);
SysFreeString(objName);
if (FAILED(hr)) if (FAILED(hr))
{
return; return;
}
DISPID namedArgs[] = {DISPID_PROPERTYPUT}; DISPID namedArgs[] = {DISPID_PROPERTYPUT};
DISPPARAMS params; DISPPARAMS params;
@ -1155,12 +1065,9 @@ void AddCustomObject(IHTMLDocument2 *doc, IDispatch *custObj, std::string name)
params.cNamedArgs = 1; params.cNamedArgs = 1;
hr = winEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL); hr = winEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
winEx->Release();
if (FAILED(hr)) if (FAILED(hr))
{
return; return;
}
} }
HRESULT MWebBrowser::Invoke(DISPID dispIdMember, REFIID, LCID, WORD, HRESULT MWebBrowser::Invoke(DISPID dispIdMember, REFIID, LCID, WORD,
DISPPARAMS *pDispParams, VARIANT *pVarResult, DISPPARAMS *pDispParams, VARIANT *pVarResult,
@ -1169,7 +1076,7 @@ HRESULT MWebBrowser::Invoke(DISPID dispIdMember, REFIID, LCID, WORD,
if (dispIdMember == DISPID_DOCUMENTCOMPLETE) if (dispIdMember == DISPID_DOCUMENTCOMPLETE)
return OnCompleted(pDispParams); return OnCompleted(pDispParams);
else if (dispIdMember == DISPID_NAVIGATECOMPLETE2) else if (dispIdMember == DISPID_NAVIGATECOMPLETE2)
return AddCustomObject(GetIHTMLDocument2(), jsobj, "LUNAJSObject"), S_OK; return AddCustomObject(GetIHTMLDocument2(), jsobj, L"LUNAJSObject"), S_OK;
else else
return S_OK; return S_OK;
} }
@ -1177,19 +1084,19 @@ HRESULT MWebBrowser::OnCompleted(DISPPARAMS *args)
{ {
HRESULT hr; HRESULT hr;
IDispatch *pDispatch = 0; CComPtr<IDispatch> pDispatch;
IHTMLDocument2 *pHtmlDoc2 = 0; CComPtr<IHTMLDocument2> pHtmlDoc2 = 0;
IPersistStreamInit *pPSI = 0; CComPtr<IPersistStreamInit> pPSI = 0;
IStream *pStream = 0; CComPtr<IStream> pStream = 0;
HGLOBAL hHTMLContent; HGLOBAL hHTMLContent;
if (htmlSource.empty()) if (htmlSource.empty())
return S_OK; return S_OK;
hr = m_web_browser2->get_Document(&pDispatch); hr = m_web_browser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) if (SUCCEEDED(hr) && pDispatch)
hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2); hr = pDispatch.QueryInterface(&pHtmlDoc2);
if (SUCCEEDED(hr) && pHtmlDoc2) if (SUCCEEDED(hr) && pHtmlDoc2)
hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI); hr = pHtmlDoc2.QueryInterface(&pPSI);
// allocate global memory to copy the HTML content to // allocate global memory to copy the HTML content to
hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, (htmlSource.size() + 1) * sizeof(TCHAR)); hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, (htmlSource.size() + 1) * sizeof(TCHAR));
@ -1208,14 +1115,6 @@ HRESULT MWebBrowser::OnCompleted(DISPPARAMS *args)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
hr = pPSI->Load(pStream); hr = pPSI->Load(pStream);
} }
if (pStream)
pStream->Release();
if (pPSI)
pPSI->Release();
if (pHtmlDoc2)
pHtmlDoc2->Release();
if (pDispatch)
pDispatch->Release();
htmlSource = L""; htmlSource = L"";
return S_OK; return S_OK;
} }

View File

@ -84,7 +84,6 @@ public:
HRESULT get_Application(IDispatch **ppApplication) const; HRESULT get_Application(IDispatch **ppApplication) const;
HRESULT get_LocationURL(BSTR *bstrURL) const; HRESULT get_LocationURL(BSTR *bstrURL) const;
HRESULT get_mimeType(BSTR *bstrMIME) const;
HRESULT put_Silent(VARIANT_BOOL bSilent); HRESULT put_Silent(VARIANT_BOOL bSilent);
BOOL is_busy() const; BOOL is_busy() const;
HRESULT ZoomUp(); HRESULT ZoomUp();
@ -241,10 +240,10 @@ protected:
HWND m_hwndParent; HWND m_hwndParent;
HWND m_hwndCtrl; HWND m_hwndCtrl;
HWND m_hwndIEServer; HWND m_hwndIEServer;
IWebBrowser2 *m_web_browser2; CComPtr<IWebBrowser2> m_web_browser2;
IOleObject *m_ole_object; CComPtr<IOleObject> m_ole_object;
IOleInPlaceObject *m_ole_inplace_object; CComPtr<IOleInPlaceObject> m_ole_inplace_object;
IDocHostUIHandler *m_pDocHostUIHandler; CComPtr<IDocHostUIHandler> m_pDocHostUIHandler;
RECT m_rc; RECT m_rc;
HRESULT m_hr; HRESULT m_hr;
BOOL m_bAllowInsecure; BOOL m_bAllowInsecure;

View File

@ -245,16 +245,15 @@ DECLARE_API void html_add_menu(void *web, int index, int command, const wchar_t
} }
BSTR GetSelectedText(IHTMLDocument2 *pHTMLDoc2) BSTR GetSelectedText(IHTMLDocument2 *pHTMLDoc2)
{ {
IHTMLSelectionObject *pSelectionObj = nullptr; CComPtr<IHTMLSelectionObject> pSelectionObj = nullptr;
HRESULT hr = pHTMLDoc2->get_selection(&pSelectionObj); HRESULT hr = pHTMLDoc2->get_selection(&pSelectionObj);
if (FAILED(hr) || pSelectionObj == nullptr) if (FAILED(hr) || pSelectionObj == nullptr)
{ {
return nullptr; return nullptr;
} }
IHTMLTxtRange *pTxtRange = nullptr; CComPtr<IHTMLTxtRange> pTxtRange = nullptr;
hr = pSelectionObj->createRange((IDispatch **)&pTxtRange); hr = pSelectionObj->createRange((IDispatch **)&pTxtRange);
pSelectionObj->Release();
if (FAILED(hr) || pTxtRange == nullptr) if (FAILED(hr) || pTxtRange == nullptr)
{ {
return nullptr; return nullptr;
@ -262,7 +261,6 @@ BSTR GetSelectedText(IHTMLDocument2 *pHTMLDoc2)
BSTR selectedText = nullptr; BSTR selectedText = nullptr;
hr = pTxtRange->get_text(&selectedText); hr = pTxtRange->get_text(&selectedText);
pTxtRange->Release();
return selectedText; return selectedText;
} }
@ -272,10 +270,9 @@ DECLARE_API const wchar_t *html_get_select_text(void *web)
return L""; return L"";
auto ww = static_cast<MWebBrowserEx *>(web); auto ww = static_cast<MWebBrowserEx *>(web);
if (IHTMLDocument2 *pDocument = ww->GetIHTMLDocument2()) if (CComPtr<IHTMLDocument2> pDocument = ww->GetIHTMLDocument2())
{ {
auto text = GetSelectedText(pDocument); auto text = GetSelectedText(pDocument);
pDocument->Release();
// 不需要freefree会崩溃 // 不需要freefree会崩溃
return text; return text;
} }
@ -297,3 +294,49 @@ DECLARE_API HWND html_get_ie(void *web)
auto ww = static_cast<MWebBrowserEx *>(web); auto ww = static_cast<MWebBrowserEx *>(web);
return ww->GetIEServerWindow(); return ww->GetIEServerWindow();
} }
DECLARE_API void html_eval(void *web, const wchar_t *js)
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
CComPtr<IHTMLDocument2> pDocument = ww->GetIHTMLDocument2();
if (!pDocument)
return;
CComPtr<IDispatch> scriptDispatch;
if (FAILED(pDocument->get_Script(&scriptDispatch)))
return;
DISPID dispid;
BSTR evalStr = SysAllocString(L"eval");
if (scriptDispatch->GetIDsOfNames(IID_NULL, &evalStr, 1,
LOCALE_SYSTEM_DEFAULT, &dispid) != S_OK)
{
SysFreeString(evalStr);
return;
}
SysFreeString(evalStr);
DISPPARAMS params;
VARIANT arg;
VARIANT result;
EXCEPINFO excepInfo;
UINT nArgErr = (UINT)-1;
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgvarg = &arg;
arg.vt = VT_BSTR;
static const wchar_t *prologue = L"(function(){";
static const wchar_t *epilogue = L";})();";
int n = wcslen(prologue) + wcslen(epilogue) + wcslen(js) + 1;
auto eval = std::make_unique<wchar_t[]>(n);
_snwprintf(eval.get(), n, L"%s%s%s", prologue, js, epilogue);
arg.bstrVal = SysAllocString(eval.get());
if (scriptDispatch->Invoke(
dispid, IID_NULL, 0, DISPATCH_METHOD,
&params, &result, &excepInfo, &nArgErr) != S_OK)
{
SysFreeString(arg.bstrVal);
return;
}
SysFreeString(arg.bstrVal);
}

View File

@ -201,14 +201,12 @@ DECLARE_API void GetSelectedText(void (*cb)(const wchar_t *))
} }
// 提取文本 // 提取文本
BSTR text; wil::unique_bstr text;
if (FAILED(range->GetText(-1, &text)) || !text) if (FAILED(range->GetText(-1, &text)) || !text)
{ {
throw std::runtime_error("无法提取选定的文本."); throw std::runtime_error("无法提取选定的文本.");
} }
std::wstring selectedText(text, SysStringLen(text)); cb(text.get());
SysFreeString(text);
cb(selectedText.c_str());
} }
catch (std::exception &e) catch (std::exception &e)
{ {

View File

@ -6,14 +6,13 @@ DECLARE_API void GetLnkTargetPath(wchar_t *lnkFilePath, wchar_t *path, wchar_t *
wcscpy(iconpath, L""); wcscpy(iconpath, L"");
CoInitialize(NULL); CoInitialize(NULL);
IShellLink *shellLink; CComPtr<IShellLink> shellLink;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&shellLink); HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&shellLink);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
IPersistFile *persistFile; CComPtr<IPersistFile> persistFile;
hr = shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile); auto hr = shellLink.QueryInterface(&persistFile);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
WCHAR wsz[MAX_PATH]; WCHAR wsz[MAX_PATH];
@ -44,11 +43,7 @@ DECLARE_API void GetLnkTargetPath(wchar_t *lnkFilePath, wchar_t *path, wchar_t *
wcscpy(path, L""); wcscpy(path, L"");
} }
} }
persistFile->Release();
} }
shellLink->Release();
} }
CoUninitialize(); CoUninitialize();

View File

@ -1399,6 +1399,9 @@ class QWebWrap(abstractwebview):
class mshtmlWidget(abstractwebview): class mshtmlWidget(abstractwebview):
CommandBase = 10086 CommandBase = 10086
def eval(self, js):
winsharedutils.html_eval(self.browser, js)
def bindhelper(self, func, ppwc, argc): def bindhelper(self, func, ppwc, argc):
argv = [] argv = []
for i in range(argc): for i in range(argc):

View File

@ -142,7 +142,8 @@ html_bind_function.argtypes = c_void_p, c_wchar_p, html_bind_function_FT
html_get_ie = utilsdll.html_get_ie html_get_ie = utilsdll.html_get_ie
html_get_ie.argtypes = (c_void_p,) html_get_ie.argtypes = (c_void_p,)
html_get_ie.restype = HWND html_get_ie.restype = HWND
html_eval = utilsdll.html_eval
html_eval.argtypes = c_void_p, c_wchar_p
_GetLnkTargetPath = utilsdll.GetLnkTargetPath _GetLnkTargetPath = utilsdll.GetLnkTargetPath
_GetLnkTargetPath.argtypes = c_wchar_p, c_wchar_p, c_wchar_p, c_wchar_p _GetLnkTargetPath.argtypes = c_wchar_p, c_wchar_p, c_wchar_p, c_wchar_p