Preface
A client was implemented using libcef3. When previewing the screenshot, it was found that the built-in menu did not have a copy button when clicking the picture.
After researching, there is an example of adding a menu in the included example:
void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) {
CEF_REQUIRE_UI_THREAD();
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
// Add a separator if the menu already has items.
if (model->GetCount() > 0)
model->AddSeparator();
// Add DevTools items to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
model->AddSeparator();
model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
if (HasSSLInformation(browser)) {
model->AddSeparator();
model->AddItem(CLIENT_ID_SHOW_SSL_INFO, "Show SSL information");
}
// Test context menu features.
BuildTestMenu(model);
}
if (delegate_)
delegate_->OnBeforeContextMenu(model);
}
After some research:
- Determine whether the selected object is a picture
- Add menu
- Handling click events
enum client_menu_ids {
CLIENT_ID_COPY_IMAGE = MENU_ID_USER_FIRST, // 复制
CLIENT_ID_SAVE_IMAGE_AS, // 另存为
};
// CefContextMenuHandler methods
void BrowserHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) {
REQUIRE_UI_THREAD();
// CM_TYPEFLAG_MEDIA 包含图片、视频、文件等等
// 可以再进行细化判断:params->GetMediaType() & CM_MEDIATYPE_IMAGE != 0
if ((params->GetTypeFlags() & CM_TYPEFLAG_MEDIA) != 0 && (params->GetMediaType() & CM_MEDIATYPE_IMAGE != 0)) {
if (model->GetCount() > 0) {
// 禁止右键菜单
model->Clear();
}
model->InsertItemAt(0, CLIENT_ID_COPY_IMAGE, L"复制图片");
model->InsertItemAt(1, CLIENT_ID_SAVE_IMAGE_AS, L"图片另存为...");
model->InsertSeparatorAt(2);
model->AddItem(MENU_ID_PRINT, L"打印");
}
}
// 处理点击事件
bool BrowserHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefContextMenuParams> params, int command_id, EventFlags event_flags) {
// 复制图片到剪切板
if (command_id == CLIENT_ID_COPY_IMAGE) {
frame->Copy();
} else if (command_id == CLIENT_ID_SAVE_IMAGE_AS) {
// 存储图片
frame->GetBrowser().get()->GetHost().get()->StartDownload(frame->GetURL());
}
if (handle_delegate_)
return handle_delegate_->OnContextMenuCommand(browser, frame, params, command_id, event_flags);
else
return false;
}
// 存储图片后,会回调到这里,弹出保存文件框
// 注意使用了windows api,#include <shlobj.h>
void BrowserHandler::OnBeforeDownload(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr<CefBeforeDownloadCallback> callback) {
CEF_REQUIRE_UI_THREAD();
TCHAR szFolderPath[MAX_PATH];
std::string path;
const std::string& file_name = suggested_name;
// Save the file in the user's "My Documents" folder.
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL,
0, szFolderPath))) {
path = CefString(szFolderPath);
path += "\\" + file_name;
}
callback->Continue(path, true);//第一个参数是设置文件保存全路径包含文件名
if (handle_delegate_)
handle_delegate_->OnBeforeDownload(browser, download_item, suggested_name, callback);
}
If it doesn't take effect, check if it's overloaded here:
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
return this; }
effect