截图 不需要专用工具
模仿功能:截图模块
模仿对象:手机QQ 2008
模仿进度:第四期
开发平台:Java 平台
涉及网络应用和游戏的手机程序可以嵌入截图模块,这样需要截图时直接在程序中完成,不要再调用专门的截图工具。
截图模块设计思路
截图模块的作用是将当前屏幕中的内容存储起来,而被存储起来的内容可以发送给好友或存储到本地(截图模块下载地址: http://www.shudoo.com/bzsoft )。截图模块的用途比较多,例如在手机游戏中通关时可以用到截图,手机上网时看到有趣的新闻可以截图等。
设计截图模块,先要设计一个截图界面,然后设计一个计数进程,这个进程的作用是每隔 0.1 秒计数一次。再设计一个截图的快捷键,例如“ # ”号键。当用户按下手机上的“ # ”号键时,调用屏幕存储方法保存屏幕内容,再将存储的内容转换为图片。当截图效果图显示达到 3 秒时(时间可以修改),自动切换到正常的界面。而截图的内容也会在用户按下 # 号键存储在手机的记录仓库中。程序流程如下图 1 所示。
用缓冲图片
截图模块的关键就是屏幕存储,有两种实现方法。
方法 1 : 依次读取屏幕上每个点的信息并进行保存。这种方式是利用系统提供的读取屏幕的函数获得信息。
小知识: 常见的PC 屏幕一般是1024*768 ,则表示屏幕被分为1024 列、768 行,则屏幕上点的总数量为:1024X768=786432 个。在手机中例如Nokia S60 系列的手机是176*208 ,则表示屏幕被分为176 列、208 行。
方法 2 : 借鉴“双缓冲”技术的思路,将需要绘制的内容全部绘制在一张缓冲图片中,然后将缓冲图片的内容转换成一定格式存储起来。
小知识: 双缓冲(double buffer) 是一种解决在播放动画时屏幕闪烁的技术,该技术在程序中的使用很广泛,是一种很成熟的实用技术。
在 PC 编程中,由于第一种方法实现比较简单,所以多采用第一种方式实现。而 J2ME 技术是不支持第一种方法的,所以我们采用第二种方法实现屏幕存储。如果要使用第一种方法,可以换其他的语言。
在程序中将界面的内容全部绘制在一张预先创建完成的“缓冲图片”中,该缓冲图片上绘制的内容就是手机屏幕显示的内容,程序界面中的变化也就是缓冲图片内容的变化,在需要存储时,调用换成图片 Image 对象中的 getRGB 方法获得每个点的颜色信息,然后将所有的颜色信息存储起来,例如:
private void saveImage(){
imgWidth = width;
imgHeight = height;
rgb = new int[imgWidth * imgHeight]; // 屏幕大小
// 将图片信息读入数组中
bufferImg.getRGB(rgb, 0, imgWidth, 0, 0, imgWidth, imgHeight);
save(); // 保存到记录仓库
“双缓冲”技术除了可以用来设计截图模块,还可以用来解决屏幕在动画过程中的闪烁、以及在绘制块状地图时提高程序的执行效率等,总之双缓冲技术在实际的程序编程中获得了大量的使用。
截图模块设计步骤
第一步:创建项目
启动Eclipse 环境,选择“File →New →J2ME MIDlet Suit ”,设置项目名称为“ScreenSave ”,并一路选择“Next ”, 完成项目的建立。然后新建一 个J2ME 入口类 , 选择“File →New →J2ME MIDlet ”,并设置名称为“ScreenSaveMIDlet ”,点击“Finish ”。创建项目的代码下载地址是http://www.shudoo.com/bzsoft 。
第二步:设计界面
选择“File →New →Class ”,并设置名称为“MainCanvas ”,点击“Finish ”完成界面类的创建。接着,开始初始化界面。关键码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft ):
// 绘制数字
bufferG.drawString(String.valueOf(n), width/2,
height/2, HCENTERBASELINE);
// 绘制按钮文字
bufferG.drawString(screenSaveInfoStr, width/2, height, HCENTERBOTTOM);
bufferG.drawString(quitStr, width, height, RIGHTBOTTOM);
// 绘制缓冲图片
g.drawImage(bufferImg, 0, 0, TOPLEFT);
第三步:设置 # 号键
在程序运行时,按下手机上的# 号键,启动截图功能并将截图的效果显示3 秒,然后程序继续运行。核心代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft ):
public void keyPressed(int keyCode){
switch(status){
case NORMAL:
if(keyCode == Canvas.KEY_POUND ){ //# 号键
saveImage(); // 保存图片
savedImg = displayImg(); // 获得保存的图片
status = DISPLAY_SAVED;
}
if(keyCode == -7){// 右软键
ScreenSaveMIDlet.quitApp();
isRun = true;
第四步: 3 秒计时
当截图功能启动后,在线程中每隔0.1 秒计数一次,达到3 秒后界面切换回正常的界面。
核心代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft ):
public void run() {
try{
while(isRun){
Thread.sleep(SPF); // 延时SPF
logic();
}
}catch(Exception e){}
private void logic(){
switch(status){ // 根据状态值进行不同的处理
case NORMAL: // 正常状态
n++; // 数字值增加1
repaint(); // 重画界面
break;
case DISPLAY_SAVED: // 显示截图状态
count++; // 计数
if(count * SPF >= 3000){ // 显示时间达到3 秒
status = NORMAL; // 切换到正常状态
第五步:运行程序
在Eclipse 主界面左侧的“Package Explorer ”中,选中项目源代码“ScreenSaveMIDlet.java ”,单击鼠标右键,选择“Run As →Emulated J2ME Midlet ”即可运行程序(图2 )。
读者反馈
开发 QQ 群 : 看了上期的文章,我想把户外模式再细化一下,分成清晨户外、中午户外,下午户外,不知道《电脑报》小编有什么建议?
小编 : 您这个提议很好,在程序中是可以实现,这样对于用户界面来说将会更加完善,从而可以使用户在使用手机软件时有更多的选择,可以从中选择出更加适合适应环境 的模式。在实际设计时,需要根据各种户外模式先的光照强度等,重新设置出适合的文字颜色、背景颜色和屏幕亮度,在程序中控制切换就可以实现该功能了。
开发 QQ 群 : 看了上期的文章,夜间模式是程序设定好了,可以让用户自己设定不?
小编 : 在该示例程序中,夜间模式,包括其它模式,都是由程序预先设置好了相关的数值,其实如果需要让程序更加通用的话,应该允许用户自己进行设定。或者在实现 时,使用固定模式和用户自定义模式组合进行使用。在技术上,让用户自己设定是可以实现的,可以对示例程序进行相应的修改来增加该功能。
开发 QQ 群 : 为什么我下载的Nokia S40 模拟器不支持中文显示?
小编 :在 Nokia 的官方网站上,可以下载 Nokia S40 系列的专用模拟器,其下载地址为:
http://www.forum.nokia.com/info/sw.nokia.com/id/cc48f9a1-f5cf-447b-bdba-c4d41b3d05ce/Series_40_Platform_SDKs.html 。但是如果只安装该 SDK 的话,是无法显示中文的,需要再专门下载语言包,选择模拟器中的“ Tool-Preferences ”中的“ Download languages ”下载并安装语言包,然后重启启动模拟器,在相同的位置设置“ Current language: ”为“ Chinese_simplified ”即可。
开发 QQ 群 : 是否可以实现用程序控制手机的摄像头?
小编 :如果手机支持的话,可以实现控制手机的摄像头编程,从而实现拍照和录制视频的功能。手机要支持 MIDP2.0 或 MMAPI 可选包( MIDP2.0 中包含的支持视频编程的框架是 MMAPI 的一个子集),这样在能进行编程。
开发 QQ 群 : 在下载手机软件时,分为Nokia S40 、S60 等版本,怎么还包含通用版本,这些版本之间有哪些区别呢?
小编 : 手机软件和计算机上的软件不一样,由于不同手机之间硬件的差异,例如屏幕大小,以及支持的软件不一样,所以同一个手机软件需要出多个版本,从而适应不同的 软硬件环境,也可以充分发挥手机的性能,所以就出现了专用版本。而手机的型号太多,对于每个系列都编写专门的版本不太现实,所以就出现了通用版本。一般情 况下,由于要做到通用,通用版本的功能要专用版本的功能稍微弱一些。
读者问题 : “弱弱”地问一下,如何在手机程序中添加读取手机电话簿的功能,希望高手给我指点迷津。
高手 二龙宝: 在标准的 MIDP API 中,是不支持读取手机电话簿的,如果需要读取,则需要手机支持 JSR75 中的 PIM API 。如果手机支持 JSR75 可选包,即可进行调用该组 API 读取电话簿了。但是在读取时,手机上会弹出相应的提示窗口。
读者问题 : 我要在手机程序中设计一个定时器,定时器会调用函数访问一个类的成员,我应该怎么设计?
你是手机编程的高手吗?你能解答上面这位读者的疑问吗?不要犹豫,来我们这里展示一下你的风采吧,来信请发到pcw-chendx@vip.sina.com (也可以给我们发送问题)。