我们知道了如何使用命令行执行模式来增加参数。
Command-Line可以不可以在代码里进行修改呢?答案是可以的。
其实我只需要重载OnBeforeCommandLineProcessing就可以了。
下面给出片段的代码
class CCefClientApp : public CefApp, public CefBrowserProcessHandler
{
public:
CCefClientApp();
~CCefClientApp();
virtual CefRefPtr GetBrowserProcessHandler() override
{
return this;
}
//重新这里用来在代码里执行command-line
virtual void OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr command_line) override;
virtual void OnContextInitialized() override;
private:
IMPLEMENT_REFCOUNTING(CCefClientApp);
private:
};
//cefclient.exe -ppapi-flash-path="flashplayer.dll" -url="http://www.163.com" 的效果一致
void CCefClientApp::OnBeforeCommandLineProcessing(const CefString & process_type, CefRefPtr command_line)
{
//flash插件
command_line->AppendSwitchWithValue("-ppapi-flash-path", "flashplayer.dll");
//修改加载url
command_line->AppendSwitchWithValue("-url", "http://www.163.com");
}
是不是很简单。
因为上一章我们搭建的干净cef项目的事例代码只是为了实现一个简单演示,存在某些网站打开会崩溃的问题,现在我提供一个稳定的事例代码。代码一共6个文件,可以直接拷贝到上一章搭建的干净项目内,删除main.cc。编译运行即可。
1.simple_app.h
#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
#include "include/cef_app.h"
//CefApp接口提供了不同进程的可定制回调函数
class SimpleApp : public CefApp, public CefBrowserProcessHandler {
public:
SimpleApp();
// CefApp 方法:返回定制Browser进程的Handler,该Handler包括了诸如OnContextInitialized的回调。
virtual CefRefPtr GetBrowserProcessHandler()
OVERRIDE {
return this;
}
// CefBrowserProcessHandler 方法:
virtual void OnContextInitialized() OVERRIDE;
private:
// 包括默认的引用计数实现。
IMPLEMENT_REFCOUNTING(SimpleApp);
};
#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
2.simple_handler.h
#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#include "include/cef_client.h"
#include
// CefClient提供访问Browser实例的回调接口。一个CefClient实现可以在任意数量的Browser进程中共享。以下为几个重要的回调:
class SimpleHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler {
public:
explicit SimpleHandler(bool use_views);
~SimpleHandler();
// 工厂实例
static SimpleHandler* GetInstance();
// CefClient 方法:
virtual CefRefPtr GetDisplayHandler() OVERRIDE {
return this;
}
// CefLifeSpanHandler 类提供管理 Browser生命周期必需的回调。以下为相关方法和成员。
virtual CefRefPtr GetLifeSpanHandler() OVERRIDE {
return this;
}
virtual CefRefPtr GetLoadHandler() OVERRIDE { return this; }
// CefDisplayHandler 方法:
virtual void OnTitleChange(CefRefPtr browser,
const CefString& title) OVERRIDE;
virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE;
virtual bool DoClose(CefRefPtr browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE;
// CefLoadHandler 方法:
virtual void OnLoadError(CefRefPtr browser,
CefRefPtr frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// 请求所有现有的浏览器窗口关闭。
void CloseAllBrowsers(bool force_close);
bool IsClosing() const { return is_closing_; }
private:
// 平台的实现修改title。
void PlatformTitleChange(CefRefPtr browser,
const CefString& title);
// 是否使用视图框架
const bool use_views_;
// 现有浏览器窗口的列表。只在CEF UI线程上访问。
typedef std::list > BrowserList;
BrowserList browser_list_;
bool is_closing_;
// 包括默认的引用计数实现。
IMPLEMENT_REFCOUNTING(SimpleHandler);
};
#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
3.simple_app.cc
#include "simple_app.h"
#include <string>
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_helpers.h"
#include "simple_handler.h"
namespace {
// 当使用Views框架时,这个对象提供了委托
// CefWindow的实现承载基于Views的浏览器。
class SimpleWindowDelegate : public CefWindowDelegate {
public:
explicit SimpleWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
: browser_view_(browser_view) {}
//窗口创建
void OnWindowCreated(CefRefPtr<CefWindow> window) OVERRIDE {
// 添加浏览器视图并显示窗口。
window->AddChildView(browser_view_);
window->Show();
// 将键盘焦点置于浏览器视图。
browser_view_->RequestFocus();
}
//窗口销毁
void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE {
browser_view_ = NULL;
}
bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE {
// 如果浏览器允许,让窗口关闭。
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser)
return browser->GetHost()->TryCloseBrowser();
return true;
}
private:
CefRefPtr<CefBrowserView> browser_view_;
IMPLEMENT_REFCOUNTING(SimpleWindowDelegate);
DISALLOW_COPY_AND_ASSIGN(SimpleWindowDelegate);
};
} // namespace
//-------------------------------------------------------
/*SimpleApp 实现
CefApp接口提供了不同进程的可定制回调函数。毕竟重要的回调函数如下:
OnBeforeCommandLineProcessing 提供了以编程方式设置命令行参数的机会,更多细节,请参考Command Line Arguments一节。
OnRegisterCustomSchemes 提供了注册自定义schemes的机会,更多细节,请参考Request Handling一节。
GetBrowserProcessHandler 返回定制Browser进程的Handler,该Handler包括了诸如OnContextInitialized的回调。
GetRenderProcessHandler 返回定制Render进程的Handler,该Handler包含了JavaScript相关的一些回调以及消息处理的回调。 更多细节,请参考JavascriptIntegration和Inter-Process Communication两节。
*/
SimpleApp::SimpleApp() {}
void SimpleApp::OnContextInitialized() {
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool use_views = command_line->HasSwitch("use-views");
// SimpleHandler实现浏览器级别的回调。
CefRefPtr<SimpleHandler> handler(new SimpleHandler(use_views));
// CefBrowser 设置
CefBrowserSettings browser_settings;
std::string url;
// 检测 "--url=" command-line. 是否有值,有就使用
url = command_line->GetSwitchValue("url");
if (url.empty())
//url = "https://tool.lu/useragent";
url = "http://www.baidu.com";
if (use_views) {
//创建 BrowserView.主要用于Windows的窗口显示
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
handler, url, browser_settings, NULL, NULL);
//创建Windows窗口之后显现出来。
CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
}
else {
// 创建本机窗口时使用的信息。
CefWindowInfo window_info;
#if defined(OS_WIN)
//在Windows上,我们需要指定将传递给的某些标志
// CreateWindowEx().
window_info.SetAsPopup(NULL, "myclient");
#endif
// 创建一个cefbrowser
CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
NULL);
}
}
4.simple_handler.cc
#include "simple_handler.h"
#include
#include
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
// CefClient提供访问Browser实例的回调接口。一个CefClient实现可以在任意数量的Browser进程中共享。以下为几个重要的回调:
/*
public CefClient,
public CefContextMenuHandler,
public CefDisplayHandler,
public CefDownloadHandler,
public CefDragHandler,
public CefGeolocationHandler,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler
*/
namespace {
SimpleHandler* g_instance = NULL;
} // namespace
// 构造
SimpleHandler::SimpleHandler(bool use_views)
: use_views_(use_views), is_closing_(false) {
DCHECK(!g_instance);
g_instance = this;
}
// 析构
SimpleHandler::~SimpleHandler() {
g_instance = NULL;
}
// 静态工厂
SimpleHandler* SimpleHandler::GetInstance() {
return g_instance;
}
// 修改CefBrowser的title
void SimpleHandler::OnTitleChange(CefRefPtr browser,
const CefString& title) {
CEF_REQUIRE_UI_THREAD();
if (use_views_) {
// 使用视图框架设置窗口的标题。
CefRefPtr browser_view =
CefBrowserView::GetForBrowser(browser);
if (browser_view) {
CefRefPtr window = browser_view->GetWindow();
if (window)
window->SetTitle(title);
}
} else {
// 使用平台api设置窗口的标题。
PlatformTitleChange(browser, title);
}
}
void SimpleHandler::OnAfterCreated(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
//添加到现有浏览器的列表中。
browser_list_.push_back(browser);
}
bool SimpleHandler::DoClose(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
// 关闭主窗口需要特殊处理。看到DoClose()
if (browser_list_.size() == 1) {
// 设置一个标志以表明应该允许关闭窗口。
is_closing_ = true;
}
// 允许关闭。
return false;
}
// 关闭browser 在之前
void SimpleHandler::OnBeforeClose(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
// 从现有的浏览器列表中删除。
BrowserList::iterator bit = browser_list_.begin();
for (; bit != browser_list_.end(); ++bit) {
if ((*bit)->IsSame(browser)) {
browser_list_.erase(bit);
break;
}
}
if (browser_list_.empty()) {
// 所有的浏览器窗口都关闭了。退出应用程序消息循环。
CefQuitMessageLoop();
}
}
// 加载错误
void SimpleHandler::OnLoadError(CefRefPtr browser,
CefRefPtr frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
CEF_REQUIRE_UI_THREAD();
// 不要为下载的文件显示错误。
if (errorCode == ERR_ABORTED)
return;
// 显示一个加载错误消息。
std::stringstream ss;
ss << ""
"Failed to load URL "
<< std::string(failedUrl) << " with error " << std::string(errorText)
<< " (" << errorCode << ").";
frame->LoadString(ss.str(), failedUrl);
}
// 关闭所有Browers
void SimpleHandler::CloseAllBrowsers(bool force_close) {
if (!CefCurrentlyOn(TID_UI)) {
// 提交关闭任务
CefPostTask(TID_UI, base::Bind(&SimpleHandler::CloseAllBrowsers, this,
force_close));
return;
}
if (browser_list_.empty())
return;
BrowserList::const_iterator it = browser_list_.begin();
for (; it != browser_list_.end(); ++it)
(*it)->GetHost()->CloseBrowser(force_close);
}
5.simple_handler_win.cc
#include "simple_handler.h"
#include <windows.h>
#include <string>
#include "include/cef_browser.h"
void SimpleHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) {
CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
SetWindowText(hwnd, std::wstring(title).c_str());
}
6.cefsimple_win.cc
#include
#include "simple_app.h"
#include "include/cef_parser.h"
#include "include/cef_urlrequest.h"
//window 窗体入口函数
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// 启用High-DPI支持Windows 7或更新。
//CefEnableHighDPISupport();
void* sandbox_info = NULL;
//1 声明command-line 参数
CefMainArgs main_args(hInstance);
//3 检测CEF其他子进程
int exit_code = CefExecuteProcess(main_args, NULL, sandbox_info);
if (exit_code >= 0) {
return exit_code;
}
//------------------------------------------1 设置------------------------------------------------------
// 设置cef的全局配置
CefSettings settings;
//设置语言
CefString(&settings.locale).FromString("zh - CN");
//设置不使用沙盒
settings.no_sandbox = true;
// cefApp
CefRefPtr app(new SimpleApp);
CefInitialize(main_args, settings, app.get(), sandbox_info);
// 循环消息
CefRunMessageLoop();
// 关闭cef
CefShutdown();
return 0;
}
编译生成运行即可。
预计下一篇:
CEF小白人系列11-构建编译CEF源代码
问题:
Q&A
学习交流:
QQ群:14764183
加入验证标注 cef入坑。