您的位置:首页 > 产品设计 > UI/UE

[原创]升级SOUI WKE以支持_blank

2016-04-12 16:13 375 查看
由于WKE的精简模式,导致原有的SOUI不支持针对诸多内容的调用,此处针对WKE的部分内容做升级,以支持对应的功能。

目的:使WKE可以_blank弹出新窗口。

由国人 海绵宝宝维护的WKE新分支:https://github.com/cexer/wke

编译新WKE的方式很简单:

1、下载master,并解压缩,如果有git就自己clone一下就好了

2、运行根目录下的vs2008.bat,打开后直接编译即可,时间根据CPU不同而不同。

SOUI的模式是动态加载函数,所以参考一下WKE头文件,即可完成函数调用。

特别注意,SOUI的WKE.DLL中已经将WKE封装为类,此处的WKE.DLL内是纯C函数,无类,所以我们要自己写。

如果懒得自己写动态接口,就直接引用WKE.H就好了,然后连接一下WKE.LIB(这样只是不太好剥离或按目录加载库)。

由于本人巨懒,懒癌晚期,所以我直接引用lib了,哈哈哈。

直接上点干货

/*!
* \file SWkeWebkitEx.h
* \date 2016/04/12 14:31
*
* \author koangel
* Contact: jackliu100@gmail.com
*
* \brief 针对新版本WKE的封装,使用C函数版本
*
* 为了区分改为SWkeWbkitEx名,与之前版本不冲突。
*/
#pragma once
#include <wke.h>

#pragma comment(lib,"wke.lib")

namespace SOUI
{
// 此处改为自己渲染程序
class SWkeRenderGDI
{
public:
SWkeRenderGDI()
:m_hView(NULL)
, m_hDC(NULL)
, m_hBitmap(NULL)
, m_pixels(NULL)
, m_width(0)
, m_height(0)
{
}

virtual ~SWkeRenderGDI()
{
if (m_hDC)
DeleteDC(m_hDC);

if (m_hBitmap)
DeleteObject(m_hBitmap);
}

virtual bool init(HWND hView)
{
m_hView = hView;
m_hDC = CreateCompatibleDC(0);

RECT rect;
GetClientRect(hView, &rect);
resize(rect.right, rect.bottom);
return true;
}

virtual void destroy()
{
delete this;
}

virtual void resize(unsigned int w, unsigned int h)
{
if (m_width == w && m_height == h)
return;

m_width = w;
m_height = h;
m_pixels = NULL;
}

virtual void render(wkeWebView webView)
{
if (wkeIsDirty(webView))
{
if (m_pixels == NULL)
createBitmap();

wkePaint2(webView, m_pixels, 0);

HDC hDC = GetDC(m_hView);
BitBlt(hDC, 0, 0, m_width, m_height, m_hDC, 0, 0, SRCCOPY);
ReleaseDC(m_hView, hDC);
}
}

void createBitmap()
{
BITMAPINFO bi;
memset(&bi, 0, sizeof(bi));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = int(m_width);
bi.bmiHeader.biHeight = -int(m_height);
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;

HBITMAP hbmp = ::CreateDIBSection(0, &bi, DIB_RGB_COLORS, &m_pixels, NULL, 0);

SelectObject(m_hDC, hbmp);

if (m_hBitmap)
DeleteObject(m_hBitmap);

m_hBitmap = hbmp;
}

private:
HWND m_hView;
HBITMAP m_hBitmap;
HDC m_hDC;
unsigned int m_width;
unsigned int m_height;
void* m_pixels;
};

const char TM_TICKER = 1;
class SWkeWebkitEx :
public SWindow,protected IIdleHandler
{
SOUI_CLASS_NAME(SWkeWebkit, L"wkeWebkit")
public:
SWkeWebkitEx();
virtual ~SWkeWebkitEx();

// 初始化WKE
static void SWkeInit();
// 销毁WKE
static void SWkeFinalize();

wkeWebView    GetWebView() { return m_pWebView; }
protected:
virtual BOOL OnIdle();
protected:
int OnCreate(void *);
void OnDestroy();
void OnPaint(IRenderTarget *pRT);
void OnSize(UINT nType, CSize size);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnKeyUp(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnImeStartComposition(UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnSetFocus();
void OnKillFocus();
void OnTimer(char cTimerID);

virtual BOOL OnSetCursor(const CPoint &pt);
virtual UINT OnGetDlgCode() { return SC_WANTALLKEYS; }
BOOL OnAttrUrl(SStringW strValue, BOOL bLoading);
SOUI_ATTRS_BEGIN()
ATTR_CUSTOM(L"url", OnAttrUrl)
SOUI_ATTRS_END()

SOUI_MSG_MAP_BEGIN()
MSG_WM_PAINT_EX(OnPaint)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_SIZE(OnSize)
MSG_WM_TIMER_EX(OnTimer)
MSG_WM_SETFOCUS_EX(OnSetFocus)
MSG_WM_KILLFOCUS_EX(OnKillFocus)
MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, 0x209, OnMouseEvent)
MESSAGE_HANDLER_EX(WM_MOUSEWHEEL, OnMouseWheel)
MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyUp)
MESSAGE_HANDLER_EX(WM_CHAR, OnChar)
MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeStartComposition)
SOUI_MSG_MAP_END()
protected:
wkeWebView m_pWebView;
SStringW m_strUrl;
SWkeRenderGDI m_render;

static wkeWebView onCreateView(wkeWebView webView, void* param, const wkeNewViewInfo* info);
};
}


Cpp部分代码

/*!
* \file SWkeWebkitEx.cpp
* \date 2016/04/12 14:31
*
* \author koangel
* Contact: jackliu100@gmail.com
*
* \brief 针对新版本WKE的封装,使用C函数版本
*
* 为了区分改为SWkeWbkitEx名,与之前版本不冲突。
*/
#include "stdafx.h"
#include "SWkeWebkitEx.h"
#pragma comment(lib,"imm32.lib")
#pragma comment(lib,"msimg32.lib")

namespace SOUI
{
SWkeWebkitEx::SWkeWebkitEx()
{
SWkeInit(); // 如果需要请此处屏蔽(有多个WEBVIEW时)
m_pWebView = nullptr;
}

SWkeWebkitEx::~SWkeWebkitEx()
{
SWkeFinalize(); // 如果需要请此处屏蔽
}

void SWkeWebkitEx::SWkeInit()
{
wkeInitialize();
}

void SWkeWebkitEx::SWkeFinalize()
{
wkeFinalize();
}

BOOL SWkeWebkitEx::OnIdle()
{
m_render.render(m_pWebView);
InvalidateRect(NULL);
return TRUE;
}

int SWkeWebkitEx::OnCreate(void *)
{
m_pWebView = wkeCreateWebView();
if (!m_pWebView) return 1;

HWND hWnd=GetContainer()->GetHostHwnd();

m_render.init(hWnd);

wkeSetHostWindow(m_pWebView, hWnd);
wkeSetTransparent(m_pWebView, false);
wkeOnCreateView(m_pWebView, &SWkeWebkitEx::onCreateView, nullptr);
wkeSetUserAgent(m_pWebView, "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
wkeLoadURLW(m_pWebView,m_strUrl);
SetTimer(TM_TICKER,50);
return 0;
}

void SWkeWebkitEx::OnDestroy()
{
if (m_pWebView)
{
wkeDestroyWebView(m_pWebView);
m_pWebView = nullptr;
}
}

void SWkeWebkitEx::OnPaint(IRenderTarget *pRT)
{
CRect rcClip;
pRT->GetClipBox(&rcClip);
CRect rcClient;
GetClientRect(&rcClient);
CRect rcInvalid;
rcInvalid.IntersectRect(&rcClip, &rcClient);
HDC hdc = pRT->GetDC();
HDC hWebviewHC = (HDC)wkeGetViewDC(m_pWebView);
if (GetStyle().m_byAlpha != 0xff)
{
BLENDFUNCTION bf = { AC_SRC_OVER,0,GetStyle().m_byAlpha,AC_SRC_ALPHA };
AlphaBlend(hdc, rcInvalid.left, rcInvalid.top, rcInvalid.Width(), rcInvalid.Height(),hWebviewHC, rcInvalid.left - rcClient.left, rcInvalid.top - rcClient.top, rcInvalid.Width(), rcInvalid.Height(), bf);
}
else
{
BitBlt(hdc, rcInvalid.left, rcInvalid.top, rcInvalid.Width(), rcInvalid.Height(),hWebviewHC, rcInvalid.left - rcClient.left, rcInvalid.top - rcClient.top, SRCCOPY);
}
pRT->ReleaseDC(hdc);
}

void SWkeWebkitEx::OnSize(UINT nType, CSize size)
{
__super::OnSize(nType,size);
wkeResize(m_pWebView, size.cx, size.cy);
m_render.resize(size.cx, size.cy);
}

LRESULT SWkeWebkitEx::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN)
{
SetFocus();
SetCapture();
}
else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP)
{
ReleaseCapture();
}

CRect rcClient;
GetClientRect(&rcClient);

int x = GET_X_LPARAM(lParam) - rcClient.left;
int y = GET_Y_LPARAM(lParam) - rcClient.top;

unsigned int flags = 0;

if (wParam & MK_CONTROL)
flags |= WKE_CONTROL;
if (wParam & MK_SHIFT)
flags |= WKE_SHIFT;

if (wParam & MK_LBUTTON)
flags |= WKE_LBUTTON;
if (wParam & MK_MBUTTON)
flags |= WKE_MBUTTON;
if (wParam & MK_RBUTTON)
flags |= WKE_RBUTTON;

bool bHandled = wkeFireMouseEvent(m_pWebView, message, x, y, flags); //m_pWebView->mouseEvent(message, x, y, flags);
SetMsgHandled(bHandled);
return 0;
}

LRESULT SWkeWebkitEx::OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
HWND hWnd=GetContainer()->GetHostHwnd();
ScreenToClient(hWnd, &pt);

int delta = GET_WHEEL_DELTA_WPARAM(wParam);

unsigned int flags = 0;

if (wParam & MK_CONTROL)
flags |= WKE_CONTROL;
if (wParam & MK_SHIFT)
flags |= WKE_SHIFT;

if (wParam & MK_LBUTTON)
flags |= WKE_LBUTTON;
if (wParam & MK_MBUTTON)
flags |= WKE_MBUTTON;
if (wParam & MK_RBUTTON)
flags |= WKE_RBUTTON;

bool bHandled = wkeFireMouseWheelEvent(m_pWebView, pt.x,pt.y,delta,flags); //m_pWebView->mouseEvent(message, x, y, flags);
SetMsgHandled(bHandled);
return 0;
}

LRESULT SWkeWebkitEx::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
unsigned int virtualKeyCode = wParam;
unsigned int flags = 0;
if (HIWORD(lParam) & KF_REPEAT)
flags |= WKE_REPEAT;
if (HIWORD(lParam) & KF_EXTENDED)
flags |= WKE_EXTENDED;

bool handled = wkeFireKeyDownEvent(m_pWebView, virtualKeyCode, flags, false);
SetMsgHandled(handled);
return 0;
}

LRESULT SWkeWebkitEx::OnKeyUp(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
unsigned int virtualKeyCode = wParam;
unsigned int flags = 0;
if (HIWORD(lParam) & KF_REPEAT)
flags |= WKE_REPEAT;
if (HIWORD(lParam) & KF_EXTENDED)
flags |= WKE_EXTENDED;

bool handled = wkeFireKeyUpEvent(m_pWebView, virtualKeyCode, flags, false);
SetMsgHandled(handled);
return 0;
}

LRESULT SWkeWebkitEx::OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
unsigned int charCode = wParam;
unsigned int flags = 0;
if (HIWORD(lParam) & KF_REPEAT)
flags |= WKE_REPEAT;
if (HIWORD(lParam) & KF_EXTENDED)
flags |= WKE_EXTENDED;

bool handled = wkeFireKeyPressEvent(m_pWebView, charCode, flags, false);
SetMsgHandled(handled);
return 0;
}

LRESULT SWkeWebkitEx::OnImeStartComposition(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
wkeRect caret = wkeGetCaretRect(m_pWebView);

CRect rcClient;
GetClientRect(&rcClient);

CANDIDATEFORM form;
form.dwIndex = 0;
form.dwStyle = CFS_EXCLUDE;
form.ptCurrentPos.x = caret.x + rcClient.left;
form.ptCurrentPos.y = caret.y + caret.h + rcClient.top;
form.rcArea.top = caret.y + rcClient.top;
form.rcArea.bottom = caret.y + caret.h + rcClient.top;
form.rcArea.left = caret.x + rcClient.left;
form.rcArea.right = caret.x + caret.w + rcClient.left;
COMPOSITIONFORM compForm;
compForm.ptCurrentPos = form.ptCurrentPos;
compForm.rcArea = form.rcArea;
compForm.dwStyle = CFS_POINT;

HWND hWnd = GetContainer()->GetHostHwnd();
HIMC hIMC = ImmGetContext(hWnd);
ImmSetCandidateWindow(hIMC, &form);
ImmSetCompositionWindow(hIMC, &compForm);
ImmReleaseContext(hWnd, hIMC);

return 0;
}

void SWkeWebkitEx::OnSetFocus()
{
wkeSetFocus(m_pWebView);
}

void SWkeWebkitEx::OnKillFocus()
{
wkeKillFocus(m_pWebView);
}

void SWkeWebkitEx::OnTimer(char cTimerID)
{
if (cTimerID == TM_TICKER)
{
m_render.render(m_pWebView);
InvalidateRect(NULL);
}
}

BOOL SWkeWebkitEx::OnSetCursor(const CPoint &pt)
{
return TRUE;
}

BOOL SWkeWebkitEx::OnAttrUrl(SStringW strValue, BOOL bLoading)
{
m_strUrl = strValue;
if (!bLoading)
wkeLoadURLW(m_pWebView,m_strUrl);
return !bLoading;
}

wkeWebView SWkeWebkitEx::onCreateView(wkeWebView webView, void* param, const wkeNewViewInfo* info)
{
const wchar_t* target = wkeGetStringW(info->target);
const wchar_t* url = wkeGetStringW(info->url);

if (wcscmp(target, L"") == 0 || wcscmp(target, L"_blank") == 0)
{
if (wcsnicmp(url, L"file:///", 8) == 0)
url += 8;
// 此处弹出其他程序运行指定内容 WKE代码部分
ShellExecuteW(NULL, L"open", (LPWSTR)url, NULL, NULL, SW_SHOW);
return NULL;
}
else if (wcscmp(target, L"_self") == 0)
{
return webView;
}
else if (wcscmp(target, L"wontOpen") == 0)
{
return NULL;
}

return webView;
}

}


对于Alert本人暂未测试,请稍后自行测试。

编译请使用海面宝宝同学的WKE,妥妥的赞一个。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: