Qt内嵌CEF思路

客户端和网页交互,为了兼容网页各种功能,经比较选择CEF框架内嵌web网页;

首先,从cef简单示例可知其框架使用大概流程,兼容Qt的大概如下:

int main(int argc, char *argv[])
{
void* sandbox_info = NULL;
#if defined(CEF_USE_SANDBOX)
CefScopedSandboxInfo scoped_sandbox;
sandbox_info = scoped_sandbox.sandbox_info();//沙盒指针是用来隔离层与层的接口的,起安全作用;
#endif
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);//获取一个应用程序或动态链接库的模块句柄。只有在当前进程的场景中,这个句柄才会有效。
//每个子进程运行时使用运行行来指定配置信息并通过CefMainArgs结构传递给CefExecuteProcess函数,CefMainArgs结构是跨平台的。
CefMainArgs main_args(hInstance);
CefRefPtr app(new CefClientApp());//获取cefapp进程接口实例
int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);//启动进程
if (exit_code >= 0)
{
return exit_code;

}

        NewApp mainApp( argc,argv);//Qt框架下的运行

// Specify CEF global settings here.
CefSettings settings;
settings.no_sandbox = true;

CefInitialize(main_args, settings,app.get(), NULL);//初始化Cef框架

      //CefRunMessageLoop();

int ret=  mainApp.exec();
//CefDoMessageLoopWork();
CefShutdown();
return ret;
}

正常情况下,仅仅是win32的话,单进程情况下使用CefRunMessageLoop();而在Qt中,也需要使用mainApp.exec();这都会造成线程阻塞,导致某个模块无法响应。这里我的做法是QApplication中某个子类或者就本身中,有一个QTimer,用于响应一个cef单出执行的函数,CefDoMessageLoopWork();其实这个函数与Qt里面的QApplication::process Events()很类似,避免阻塞造成无法响应;由于CEF是多进程架构,所以在使用的时候一定要注意,先对cef初始化后再创建QApplication这个实例,否则会出现一些怪怪的(我的水平无法知道原因的)bug


而主要的就是网页的内嵌了,这里可以自己写一个也可以使用demo中的hander,写为单例模式:创建网页方式如下:

CefRefPtr handler(NewCefHander::GetInstance());//单例模式下的浏览器处理器,用于处理浏览器相关操作及响应
// // Information used when creating the native window.
CefWindowInfo window_info;//准备创建窗口的窗口信息
#if defined(OS_WIN)
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right =QApplication::desktop()->size().width();//m_MainWnd->size().width();
rect.bottom = QApplication::desktop()->size().height();//m_MainWnd->size().height();
window_info.SetAsPopup(NULL, "cefsimple");//设置父窗口和名字
//window_info.SetAsChild(m_NewMainWindow?m_NewMainWindow->m_CenWidgetID:nullptr,rect);//这里也可以设置显示在某窗口某位置,作为子窗口,进程间内嵌窗口,一般使用这个,但是大小是固定的,需要自己重写某些事件调整网页在窗口中的大小,参数就是窗口句柄和大小
#endif
// Specify CEF browser settings here.//浏览器设置
CefBrowserSettings browser_settings;//这里可以设置一些浏览器属性,否则使用默认设置
// Check if a "--url=" value was provided via the command-line. If so, use
// that instead of the default URL.检查命令行是否有网页地址,如果没有,选择百度,这里根据需求灵活处理,也可封装函数传入地址
CefRefPtr command_line =CefCommandLine::GetGlobalCommandLine();
std::string url= command_line->GetSwitchValue("url");
if (url.empty())
url="http://www.baidu.com";//设置默认主页
// Create the first browser window.
//第一个参数表示该窗口情况,比如父窗口,比如名字、格式大小等
//第二个参数是
//第三个参数是网页地址
//第四个参数是浏览器设置

CefBrowserHost::CreateBrowser(window_info, handler.get(), url,browser_settings, NULL);//这样网页窗口就创建成功了

当然cef还有很多很多很多需要初学者去爬的问题,比如,创建出来的exe,需要和二进制文件*.pak同一目录下,否则初始化cef框架时就直接内存报错;

最好是使用进程间通信模式,自己封装一个口令自己处理,重写winEvent()函数而已。主要用SendMessage或者PostMessage来互相发送指令,而同步和异步需要因情况来封装。一般而言,网页都需要用容器来管理比较合适。一个简单的思路,其他进程SendMessage()的,copydata这种(这种只能用SendMessage),可以先接受着,保存在自己的队列里面,然后再post给自己,就不会影响进程间通信了。

你可能感兴趣的:(Qt内嵌CEF思路)