LunaTranslator/cpp/winsharedutils/SimpleBrowser.cpp

292 lines
7.5 KiB
C++
Raw Normal View History

2024-11-21 21:50:52 +08:00
// SimpleBrowser.cpp --- simple Win32 browser
2024-01-22 12:56:15 +08:00
// 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
2024-04-02 15:36:52 +08:00
#include "MWebBrowser.hpp"
2024-01-22 12:56:15 +08:00
2024-01-22 14:33:11 +08:00
BOOL GetIEVersion(LPWSTR pszVersion, DWORD cchVersionMax)
{
pszVersion[0] = 0;
HKEY hKey = NULL;
RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Internet Explorer", 0,
2024-04-02 15:36:52 +08:00
KEY_READ, &hKey);
2024-01-22 14:33:11 +08:00
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;
}
2024-04-02 15:36:52 +08:00
static DWORD getemulation()
{
2024-01-22 14:33:11 +08:00
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;
}
2024-01-22 12:56:15 +08:00
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;
}
2024-11-21 21:50:52 +08:00
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()
2024-05-31 16:53:16 +08:00
{
return getemulation();
}
2024-11-21 21:50:52 +08:00
DECLARE_API void *html_new(HWND parent)
2024-04-02 15:36:52 +08:00
{
DoSetBrowserEmulation(getemulation());
2024-11-21 21:50:52 +08:00
auto s_pWebBrowser = MWebBrowserEx::Create(parent);
2024-01-22 12:56:15 +08:00
if (!s_pWebBrowser)
return NULL;
2024-04-02 15:36:52 +08:00
s_pWebBrowser->put_Silent(VARIANT_TRUE);
s_pWebBrowser->AllowInsecure(TRUE);
return s_pWebBrowser;
2024-01-22 12:56:15 +08:00
}
2024-11-21 21:50:52 +08:00
DECLARE_API void html_navigate(void *web, wchar_t *path)
2024-04-02 15:36:52 +08:00
{
if (!web)
return;
2024-11-21 21:50:52 +08:00
auto ww = static_cast<MWebBrowserEx *>(web);
2024-04-02 15:36:52 +08:00
ww->Navigate2(path);
2024-01-22 12:56:15 +08:00
}
2024-11-21 21:50:52 +08:00
DECLARE_API void html_resize(void *web, int x, int y, int w, int h)
2024-04-02 15:36:52 +08:00
{
if (!web)
return;
2024-11-21 21:50:52 +08:00
auto ww = static_cast<MWebBrowserEx *>(web);
2024-04-02 15:36:52 +08:00
RECT r;
r.left = x;
r.top = y;
r.right = x + w;
r.bottom = y + h;
ww->MoveWindow(r);
2024-01-22 12:56:15 +08:00
}
2024-11-21 21:50:52 +08:00
DECLARE_API void html_release(void *web)
2024-04-02 15:36:52 +08:00
{
if (!web)
return;
2024-11-21 21:50:52 +08:00
auto ww = static_cast<MWebBrowserEx *>(web);
2024-01-22 12:56:15 +08:00
ww->Destroy();
2024-04-02 15:36:52 +08:00
// ww->Release(); Destroy减少引用计数自动del
}
2024-11-21 21:50:52 +08:00
DECLARE_API const wchar_t *html_get_current_url(void *web)
{
if (!web)
2024-11-21 21:50:52 +08:00
return L"";
auto ww = static_cast<MWebBrowserEx *>(web);
wchar_t *_u;
ww->get_LocationURL(&_u);
2024-11-21 21:50:52 +08:00
return _u;
}
2024-05-18 17:53:33 +08:00
2024-11-21 21:50:52 +08:00
DECLARE_API void html_set_html(void *web, wchar_t *html)
2024-05-18 17:53:33 +08:00
{
if (!web)
return;
2024-11-21 21:50:52 +08:00
auto ww = static_cast<MWebBrowserEx *>(web);
2024-05-18 17:53:33 +08:00
ww->SetHtml(html);
}
2024-11-21 21:50:52 +08:00
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"";
}
2024-12-22 01:02:46 +08:00
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);
}