JCEF3——谷歌浏览器内核Java版实现(一):使用jawt获取窗体句柄

前言

  最近一段时间研究谷歌浏览器内核。谷歌浏览器内核一直开源,并维护更新,它的开源项目中内核更新速度和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方法。

 1 /*
 2  * Copyright 2014 JootMir Project
 3  * Licensed under the Apache License, Version 2.0 (the "License");
 4  * you may not use this file except in compliance with the License.
 5  * You may obtain a copy of the License at
 6
 7     http://www.apache.org/licenses/LICENSE-2.0
 8
 9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Support: http://www.cnblogs.com/johness
16  */
17 package johness.jcef3.util;
18
19 import javax.swing.JFrame;
20
21 /**
22  * AWT工具集
23  *
24  * @author ShawRyan
25  */
26 public final class AWTUtil {
27     /**
28      * 获取某个窗体句柄(在Windows平台下)
29      *
30      * @param window
31      *         需要获取句柄的窗体对象
32      * @return 窗体应用句柄
33      */
34     public static native int getWindowHandleInWindows(JFrame window);
35 }

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里有使用示例,我们照着改)

 1 #include "jni.h"
 2 #include "jawt_md.h"
 3 #include "johness_jcef3_util_AWTUtil.h"
 4
 5 JNIEXPORT jint JNICALL Java_johness_jcef3_util_AWTUtil_getWindowHandleInWindows (JNIEnv *env, jclass sender, jobject window) {
 6     HWND hwnd = NULL;
 7
 8     JAWT_DrawingSurface *ds;
 9     JAWT_DrawingSurfaceInfo *dsi;
10     JAWT_Win32DrawingSurfaceInfo *win;
11
12     JAWT awt;
13     awt.version = JAWT_VERSION_1_3;
14
15     jboolean result = JAWT_GetAWT(env, &awt);
16     if (result == JNI_TRUE) {
17         ds = awt.GetDrawingSurface(env, window);
18         jint lock = ds -> Lock(ds);
19         if (lock != JAWT_LOCK_ERROR) {
20             dsi = ds -> GetDrawingSurfaceInfo(ds);
21             win = (JAWT_Win32DrawingSurfaceInfo *) dsi -> platformInfo;
22
23             hwnd = win -> hwnd;
24
25             ds -> FreeDrawingSurfaceInfo(dsi);
26             ds -> Unlock(ds);
27             awt.FreeDrawingSurface(ds);
28             return jint(hwnd);
29         }
30         return 0;
31     }
32     return 0;
33 }

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”这种错,可以把这些个运行时环境的库打包过去。

    ……还有,想起来再说吧。


联系我,一起交流

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

或者通过QQ与我联系:

(最后编辑时间2015-01-26 20:03:51)

时间: 2024-10-23 11:56:19

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

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

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享.扫一扫.卡券.支付等微信特有的能力,为微信用户提供更优质的网页体验. 本次的内容: 实现:分享到朋友圈,qq,qq空间,微信朋友的功能. 基础接口 判断当前客户端版本是否支持指定JS接口 wx.checkJsApi({ jsApiList: ['chooseImage'], // 需要检测的JS接

AKKA文档(java版)

目前我正在翻译AKKA官网文档.翻译:吴京润 译者注:本人正在翻译AKKA官网文档,本篇是文档第一章,欢迎有兴趣的同学加入一起翻译.更多内容请读这里:https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/lists/ded96c34f7ce4a6bb8b5473f596e1008/show/https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/todos/640e53d

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

Java版贪吃蛇(比较完善的版本)

很认真的写的一个java版的贪吃蛇游戏,图形界面,支持菜单操作,键盘监听,可加速,减速,统计得分,设定运动速度,设定游戏背景颜色等!应该没有Bug了,因为全被我修改没了.哈哈. 下面是项目各包及类的层次关系: 游戏的主要运行界面截图如下: 下面是部分代码,详细源码见此链接:http://pan.baidu.com/s/1bnubnzh //Snake类: package com.huowolf.entities; import java.awt.Color; import java.awt.Gr

回溯算法解八皇后问题(java版)

八皇后问题是学习回溯算法时不得不提的一个问题,用回溯算法解决该问题逻辑比较简单. 下面用java版的回溯算法来解决八皇后问题. 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 思路是按行来规定皇后,第一行放第一个皇后,第二行放第二个,然后通过遍历所有列,来判断下一个皇后能否放在该列.直到所有皇后都放完,或者放哪

pureMVC java版搭建流程

转自:http://blog.csdn.net/sutaizi/article/details/6588004 pureMVC 是一个轻量级的框架 它在 flex中非常流行(和cairngorm差不多火) 目前几乎已经移植到所有平台上. 下面实现java版得pureMVC搭建 先给大家看总体的层次: 众所周知 pureMVC是一个轻量级的MVC框架 分为 Model ,View ,Controller.这三个是pureMVC的核心. 除此之外pureMVC中含有一个单例模式Facade.faca

应用程序初次运行数据库配置小程序(Java版)

应用程序初始化数据库配置小程序 之前写过一个Java版的信息管理系统,但部署系统的时候还需要手动的去配置数据库和导入一些初始化的数据才能让系统运行起来,所以我在想是不是可以写一个小程序在系统初次运行的时候自动部署数据库和导入一些初始化数据.然后就有了以下的思路: 在应用程序入口处判断数据库是否已经配置完成,若配置完成则进入正常的登录系统完成正常操作即可,若未配置则进入数据库配置的小程序完成数据库配置然后再进入系统,但如何来判断是否已经配置完成呢,在这里我用的是比较原始的方法,配置数据库的时候系统

微博地址url(id)与mid的相互转换 Java版

原理: 新浪微博的URL都是如:http://weibo.com/2480531040/z8ElgBLeQ这样三部分. 第一部分(绿色部分)为新浪微博的域名,第二部分(红色部分)为博主Uid,第三部分(蓝色)为一串貌似随机的字符串. 如果通过方法能计算出蓝色字串与返回的数组里的对应关系则好解决多了. 首先分组蓝色字串 ,从后往前4个字符一组,得到以下三组字符:z8ElgBLeQ 将它们分别转换成62进制的数值则为 35, 2061702, 8999724  将它们组合起来就是一串 3520617

java版的QQ小程序

转载自:http://blog.csdn.net/lihongxun945/article/details/6114290 这是一个简单的java版的QQ小程序. 包括一个简单的服务器和一个简单的客户端. 运行时,先运行服务器,然后在运行客户端,就可以进行聊天了. 默认的配置是localhost,端口4545,更改ip就可以在两天电脑上进行聊天了. 目前不支持内网和外网之间的访问,也不支持多人聊天. 因为这只是一个简单的例子,感兴趣的同学可以通过改进,实现多人聊天和内外网之间的访问. 效果图: