前言
利用libcef3实现了一个客户端,当预览截图的时候,发现自带的菜单点击图片的时候没有复制按钮。
研究了一下,自带的例子中有增加菜单的示例:
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);
}
经过一番研究:
- 判断选中的对象是否是图片
- 增加菜单
- 处理点击事件
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);
}
如果没生效,检查这里是不是重载了:
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE { return this; }
效果