443 lines
14 KiB
C++
443 lines
14 KiB
C++
/** @file cef_control_base.h
|
||
* @brief 封装Cef浏览器对象为duilib控件基类
|
||
* @copyright (c) 2016, NetEase Inc. All rights reserved
|
||
* @author Redrain
|
||
* @date 2019/3/20
|
||
*/
|
||
#pragma once
|
||
#include "include/cef_base.h"
|
||
#include "cef_control_event.h"
|
||
#include "cef_control/app/cef_js_bridge.h"
|
||
#include "cef_control/handler/browser_handler.h"
|
||
|
||
namespace nim_comp {
|
||
|
||
using namespace ui;
|
||
|
||
class CefControlBase : public Control, public nim_comp::BrowserHandler::HandlerDelegate
|
||
{
|
||
public:
|
||
CefControlBase(void);
|
||
virtual ~CefControlBase(void);
|
||
|
||
public:
|
||
/**
|
||
* @brief 加载一个地址
|
||
* @param[in] url 网站地址
|
||
* @return 无
|
||
*/
|
||
void LoadURL(const CefString& url);
|
||
|
||
/**
|
||
* @brief 给指定地址添加一个字符串资源
|
||
* @param[in] stringW 字符串资源
|
||
* @param[in] url 网址
|
||
* @return 无
|
||
*/
|
||
void LoadString(const CefString& stringW, const CefString& url);
|
||
|
||
/**
|
||
* @brief 后退
|
||
* @return 无
|
||
*/
|
||
void GoBack();
|
||
|
||
/**
|
||
* @brief 前进
|
||
* @return 无
|
||
*/
|
||
void GoForward();
|
||
|
||
/**
|
||
* @brief 判断是否可以后退
|
||
* @return 返回 true 表示可以,false 表示不可以
|
||
*/
|
||
bool CanGoBack();
|
||
|
||
/**
|
||
* @brief 判断是否可以前进
|
||
* @return 返回 true 表示可以,false 表示不可以
|
||
*/
|
||
bool CanGoForward();
|
||
|
||
/**
|
||
* @brief 刷新
|
||
* @return 无
|
||
*/
|
||
void Refresh();
|
||
|
||
/**
|
||
* @brief 停止加载
|
||
* @return 无
|
||
*/
|
||
void StopLoad();
|
||
|
||
/**
|
||
* @brief 是否加载中
|
||
* @return 返回 true 表示加载中,否则为 false
|
||
*/
|
||
bool IsLoading();
|
||
|
||
/**
|
||
* @brief 开始一个下载任务
|
||
* @param[in] url 要下载的文件地址
|
||
* @return 无
|
||
*/
|
||
void StartDownload(const CefString& url);
|
||
|
||
/**
|
||
* @brief 设置页面缩放比例
|
||
* @param[in] zoom_level 比例值
|
||
* @return 无
|
||
*/
|
||
void SetZoomLevel(float zoom_level);
|
||
|
||
/**
|
||
* @brief 获取浏览器对象所属的窗体句柄
|
||
* @return 窗口句柄
|
||
*/
|
||
HWND GetCefHandle() const;
|
||
|
||
/**
|
||
* @brief 获取页面 URL
|
||
* @return 返回 URL 地址
|
||
*/
|
||
CefString GetURL();
|
||
|
||
/**
|
||
* @brief 获取 UTF8 格式 URL
|
||
* @return 返回 URL 地址
|
||
*/
|
||
std::string GetUTF8URL();
|
||
|
||
/**
|
||
* @brief 获取网址 # 号前的地址
|
||
* @param[in] url 要获取的完整地址
|
||
* @return 返回截取后的地址
|
||
*/
|
||
CefString GetMainURL(const CefString& url);
|
||
|
||
/**
|
||
* @brief 注册一个 C++ 方法提供前端调用
|
||
* @param[in] function_name 方法名称
|
||
* @param[in] function 方法函数体
|
||
* @param[in] global_function 是否是一个全局方法
|
||
* @return 返回 true 表示注册成功,false 可能已经注册
|
||
*/
|
||
bool RegisterCppFunc(const std::wstring& function_name, nim_comp::CppFunction function, bool global_function = false);
|
||
|
||
/**
|
||
* @brief 反注册一个 C++ 方法
|
||
* @param[in] function_name 方法名称
|
||
* @return 无
|
||
*/
|
||
void UnRegisterCppFunc(const std::wstring& function_name);
|
||
|
||
/**
|
||
* @brief 调用一个前端已经注册好的方法
|
||
* @param[in] js_function_name 前端提供的方法名
|
||
* @param[in] params 传递 JSON 字符串格式的参数
|
||
* @param[in] callback 前端执行完成后的回调函数
|
||
* @param[in] frame_name 要调用哪个名称 frame 下的方法,默认使用主 frame
|
||
* @return 返回 true 表示成功调用,false 表示调用失败,方法可能不存在
|
||
*/
|
||
bool CallJSFunction(const std::wstring& js_function_name, const std::wstring& params, nim_comp::CallJsFunctionCallback callback, const std::wstring& frame_name = L"");
|
||
|
||
/**
|
||
* @brief 调用一个前端已经注册好的方法
|
||
* @param[in] js_function_name 前端提供的方法名
|
||
* @param[in] params 传递 JSON 字符串格式的参数
|
||
* @param[in] callback 前端执行完成后的回调函数
|
||
* @param[in] frame_id 要调用哪个 ID frame 下的方法,默认使用主 frame
|
||
* @return 返回 true 表示成功调用,false 表示调用失败,方法可能不存在
|
||
*/
|
||
bool CallJSFunction(const std::wstring& js_function_name, const std::wstring& params, nim_comp::CallJsFunctionCallback callback, int frame_id);
|
||
|
||
/**
|
||
* @brief 修复浏览器
|
||
* @return 无
|
||
*/
|
||
virtual void RepairBrowser();
|
||
|
||
/**
|
||
* @brief 打开开发者工具
|
||
* @param[in] view 一个 CefControl 控件实例(仅在CefControl类里需要传入)
|
||
* @return 成功返回 true,失败返回 false
|
||
*/
|
||
virtual bool AttachDevTools(Control* view) = 0;
|
||
|
||
/**
|
||
* @brief 关闭开发者工具
|
||
* @return 无
|
||
*/
|
||
virtual void DettachDevTools();
|
||
|
||
/**
|
||
* @brief 判断是否打开开发者工具
|
||
* @return 返回 true 表示已经绑定,false 为未绑定
|
||
*/
|
||
virtual bool IsAttachedDevTools() const { return devtool_attached_; }
|
||
|
||
protected:
|
||
virtual void ReCreateBrowser() = 0;
|
||
|
||
public:
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听右键菜单弹出
|
||
* @param[in] callback 一个回调函数,参考 OnBeforeMenuEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachBeforeContextMenu(const OnBeforeMenuEvent& callback){ cb_before_menu_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听选择了哪个右键菜单
|
||
* @param[in] callback 一个回调函数,参考 OnMenuCommandEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachMenuCommand(const OnMenuCommandEvent& callback){ cb_menu_command_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面 Title 改变
|
||
* @param[in] callback 一个回调函数,参考 OnTitleChangeEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachTitleChange(const OnTitleChangeEvent& callback){ cb_title_change_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面中 frame URL 地址改变
|
||
* @param[in] callback 一个回调函数,参考 OnUrlChangeEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachUrlChange(const OnUrlChangeEvent& callback){ cb_url_change_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听主页面 URL 地址改变
|
||
* @param[in] callback 一个回调函数,参考 OnMainURLChengeEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachMainURLChange(OnMainURLChengeEvent cb){ cb_main_url_change_ = cb; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面资源全部加载完毕
|
||
* @param[in] callback 一个回调函数,参考 OnBeforeResourceLoadEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachBeforeNavigate(const OnBeforeResourceLoadEvent& callback){ cb_before_resource_load_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个弹出窗口弹出的通知
|
||
* @param[in] callback 一个回调函数,参考 OnLinkClickEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachLinkClick(const OnLinkClickEvent& callback){ cb_link_click_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面加载状态改变
|
||
* @param[in] callback 一个回调函数,参考 OnLoadingStateChangeEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachLoadingStateChange(const OnLoadingStateChangeEvent& callback){ cb_loadstate_change_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面开始加载通知
|
||
* @param[in] callback 一个回调函数,参考 OnLoadStartEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachLoadStart(const OnLoadStartEvent& callback){ cb_load_start_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听页面加载完毕通知
|
||
* @param[in] callback 一个回调函数,参考 OnLoadEndEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachLoadEnd(const OnLoadEndEvent& callback){ cb_load_end_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听界面加载错误通知
|
||
* @param[in] callback 一个回调函数,参考 OnLoadErrorEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachLoadError(const OnLoadErrorEvent& callback){ cb_load_error_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听开发者工具状态改变通知
|
||
* @param[in] callback 一个回调函数,参考 OnDevToolAttachedStateChangeEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachDevToolAttachedStateChange(const OnDevToolAttachedStateChangeEvent& callback){ cb_devtool_visible_change_ = callback; };
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个新的浏览器实例创建完毕通知
|
||
* @param[in] callback 一个回调函数,参考 OnAfterCreatedEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachAfterCreated(const OnAfterCreatedEvent& callback){ cb_after_created_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个浏览器实例关闭前的通知
|
||
* @param[in] callback 一个回调函数,参考 OnBeforeCloseEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachBeforeCLose(const OnBeforeCloseEvent& callback) { cb_before_close_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个浏览器实例加载通知
|
||
* @param[in] callback 一个回调函数,参考 OnBeforeBrowserEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachBeforeBrowser(const OnBeforeBrowserEvent& callback) { cb_before_browser_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个未知的 Protocol
|
||
* @param[in] callback 一个回调函数,参考 OnProtocolExecutionEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachProtocolExecution(const OnProtocolExecutionEvent& callback) { cb_protocol_execution_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个下载任务开始之前的通知
|
||
* @param[in] callback 一个回调函数,参考 OnBeforeDownloadEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachBeforeDownload(const OnBeforeDownloadEvent& callback) { cb_before_download_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听下载过程中任务的状态改变通知
|
||
* @param[in] callback 一个回调函数,参考 OnDownloadUpdatedEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachDownloadUpdated(const OnDownloadUpdatedEvent& callback) { cb_download_updated_ = callback; }
|
||
|
||
/**
|
||
* @brief 绑定一个回调函数用于监听一个从对话框中打开文件的通知
|
||
* @param[in] callback 一个回调函数,参考 OnFileDialogEvent 声明
|
||
* @return 无
|
||
*/
|
||
void AttachFileDialog(const OnFileDialogEvent& callback) { cb_file_dialog_ = callback; }
|
||
|
||
private:
|
||
// 处理BrowserHandler的HandlerDelegate委托接口
|
||
// 当浏览器渲染数据变化时,会触发此接口,此时把渲染数据保存到内存dc
|
||
// 并且通知窗体刷新控件,在控件的Paint函数里把内存dc的位图画到窗体上
|
||
// 由此实现离屏渲染数据画到窗体上
|
||
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
|
||
CefRenderHandler::PaintElementType type,
|
||
const CefRenderHandler::RectList& dirtyRects,
|
||
const std::string* buffer,
|
||
int width,
|
||
int height) OVERRIDE;
|
||
|
||
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
|
||
|
||
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
|
||
|
||
virtual void UpdateWindowPos() OVERRIDE;
|
||
|
||
virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model) OVERRIDE;
|
||
|
||
virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefFrame> frame,
|
||
CefRefPtr<CefContextMenuParams> params,
|
||
int command_id,
|
||
CefContextMenuHandler::EventFlags event_flags) OVERRIDE;
|
||
|
||
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url) OVERRIDE;
|
||
|
||
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) OVERRIDE;
|
||
|
||
virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser, bool isLoading, bool canGoBack, bool canGoForward) OVERRIDE;
|
||
|
||
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) OVERRIDE;
|
||
|
||
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode) OVERRIDE;
|
||
|
||
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefFrame> frame,
|
||
CefLoadHandler::ErrorCode errorCode,
|
||
const CefString& errorText,
|
||
const CefString& failedUrl) OVERRIDE;
|
||
|
||
// 在非UI线程中被调用
|
||
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefFrame> frame,
|
||
const CefString& target_url,
|
||
const CefString& target_frame_name,
|
||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||
bool user_gesture,
|
||
const CefPopupFeatures& popupFeatures,
|
||
CefWindowInfo& windowInfo,
|
||
CefRefPtr<CefClient>& client,
|
||
CefBrowserSettings& settings,
|
||
bool* no_javascript_access) OVERRIDE;
|
||
|
||
virtual bool OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||
|
||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||
|
||
// 在非UI线程中被调用
|
||
virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool is_redirect) OVERRIDE;
|
||
|
||
virtual void OnProtocolExecution(CefRefPtr<CefBrowser> browser, const CefString& url, bool& allow_os_execution) OVERRIDE;
|
||
|
||
// 在非UI线程中被调用
|
||
virtual CefRequestHandler::ReturnValue OnBeforeResourceLoad(
|
||
CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefFrame> frame,
|
||
CefRefPtr<CefRequest> request,
|
||
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
|
||
|
||
virtual void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, CefRequestHandler::TerminationStatus status) OVERRIDE;
|
||
|
||
// 下载文件相关
|
||
virtual void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefDownloadItem> download_item,
|
||
const CefString& suggested_name,
|
||
CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE;
|
||
|
||
virtual void OnDownloadUpdated(
|
||
CefRefPtr<CefBrowser> browser,
|
||
CefRefPtr<CefDownloadItem> download_item,
|
||
CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE;
|
||
|
||
// 打开文件相关
|
||
virtual bool OnFileDialog(
|
||
CefRefPtr<CefBrowser> browser,
|
||
CefDialogHandler::FileDialogMode mode,
|
||
const CefString& title,
|
||
const CefString& default_file_path,
|
||
const std::vector<CefString>& accept_filters,
|
||
int selected_accept_filter,
|
||
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
|
||
|
||
virtual bool OnExecuteCppFunc(const CefString& function_name, const CefString& params, int js_callback_id, CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||
|
||
virtual bool OnExecuteCppCallbackFunc(int cpp_callback_id, const CefString& json_string) OVERRIDE;
|
||
|
||
protected:
|
||
CefRefPtr<nim_comp::BrowserHandler> browser_handler_ = nullptr;
|
||
std::shared_ptr<nim_comp::CefJSBridge> js_bridge_;
|
||
CefString url_;
|
||
bool devtool_attached_;
|
||
|
||
OnBeforeMenuEvent cb_before_menu_ = nullptr;
|
||
OnMenuCommandEvent cb_menu_command_ = nullptr;
|
||
OnTitleChangeEvent cb_title_change_ = nullptr;
|
||
OnBeforeResourceLoadEvent cb_before_resource_load_ = nullptr;
|
||
OnUrlChangeEvent cb_url_change_ = nullptr;
|
||
OnMainURLChengeEvent cb_main_url_change_ = nullptr;
|
||
OnLinkClickEvent cb_link_click_ = nullptr;
|
||
OnLoadingStateChangeEvent cb_loadstate_change_ = nullptr;
|
||
OnLoadStartEvent cb_load_start_ = nullptr;
|
||
OnLoadEndEvent cb_load_end_ = nullptr;
|
||
OnLoadErrorEvent cb_load_error_ = nullptr;
|
||
OnAfterCreatedEvent cb_after_created_ = nullptr;
|
||
OnBeforeCloseEvent cb_before_close_ = nullptr;
|
||
OnBeforeBrowserEvent cb_before_browser_ = nullptr;
|
||
OnProtocolExecutionEvent cb_protocol_execution_ = nullptr;
|
||
OnBeforeDownloadEvent cb_before_download_ = nullptr;
|
||
OnDownloadUpdatedEvent cb_download_updated_ = nullptr;
|
||
OnFileDialogEvent cb_file_dialog_ = nullptr;
|
||
OnDevToolAttachedStateChangeEvent cb_devtool_visible_change_ = nullptr;
|
||
int js_callback_thread_id_ = -1; // 保存接收到 JS 调用 CPP 函数的代码所属线程,以后触发 JS 回调时把回调转到那个线程
|
||
};
|
||
} |