UIWebView在windows,mac中如何实现?

我现在需要用到webview控件,但是发现只有(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) 平台中有实现,MAC跟windows都没有
而且测试用例cpp-test中也没有mac与windows的?
(不想使用 openURL 等方式打开网页浏览器,想要嵌套进程序中)
疑问:
1:为什么windows mac中没有?
2:windows mac中要如何实现

1赞

晕,刚好有空。我自己给自己回答。
1:windows webView可以使用 谷歌内核(chrome内核浏览器),也就是cef 。 不过这太大,有40多M的d ll,还有一堆 .pkg 。可以选择 裁剪版的wke,不过裁剪版的 网上有嵌入 duilib的demo,嵌入cocos过于麻烦,同时,因为我使用的是监听 js 中的 iframe src自定义回调,而wke没有监听,需要改源码重新编译。最终选择 IE 内核,也就是 ActiveX控件的容器 CAxWindow , control 为 shell.Explorer.2 ,控件QueryControl为 IWebBrowser2。
不过IE内核有几点要注意的:
A:不能漏掉 CComModule _Module;不然 CAxWindow.create 的时候会报错
B:cocos 3.15的 HWND hwnd = Director::getInstance()->getOpenGlView()->getWin32Window()
C:IWebBroser2默认是使用IE7内核的,一般很容易出现web界面问题,需要手动设置 注册表 其中主义RegCreateKey 的 lpSubKey 区分win32与win64区别。 RegSetValueE FEATURE_BROWSER_EMULATION 设置为 8000 位 即 ie8,9000 即ie9 。其他的设置百度即可。这里需要vs 管理员权限 , 链接器——清单文件——UAC控制——requireAdministrator 。。。即可
D:需要而外添加对web的事件监听
HRESULT hResult;
CComPtr spConnectionPointContainer;
CComPtr spConnectionPointBrowserEvents;
m_piWebBrowser->QueryInterface(IID_IConnectionPointContainer, (void**)&spConnectionPointContainer);
spConnectionPointContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &spConnectionPointBrowserEvents);
m_dwCookie = 0;
m_pWebBrowserSink = new WebBrowserSink(this);
hResult = spConnectionPointBrowserEvents->Advise(m_pWebBrowserSink【继承 DWebBrowserEvents2 ,重写函数 STDMETHODIMP Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); 】, &m_dwCookie);
if (SUCCEEDED(hResult))

E:还有个坑爹的,就是他把 web的tab, enter , del等键盘事件,给控件处理,正常情况下 浏览器里面 无法按 tab 键,需要鼠标一个一个点击输入。这就需要监听控件CAxwindow窗口消息,分派给浏览器处理。网上很多方法是直接添加 GetMessage 加 IsDialogMessage 判定。不过我发现用这个很坑,首先首先是键盘输入两份,就算 GetMessage 第三个参数为NULL,也无法关闭窗口,具体没去看原因。所以这边我使用的是设置全局钩子函数 HHOOK。 方法也是用到hwnd 是CAxWindow.m_hWnd ,注意 这里不需要用到 HINSTANCE,SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, (HINSTANCE)NULL, GetCurrentThreadId()); 最后要给。不然 HOOK获取失败。通过这个方法监听鼠标事件,判定 需要派发给浏览器的 键盘事件,如。VK_TAB VK_RETURN 即 tab, enter 键 ,处理派发方法如下:
if (m_piWebBrowser 【IWebBrowser】!= nullptr)
{
MSG msg;
msg.hwnd = m_WinContainer【CAxWindow】.m_hWnd;
msg.message = WM_KEYDOWN;
msg.lParam = lParam;
msg.wParam = wParam;

	CComPtr<IDispatch> disp;
	HRESULT hr = m_piWebBrowser->get_Document(&disp);

	if (S_OK == hr)
	{
		CComQIPtr<IOleInPlaceActiveObject> spInPlace;

		hr = disp->QueryInterface(__uuidof(IOleInPlaceActiveObject), (void**)&spInPlace);
		if (S_OK == hr)
		{
			if (spInPlace)
			{
				spInPlace->TranslateAccelerator(&msg);
			}
		}
	}
}

2:Mac 方面就简单多了,直接在 Build Phases中 在Link Binary With Libraries 中添加 WebKit.framework。使用 WebView即可。
注意事项如下:
A:cocos提供获取Mac版本,窗口方法为:NSWindow * window = cocos2d::Director::getInstance()->getOpenGLView()->getCocoaWindow()
B:我是直接创建新的 NSWindow 添加 WebView,同时 作为 cocos 窗口的子窗口。不过这里涉及到设置的窗口是无标题栏的风格,这种风格是无法激活窗口的。所以需要继承NSWindow 重写 方法,返回 YES
-(BOOL)canBecomeKeyWindow
{
return YES;
}
C:大小位置同步方面只需要使用 setFrame即可,不过这里的大小需要扣除标题的
NSRect frame = window.frame;

    NSRect contentRect;
    contentRect = [NSWindow contentRectForFrameRect: frame styleMask: NSTitledWindowMask];

D:剩下的就是消息监听方面的需求了。这里有个吐槽。自带的消息监听 Delegate,有 6 种,20,30个消息,能够捕捉 request,respone 。但是完全没有 iframe src跳转的监听,也没有界面 start load 监听。还不如, ios的UIWebView 消息不多,刚好能用。
最终确定,只需要继承 NSURLProtocol,重写方法 + (BOOL)canInitWithRequest:(NSURLRequest *)request 就可以捕捉到了 url进行判断,通过return YES/NO 实现 屏蔽跳转,屏蔽报错 改变跳转等等功能

注册函数 [NSURLProtocol registerClass:[FilteredProtocol【自定义继承的类名】 class]];
需要取消 [NSURLProtocol unregisterClass:[FilteredProtocol class]];

1赞

研究的不错 想一个通吃吗?

您好,不知,您能发一份写好的例子给我吗?谢谢!!QQ:3161966131!@qq.com

自己写的,可以看看
https://github.com/woody006/cocos2dx-cef-wrapper

参考网上教程,我封装了下windows和mac的,可以参考下:cocos_desktop_webview