CEF完整嵌入DUI窗体(三) --基本浏览器功能

xiaoxiao2021-02-28  115

Cef将浏览器的功能非常清晰的做了封装,该抛出的接口抛出,该回调的接口回调,学习谷歌的代码,愈发的会感觉到这种清晰简洁的优美;现在我们按照功能区分来讲解代码;这一节我们首先介绍浏览器的简单功能,包括创建,导航,关闭等 一,创建浏览器 这里我们直接自己封装了一个浏览器创建接口,实现了一些回调接口solt的设置等

void CBrowserClient::CreateCefWindow(HWND hWnd, const CefString& url, ILifeSpanHandleSlot* life_handle, ILoadHandleSlot* load_handle, IDisplayHandleSolt* display_handle, ILifeSpanFileDialogSolt* filedialog_handle) { //这里Cef要求创建浏览器的接口只能在UI主线程中调用,其他地方调用可能会使程序奔溃 if (!CefCurrentlyOn(TID_UI)) { // Execute this method on the UI thread. CefPostTask(TID_UI, base::Bind(&CBrowserClient::CreateCefWindow, this, hWnd, url, life_handle, load_handle, display_handle, filedialog_handle)); return; } CEF_REQUIRE_UI_THREAD(); CefWindowInfo info; //创建子窗口 RECT rect = { 0, 0, 1, 1 }; //设置浏览器窗体为Dui的内嵌窗体 info.SetAsChild(hWnd, rect); //这里设置了我们需要的向上层抛出的回调接口,之后会讲解 life_handle_->SetSolt(life_handle); load_handle_->SetSolt(load_handle); display_handle_->SetSolt(display_handle); filedialog_handle_->SetSolt(filedialog_handle); //创建浏览器 CefBrowserSettings b_settings; CefBrowserHost::CreateBrowserSync(info, this, url, b_settings, NULL); }

二,导航,回退,重新加载,执行JS代码,关闭浏览器等普通操作 定义一个叫做 CBrowserClient 的类,继承CefClient 类(这个类是Cef回调管理类,其中定了很多接口集的指针向Cef内部返回,我们需要哪个接口就让CBrowserClient 同时继承这个接口集的类,然后多态实现CefClient的返回接口即可)这里我们需要用到的是CefLifeSpanHandler回调接口类,顾名思义,这个接口类会在Cef浏览器生命周期的各个关键点回调

class CBrowserClient : public CefClient, //回调管理类 public CefDisplayHandler//生命周期回调类

多态实现派生类指针返回

CefRefPtr<CefDisplayHandler> CBrowserClient::GetDisplayHandler() { return this; }

我们这里需要用到一个接口,在浏览器创建完成之后返回,参数中会携带创建完成的浏览器对象

void CBrowserClient::OnAfterCreated(CefRefPtr<CefBrowser> browser) { CEF_REQUIRE_UI_THREAD(); base::AutoLock lock_scope(lock_); //定义一个CefRefPtr<CefBrowser> browser_ 来保存返回的浏览器对象 if (!browser_) { browser_ = browser; } }

所有的浏览器操作都通过这个浏览器对象来主动调用:

//是否可以向前导航 browser_->CanGoForward(); //向前导航 browser_->GoForward(); //重新加载 browser_->Reload(); //忽略缓存加载 browser_->ReloadIgnoreCache(); //停止加载 browser_->StopLoad(); //是否可以向后导航 browser_->CanGoBack(); //向后导航 browser_->GoBack(); //获取浏览器窗体句柄 return browser_->GetHost()->GetWindowHandle(); //设置焦点 browser_->GetHost()->SetFocus(bool focus); //获取缩放比例 browser_->GetHost()->GetZoomLevel(); //设置缩放比例 browser_->GetHost()->SetZoomLevel(int zoomLevel); //加载url browser_->GetMainFrame()->LoadURL(std::wstring url); //获取当前Url browser_->GetMainFrame()->GetURL(); //执行js代码 browser_->GetMainFrame()->ExecuteJavaScript(std::wstring jscode, "", 0); //关闭浏览器 传参为true将不弹出alert直接关闭 browser_->GetHost()->CloseBrowser(bool /*true*/); //设置浏览器焦点 browser_->GetHost()->SetFocus(bool enable);

三,实现右键菜单 右键菜单同样需要我们在Cef的回调接口中操作,CBrowserClient类再继承CefContextMenuHandler接口集类,多态实现派生类指针的返回:

CefRefPtr<CefContextMenuHandler> CBrowserClient::GetContextMenuHandler() { return this; }

在OnBeforeContextMenu回调接口中设置右键菜单项,在OnContextMenuCommand中实现右键菜单的相关操作,我们首先定义右键菜单的枚举类型

enum ContextMenuID { RIGHT_MENU_REFRESH = 1001,//刷新 RIGHT_MENU_FORWARD, //向前 RIGHT_MENU_BACKOFF, //向后 };

接下来将这些项添加到右键菜单中

void CBrowserClient::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model) { if ((params->GetTypeFlags()&(CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) { // Add a separator if the menu already has items. if (model->GetCount() > 0) { //清除默认项 model->Clear(); //model->AddSeparator(); } //添加菜单项 model->AddItem(RIGHT_MENU_REFRESH, L"刷 新"); model->AddSeparator(); model->AddItem(RIGHT_MENU_FORWARD, L"前 进"); model->AddSeparator(); model->AddItem(RIGHT_MENU_BACKOFF, L"后 退"); } }

实现右键菜单的具体操作

bool CBrowserClient::OnContextMenuCommand(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefContextMenuParams> params, int command_id, EventFlags event_flags) { switch (command_id) { case RIGHT_MENU_REFRESH: browser_->Reload(); return true; case RIGHT_MENU_FORWARD: if(browser_->CanGoForward()) { browser_->GoForward(); } return true; case RIGHT_MENU_BACKOFF: if(browser_->CanGoBack()) { browser_->GoBack(); } return true; } return false; }

四,阻止客户端嵌入的浏览器被拖入本地文件 我们依然让CBrowserClient类来继承一个拖拽文件的接口集CefDragHandler,多态返回派生类的指针:

CefRefPtr<CefDragHandler> CBrowserClient::GetDragHandler() { return this; }

直接将拖拽触发的回调接口返回true即可

bool CBrowserClient::OnDragEnter(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDragData> dragData, DragOperationsMask mask) { return true; }

五,屏蔽一些windows键盘操作 我想你已经知道了我要干嘛,依然让CBrowserClient类来继承一个键盘操作的接口集CefKeyboardHandler,多态返回派生类的指针:

CefRefPtr<CefKeyboardHandler> CBrowserClient::GetKeyboardHandler() { return this; }

屏蔽想要屏蔽的按键操作

bool CBrowserClient::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent& event, CefEventHandle os_event, bool* is_keyboard_shortcut) { if (os_event) { //这里屏蔽掉alt+空格的操作 if (os_event->message == WM_SYSKEYDOWN || os_event->message == WM_SYSKEYUP) { return true; } } return false; }

看到这里我想你已经发现Cef的一些特点,它把一些浏览器相关的事件封装成回调接口,供我们自己实现从而定制开发出嵌入客户端的浏览器,其他的一些诸如弹出文件选择对话框,显示控制台信息等操作都能通过CefClient管理的回调接口类中找到身影,继承之即可。如果觉得不过尔尔,那么接下来我们讲解下复杂一点的功能实现;

转载请注明原文地址: https://www.6miu.com/read-45407.html

最新回复(0)