QT CEF3 消息循环处理

50 篇文章 2 订阅
15 篇文章 8 订阅

初次写博客,可能有点乱, 按照自己的实际经历谈一下CEF3钟遇到的一些坑,希望对以后的小伙有些帮助。

    先说一下经历,当初第一次接触CEF3的时候,没做特殊处理,直接将cef3封装成控件,嵌入到QT程序中,结果QT就响应不了鼠标事件了,后来经过查资料,发现是cef3的事件循环和QT的事件循环冲突了,所以QT处理不了鼠标事件了,就是鼠标只能点击网页有反应,点击QT控件就没反应。

    我们来看一下CEF的消息循环处理机制。cef事件消息循环有两种方式,一种是cef自己处理所有的消息事件(这种情况也就是将cef嵌入到QT中,QT控件都点不动的情况),另一种就是我们程序员手动去处理cef的消息事件(不用怕,这个很简单,就是调用cef的函数就行,具体调用的时机下面会讲到)。这两种消息处理的方式是通过设置

typedef CefStructBase<CefSettingsTraits> CefSettings;
CefSettings.multi_threaded_message_loop = true;//使用CEF3的自动的消息循环处理
// CefSettings.multi_threaded_message_loop = false;//需要程序员手动调用CEF的消息处理函数
// CefDoMessageLoopWork();//手动调用CEF的消息事件处理函数 

这里要讲一下手动调用cef事件处理函数的时机。一般情况下我们执行一次CefDoMessageLoopWork();是能处理一次事件循环,所以我们最好设置个定时器,每隔一段时间主动触发一下CefDoMessageLoopWork();

具体每隔多久触发一下这个值得商榷,如果间隔很小,处理的太频繁,对于资源浪费比较严重。但是如果间隔时间太久的话,会造成处理线程饿死。 我一般使用的都是10ms主动触发一下执行事件循环的函数。

所以结果就是程序刚一开始执行的时候,我们打开 定时器,程序关闭的时候关闭定时器,定时器间隔设置为10ms,槽函数就是CefDoMessageLoopWork();

好了,下面贴出来cef消息事件循环的类。

#ifndef WEBMESSAGEHELPER_H
#define WEBMESSAGEHELPER_H

#include <QObject>

class QTimer;
class WebMessageHelper : public QObject
{
    Q_OBJECT
public:
    static WebMessageHelper* instance();
    void postMessage(qint64 delay_ms);

    void start();
    void stop();

private:
    explicit WebMessageHelper(QObject *parent = 0);
signals:
    void newMessage();
private slots:
    void doWork();
private:
    QTimer* mTimer;
    static const int MESSGET_INTERVAL = 10;
};

#endif // WEBMESSAGEHELPER_H


#include "webmessagehelper.h"
#include "include/cef_app.h"
#include <QTimer>

WebMessageHelper::WebMessageHelper(QObject *parent)
                 :QObject(parent)
{
    mTimer = new QTimer(this);
    mTimer->setInterval(MESSGET_INTERVAL);
    mTimer->setSingleShot(false);
    connect(mTimer, &QTimer::timeout, this, &WebMessageHelper::doWork, Qt::QueuedConnection);
    connect(this, &WebMessageHelper::newMessage, this, &WebMessageHelper::doWork, Qt::QueuedConnection);
}

WebMessageHelper* WebMessageHelper::instance()
{
    static WebMessageHelper helper;
    return &helper;
}

void WebMessageHelper::doWork()
{
    CefDoMessageLoopWork();
}

void WebMessageHelper::postMessage(qint64 delay_ms)
{
    if(delay_ms > 0)
    {
        delay_ms = delay_ms > 20 ? 20 : delay_ms;
        QTimer::singleShot(delay_ms, this, &WebMessageHelper::newMessage);
    }
    else
    {
        emit newMessage();
    }
}

void WebMessageHelper::start()
{
    mTimer->start();
}

void WebMessageHelper::stop()
{
    mTimer->stop();
}

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
下面是一个示例程序,展示了如何在 MFC 中集成 CEF3消息循环: ``` #include "stdafx.h" #include "MyApp.h" #include "MyFrame.h" CMyApp theApp; BOOL CMyApp::InitInstance() { // 初始化 CEF3 的设置 CefMainArgs main_args(GetModuleHandle(NULL)); CefRefPtr<CefApp> app(new CMyApp); CefInitialize(main_args, app, NULL); // 创建主窗口 CMyFrame* pFrame = new CMyFrame; if (!pFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pFrame; // 创建 CEF3 的浏览器对象 CefWindowInfo window_info; window_info.SetAsChild(pFrame->GetSafeHwnd(), CRect(0, 0, 800, 600)); CefBrowserSettings browser_settings; CefRefPtr<CefClient> client(new CMyClient); CefBrowserHost::CreateBrowser(window_info, client, _T("http://www.baidu.com"), browser_settings, NULL); // 运行消息循环 Run(); // 关闭 CEF3 CefShutdown(); return TRUE; } void CMyApp::Run() { CefRefPtr<CefMessageLoop> message_loop = CefMessageLoop::GetForCurrentThread(); while (!m_bExit) { message_loop->Run(); // 运行 CEF3消息循环 CWinApp::OnIdle(); // 处理 MFC 的空闲消息 } } int CMyApp::ExitInstance() { // 关闭 CEF3 的浏览器对象 browser->CloseBrowser(true); browser = NULL; // 停止 CEF3消息循环 CefQuitMessageLoop(); return CWinApp::ExitInstance(); } ``` 在上面的示例程序中,我们在 MFC 应用程序的 InitInstance 函数中创建了 CEF3 的浏览器对象,并在 Run 函数中加入了 CEF3消息循环。在 ExitInstance 函数中关闭了 CEF3 的浏览器对象,并停止了 CEF3消息循环

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值