您的位置:首页 > 产品设计 > UI/UE

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

2017-07-10 21:39 246 查看
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管理的回调接口类中找到身影,继承之即可。如果觉得不过尔尔,那么接下来我们讲解下复杂一点的功能实现;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Cef-DuiLib