动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息

本月文章推荐
.Jakarta Struts应用的七个经验(.
.通过自建代理服务器增强 Applet .
.使用Maps.
.J2EE基础应用:J2EE中SQL语句自动.
.Java 国际化和本地化 Toolkit 2..
.由基本概念开始全面认识JAVA.
.Java理论和实践:用软引用阻止内存.
.Java高级编程——泛型类型第一部.
.XML和J2EE的组合技术.
.通过XDoclet定制模板进行快速开发.
.toArray 方法.
.《敏捷Acegi、CAS:构建安全的Ja.
.Java基础知识 J2EE初学者需要注意.
.Axis下 WebService 的调用问题.
.java图像浏览器.
.构建更好的异常处理框架.
.Turbine Howto 之 Action Event .
.Java中调用外部命令.
.多媒体和网络时代中,C++,Delph.
.编程必备经典:Java常见问题集锦.

SWT:实现自我绘制的Button组件

发表日期:2008-1-5 |



  在所有SWT组件中,Button几乎是最常用的,其功能在对于一般的情况来说也足够丰富了。你可以为Button组件设置要显示在其中的文本或者图像、设定ToolTip,甚至只要修改一个风格样式就能得到一个看上去相当不错的方向箭头按钮。

  然而,我对Button组件还是不能感到满足。最大的遗憾就是:对它的外观,所能做的工作也就仅限于此了。假如你想让按钮拥有一个漂亮的、渐变色的背景和一些非凡的文字效果,怎么办呢?答案是没有办法。Button类里面似乎没有任何方法提供我想要的功能。

  我曾尝试过的第一个想法是用Button.addPaintListener来修改按钮的外观。但是,结果令人失望——虽然它显示出来的时候的确按照预想进行绘制了,但是当你用鼠标去按它的时候,马上又变回了原本灰头土脸的样子。显然,在按下按钮的时候,它并不是触发paint事件,而是按照自己的想法画出原本的按钮,于是我的工作全部白费了。

  假如尝试为按钮设定图像会怎么样呢?这也不是一个好主意。首先,不管你选择什么样的图像,都没办法去掉按钮四面的边框,而正是这些边框严重破坏了图像的和谐感;其次,假如你的程序有几十甚至上百个按钮,为每个按钮都维护一幅图像(甚至更多——理论上每个按钮在普通状态和被按下、禁用的状态下,甚至当鼠标移进移出按钮的时候,都应当显示不同的图像)明显是在浪费系统资源;假如你们的美工听说需要做几百个图片,大概也不会给你好脸色看。此外,图像有一个严重的缺点是:它所拥有的像素数目是固定的,难以随着界面的放大和缩小同时变化。假如强制进行缩放的话,会出现明显的锯齿和失真,最终让你精心设计的窗口变得惨不忍睹。最好还是放弃这个想法。

  假如以Canvas为基础,设计一个伪装的按钮组件又如何呢?听起来似乎很不错,因为采用这种办法的话,我们对如何绘制组件的表面就有了完整的控制权。不过这也意味着你必须对按钮的状态进行手工维护。虽然Button本身是一个很简单的组件,但是重复去做标准按钮已经作好的工作似乎还是有点无谓。还有一件事情是应当考虑的:我们知道,JFace中的Action机制可以将标准按钮、菜单项和工具栏按钮这三种界面组件纳入一个统一的事件处理体系。然而,假如我们从Canvas派生去模拟一个按钮的话,不论你模拟到多么相似的地步,它究竟不是一个真正的Button,Action也不会给它同等的待遇。也就是说手工制作的按钮无法和JFace Action体系协同工作——除非你去修改Action的处理方法,让它去接纳新的按钮对象。这可不是一件轻松的工作。

  假如上面的方法都行不通的话,应当怎么办呢?我们知道,和Swing这样的框架不同,SWT中的按钮其实就是操作系统底层所实现的按钮(这一点也可以用SPY++或者Winsight32之类的工具证实)。同时我们也知道,操作系统——至少是Windows系统,对按钮已经提供了自我绘制的机制,这就是所谓的Owner Draw(称为所有者绘制的原因是因为默认情况下绘制消息是发送给按钮的父窗口处理的,但是父窗口也可以把这个皮球再踢回给按钮,让它自己解决)。在Win32 API中,凡是使用BS_OWNERDRAW风格创建、并且能够(通过消息反射)响应WS_DRAWITEM消息的按钮,都可以获得这种定制的能力。 了解这一点,接下来的任务就是研究Button组件有没有开放这个接口供我们修改了。对Button组件的源代码进行粗略的浏览后,我发现了如下的方法:

package org.eclipse.swt.widgets;

public class Button extends Control {
 …
 LRESULT wmDrawChild (int wParam, int lParam) {
 if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam);
 DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
 ....
  其中DRAWITEMSTRUCT结构的出现是一个明显的提示:这里就是WM_DRAWITEM消息的响应函数,很幸运它没有声明为final的,只要重载它并提供自己的实现就行了。

  看起来是个小case,实际上也是。不过,还有一处小麻烦需要克服。注重wmDrawChild方法没有使用任何访问限定符,这意味着它是package friendly的——同一个包中的对象可以访问和重载此方法,其他包中的对象就没有这个权力了。也就是说,要定制按钮对象,我们新建的对象也需要放在同一个包(org.eclipse.swt.widgets)中。看起来有点像在使用Hack手段,不过为了突破SWT给我们的限制,眼下也只好稍稍将就一下。好在swt的包没有密封(Sealed),不然我就不得不再次宣称此路不通了。

  既然障碍已经扫清,接下来我们可以来实现前面的想法了。这里我做了一个决定,在上述包中只加入一个抽象类,目的是把必要的接口暴露出来;至于如何绘制按钮,则留给具体的按钮对象根据应用程序的需求来决定。这样,不管你希望实现Windows XP风格的按钮、还是卡通风格的按钮、或是平面样式的,总之不论什么千奇百怪的风格,只要继续一个类并重载一个绘制方法就行了,而不必每次都要和 Button类的内部打交道。

  基于这种考虑,实现自绘按钮的抽象类如下:

package org.eclipse.swt.widgets;

import org.eclipse.swt.internal.win32.*;

public abstract class OwnerDrawButton extends Button
{
 public OwnerDrawButton( Composite parent, int style )
 {
  super( parent, style );

  int osStyle = OS.GetWindowLong( handle, OS.GWL_STYLE );
  osStyle = OS.BS_OWNERDRAW;
  OS.SetWindowLong( handle, OS.GWL_STYLE, osStyle );
 }

 LRESULT wmDrawChild( int wParam, int lParam )
 {
  super.wmDrawChild( wParam, lParam );
  DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT();
  OS.MoveMemory( struct, lParam, DRAWITEMSTRUCT.sizeof );
  ownerDraw( struct );
  return null;
 }

 protected abstract void ownerDraw( DRAWITEMSTRUCT dis );
}
  注重这个抽象类所作的工作。在构造函数中,它调用操作系统方法为自己加入了BS_OWNERDRAW风格。假如没有这一步,那么操作系统将不会把这个按钮视为自绘的按钮,也不会向其发送任何绘制消息。接下来是WM_DRAWITEM消息的响应函数。在这个函数中,我们简单的把必要的绘制参数提取出来,然后调用抽象方法ownerDraw去进行实际的绘制工作。任何从OwnerDrawButton类派生的按钮对象必须重载此ownerDraw方法,来决定如何绘制自身。
上一篇:在Oracle JDBC访问中加入Spring特性 人气:748
下一篇:了解Java密码扩展的基础 人气:575
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-10-10 企业网站智能管理系统(TZIMS) v6
2008-10-10 拓文asp.net网站内容管理系统 v6
2008-10-10 动网论坛PHP版 v2.0++ Build 081
2008-10-10 免费时代CMS v5.0
2008-10-10 wodig第四季中文DIGG社区 v4.1 b
2008-10-10 老Y文章管理系统 v2.2 bulid 081
2008-10-10 魔法盒动感相册 ASP+SQL版 v2.0
2008-10-10 Asoft签到管理系统 v3.0 Pack1
2008-10-10 哥特人音乐网潮流留言本 v1.1
2008-10-11 联系人分组工具 v1.1 中文破解版
2008-10-11 FaceMelter变脸 v2.0 汉化破解版
2008-10-11 PathTracker道路跟踪仪 v1.2 破解
2008-10-11 Rooms手机聊天室 v0.6.7 破解版
2008-10-11 RemoteDesktop远程桌面 v1.0 破解
2008-10-11 ProRemote远程调音台 v1.0.1 破解
2008-10-11 PicShare照片共享 v1.0.0 破解版
2008-10-11 Photogene照片编辑器 v1.5 汉化破
2008-10-11 WriteRoom共享文档 v1.0 破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成