概述 wke是基于谷歌chrome浏览器源代码的裁剪版本,大小仅仅只有10M左右,无需依赖其他的扩展库(跟CEF的一大堆大约40M的DLL来比简直爽呆了),就可以在本地使用谷歌内核快速加载网页。网上也有基于wke在Duilib 上扩展的控件代码,其实wke头文件挺清楚的了,接口一目了然,特别是JS与C++交互的函数更是容易看懂,也没什么难的,你也可以做到的。
代码 毕竟是裁剪库,有的功能还是没有接口来处理的(比如网页加载前、页面跳转、菜单消息……),头文件代码:
放在一个布局里面,指定URL即可,你也可以加上其他属性然后在SetAttribute中对这些属性进行初始化。
运行程序,一个无窗口的chrome内核网页控件就展示出来了:
转自:疯狂-的-蜗牛
代码 毕竟是裁剪库,有的功能还是没有接口来处理的(比如网页加载前、页面跳转、菜单消息……),头文件代码:
#ifndef __UIWKEWEBKIT_H_ #define __UIWKEWEBKIT_H_ #pragma once #include "wke.h" #include实现部分代码: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_
#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(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内核网页控件就展示出来了:

转自:疯狂-的-蜗牛
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2313
- 用户1336
- 访客11759002
每日一句
Happiness depends on your mindset.
幸福取决于你的心态。
幸福取决于你的心态。
新会员