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

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管理的回调接口类中找到身影,继承之即可。如果觉得不过尔尔,那么接下来我们讲解下复杂一点的功能实现;

猜你喜欢

转载自blog.csdn.net/u012778714/article/details/74936835
今日推荐