treenode

在路上。

BlogJava 首页 新随笔 联系 聚合 管理
  5 Posts :: 1 Stories :: 53 Comments :: 0 Trackbacks
可能是为了保持平台独立性,SWT没有开放许多控件的自定义接口。例如,Win32中的Button、Label、List和ComboBox都是可以自绘(Owner Draw)的,但是SWT并没有把这些绘制方法开放出来。在最新的3.2版本中添加的一个新特性是Table和Tree现在支持Custom Draw了(但是并未整合到Viewer体系中),不过对于上述控件的支持仍付阙如。

上一次,我实现了一个自绘的按钮。现在,看到有人询问是否可以在Combo的列表中加入图像。其实这相当容易,只要重载Combo Widget并把自绘接口暴露出来即可。以下是简单的代码示例:

package org.eclipse.swt.widgets;

import java.io.*;

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

public class CustomCombo extends Combo
{
    
public CustomCombo( Composite parent, int style )
    {
        
super( parent, style );

        
try
        {
            InputStream is 
= getClass().getResourceAsStream( "bullet.gif" );
            image 
= new Image( getDisplay(), is );
            is.close();
        }
        
catch ( IOException e )
        {
            e.printStackTrace();
        }
        
final int CB_SETITEMHEIGHT = 0x0153;

        OS.SendMessage( handle, CB_SETITEMHEIGHT, 
024 );
        OS.SendMessage( handle, CB_SETITEMHEIGHT, 
-124 );
    }

    @Override
    
int widgetStyle()
    {
        
final int CBS_OWNERDRAWFIXED = 0x0010;
        
final int CBS_HASSTRINGS = 0x0200;
        
// final int CBS_OWNERDRAWVARIABLE = 0x0020;
        return super.widgetStyle() | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
    }

    @Override
    
protected void checkSubclass()
    {
    }

    @Override
    
public void dispose()
    {
        image.dispose();
        
super.dispose();
    }

    
/* @Override
    LRESULT wmMeasureChild( int wParam, int lParam )
    {
        MEASUREITEMSTRUCT mis = new MEASUREITEMSTRUCT();
        OS.MoveMemory( mis, lParam, MEASUREITEMSTRUCT.sizeof );
        mis.itemHeight = 40;
        OS.MoveMemory( lParam, mis, MEASUREITEMSTRUCT.sizeof );
        return null; // super.wmMeasureChild( wParam, lParam );
    } 
*/

    @Override
    LRESULT wmDrawChild( 
int wParam, int lParam )
    {
        DRAWITEMSTRUCT dis 
= new DRAWITEMSTRUCT();
        OS.MoveMemory( dis, lParam, DRAWITEMSTRUCT.sizeof );

        GC gc 
= new GC( new DCWrapper( dis.hDC ) );
        Rectangle rc 
= new Rectangle( dis.left, dis.top, dis.right - dis.left,
                dis.bottom 
- dis.top );
        Display display 
= getDisplay();
        
if ( (dis.itemState & OS.ODS_SELECTED) != 0 )
        {
            gc
                    .setBackground( display
                            .getSystemColor( SWT.COLOR_LIST_SELECTION ) );
            gc.setForeground( display
                    .getSystemColor( SWT.COLOR_LIST_SELECTION_TEXT ) );
            gc.fillRectangle( rc );
        }
        
else
        {
            gc.setBackground( display
                    .getSystemColor( SWT.COLOR_LIST_BACKGROUND ) );
            gc.setForeground( display
                    .getSystemColor( SWT.COLOR_LIST_FOREGROUND ) );
            gc.fillRectangle( rc );
        }
        String text 
= getItem( dis.itemID );
        gc.drawImage( image, dis.left 
+ 1, dis.top + 1 );
        gc.drawText( text, dis.left 
+ 20, dis.top );

        gc.dispose();

        
return null;
    }

    
private static class DCWrapper implements Drawable
    {
        
private int    hdc;

        DCWrapper( 
int hdc )
        {
            
this.hdc = hdc;
        }

        
public int internal_new_GC( GCData data )
        {
            
return hdc;
        }

        
public void internal_dispose_GC( int handle, GCData data )
        {
        }
    }

    
private Image    image;
}


值得说明的是,如果设置Combo为OwnerDraw Variable风格,则必须重载wmMeasureChild方法来指定每一项的高度。如果使用OwnerDraw Fixed风格,则只需要在构造的时候发送一条CB_SETITEMHEIGHT消息就行了。

 另外一种值得考虑的选择是将Win32的ComboBoxEx控件包装成SWT Widget。不过,这需要转换若干结构并提供接口,Win32的ImageList管理机制和SWT的Image包装方法差别比较大,使得这种方法实现起来麻烦的多。

posted on 2006-07-06 10:08 TreeNode 阅读(2305) 评论(4)  编辑  收藏 所属分类: SWT,JFace和RCP

Feedback

# re: 在SWT中实现自绘Combo 2007-02-08 20:40 催月泪
treenode前辈:你好

在eclipse中国社区看了你的几篇文章,我好生佩服你.我在你的自定义控件的两篇文章中都看到了import org.eclipse.swt.internal.win32.这个包,但是我在eclipse3.2的API文档中怎么也找到相关的说明,在google中也搜索不到有用的信息.我找你找了好久,并且在eclipse中国社区发了寻人启示贴,但都没有回音,今天终于找到你的BLOG了.我很高兴.
我想请教一下,关于这个包那里相关的资料呢?如果可以的话,您能不能给我一些.

不胜感激!

gaojinglin@gmail.com
催月泪 西安
2007.2.8  回复  更多评论
  

# re: 在SWT中实现自绘Combo[未登录] 2007-02-08 22:07 treenode
文档里是没有写的,因为这是SWT的内部实现。你从Eclipse网站上下载SWT源代码包,打开以后就可以找到这些包和所有代码,里面实现了什么则需要自己去研究。

  回复  更多评论
  

# re: 在SWT中实现自绘Combo 2007-02-09 23:15 催月泪
哦!原来如此,看的出来前辈你是研究过SWT源代码的,真是不简单。
对于WIN32SDK我只有浅薄的基础,在阅读SWT源代码一定会很不适应,所以今后我一定会常来这里的。
谢谢!非常感谢前辈指点
  回复  更多评论
  

# re: 在SWT中实现自绘Combo[未登录] 2013-05-14 00:51 振兴
你好,我用了你写的这个代码,但是报:java.lang.SecurityException: class "org.eclipse.swt.widgets.CustomComboDemo"'s signer information does not match signer information of other classes in the same package,这是为什么呢,帮忙看一下可以吗,不胜感激  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: