前言

  最近一段时间研究谷歌浏览器内核。谷歌浏览器内核一直开源,并维护更新,它的开源项目中内核更新速度和Chrome浏览器版本更新进度一样!而且它不同于WebKit(值得一题的是谷歌浏览器已不使用WebKit内核了),它提供的不仅仅是页面渲染,而是提供一整浏览器解决方案和插件规则。

  使用方便:我们给它一个“窗体”(操作系统或系统资源管理器中的本地窗体,本系列都使用Win32平台作为示例)和一些配置参数,它就能将你需要渲染的页面在给定窗口中完美地展示。

  插件支持:Adobe和Google联合开发的pepperflashplayer功能完善,而且我们作为进程外插件安装的话可以不用考虑它的自动升级给用户造成困扰或我们开发中的版本变化。而你只需要一句代码即可完成插件的启用,获取和升级插件方式也很简单(先在电脑上装一个chrome浏览器,去安装目录下copy:-_-)。谷歌对pdf的插件也可以这样。

  这个随笔系列主要使用Java给谷歌浏览套一个壳。因为cef(即“谷歌浏览器内核chromium embedded framework”,后文都使用cef作为简称,并且本系列都使用cef3)使用c/c++编写,并未直接提供Java语言API,虽然有Java版的一个维护版本,但本人认为并不好用。


获取AWT窗体句柄

  我们今天要做的跟cef内核还没太大关系,我们先解决一个问题:获取Java窗体的句柄。

  我们都知道:Java语言提供的GUI支持是建立在操作系统资源管理系统(或者桌面环境)的支持上的(在Java的2D/GUI中,最外层的窗体肯定是操作系统相关的),那么很简单的道理,我们可以使用JNI的一些API来获取窗体句柄。

  •   jni?

    JNI是Java语言提供的本地化代码调用接口(在Java虚拟机里实际上不在乎下一个方法入口是内部指针还是外部-操作系统指针),我们可以写一个c/c++的函数去找到窗体句柄,然后返回给Java虚拟机,让我们在虚拟机内部也知晓某个Java窗体被操作系统分配的句柄。

  •   jawt

    Java官方已经考虑到我们这种需求了,它提供了一个接口:jawt。包括一系列c/c++包含(头文件.h,平台相关)和一系列c/c++静态库文件。

    具体包括jawt.h、jawt_md.h、jawt.lib(另外jni.h以及jni_md.h是使用jni必须的)

  •   javah

    编写动态链接库(dll)需要使用c/c++头文件与c/++源文件联合编译。我们先使用JDK自带的javah工具(javah.exe)生成一个头文件并实现它。

    当然,我们先写一个Java类,标注其native方法。

 /*
* Copyright 2014 JootMir Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Support: http://www.cnblogs.com/johness
*/
package johness.jcef3.util; import javax.swing.JFrame; /**
* AWT工具集
*
* @author ShawRyan
*/
public final class AWTUtil {
/**
* 获取某个窗体句柄(在Windows平台下)
*
* @param window
* 需要获取句柄的窗体对象
* @return 窗体应用句柄
*/
public static native int getWindowHandleInWindows(JFrame window);
}

AWTUtil

    然后使用javah生成其对应头文件。

    

    

    头文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class johness_jcef3_util_AWTUtil */ #ifndef _Included_johness_jcef3_util_AWTUtil
#define _Included_johness_jcef3_util_AWTUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: johness_jcef3_util_AWTUtil
* Method: getWindowHandleInWindows
* Signature: (Ljavax/swing/JFrame;)I
*/
JNIEXPORT jint JNICALL Java_johness_jcef3_util_AWTUtil_getWindowHandleInWindows
(JNIEnv *, jclass, jobject); #ifdef __cplusplus
}
#endif
#endif

    jni细则我就不赘述了。

  •   visual studio

    接下来我们使用c++代码来实现接口函数并编译为动态链接库。

    经典的VC++6.0或者优秀的Dev C++我都不喜欢使用,我就用Visual Studio 2012来编写并编译吧。

    建立项目

    

    

    删除一切我们不需要(我们就没有需要的-_-)文件

    

    复制jni和jawt相关头文件及库文件到项目中(值得一题的是不是说让你复制粘贴到vs窗体内,而是真正复制到你c++项目文件夹内)

    %JAVA_HOME%\include\jni.h

    %JAVA_HOME%\include\jawt.h

    %JAVA_HOME%\include\jni_md.h

    %JAVA_HOME%\include\jawt_md.h

    %JAVA_HOME%\lib\jawt.lib

    你项目中的那个头文件

    

    

    配置项目

    配置项目为Release

    

    配置项目使用jawt.lib静态库

    

    更改头文件,把#include <jni.h>改为#include "jni.h"

    

    (后面的竖线是光标)

    写源文件

    (创建好源文件并准备开始编写代码之前取消源文件预编译头)

    

    开始编码(jawt.h里有使用示例,我们照着改)

 #include "jni.h"
#include "jawt_md.h"
#include "johness_jcef3_util_AWTUtil.h" JNIEXPORT jint JNICALL Java_johness_jcef3_util_AWTUtil_getWindowHandleInWindows (JNIEnv *env, jclass sender, jobject window) {
HWND hwnd = NULL; JAWT_DrawingSurface *ds;
JAWT_DrawingSurfaceInfo *dsi;
JAWT_Win32DrawingSurfaceInfo *win; JAWT awt;
awt.version = JAWT_VERSION_1_3; jboolean result = JAWT_GetAWT(env, &awt);
if (result == JNI_TRUE) {
ds = awt.GetDrawingSurface(env, window);
jint lock = ds -> Lock(ds);
if (lock != JAWT_LOCK_ERROR) {
dsi = ds -> GetDrawingSurfaceInfo(ds);
win = (JAWT_Win32DrawingSurfaceInfo *) dsi -> platformInfo; hwnd = win -> hwnd; ds -> FreeDrawingSurfaceInfo(dsi);
ds -> Unlock(ds);
awt.FreeDrawingSurface(ds);
return jint(hwnd);
}
return ;
}
return ;
}

johness_jcef3_util_AWTUtil

    编译生成

    

  •   使用或测试

    把生成的dll复制到Java项目中,在项目配置中配置librarypath,然后编写测试代码。

    

    

    测试代码也很简单:

package johness.jcef3.util;

import javax.swing.JFrame;

public class Main {

    public static void main(String[] args) {
System.loadLibrary("jawt");
System.loadLibrary("JCEF3");
JFrame frame = new JFrame();
frame.setSize(400, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
System.out.println(AWTUtil.getWindowHandleInWindows(frame));
} }

最后总结

    使用visual studio编译时注意不使用预编译文件头。当然如果你稍微了解vc++的话可能也不用这么麻烦。

    使用visual studio编译生成的dll需要运行时环境,比如msvcr110.dll之类的。如果你机器上没有安装过的话可能会爆出“Can't find dependent libraries”这种错,可以把这些个运行时环境的库打包过去。

    写于2016-03-29

    本来我想自己做java-cef,不过官方已经做了

    写于2019-11-28

    java-cef已经不维护了,有很多bug。几年前我自己维护了一个maven版本的项目 https://mvnrepository.com/artifact/org.bitbucket.johness/java-cef/49.87.win32.2 https://mvnrepository.com/artifact/org.bitbucket.johness/java-cef/49.87.win64.2。但也不更新了,注意,这也是几年前的东西了,请大家不要用,尽量使用时兴的开源组件。如果一个项目你看它超过一个月没活跃(发布版本,提交代码等),那你最好别用。


联系我,一起交流

欢迎您移步我们的交流群,无聊的时候大家一起打发时间:

或者通过QQ与我联系:

(最后编辑时间2016-03-29 10:26:41)

JCEF3——谷歌浏览器内核Java版实现(一):使用jawt获取窗体句柄的更多相关文章

  1. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

  2. 微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

  3. 第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容

    第一部分:微信JS-SDK介绍 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统 ...

  4. 第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同). 公众号可通过本接口来根据O ...

  5. 第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    我们来了解一下 自定义菜单创建接口: http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

  6. 第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token

    一.access_token简介 为了使第三方开发者能够为用户提供更多更有价值的个性化服务,微信公众平台 开放了许多接口,包括自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等, 开 ...

  7. 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众 ...

  8. 第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装

    微信服务器和第三方服务器之间究竟是通过什么方式进行对话的? 下面,我们先看下图: 其实我们可以简单的理解: (1)首先,用户向微信服务器发送消息: (2)微信服务器接收到用户的消息处理之后,通过开发者 ...

  9. 第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发

    第一部分:微信公众号对接的基本介绍 一.填写服务器配置信息的介绍 登录微信公众平台官网后,进入到公众平台后台管理页面. 选择 公众号基本设置->基本配置 ,点击“修改配置”按钮,填写服务器地址( ...

随机推荐

  1. Asp.Net Web API 2第五课——Web API路由

    Asp.Net Web API 导航   Asp.Net Web API第一课——入门 http://www.cnblogs.com/aehyok/p/3432158.html Asp.Net Web ...

  2. JS获取元素CSS值的各种方法分析

    先来看一个实例:如何获取一个没有设置大小的字体? <!DOCTYPE html> <html lang="en"> <head> <met ...

  3. paip.函数式编程方法概述以及总结

    paip.函数式编程方法概述以及总结 1     函数式编程:函数式风格..很多命令式语言里支持函数式编程风格 1.1      起源 (图灵机,Lisp机器, 神经网络计算机) 1.2      函 ...

  4. java封装性

    原先是class Person{ public string name; public  int age } public void main{ Person person=new person(); ...

  5. Leetcode 190 Reverse Bits 位运算

    反转二进制 class Solution { public: uint32_t reverseBits(uint32_t n) { uint32_t ans = ; ; i<; ++i,n &g ...

  6. Html+css 练习写页面发现的错误及解决办法。

    最近开始模仿写一些静态页面,今天模仿的是中华咨询网.写了一个简单的js(功能:当鼠标hover一级菜单的时候,设置二级菜单为显示,当鼠标hover二级菜单的选项时候,二级菜单不收回.当鼠标移出菜单一级 ...

  7. 详解Bootstrap面板组件

    面板组件主要作用是用来处理一些其他组件无法完成的功能,在不同的版本中具有不同的源码: LESS:panels.less SASS:_panels.scss 基础面板非常简单,就是一个div容器中运用了 ...

  8. Android Studio使用小技巧:提取方法代码片段

    http://www.jb51.net/article/65510.htm 今天来给大家介绍一个非常有用的Studio Tips,有些时候我们在一个方法内部写了过多的代码,然后想要把一些代码提取出来再 ...

  9. How to use “svn add” recursively in Linux shell?

    This command will add any un-versioned files listed in svn st command output to subversion. Note tha ...

  10. 使用Git Bash for Windows

    本篇体验Git Bash在Windows操作系统上的用法. 什么是Bash? 是一个Shell环境,Bourne Again Shell的缩写. 安装git for windows → http:// ...