分享Duilib中基于wke的浏览器控件
文章转自王牌软件
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
只回答业务咨询
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
概述
wke是基于谷歌chrome浏览器源代码的裁剪版本,大小仅仅只有10M左右,无需依赖其他的扩展库(跟CEF的一大堆大约40M的DLL来比简直爽呆了),就可以在本地使用谷歌内核快速加载网页。网上也有基于wke在Duilib 上扩展的控件代码,其实wke头文件挺清楚的了,接口一目了然,特别是JS与C++交互的函数更是容易看懂,也没什么难的,你也可以做到的。
代码
毕竟是裁剪库,有的功能还是没有接口来处理的(比如网页加载前、页面跳转、菜单消息……),头文件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
#ifndef __UIWKEWEBKIT_H_ #define __UIWKEWEBKIT_H_ #pragma once #include "wke.h" #include <string> using std::wstring; namespace DuiLib { /////////////////////////////////////////// //网页加载状态改变的回调 class CWkeWebkitLoadCallback { public: virtual void OnLoadFailed()=0; virtual void OnLoadComplete()=0; virtual void OnDocumentReady()=0; }; /////////////////////////////////////////// //网页标题、地址改变的回调 class CWkeWebkitClientCallback { public: virtual void OnTitleChange(const CDuiString& strTitle)=0; virtual void OnUrlChange(const CDuiString& strUrl)=0; }; class CWkeWebkitUI : public CControlUI, public wkeBufHandler { public: CWkeWebkitUI(void); ~CWkeWebkitUI(void); virtual void onBufUpdated (const HDC hdc,int x, int y, int cx, int cy); virtual LPCTSTR GetClass()const; virtual LPVOID GetInterface(LPCTSTR pstrName); virtual void DoEvent(TEventUI& event); virtual void DoPaint(HDC hDC, const RECT& rcPaint); virtual void SetPos(RECT rc); virtual void DoInit(); virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue); ////////////////////////////////////// const wstring& GetUrl()const ; bool CanGoBack() const; bool GoBack(); bool CanGoForward() const; bool GoForward(); void StopLoad(); void Refresh(); wkeWebView GetWebView(); void SetLoadCallback(CWkeWebkitLoadCallback* pCallback); CWkeWebkitLoadCallback* GetLoadCallback(); void Navigate(LPCTSTR lpUrl); void LoadFile(LPCTSTR lpFile); void LoadHtml(LPCTSTR lpHtml); protected: void StartCheckThread(); void StopCheckThread(); static void OnTitleChange(const struct _wkeClientHandler* clientHandler, const wkeString title); static void OnUrlChange(const struct _wkeClientHandler* clientHandler, const wkeString url); private: static int m_bWebkitCount; HANDLE m_hCheckThread; wstring m_strUrl; wkeWebView m_pWebView; wkeClientHandler m_ClientHandler; CWkeWebkitLoadCallback* m_pLoadCallback; CWkeWebkitClientCallback* m_pClientCallback; }; } #endif//__UIWKEWEBKIT_H_ |
实现部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
#include "StdAfx.h" #include "UIWkeWebkit.h" #pragma comment(lib, "DuiEx/wke/wke") namespace DuiLib{ /////////////////////////////////////////////////// //网页加载状态监测线程 DWORD WINAPI CheckThreadFun(LPVOID lpParam) { CWkeWebkitUI* pWebkitUI=(CWkeWebkitUI*)lpParam; wkeWebView pWebView=pWebkitUI->GetWebView(); if ( NULL == pWebView ) return 1; CWkeWebkitLoadCallback* pCallback=pWebkitUI->GetLoadCallback(); if ( NULL == pCallback ) return 1; bool bOver=false; while( !pWebView->isLoaded() ) { if ( !bOver && pWebView->isDocumentReady() ) { pCallback->OnDocumentReady(); bOver=true; } if ( pWebView->isLoadFailed() ) { pCallback->OnLoadFailed(); return 1; } ::Sleep(30); } if ( pWebView->isLoadComplete() ) pCallback->OnLoadComplete(); return 0; } ////////////////////////////////////////////////////// int CWkeWebkitUI::m_bWebkitCount=0; CWkeWebkitUI::CWkeWebkitUI(void) :m_pWebView(NULL) ,m_hCheckThread(NULL) ,m_pLoadCallback(NULL) ,m_pClientCallback(NULL) { if ( 0 == m_bWebkitCount ) wkeInit(); m_pWebView=wkeCreateWebView(); m_pWebView->setBufHandler(this); m_ClientHandler.onTitleChanged =&CWkeWebkitUI::OnTitleChange; m_ClientHandler.onURLChanged =&CWkeWebkitUI::OnUrlChange; m_bWebkitCount++; } CWkeWebkitUI::~CWkeWebkitUI(void) { StopCheckThread(); m_pManager->KillTimer(this); wkeDestroyWebView(m_pWebView); m_bWebkitCount--; if ( 0 == m_bWebkitCount ) wkeShutdown(); } LPCTSTR CWkeWebkitUI::GetClass() const { return L"WkeWebkitUI"; } LPVOID CWkeWebkitUI::GetInterface( LPCTSTR pstrName ) { if( _tcscmp(pstrName, _T("WkeWebkit")) == 0 ) return static_cast<CWkeWebkitUI*>(this); return CControlUI::GetInterface(pstrName); } void CWkeWebkitUI::DoEvent( TEventUI& event ) { switch( event.Type ) { case UIEVENT_SETFOCUS: if ( m_pWebView ) m_pWebView->focus(); break; case UIEVENT_KILLFOCUS: if ( m_pWebView ) m_pWebView->unfocus(); break; case UIEVENT_WINDOWSIZE: if ( m_pWebView ) m_pWebView->resize(GET_X_LPARAM(event.lParam), GET_Y_LPARAM(event.lParam)); break; case UIEVENT_CHAR: { if ( NULL == m_pWebView ) break; unsigned int charCode = event.wParam; unsigned int flags = 0; if (HIWORD(event.lParam) & KF_REPEAT) flags |= WKE_REPEAT; if (HIWORD(event.lParam) & KF_EXTENDED) flags |= WKE_EXTENDED; bool bHandled=m_pWebView->keyPress(charCode, flags, false); if ( bHandled ) return ; break; } case UIEVENT_KEYDOWN: { if ( NULL == m_pWebView ) break; unsigned int flags = 0; if (HIWORD(event.lParam) & KF_REPEAT) flags |= WKE_REPEAT; if (HIWORD(event.lParam) & KF_EXTENDED) flags |= WKE_EXTENDED; bool bHandled=m_pWebView->keyDown(event.wParam, flags, false); if ( event.wParam == VK_F5 ) Refresh(); if ( bHandled ) return ; break; } case UIEVENT_KEYUP: { if ( NULL == m_pWebView ) break; unsigned int flags = 0; if (HIWORD(event.lParam) & KF_REPEAT) flags |= WKE_REPEAT; if (HIWORD(event.lParam) & KF_EXTENDED) flags |= WKE_EXTENDED; bool bHandled=m_pWebView->keyUp(event.wParam, flags, false); if ( bHandled ) return ; break; } case UIEVENT_CONTEXTMENU: { if ( NULL == m_pWebView ) break; unsigned int flags = 0; if (event.wParam & MK_CONTROL) flags |= WKE_CONTROL; if (event.wParam & MK_SHIFT) flags |= WKE_SHIFT; if (event.wParam & MK_LBUTTON) flags |= WKE_LBUTTON; if (event.wParam & MK_MBUTTON) flags |= WKE_MBUTTON; if (event.wParam & MK_RBUTTON) flags |= WKE_RBUTTON; bool handled = m_pWebView->contextMenuEvent(event.ptMouse.x, event.ptMouse.y, flags); if ( handled ) return ; break; } case UIEVENT_MOUSEMOVE: case UIEVENT_BUTTONDOWN: case UIEVENT_BUTTONUP: case UIEVENT_RBUTTONDOWN: case UIEVENT_DBLCLICK: { HWND hWnd=m_pManager->GetPaintWindow(); if ( event.Type == UIEVENT_BUTTONDOWN ) { ::SetFocus(hWnd); SetCapture(hWnd); } else if ( event.Type == UIEVENT_BUTTONUP ) ReleaseCapture(); unsigned int flags = 0; if (event.wParam & MK_CONTROL) flags |= WKE_CONTROL; if (event.wParam & MK_SHIFT) flags |= WKE_SHIFT; if (event.wParam & MK_LBUTTON) flags |= WKE_LBUTTON; if (event.wParam & MK_MBUTTON) flags |= WKE_MBUTTON; if (event.wParam & MK_RBUTTON) flags |= WKE_RBUTTON; UINT uMsg=0; switch ( event.Type ) { case UIEVENT_BUTTONDOWN: uMsg=WM_LBUTTONDOWN; break; case UIEVENT_BUTTONUP: uMsg=WM_LBUTTONUP; break; case UIEVENT_RBUTTONDOWN: uMsg=WM_RBUTTONDOWN; break; case UIEVENT_DBLCLICK: uMsg=WM_LBUTTONDBLCLK; break; case UIEVENT_MOUSEMOVE: uMsg=WM_MOUSEMOVE; break; } bool bHandled = m_pWebView->mouseEvent(uMsg, event.ptMouse.x-m_rcItem.left, \ event.ptMouse.y-m_rcItem.top, flags); if ( bHandled ) return ; break; } case UIEVENT_TIMER: if ( m_pWebView ) m_pWebView->tick(); break; case UIEVENT_SCROLLWHEEL: { POINT pt; pt.x = LOWORD(event.lParam); pt.y = HIWORD(event.lParam); int nFlag=GET_X_LPARAM(event.wParam); int delta = (nFlag==SB_LINEDOWN)?-120:120; unsigned int flags = 0; if (event.wParam & MK_CONTROL) flags |= WKE_CONTROL; if (event.wParam & MK_SHIFT) flags |= WKE_SHIFT; if (event.wParam & MK_LBUTTON) flags |= WKE_LBUTTON; if (event.wParam & MK_MBUTTON) flags |= WKE_MBUTTON; if (event.wParam & MK_RBUTTON) flags |= WKE_RBUTTON; bool handled = m_pWebView->mouseWheel(pt.x, pt.y, delta, flags); if ( handled ) return ; break; } default: CControlUI::DoEvent(event); break; } } void CWkeWebkitUI::DoPaint( HDC hDC, const RECT& rcPaint ) { if ( m_pWebView ) { RECT rcInsert; IntersectRect(&rcInsert, &m_rcItem, &rcPaint); m_pWebView->paint(hDC, rcInsert.left, rcInsert.top, \ rcInsert.right-rcInsert.left, rcInsert.bottom-rcInsert.top, \ rcInsert.left-m_rcItem.left, rcInsert.top-m_rcItem.top, true); } } void CWkeWebkitUI::onBufUpdated( const HDC hdc,int x, int y, int cx, int cy ) { RECT rcValide={ x, y, x+cx, y+cy }; ::OffsetRect(&rcValide, m_rcItem.left, m_rcItem.top); HWND hWnd=m_pManager->GetPaintWindow(); ::InvalidateRect(hWnd, &rcValide, TRUE); } void CWkeWebkitUI::Navigate( LPCTSTR lpUrl ) { if ( m_pWebView ) { m_pWebView->loadURL(lpUrl); StartCheckThread(); } } void CWkeWebkitUI::SetPos( RECT rc ) { CControlUI::SetPos(rc); if ( m_pWebView ) m_pWebView->resize(rc.right-rc.left, rc.bottom-rc.top); } void CWkeWebkitUI::DoInit() { if ( !m_strUrl.empty() ) Navigate(m_strUrl.c_str()); m_pManager->SetTimer(this, 100, 100); } void CWkeWebkitUI::StartCheckThread() { StopCheckThread(); m_hCheckThread=::CreateThread(NULL, 0, CheckThreadFun, this, 0, NULL); } void CWkeWebkitUI::StopCheckThread() { if ( m_hCheckThread ) { if ( ::WaitForSingleObject(m_hCheckThread, 10) != WAIT_OBJECT_0 ) ::TerminateThread(m_hCheckThread, 0); ::CloseHandle(m_hCheckThread); m_hCheckThread = NULL; } } bool CWkeWebkitUI::CanGoBack() const { return m_pWebView?m_pWebView->canGoBack():false; } bool CWkeWebkitUI::GoBack() { return m_pWebView?m_pWebView->goBack():false; } bool CWkeWebkitUI::CanGoForward() const { return m_pWebView?m_pWebView->canGoForward():false; } bool CWkeWebkitUI::GoForward() { return m_pWebView?m_pWebView->goForward():false; } void CWkeWebkitUI::StopLoad() { if ( m_pWebView ) m_pWebView->stopLoading(); } void CWkeWebkitUI::Refresh() { if ( m_pWebView ) { StopCheckThread(); m_pWebView->reload(); StartCheckThread(); } } wkeWebView CWkeWebkitUI::GetWebView() { return m_pWebView; } void CWkeWebkitUI::SetLoadCallback( CWkeWebkitLoadCallback* pCallback ) { m_pLoadCallback=pCallback; } CWkeWebkitLoadCallback* CWkeWebkitUI::GetLoadCallback() { return m_pLoadCallback; } void CWkeWebkitUI::OnTitleChange( const struct _wkeClientHandler* clientHandler, const wkeString title ) { } void CWkeWebkitUI::OnUrlChange( const struct _wkeClientHandler* clientHandler, const wkeString url ) { } void CWkeWebkitUI::LoadFile( LPCTSTR lpFile ) { if ( m_pWebView ) m_pWebView->loadFile(lpFile); } void CWkeWebkitUI::LoadHtml( LPCTSTR lpHtml ) { if ( m_pWebView ) m_pWebView->loadHTML(lpHtml); } const wstring& CWkeWebkitUI::GetUrl() const { return m_strUrl; } void CWkeWebkitUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue ) { if ( _tcscmp(pstrName, _T("url")) == 0 ) m_strUrl = pstrValue; else CControlUI::SetAttribute(pstrName, pstrValue); } } |
解析:
主要处理的就是消息部分,把这个区域的那种消息分发给wke的接口去处理。另外就是加了个线程,检测网页加载状态,通过回调通知网页加载完成、失败、DOC完成(需要用户先初始化回调指针才会通知用户)。
控件定义完成后,我们需要来配置XML了:
放在一个布局里面,指定URL即可,你也可以加上其他属性然后在SetAttribute中对这些属性进行初始化。
运行程序,一个无窗口的chrome内核网页控件就展示出来了:
学习日记,兼职软件设计,软件修改,毕业设计。
本文出自 学习日记,转载时请注明出处及相应链接。
本文永久链接: https://www.softwareace.cn/?p=1615