cefclient这个项目启动后,默认情况下会有下图所示的右键菜单
我们要做的就是仿照这个菜单,添加新的菜单项。
根据关键字搜索,可以找到client_handler.cpp文件,有两函数OnBeforeContextMenu
、OnContextMenuCommand
,用来处理菜单项。修改这两个函数,增加新的菜单项,例如重新加载当前页面。
///
enum client_menu_ids {
CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST,
....
CLIENT_ID_TESTMENU_RADIOITEM3,
CLIENT_ID_RELOAD_PAGE /// 添加一个菜单项枚举
};
void ClientHandler::OnBeforeContextMenu(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr params,
CefRefPtr model) {
///在菜单显示前,处理菜单项
....
model->AddItem(CLIENT_ID_RELOAD_PAGE, "重新加载页面");
....
}
bool ClientHandler::OnContextMenuCommand(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr params,
int command_id,
EventFlags event_flags){
///对应菜单项的响应处理
switch (command_id) {
case CLIENT_ID_RELOAD_PAGE:
browser->Reload();
return true;
case CLIENT_ID_SHOW_DEVTOOLS:
.....
...
}
}
至此,添加右键菜单的需求实现了。
再回过来看看ClientHandler
,看它的定义
class ClientHandler : public CefClient,
public CefContextMenuHandler,
public CefDisplayHandler,
public CefDownloadHandler,
public CefDragHandler,
public CefFocusHandler,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler,
public CefResourceRequestHandler
ClientHandler
采用多继承方式,把上下文菜单、显示状态、下载、拖拽、焦点、键盘等浏览器事件集中起来处理,如果我们要修改相关需求,改变ClientHandler的对应实现就可以了。
那么ClientHandler是在什么时候注册到事件循环中的?通过断点查看调用栈,大致的过程如下:
CefBrowserHost::CreateBrowser() 创建浏览器窗口
-> CefClientCppToC::Wrap()
-> CefClientCppToC::CefClientCppToC() 设置浏览器的事件处理句柄
-> 进入消息循环
-> 分发消息事件
-> client_get_context_menu_handler() 处理上下文菜单事件
-> CefContextMenuHandlerCppToC::Wrap()
-> CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC() 设置上下文菜单的过程处理句柄(显示前、点击、消失等)
-> context_menu_handler_on_before_context_menu() c函数 显示前处理
-> ClientHandler::OnBeforeContextMenu() c++函数 显示前处理