libcef3在vs2017下的配置,window和js交互实现

目录

1.应用背景

2.下载CEF

3.编译 libcef_dll_wrapper

4.新建MFC对话框程序

5.运行程序

6.OK,好了


1.应用背景

随着 HTML5 的崛起和 IE 的淘汰,微软 Web Browser 控件越来越不合时宜,CEF (Chromium Embedded Framework) 越来越受欢迎。但 CEF 使用起来比 Web Browser 复杂的多,而且它的官方例子 cefsimple 和 cefclient 都是使用 Win32 API 开发的,这给大家学习使用 CEF 带来了很大不便,很多人更需要一个使用 MFC 开发的例子。

CEF版本:cef_binary_3.2704.1434.gec3e9ed_windows32

开发工具:visual studio 2017

2.下载CEF

获得 CEF 有两种方法,一种是下载源码自己编译,另一种是直接下载编译好的二进制文件。自己编译 CEF 源码太麻烦了,可谓困难重重,直接pass。

只有第二种方法了,我用的版本是cef_binary_3.2704.1434.gec3e9ed_windows32.7z

3.编译 libcef_dll_wrapper

解压好之后里面默认含libcef.dll 提供的是 C 接口。我们既然都已经使用 MFC 了,当然更想用 C++ 接口,但C++接口需要自己编译,

我们用CMake编译,下载地址:cmake-3.8.2-win32-x86.msi ,安装CMake时需要选择“添加到环境变量”

编译好后,打开工程,编译 libcef_dll_wrapper项目。

至此准备工作全部完成。

4.新建MFC对话框程序

3.1属性中添加包含目录,库目录。

3.2属性中,"C/C++"->"预编译头"->"不使用预编译头"。

3.3属性中,"链接器"->"输入"->"附加依赖项",填入libcef.lib,libcef_dll_wrapper.lib两个静态库

4.coding

4.1声明CSimpleClient类,如下,常规做法是定义CSimpleClient类,继承自所有的event handling classes。

class CSimpleClient : public CefClient, public CefLifeSpanHandler, public CefDownloadHandler, public CefKeyboardHandler, public CefContextMenuHandler, public CefBrowserProcessHandler, public CefApp

4.2实现CSimpleClient类

#include "SimpleClient.h"
#include  <tchar.h>

enum { ID_CMD_REFRESH = 0 ,
	ID_SHOW_DEV_TOOLS
};

CSimpleClient::CSimpleClient()
{
	hWnd_ = NULL;
}


CSimpleClient::~CSimpleClient()
{
}

void CSimpleClient::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
	if (!m_cefBrowser.get())
	{
		m_cefBrowser = browser;
		m_BrowserHwnd = browser->GetHost()->GetWindowHandle();
	}
}

//void CSimpleClient::OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr<CefCommandLine> command_line)
//{
//
//	command_line->AppendSwitch("no-proxy-server");
//	command_line->AppendSwitch("--enable-npapi");
//	command_line->AppendSwitch("--disable-web-security");
//	command_line->AppendSwitch("allow-outdated-plugins");
//
//	//manifest.json中的version
//	command_line->AppendSwitchWithValue("ppapi-flash-version","20.0.0.228");
//
//	//加载flash插件
//	command_line->AppendSwitchWithValue("ppapi-flash-path", "PepperFlash\\pepflashplayer.dll");
//
//}

bool CSimpleClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
	CefProcessId source_process,
	CefRefPtr<CefProcessMessage> message)
{
	const std::string& messageName = message->GetName();
	if (messageName == "login_msg")
	{
		// extract message
		CefRefPtr<CefListValue> args = message->GetArgumentList();
		CefString strUser = args->GetString(0);
		CefString strPassword = args->GetString(1);
		TCHAR szLog[256] = { 0 };
		_stprintf_s(szLog, 256, L"BrowserProcess, user - %s, password - %s\r\n", strUser.c_str(), strPassword.c_str());
		OutputDebugString(szLog);

		//send reply to render process
		CefRefPtr<CefProcessMessage> outMsg = CefProcessMessage::Create("login_reply");

		// Retrieve the argument list object.
		CefRefPtr<CefListValue> replyArgs = outMsg->GetArgumentList();

		// Populate the argument values.
		replyArgs->SetSize(1);
		replyArgs->SetInt(0, 0);

		// Send the process message to the renderer process.
		browser->SendProcessMessage(PID_RENDERER, outMsg);

		return true;
	}
	return false;
}

bool CSimpleClient::OnBeforePopup(CefRefPtr<CefBrowser> browser,
	CefRefPtr<CefFrame> frame,
	const CefString& target_url,
	const CefString& target_frame_name,
	WindowOpenDisposition target_disposition,
	bool user_gesture,
	const CefPopupFeatures& popupFeatures,
	CefWindowInfo& windowInfo,
	CefRefPtr<CefClient>& client,
	CefBrowserSettings& settings,
	bool* no_javascript_access)
{
	switch (target_disposition)
	{
	case WOD_NEW_FOREGROUND_TAB:
	case WOD_NEW_BACKGROUND_TAB:
	case WOD_NEW_POPUP:
	case WOD_NEW_WINDOW:
		browser->GetMainFrame()->LoadURL(target_url);
		return true; //cancel create
	}

	return false;
}

void CSimpleClient::OnBeforeDownload(
	CefRefPtr<CefBrowser> browser,
	CefRefPtr<CefDownloadItem> download_item,
	const CefString& suggested_name,
	CefRefPtr<CefBeforeDownloadCallback> callback)
{
	callback->Continue(download_item->GetURL(), true);
}

void CSimpleClient::OnDownloadUpdated(
	CefRefPtr<CefBrowser> browser,
	CefRefPtr<CefDownloadItem> download_item,
	CefRefPtr<CefDownloadItemCallback> callback)
{
	if (download_item->IsComplete())
	{
		//MessageBox.Show("下载成功");
		OutputDebugString(L"下载成功");
		if (browser->IsPopup() && !browser->HasDocument())
		{
			//browser->GetHost()->ParentWindowWillClose();
			browser->GetHost()->CloseBrowser(true);
		}
	}
	else
	{
		//如果取消应该跳转到一个网页
		browser->GoBack();
	}
}

bool CSimpleClient::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
	const CefKeyEvent& event,
	CefEventHandle os_event,
	bool* is_keyboard_shortcut) 
{
	if (event.type != KEYEVENT_RAWKEYDOWN)
		return false;

	if (event.windows_key_code == 116)//F5刷新
		browser->Reload();
	else if (event.windows_key_code == VK_F12)
	{
		ShowDevelopTools(browser, CefPoint(0, 0));
	}
	return false;
}

bool CSimpleClient::OnKeyEvent(CefRefPtr<CefBrowser> browser,
	const CefKeyEvent& event,
	CefEventHandle os_event) {
	return false;
}

//右键菜单
void CSimpleClient::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
	CefRefPtr<CefFrame> frame,
	CefRefPtr<CefContextMenuParams> params,
	CefRefPtr<CefMenuModel> model) 
{
	if (model->GetCount() > 0) {// 刷新菜单
		model->AddSeparator();
		model->AddItem(ID_CMD_REFRESH, __TEXT("刷新"));
		model->AddItem(ID_SHOW_DEV_TOOLS, __TEXT("开发者选项"));
	}
}

bool CSimpleClient::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
	CefRefPtr<CefFrame> frame,
	CefRefPtr<CefContextMenuParams> params,
	int command_id, EventFlags event_flags) 
{
	switch (command_id)
	{
	case ID_CMD_REFRESH:
		browser->Reload();
		break;
	case ID_SHOW_DEV_TOOLS:
	{
		ShowDevelopTools(browser, CefPoint(0,0));
		break;
	}
	default:
		break;
	}
	return false;
}

//开发选项
void CSimpleClient::ShowDevelopTools(CefRefPtr<CefBrowser> browser, const CefPoint& inspect_element_at) 
{
	CefWindowInfo windowInfo;
	CefBrowserSettings settings;
	windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools");
	browser->GetHost()->ShowDevTools(windowInfo, this, settings, CefPoint());
}

void CSimpleClient::CloseDevelopTools(CefRefPtr<CefBrowser> browser)
{
	browser->GetHost()->CloseDevTools();
}

bool CSimpleClient::DoClose(CefRefPtr<CefBrowser> browser)
{
	同一个browser可能有多个浏览器窗口(在新的子窗口打开链接,而不是在当前窗口跳转时会出现.),此时返回值可能会被用来做一些特别处理.想了解请参考官方demo.
	//if (CefCurrentlyOn(TID_UI))
	//{
	//	return true;
	//}
	return false;	//返回true取消关闭
}
void CSimpleClient::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
	if (m_BrowserHwnd == browser->GetHost()->GetWindowHandle())
	{// 浏览器窗口被销毁的话,browser指针置为NULL.
		m_cefBrowser = NULL;
	}

}

5.在主Dlg的OnInitDialog()函数中

	// TODO: 在此添加额外的初始化代码

	CefRefPtr<CSimpleClient> client(new CSimpleClient());
	m_simpleClient = client;

	CefRefPtr<ClientAppRender> app(new ClientAppRender());


	CefSettings settings;
	CefSettingsTraits::init(&settings);
	settings.multi_threaded_message_loop = true;
	settings.remote_debugging_port = 8088;//如果不定义,则不能运行调试工具
	settings.single_process = false;

	CefMainArgs mainArgs;

	CefRefPtr<CefApp> cefApp;
	cefApp = app;

	CefInitialize(mainArgs, settings, cefApp, NULL);

	RECT rect;
	GetClientRect(&rect);
	RECT rectnew = rect;
	rectnew.top = rect.top + 50;
	rectnew.bottom = rect.bottom;
	rectnew.left = rect.left;
	rectnew.right = rect.right;

	CefWindowInfo winInfo;
	winInfo.SetAsChild(GetSafeHwnd(), rectnew);

	std::wstring domain = GetInstallPath() + "test.html";
	//CefPostTask(TID_IO, NewCefRunnableMethod(manager.get(), &CefCookieManager::SetCookie, CefString(domain.c_str()), cookie, callback));

	CefBrowserSettings browserSettings;
	CefBrowserHost::CreateBrowser(winInfo, m_simpleClient, domain.c_str(), browserSettings, NULL);

5.运行程序

5.1需要将D:\cef_binary_3.2704.1434.gec3e9ed_windows32\Debug下面所有文件都拷贝到demo的Debug目录下,

还需要将D:\cef_binary_3.2704.1434.gec3e9ed_windows32\cefclient\Debug目录下的所有文件都拷贝到demo的Debug目录下

 

 

6.OK,运行效果如下:

参考链接:

https://blog.csdn.net/blackwoodcliff/article/details/74276848

https://blog.csdn.net/mushao999/article/details/37606189

 

欢迎加入我们的qq讨论群:184821652

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏克贝塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值