2024-11-21 16:20:54 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-05 02:27:47 +08:00
|
|
|
|
|
|
|
|
|
#include <wrl.h>
|
|
|
|
|
#include <wil/com.h>
|
|
|
|
|
#include <wil/result.h>
|
|
|
|
|
#include <wil/com.h>
|
|
|
|
|
#include <wrl/implements.h>
|
|
|
|
|
using namespace Microsoft::WRL;
|
|
|
|
|
#include <WebView2.h>
|
2024-06-17 17:01:01 +08:00
|
|
|
|
#define CHECK_FAILURE(x) \
|
|
|
|
|
if (FAILED((x))) \
|
|
|
|
|
return x;
|
2024-06-05 02:27:47 +08:00
|
|
|
|
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#endif
|
2024-11-12 02:57:11 +08:00
|
|
|
|
DECLARE_API void set_transparent_background(void *m_host)
|
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-18 17:44:02 +08:00
|
|
|
|
COREWEBVIEW2_COLOR color;
|
2024-11-12 02:57:11 +08:00
|
|
|
|
ZeroMemory(&color, sizeof(color));
|
2024-06-18 17:44:02 +08:00
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
|
|
|
|
|
wil::com_ptr<ICoreWebView2Controller2> coreWebView2 =
|
2024-11-12 02:57:11 +08:00
|
|
|
|
m_controller.try_query<ICoreWebView2Controller2>();
|
|
|
|
|
if (coreWebView2)
|
|
|
|
|
{
|
2024-06-18 17:44:02 +08:00
|
|
|
|
coreWebView2->put_DefaultBackgroundColor(color);
|
|
|
|
|
}
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#endif
|
2024-06-18 17:44:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-15 03:34:15 +08:00
|
|
|
|
#ifndef WINXP
|
2024-11-12 02:57:11 +08:00
|
|
|
|
DECLARE_API void put_PreferredColorScheme(void *m_host, COREWEBVIEW2_PREFERRED_COLOR_SCHEME scheme)
|
2024-06-05 02:27:47 +08:00
|
|
|
|
{
|
2024-06-17 17:01:01 +08:00
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
|
|
|
|
|
wil::com_ptr<ICoreWebView2> coreWebView2;
|
2024-11-12 02:57:11 +08:00
|
|
|
|
[&]()
|
2024-06-17 17:01:01 +08:00
|
|
|
|
{
|
2024-11-12 02:57:11 +08:00
|
|
|
|
CHECK_FAILURE(m_controller->get_CoreWebView2(&coreWebView2));
|
|
|
|
|
auto webView2_13 = coreWebView2.try_query<ICoreWebView2_13>();
|
|
|
|
|
if (webView2_13)
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2Profile> profile;
|
|
|
|
|
CHECK_FAILURE(webView2_13->get_Profile(&profile));
|
|
|
|
|
CHECK_FAILURE(profile->put_PreferredColorScheme(scheme));
|
|
|
|
|
}
|
|
|
|
|
return S_OK;
|
|
|
|
|
}();
|
2024-06-17 17:01:01 +08:00
|
|
|
|
}
|
2024-11-15 03:34:15 +08:00
|
|
|
|
#else
|
|
|
|
|
DECLARE_API void put_PreferredColorScheme(void *m_host, int scheme)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API void *add_ZoomFactorChanged(void *m_host, void (*signal)(double))
|
2024-06-17 17:01:01 +08:00
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-05 02:27:47 +08:00
|
|
|
|
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(
|
|
|
|
|
Callback<ICoreWebView2ZoomFactorChangedEventHandler>(
|
|
|
|
|
[signal](ICoreWebView2Controller *sender, IUnknown *args) -> HRESULT
|
|
|
|
|
{
|
|
|
|
|
double zoomFactor;
|
|
|
|
|
sender->get_ZoomFactor(&zoomFactor);
|
|
|
|
|
signal(zoomFactor);
|
|
|
|
|
// std::wstring message = L"WebView2APISample (Zoom: " +
|
|
|
|
|
// std::to_wstring(int(zoomFactor * 100)) + L"%)";
|
|
|
|
|
// SetWindowText(m_appWindow->GetMainWindow(), message.c_str());
|
|
|
|
|
return S_OK;
|
|
|
|
|
})
|
|
|
|
|
.Get(),
|
|
|
|
|
m_zoomFactorChangedToken);
|
|
|
|
|
return m_zoomFactorChangedToken;
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
2024-06-05 02:27:47 +08:00
|
|
|
|
}
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API void remove_ZoomFactorChanged(void *m_host, void *m_zoomFactorChangedToken)
|
2024-06-05 02:27:47 +08:00
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-11-12 02:57:11 +08:00
|
|
|
|
auto token = reinterpret_cast<EventRegistrationToken *>(m_zoomFactorChangedToken);
|
|
|
|
|
reinterpret_cast<ICoreWebView2Controller *>(m_host)->remove_ZoomFactorChanged(*token);
|
|
|
|
|
delete token;
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#endif
|
2024-06-05 02:27:47 +08:00
|
|
|
|
}
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API double get_ZoomFactor(void *m_host)
|
2024-06-05 02:27:47 +08:00
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-05 02:27:47 +08:00
|
|
|
|
double zoomFactor;
|
|
|
|
|
reinterpret_cast<ICoreWebView2Controller *>(m_host)->get_ZoomFactor(&zoomFactor);
|
|
|
|
|
return zoomFactor;
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#else
|
|
|
|
|
return 1;
|
|
|
|
|
#endif
|
2024-06-05 02:27:47 +08:00
|
|
|
|
}
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API void put_ZoomFactor(void *m_host, double zoomFactor)
|
2024-06-05 02:27:47 +08:00
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-05 02:27:47 +08:00
|
|
|
|
reinterpret_cast<ICoreWebView2Controller *>(m_host)->put_ZoomFactor(zoomFactor);
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#endif
|
2024-11-12 02:57:11 +08:00
|
|
|
|
}
|
|
|
|
|
// https://github.com/MicrosoftEdge/WebView2Feedback/blob/main/specs/WebMessageObjects.md
|
|
|
|
|
DECLARE_API void remove_WebMessageReceived(void *m_host, void *m_webMessageReceivedToken)
|
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-11-12 02:57:11 +08:00
|
|
|
|
auto token = reinterpret_cast<EventRegistrationToken *>(m_webMessageReceivedToken);
|
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
|
|
|
|
|
wil::com_ptr<ICoreWebView2> m_webView;
|
|
|
|
|
[&]()
|
|
|
|
|
{
|
|
|
|
|
CHECK_FAILURE(m_controller->get_CoreWebView2(&m_webView));
|
|
|
|
|
CHECK_FAILURE(m_webView->remove_WebMessageReceived(*token));
|
|
|
|
|
return S_OK;
|
|
|
|
|
}();
|
|
|
|
|
delete token;
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#endif
|
2024-11-12 02:57:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DECLARE_API void *add_WebMessageReceived(void *m_host, void (*callback)(const wchar_t *))
|
|
|
|
|
{
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#ifndef WINXP
|
2024-11-12 02:57:11 +08:00
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(m_host));
|
|
|
|
|
wil::com_ptr<ICoreWebView2Controller4> coreWebView4 =
|
|
|
|
|
m_controller.try_query<ICoreWebView2Controller4>();
|
|
|
|
|
if (coreWebView4)
|
|
|
|
|
{
|
|
|
|
|
coreWebView4->put_AllowExternalDrop(true);
|
|
|
|
|
}
|
|
|
|
|
wil::com_ptr<ICoreWebView2> m_webView;
|
|
|
|
|
EventRegistrationToken *m_webMessageReceivedToken = new EventRegistrationToken;
|
|
|
|
|
[&]()
|
|
|
|
|
{
|
|
|
|
|
CHECK_FAILURE(m_controller->get_CoreWebView2(&m_webView));
|
|
|
|
|
CHECK_FAILURE(m_webView->add_WebMessageReceived(
|
|
|
|
|
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
|
|
|
|
|
[=](ICoreWebView2 *sender, ICoreWebView2WebMessageReceivedEventArgs *args) noexcept
|
|
|
|
|
{
|
|
|
|
|
wil::unique_cotaskmem_string message;
|
|
|
|
|
CHECK_FAILURE(args->TryGetWebMessageAsString(&message));
|
|
|
|
|
if (std::wstring(L"FilesDropped") == message.get())
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2WebMessageReceivedEventArgs2> args2 =
|
|
|
|
|
wil::com_ptr<ICoreWebView2WebMessageReceivedEventArgs>(args)
|
|
|
|
|
.query<ICoreWebView2WebMessageReceivedEventArgs2>();
|
|
|
|
|
if (args2)
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2ObjectCollectionView>
|
|
|
|
|
objectsCollection;
|
|
|
|
|
CHECK_FAILURE(args2->get_AdditionalObjects(&objectsCollection));
|
|
|
|
|
unsigned int length;
|
|
|
|
|
CHECK_FAILURE(objectsCollection->get_Count(&length));
|
|
|
|
|
std::vector<std::wstring> paths;
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < length; i++)
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<IUnknown> object;
|
|
|
|
|
CHECK_FAILURE(objectsCollection->GetValueAtIndex(i, &object));
|
|
|
|
|
// Note that objects can be null.
|
|
|
|
|
if (object)
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2File> file =
|
|
|
|
|
object.query<ICoreWebView2File>();
|
|
|
|
|
if (file)
|
|
|
|
|
{
|
|
|
|
|
// Add the file to message to be sent back to webview
|
|
|
|
|
wil::unique_cotaskmem_string path;
|
|
|
|
|
CHECK_FAILURE(file->get_Path(&path));
|
|
|
|
|
paths.push_back(path.get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// ProcessPaths(paths);
|
|
|
|
|
if (paths.size())
|
|
|
|
|
{
|
|
|
|
|
callback(paths[0].c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return S_OK;
|
|
|
|
|
})
|
|
|
|
|
.Get(),
|
|
|
|
|
m_webMessageReceivedToken));
|
|
|
|
|
return S_OK;
|
|
|
|
|
}();
|
|
|
|
|
return m_webMessageReceivedToken;
|
2024-11-15 03:30:21 +08:00
|
|
|
|
#else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
2024-11-15 03:21:30 +08:00
|
|
|
|
}
|
2024-11-20 20:58:36 +08:00
|
|
|
|
|
|
|
|
|
#ifndef WINXP
|
2024-11-20 20:53:01 +08:00
|
|
|
|
struct contextcallbackdatas
|
|
|
|
|
{
|
|
|
|
|
EventRegistrationToken contextMenuRequestedToken;
|
|
|
|
|
std::wstring label;
|
|
|
|
|
};
|
2024-11-20 20:58:36 +08:00
|
|
|
|
#endif
|
2024-11-20 20:53:01 +08:00
|
|
|
|
// 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_ContextMenuRequested(void *m_host, int index, const wchar_t *label, void (*callback)(const wchar_t *))
|
|
|
|
|
{
|
|
|
|
|
#ifndef WINXP
|
|
|
|
|
contextcallbackdatas *data = new contextcallbackdatas;
|
|
|
|
|
data->label = label; // 持久化
|
|
|
|
|
[=]()
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(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>();
|
|
|
|
|
if (!m_webView2_11)
|
|
|
|
|
return S_OK;
|
|
|
|
|
m_webView2_11->add_ContextMenuRequested(
|
|
|
|
|
Callback<ICoreWebView2ContextMenuRequestedEventHandler>(
|
|
|
|
|
[=](
|
|
|
|
|
ICoreWebView2 *sender,
|
|
|
|
|
ICoreWebView2ContextMenuRequestedEventArgs *args)
|
|
|
|
|
{
|
|
|
|
|
wil::com_ptr<ICoreWebView2ContextMenuTarget> target;
|
|
|
|
|
CHECK_FAILURE(args->get_ContextMenuTarget(&target));
|
|
|
|
|
COREWEBVIEW2_CONTEXT_MENU_TARGET_KIND targetKind;
|
|
|
|
|
BOOL hasselection;
|
|
|
|
|
CHECK_FAILURE(target->get_Kind(&targetKind));
|
|
|
|
|
CHECK_FAILURE(target->get_HasSelection(&hasselection));
|
|
|
|
|
if (!(hasselection && (targetKind ==
|
|
|
|
|
COREWEBVIEW2_CONTEXT_MENU_TARGET_KIND_SELECTED_TEXT)))
|
|
|
|
|
return S_OK;
|
|
|
|
|
wil::com_ptr<ICoreWebView2_11> m_webView2_11;
|
|
|
|
|
CHECK_FAILURE(sender->QueryInterface(IID_PPV_ARGS(&m_webView2_11)));
|
|
|
|
|
|
|
|
|
|
wil::com_ptr<ICoreWebView2Environment> webviewEnvironment;
|
|
|
|
|
CHECK_FAILURE(m_webView2_11->get_Environment(&webviewEnvironment));
|
|
|
|
|
auto webviewEnvironment_5 = webviewEnvironment.try_query<ICoreWebView2Environment9>();
|
|
|
|
|
if (!webviewEnvironment_5)
|
|
|
|
|
return S_OK;
|
|
|
|
|
wil::com_ptr<ICoreWebView2ContextMenuItemCollection> items;
|
|
|
|
|
CHECK_FAILURE(args->get_MenuItems(&items));
|
|
|
|
|
UINT32 itemsCount;
|
|
|
|
|
CHECK_FAILURE(items->get_Count(&itemsCount));
|
|
|
|
|
// Adding a custom context menu item for the page that will display the page's URI.
|
|
|
|
|
wil::com_ptr<ICoreWebView2ContextMenuItem> newMenuItem;
|
2024-11-29 22:58:22 +08:00
|
|
|
|
if (data->label.size())
|
|
|
|
|
{
|
|
|
|
|
CHECK_FAILURE(webviewEnvironment_5->CreateContextMenuItem(
|
|
|
|
|
data->label.c_str(),
|
|
|
|
|
nullptr,
|
|
|
|
|
COREWEBVIEW2_CONTEXT_MENU_ITEM_KIND_COMMAND, &newMenuItem));
|
|
|
|
|
newMenuItem->add_CustomItemSelected(
|
|
|
|
|
Callback<ICoreWebView2CustomItemSelectedEventHandler>(
|
|
|
|
|
[=](
|
|
|
|
|
ICoreWebView2ContextMenuItem *sender,
|
|
|
|
|
IUnknown *args)
|
|
|
|
|
{
|
|
|
|
|
LPWSTR selecttext;
|
|
|
|
|
CHECK_FAILURE(target->get_SelectionText(&selecttext));
|
|
|
|
|
callback(selecttext);
|
|
|
|
|
// 不需要free,free反而会崩溃
|
|
|
|
|
return S_OK;
|
|
|
|
|
})
|
|
|
|
|
.Get(),
|
|
|
|
|
nullptr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CHECK_FAILURE(webviewEnvironment_5->CreateContextMenuItem(
|
|
|
|
|
L"",
|
|
|
|
|
nullptr,
|
|
|
|
|
COREWEBVIEW2_CONTEXT_MENU_ITEM_KIND_SEPARATOR, &newMenuItem));
|
|
|
|
|
}
|
2024-11-20 20:53:01 +08:00
|
|
|
|
UINT idx;
|
|
|
|
|
if (index == -1)
|
|
|
|
|
idx = itemsCount;
|
|
|
|
|
else
|
|
|
|
|
idx = index;
|
|
|
|
|
CHECK_FAILURE(items->InsertValueAtIndex(idx, newMenuItem.get()));
|
|
|
|
|
return S_OK;
|
|
|
|
|
})
|
|
|
|
|
.Get(),
|
|
|
|
|
&data->contextMenuRequestedToken);
|
|
|
|
|
return S_OK;
|
|
|
|
|
}();
|
|
|
|
|
return data;
|
|
|
|
|
#else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
DECLARE_API void remove_ContextMenuRequested(void *m_host, void *data)
|
|
|
|
|
{
|
|
|
|
|
#ifndef WINXP
|
|
|
|
|
auto token = reinterpret_cast<contextcallbackdatas *>(data);
|
|
|
|
|
wil::com_ptr<ICoreWebView2Controller> m_controller(reinterpret_cast<ICoreWebView2Controller *>(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>();
|
|
|
|
|
if (!m_webView2_11)
|
|
|
|
|
return S_OK;
|
|
|
|
|
CHECK_FAILURE(m_webView2_11->remove_ContextMenuRequested(token->contextMenuRequestedToken));
|
|
|
|
|
return S_OK;
|
|
|
|
|
}();
|
|
|
|
|
delete token;
|
|
|
|
|
#endif
|
|
|
|
|
}
|