CEF的详细关闭流程参考:https://blog.csdn.net/louis_815/article/details/76269057

通过上述博客我们首先需要明白WM_CLOSE,会在什么情况下触发:

  1. CefBrowserHost::CloseBrowser(false)
  2. 用户主动关闭窗口,发送WM_CLOSE

那么如果一个wnd拥有多个浏览器窗口(eg:多标签浏览器)。那么每关闭一次浏览器标签都会触发WM_CLOSE。此时我们就要决定何时以及怎么处理WM_CLOSE,抛弃还是交给系统处理??

为了方便处理WM_CLOSE,需要优化WM_CLOSE通知策略。对于开发者而言,CloseBrowser(false)产生的WM_CLOSE不需要关心,只需要关心用户到底是想关闭整个程序还是其中某一个网页?

优化策略:

  1. 将CloseBrowser(false)产生的WM_CLOSE丢给桌面窗口(对桌面没影响)
  2. 打标是否需要关闭应用程序,如果需要关闭的话,则在WM_CLOSE里面打标,并且关闭所有的网页窗口,当所有的网页窗口关闭完成的时候,投递WM_CLOSE给主窗口,然后关闭程序。

优化代码(一个网页窗口对应一个CefClient,外部管理CefClient):
创建Browser:

CefRefPtr<CBrowserHandler> CBrowserApp::CreateBrowser(HWND hParentWnd,std::string url)
{.....//每次人为CreateBroswer的时候创建一个对应的CBrowserHandler//如果是通过网页内部打开或者ShowDevTool则共享CBrowserHandler,所以在共享句柄内部需要管理BrowserCefRefPtr<CBrowserHandler> simple_handler = new CBrowserHandler(hParentWnd);CefBrowserSettings browser_settings;CefBrowserHost::CreateBrowser(wnd_info, simple_handler, url, browser_settings, NULL);return simple_handler;
}

管理类:

class CBrowserHandlerMgr
{typedef std::map<int,CefRefPtr<CBrowserHandler> > vMapIDBrowsersHandler;
public:...void CBrowserHandlerMgr::AddBrowser(int nBrowserID, CefRefPtr<CBrowserHandler> pHandler){//不能仅仅以pHandler为,因为可能一个Handler附加多个BrowserCCritical lk(m_cs);if (!pHandler || !pHandler.get()) return;bool bExist = false;//理论上这句应该不成功assert(m_vMapIDBrowsers.count(nBrowserID) <= 0);m_vMapIDBrowsers[nBrowserID] = pHandler;}void CBrowserHandlerMgr::RemoveBrowser(int nBrowserID, CefRefPtr<CBrowserHandler> pHandler){bool bEmpty = false;{CCritical lk(m_cs);if (!pHandler || !pHandler.get()) return ;m_vMapIDBrowsers.erase(nBrowserID);bEmpty = m_vMapIDBrowsers.empty();}//如果打标为quit,则退出if (m_hQuitWnd != NULL && bEmpty)::PostMessage(m_hQuitWnd, WM_CLOSE, 0, 0);}void CBrowserHandlerMgr::CloseBrowser(int nBrowserID){//防止长时间占用,导致死锁CefRefPtr<CBrowserHandler> pHandler = NULL;{CCritical lk(m_cs);if (m_vMapIDBrowsers.count(nBrowserID))pHandler = m_vMapIDBrowsers[nBrowserID];}if (pHandler && pHandler.get()){//为了避免更换父窗口的时候闪现白屏,先隐藏窗口,在关闭::ShowWindow(pHandler->GetBrowser(nBrowserID)->GetHost()->GetWindowHandle(), SW_HIDE);::SetParent(pHandler->GetBrowser(nBrowserID)->GetHost()->GetWindowHandle(), GetDesktopWindow());return pHandler->CloseBrowser(nBrowserID);}}//如果HQuitWnd不为空,则退出应用程序void CBrowserHandlerMgr::CloseAllBrowser(HWND hQuitWnd){vMapIDBrowsersHandler vTempBrowsers;{CCritical lk(m_cs);m_hQuitWnd = hQuitWnd;vTempBrowsers = m_vMapIDBrowsers;}for (vMapIDBrowsersHandler::iterator it = vTempBrowsers.begin(); it != vTempBrowsers.end();++it){if (it->second && it->second.get()){//由于一个窗口作为多个Browser的父窗口,为了防止WM_CLOSE捣鬼,需要更换brower的父窗口//如果一个窗口仅仅作为一个Browser的父窗口,那么可以不需要切换brower的父窗口,正常处理即可//为了避免更换父窗口的时候闪现白屏,先隐藏窗口,在关闭::ShowWindow(it->second->GetBrowser(it->first)->GetHost()->GetWindowHandle(), SW_HIDE);::SetParent(it->second->GetBrowser(it->first)->GetHost()->GetWindowHandle(), GetDesktopWindow());it->second->CloseBrowser(it->first);}}}bool CBrowserHandlerMgr::IsCanClose(){CCritical lk(m_cs);return m_vMapIDBrowsers.empty();}...
private:vMapIDBrowsersHandler m_vMapIDBrowsers;HWND m_hQuitWnd;//当需要关闭APP的时候指定,否则当浏览器数量为0的时候会误通知WM_CLOSECRITICAL_SECTION m_cs;
};

Render进程事件处理类:

class CBrowserHandler:public CefClient,public CefDisplayHandler,public CefLifeSpanHandler,public CefLoadHandler
{void CBrowserHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {CEF_REQUIRE_UI_THREAD();...//增加到管理类CBrowserHandlerMgr::instance()->AddBrowser(browser->GetIdentifier(),this);// Add to the list of existing browsers.m_vMapIDBrowser[browser->GetIdentifier()] = browser;...}void CBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {CEF_REQUIRE_UI_THREAD();CBrowserHandlerMgr::instance()->RemoveBrowser(browser->GetIdentifier(), this);}void CBrowserHandler::CloseBrowser(int nBrowserID){CefRefPtr<CefBrowser> pBrowser = GetBrowser(nBrowserID);if (pBrowser && pBrowser.get()){pBrowser->GetHost()->CloseBrowser(false);}        }bool CBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser) {CEF_REQUIRE_UI_THREAD();//释放Browser引用int nBrowserID = browser->GetIdentifier();m_vMapIDBrowser[nBrowserID] = NULL;m_vMapIDBrowser.erase(nBrowserID);return false;}
}

主窗口WM_CLOSE消息处理

void CCefDemoDlg::OnClose()
{// TODO:  在此添加消息处理程序代码和/或调用默认值//因为CefClient关闭的时候更改了窗口句柄,所以投递的WM_CLOSE当前窗口并不会收到,此时我们可能只是关闭某个标签并不需要关闭浏览器if (m_browser_app && m_browser_app.get() && m_browser_app->CloseAllBrowser(GetSafeHwnd()) && !m_browser_app->isCanClosed())return;CDialogEx::OnClose();
}

CEF 关闭流程优化相关推荐

  1. 协同工作流引擎,开启流程优化新纪元

    2019独角兽企业重金招聘Python工程师标准>>> 协同工作流引擎(Synchro flow)是业界领先的企业业务流程自动化的基础平台产品以及企业流程再造的核心产品,提供以业务建 ...

  2. APDPlat的系统启动和关闭流程剖析

    2019独角兽企业重金招聘Python工程师标准>>> APDPlat接管了Spring的启动关闭权,为各种运行其上的开源框架和类库的无缝集成提供了支持. 当然,大家都知道,一个JA ...

  3. mysql启动关闭步骤_MYSQL的连接管理与启动关闭流程

    1.mysql启动关闭流程 1.启动数据库 1.systemctl start mysqld 2./etc/init.d/mysqld start 3.mysqld_safe --defaults-f ...

  4. Android WiFi 打开关闭流程

    本文简单介绍下WiFi打开与关闭流程,参考源码Android P. 一.WiFi 开机自动打开流程 系统服务启动的时候会启动WifiService,在SystemService.PHASE_SYSTE ...

  5. 华为:实现流程优化的方法

    掌握速度优势,只有速度足够快的企业才能继续生存下去:打破惯性思维,正向逆向梳理:精简冗余,爱上分析工作流程图:合并同类项,去劣存优释放生产能力:多维度合理规划,时间地点人物都要考虑到. 掌握速度优势- ...

  6. 以业务改进为目标的流程优化方法

    公众号回复:干货,领取价值58元/套IT管理体系文档 公众号回复:ITIL教材,领取最新ITIL4中文教材 正文 企业在流程优化过程中会面临以下方面的问题: 第一个问题:有的企业制定好了战略,但是对于 ...

  7. 康青老师--产品开发IPD流程和研发项目管理--流程建设和流程优化-沪师经纪刘建

    康青老师 产品研发IPD流程和项目管理实战专家 20年产品研发和项目管理工作经验 洞悉中国企业产品规划和项目管理的困局和破解之道 *项目管理协会PMP,*-ACP认证专家 华为研发项目管理RDPM认证 ...

  8. 逾期催收管理流程优化与催收系统配置

    在目前强监管的形势下,各路政策一直升级.比如对于逾期客户的触达,自2021年的11月31起,一般对客户的催收已经明文规定一天内不能超过六次.这里的次数是以对一个客户的有限触达而言,就是你通知到他欠款的 ...

  9. 从项目管理角度谈OA流程优化

    企业流程管理的目的是提升企业管理和优化企业的业务流程,从而创造更多的效益.OA流程的改进,能大大提高工作的效率,而现在公司的OA流程自上线以来,很多流程已显得异常的繁琐,因此公司也急迫需要对流程进行优 ...

最新文章

  1. 使用EF框架实现MVC的增删改查功能!!!Entity Framework
  2. 德华安顾人寿签约神策数据,精耕数字化加速保险服务质效升级
  3. 综合模拟试题计算机指南,综合全国计算机文管二级模拟试题.doc
  4. java 置顶_[置顶]java开发之基础篇2
  5. 控制用户的访问之权限、角色【weber出品必属精品】
  6. css 类别选择器 并集,CSS常用选择器
  7. 【笔记】LR录制方式和常用函数
  8. tomcat多实例的端口设置
  9. 计算机那种专业包括vr,VR技术的大学专业有哪些
  10. 微运行库2015_vc++2015运行库下载_vc++2015运行库64位官方下载「vc2015」-太平洋下载中心...
  11. cam_lidar_calib激光雷达和相机联合标定
  12. Codeforces Round #614 (Div. 2)A. ConneR and the A.R.C. Markland-N
  13. 工作9年的程序员几点感受
  14. JavaScript 日期处理类库 --- Moment.js
  15. 字节跳动大数据中心17万服务器硬实力支撑今日头条等产品线(公号回复“字节跳动”下载PDF典型资料,欢迎转发、赞赏支持科普)
  16. 高等代数 :2 行列式
  17. java批量生成二维码图片,并打包成zip
  18. 窃听风云下载_窃听风云高清下载_窃听风云在线观看
  19. Unity Input 通过蓝牙手柄控制游戏
  20. Go并发原语/并发组件/go并发核心语法 之channel

热门文章

  1. 我的U盘啊!CHK、FAT和其他。
  2. Jupyter Notebook 最全快捷键(逐渐补充)
  3. Ubuntu16.04安装caffe问题总结以及解决方案
  4. 六张图看透孙权和刘备管理的成与败
  5. 适合游戏建模的笔记本推荐
  6. 消失了一年,我都干了些什么?
  7. 刀塔传奇装备系统分析
  8. 第二章《计算机系统》复习测试,职中计算机应用基础第二章测试题及答案
  9. cmake源码静态编译
  10. 打工人必学的法律知识(二)——《中华人民共和国劳动合同法》必知必会