libcef3-Customize the right-click menu, copy pictures and save pictures as

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.
Insert picture description here
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:

  1. Determine whether the selected object is a picture
  2. Add menu
  3. 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

Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/xmcy001122/article/details/109516394