LunaTranslator/cpp/winsharedutils/SimpleBrowser.cpp
恍兮惚兮 f4f337474c .
2024-12-22 01:04:42 +08:00

292 lines
7.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SimpleBrowser.cpp --- simple Win32 browser
// Copyright (C) 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
// This file is public domain software.
#define _CRT_SECURE_NO_WARNINGS
// SimpleBrowser.cpp --- simple Win32 browser
// Copyright (C) 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
// This file is public domain software.
#define _CRT_SECURE_NO_WARNINGS
#include "MWebBrowser.hpp"
BOOL GetIEVersion(LPWSTR pszVersion, DWORD cchVersionMax)
{
pszVersion[0] = 0;
HKEY hKey = NULL;
RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Internet Explorer", 0,
KEY_READ, &hKey);
if (hKey)
{
DWORD cb = cchVersionMax * sizeof(WCHAR);
LONG ret = RegQueryValueExW(hKey, L"svcVersion", NULL, NULL, (LPBYTE)pszVersion, &cb);
if (ret != ERROR_SUCCESS)
{
ret = RegQueryValueExW(hKey, L"Version", NULL, NULL, (LPBYTE)pszVersion, &cb);
}
RegCloseKey(hKey);
return ret == ERROR_SUCCESS;
}
return FALSE;
}
static DWORD getemulation()
{
DWORD m_emulation = 0;
WCHAR szVersion[32];
if (GetIEVersion(szVersion, ARRAYSIZE(szVersion)))
{
if (szVersion[1] == L'.')
{
switch (szVersion[0])
{
case '7':
m_emulation = 7000;
break;
case '8':
m_emulation = 8888;
break;
case '9':
m_emulation = 9999;
break;
}
}
else if (szVersion[2] == L'.')
{
if (szVersion[0] == L'1' && szVersion[1] == L'0')
{
m_emulation = 10001;
}
if (szVersion[0] == L'1' && szVersion[1] == L'1')
{
m_emulation = 11001;
}
}
}
return m_emulation;
}
BOOL DoSetBrowserEmulation(DWORD dwValue)
{
static const TCHAR s_szFeatureControl[] =
TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl");
TCHAR szPath[MAX_PATH], *pchFileName;
GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath));
pchFileName = PathFindFileName(szPath);
BOOL bOK = FALSE;
HKEY hkeyControl = NULL;
RegOpenKeyEx(HKEY_CURRENT_USER, s_szFeatureControl, 0, KEY_ALL_ACCESS, &hkeyControl);
if (hkeyControl)
{
HKEY hkeyEmulation = NULL;
RegCreateKeyEx(hkeyControl, TEXT("FEATURE_BROWSER_EMULATION"), 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &hkeyEmulation, NULL);
if (hkeyEmulation)
{
if (dwValue)
{
DWORD value = dwValue, size = sizeof(value);
LONG result = RegSetValueEx(hkeyEmulation, pchFileName, 0,
REG_DWORD, (LPBYTE)&value, size);
bOK = (result == ERROR_SUCCESS);
}
else
{
RegDeleteValue(hkeyEmulation, pchFileName);
bOK = TRUE;
}
RegCloseKey(hkeyEmulation);
}
RegCloseKey(hkeyControl);
}
return bOK;
}
class MWebBrowserEx : public MWebBrowser
{
HWND hwndParent;
public:
std::vector<std::tuple<std::optional<std::wstring>, int>> menuitems;
static MWebBrowserEx *Create(HWND _hwndParent);
// IDocHostUIHandler interface
STDMETHODIMP ShowContextMenu(
DWORD dwID,
POINT *ppt,
IUnknown *pcmdtReserved,
IDispatch *pdispReserved);
protected:
MWebBrowserEx(HWND _hwndParent);
};
MWebBrowserEx::MWebBrowserEx(HWND _hwndParent) : MWebBrowser(_hwndParent), hwndParent(_hwndParent)
{
}
MWebBrowserEx *MWebBrowserEx::Create(HWND _hwndParent)
{
MWebBrowserEx *pBrowser = new MWebBrowserEx(_hwndParent);
if (!pBrowser->IsCreated())
{
pBrowser->Release();
pBrowser = NULL;
}
return pBrowser;
}
STDMETHODIMP MWebBrowserEx::ShowContextMenu(
DWORD dwID,
POINT *ppt,
IUnknown *pcmdtReserved,
IDispatch *pdispReserved)
{
HMENU hMenu = NULL;
switch (dwID)
{
case CONTEXT_MENU_TEXTSELECT:
{
if (!menuitems.size())
return S_FALSE;
HMENU hMenu = CreatePopupMenu();
int idx = 0;
for (auto &item : menuitems)
{
if (std::get<0>(item))
{
AppendMenu(hMenu, MF_STRING, std::get<1>(item), std::get<0>(item).value().c_str());
}
else
AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr);
idx += 1;
}
TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, ppt->x, ppt->y, 0, hwndParent, nullptr);
DestroyMenu(hMenu);
return S_OK;
}
default:
return S_FALSE;
}
}
DECLARE_API DWORD html_version()
{
return getemulation();
}
DECLARE_API void *html_new(HWND parent)
{
DoSetBrowserEmulation(getemulation());
auto s_pWebBrowser = MWebBrowserEx::Create(parent);
if (!s_pWebBrowser)
return NULL;
s_pWebBrowser->put_Silent(VARIANT_TRUE);
s_pWebBrowser->AllowInsecure(TRUE);
return s_pWebBrowser;
}
DECLARE_API void html_navigate(void *web, wchar_t *path)
{
if (!web)
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)
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
RECT r;
r.left = x;
r.top = y;
r.right = x + w;
r.bottom = y + h;
ww->MoveWindow(r);
}
DECLARE_API void html_release(void *web)
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->Destroy();
// ww->Release(); Destroy减少引用计数自动del
}
DECLARE_API const wchar_t *html_get_current_url(void *web)
{
if (!web)
return L"";
auto ww = static_cast<MWebBrowserEx *>(web);
wchar_t *_u;
ww->get_LocationURL(&_u);
return _u;
}
DECLARE_API void html_set_html(void *web, wchar_t *html)
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->SetHtml(html);
}
DECLARE_API void html_add_menu(void *web, int index, int command, const wchar_t *label)
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
std::optional<std::wstring> _label;
if (label)
_label = label;
auto ptr = ww->menuitems.begin() + index;
ww->menuitems.insert(ptr, {_label, command});
}
BSTR GetSelectedText(IHTMLDocument2 *pHTMLDoc2)
{
IHTMLSelectionObject *pSelectionObj = nullptr;
HRESULT hr = pHTMLDoc2->get_selection(&pSelectionObj);
if (FAILED(hr) || pSelectionObj == nullptr)
{
return nullptr;
}
IHTMLTxtRange *pTxtRange = nullptr;
hr = pSelectionObj->createRange((IDispatch **)&pTxtRange);
pSelectionObj->Release();
if (FAILED(hr) || pTxtRange == nullptr)
{
return nullptr;
}
BSTR selectedText = nullptr;
hr = pTxtRange->get_text(&selectedText);
pTxtRange->Release();
return selectedText;
}
DECLARE_API const wchar_t *html_get_select_text(void *web)
{
if (!web)
return L"";
auto ww = static_cast<MWebBrowserEx *>(web);
if (IHTMLDocument2 *pDocument = ww->GetIHTMLDocument2())
{
auto text = GetSelectedText(pDocument);
pDocument->Release();
// 不需要freefree会崩溃
return text;
}
return L"";
}
DECLARE_API void html_bind_function(void *web, const wchar_t *name, void (*function)(wchar_t **, int))
{
if (!web)
return;
auto ww = static_cast<MWebBrowserEx *>(web);
ww->jsobj->bindfunction(name, function);
}