combobox自绘试验

By admin at 2018-08-04 • 0人收藏 • 437人看过

看到论坛上有人问combobox这个控件可以自绘吗?

于是去看了下控件属性里面

blob.png

貌似有个自绘选项,那么开启之后应该怎么操作呢,

于是我打开了aar的例程里面的listbox和listview的自绘案例

主要是我也不懂怎么自绘,上次那个listview画线和进度条也差不多是试了各种网上的方法才搞定。

那么就按照那个写了两个oN 事件。

但是,我在这两个oN事件中都添加一个console.log()来随意的在控制台观察到底有没有进入这两个事件函数。。。发现并没有,那么这样写看来是行不通的吧?....


那么我拦截WM_Paint事件是不是可行呢?

于是网上找到一个重画combobox背景色的示例

https://www.cnblogs.com/colder/p/3333118.html

参考上面的写了下面的代码:

import console
console.open()

import win.graphics;
winform.combobox.wndproc = function(hwnd,message,wParam,lParam){
	select(message) {
		case 0xF/*_WM_PAINT*/ {
			var hdc = ::GetWindowDC(winform.combobox.hwnd)
			console.log(hdc)
			
			var cvs = win.graphics.canvas(); // 创建一个画布
    		cvs.fromHDC(hdc); // 传入 hDC
    		cvs.brush.color = 0xfccf55; // 定义刷子颜色
    		cvs.fillRect(winform.combobox.getClientRect());
    		//cvs.pen.color = 0xffff55; // 定义画笔的颜色
            //cvs.drawEdge(winform.combobox.getRect());
            //winform.combobox.update()
    		cvs.destroy();
			::ReleaseDC(winform.combobox.hwnd,hdc);
			
		}
		case 0x2B/*_WM_DRAWITEM*/{
			//console.log("3333333333333")
		}
		else {
		}
	}
	//无返回值则继续调用默认回调函数
}

运行后效果和想象的不一样。但是也能看出来有那么一点点的变化了。

blob.png

后面继续测试。

10 个回复 | 最后更新于 2018-08-05
2018-08-05   #2

仔细看了几篇文章,发现还是style没设置好。

虽然我里面用了

winform.combobox.modifyStyle(,0x20/*_CBS_OWNERDRAWVARIABLE*/);

但是貌似没写进图,于是,我先跳转到combobox.aardio这个库里面,在

blob.png

在dropdown这个模式下,直接手动增加0x20这个自绘样式。

再次运行,在以下的代码里可以接受到数据返回了。

winform.combobox.onMeasureItem = function(measureItem){
    //注意listbox的实际高度受行高的影响,只有自绘时才能设置行高
	//measureItem.itemWidth = 51; 
	//measureItem.itemHeight = 500
	 console.log("2222222222")
}
winform.combobox.onDrawItem = function(drawItem){
    //var rc = drawItem.rcItem;
    console.log("3333333333333")
}

这里只有onDrawItem()这个函数有输出指示,MeasureItem这个还是没有。

虽然这样,但是至少是迈出了一大步。


这里我再次考虑,如果修改了标准库,那么以后所有的项目都会受到影响,这样显然不行。

那么就应该考虑怎么最低的消除隐患。

blob.png

看到combobox这个库里面,生成控件的时候其实写了很多属性进去,那么从上图可以看出,这些红色框中的属性,对应的来自哪里??

我们打开界面的代码

blob.png

原来这些属性是这里的。。。。

那么我是不是可以直接写入这里?

我在后面增加

style=0x20;

blob.png

再次运行,效果和修改库是一样的,猜测正确。

2018-08-05   #3

根据如上的改动,增加代码:

import win.graphics;
winform.combobox.onDrawItem = function(drawItem){
    var cvs = win.graphics.canvas(); // 创建一个画布
    cvs.fromHDC(drawItem.hDC); // 传入 hDC
    cvs.brush.color = 0xfccf55; // 定义刷子颜色
    cvs.fillRect(drawItem.rcItem);
    cvs.pen.color = 0xffff55; // 定义画笔的颜色
    cvs.drawEdge(drawItem.rcItem);
    cvs.destroy();
}

效果如下:

blob.png

上面没有显示字,是因为还没调用绘制字的函数,下次继续修改。

2018-08-05   #4

我在aardio的全部文件中搜索ownerDraw

对比listbox和tab等等,发现combobox库里是不是少写了一句代码,因为少了下面这句,那么创建控件的时候,这个ownerDraw=1 这个参数就毫无用处。

于是我在库中增加:

if(tParam.ownerDraw) 
tParam.style |= ( 0x20/*_LBS_OWNERDRAWVARIABLE*/|0x40/*_LBS_HASSTRINGS*/ )

blob.png

然后删除掉上面界面中添加的style=0x20,重新运行界面,发现完全和预想的一样了。

blob.png

列表中的字没显示,还是因为开启了自绘,但是我没对字进行绘制。

2018-08-05   #5

blob.png

把字体画出来。

winform.combobox.onDrawItem = function(drawItem){
    var cvs = win.graphics.canvas(); // 创建一个画布
    cvs.fromHDC(drawItem.hDC); // 传入 hDC
    cvs.brush.color = 0xfccf55; // 定义刷子颜色
    cvs.fillRect(drawItem.rcItem);
    cvs.pen.color = 0xffff55; // 定义画笔的颜色
    cvs.drawEdge(drawItem.rcItem);
    
    cvs.font.bold = true;
    cvs.font.color = 0x11FFFF;
    cvs.textOut(drawItem.rcItem.left, drawItem.rcItem.top, winform.combobox.items[drawItem.itemID+1]);
    cvs.destroy();
}


2018-08-05   #6

想要试着增加下拉的宽度

    cvs.brush.color = 0xfccf55; // 定义刷子颜色
    var rc = ::RECT(drawItem.rcItem.left+20,drawItem.rcItem.top,drawItem.rcItem.right,drawItem.rcItem.bottom);
    
    cvs.fillRect(rc);

但是主要超过了这个控件的边界好像就不行,但是缩小显示还是可以的。。。。

2018-08-05   #7

增加隔行显示,增加焦点背景显示,单行字后移

winform.combobox.onDrawItem = function(drawItem){

    var cvs = win.graphics.canvas(); // 创建一个画布
    cvs.fromHDC(drawItem.hDC); // 传入 hDC

    if(drawItem.itemID%2!=0){
    	cvs.brush.color = 0x00c044; // 定义刷子颜色
    }
    else {
    	cvs.brush.color = 0xffffff;
    }
    
    var rc = ::RECT(drawItem.rcItem.left,drawItem.rcItem.top,drawItem.rcItem.right,drawItem.rcItem.bottom);
   
    cvs.fillRect(rc);
    cvs.pen.color = 0x000000;
    cvs.drawEdge(rc, 0x8/*_BF_BOTTOM*/);
    
    if(drawItem.itemState&1/*_ODS_SELECTED*/){
    	cvs.font.color = 0x0000ff; 
    	cvs.textOut(rc.left+20, rc.top, winform.combobox.items[drawItem.itemID+1])
    	cvs.drawFocusRect(rc);
    }else {
    	cvs.pen.color = 0xff8057; // 定义画笔的颜色
    	cvs.textOut(rc.left+20, rc.top, winform.combobox.items[drawItem.itemID+1]);
    }

    cvs.destroy();
}

blob.png

2018-08-05   #8

附上tagDRAWITEMSTRUCT结构的说明:


DRAWITEMSTRUCT 结构的定义如下:

  typedef struct tagDRAWITEMSTRUCT {

  UINT CtlType;

  UINT CtlID;

  UINT itemID;

  UINT itemAction;

  UINT itemState;

  HWND hwndItem;

  HDC hDC;

  RECT rcItem;

  ULONG_PTR itemData;

  } DRAWITEMSTRUCT, NEAR *PDRAWITEMSTRUCT, FAR *LPDRAWITEMSTRUCT ; 结构成员:

  成员:

  CtlType

   指定了控件的类型,其取值如下表所示。

  ODT_BUTTON :按钮控件

  ODT_COMBOBOX :组合框控件

  ODT_LISTBOX :列表框控件

  ODT_LISTVIEW :列表视图控件

  ODT_MENU :菜单项

  ODT_STATIC :静态文本控件

  ODT_TAB :Tab 控件

  CtlID

   指定了自绘控件的ID 值,而对于菜单项则不需要使用该成员

  itemID

  表示菜单项ID ,也可以表示列表框或者组合框中某项的索引值。对于一个空的列表框或组合框,该 成员的值为–1 。这时应用程序只绘制焦点矩形(该矩形的坐标由rcItem 成员给出)虽然此时控件中没有需要显示的项,但是绘制焦点矩形还是很有必要的,因为这样做能够提示用户该控件是否具有输入焦点。当然也可以设置 itemAction 成员为合适值,使得无需绘制焦点。

  itemAction

  指定绘制行为,其取值可以为下表中所示值的一个或者多个的联合。

  ODA_DRAWENTIRE :当整个控件都需要被绘制时,设置该值

  ODA_FOCUS :如果控件需要在获得或失去焦点时被绘制,则设置该值。此时应该检查itemState成员,以确定控件是否具有输入焦点。

  ODA_SELECT

  如果控件需要在选中状态改变时被绘制,则设置该值。此时应该检查itemState 成员,以确定控件是否处于选中状态。

  itemState

  指定了当前绘制操作完成后,所绘项的可见状态。例如,如果菜单项应该被灰色显示,则可以指定ODS_GRAYED 状态标志。其取值可以为下表中所示值的一个或者多个的联合。

  ODS_CHECKED :如果菜单项将被选中,则可设置该值。该值只对菜单项有用。

  ODS_COMBOBOXEDIT :在自绘组合框控件中只绘制选择区域。

  ODS_DEFAULT :默认值。

  ODS_DISABLED :如果控件将被禁止,则设置该值。

  ODS_FOCUS :如果控件需要输入焦点,则设置该值。

  ODS_GRAYED :如果控件需要被灰色显示,则设置该值。该值只在绘制菜单时使用。

  ODS_HOTLIGHT :Windows 98/Me, Windows 2000/XP: 如果鼠标指针位于控件之上,则设置该值,这时控件会显示高亮颜色。

  ODS_INACTIVE :Windows 98/Me, Windows 2000/XP: 表示没有激活的菜单项。

  ODS_NOACCEL :Windows 2000/XP: 控件是否有快速键盘。

  ODS_NOFOCUSRECT :Windows 2000/XP: 不绘制捕获焦点的效果。

  ODS_SELECTED :选中的菜单项。

  hwndItem

  指定了组合框、列表框和按钮等自绘控件的窗口句柄;如果自绘的对象时菜单项,则表示包含该菜单项的菜单句柄。

  hDC

  指定了绘制操作所使用的设备环境。

  rcItem

  指定了将被绘制的矩形区域。这个矩形区域就是上面hDC 的作用范围。系统会自动裁剪组合框、列 表框或按钮等控件的自绘制区域以外的部分。也就是说rcItem 中的坐标点(0 ,0 )指的就是控件的左上角。但是系统不裁剪菜单项,所以在绘制菜单项的时 候,必须先通过一定的换算得到该菜单项的位置,以保证绘制操作在我们希望的区域中进行。

  itemData

  对于菜单项,该成员的取值可以是由

  CMenu::AppendMenu 、

  CMenu::InsertMenu 或者

  CMenu::ModifyMenu

  等函数传递给菜单的值。

  对于列表框或这组合框,该成员的值可以为由

  ComboBox::AddString 、

  CComboBox::InsertString 、

  CListBox::AddString 或者

  CListBox::InsertString

  等传递给控件的值。

如果ctlType 的取值是ODT_BUTTON 或者ODT_STATIC, itemData 的取值为0 。


2018-08-05   #9

blob.png

增加位图到下拉。

    //从文件创建位图
	var bmp = gdip.bitmap("C:\Users\popdes\Desktop\bbb.png");
    //图形对象graphics(可以看作是画板)
	var graphics = gdip.graphics(drawItem.hDC) 
	graphics.drawImageRect(bmp,drawItem.rcItem.left,drawItem.rcItem.top+2.5,drawItem.rcItem.height()-5,drawItem.rcItem.height()-5);
	graphics.delete();


2018-08-05   #10

http://www.aiuxian.com/article/p-425117.html

组合框控件(combobox)

组合框把一个编辑框和一个单选择列表框结合在了一起.用户既可以在编辑框中输入,也可以从列表框中选择一个列表项来完成输入。组合框分为简易式(Simple combo box)、下拉式(Drop-down combo box)和下拉列表式(Drop-down list box)三种.简易式组合框包含一个编辑框和一个总是显示的列表框。下拉式组合框同简易式组合框类似,二者的区别在于仅当单击下滚箭头后列表框才会弹出。下拉列表式组合框也有一个下拉的列表框,但它的编辑框是只读的,不能输入字符。 
  应用程序用CreateWindowEx创建组合框控件时,可根据控件的用途在下表中选择部份常数来设定其风格属性(style)。

blob.png

应用程序可以通过调用SendMessage向控件发送如下消息来设定和查询控件各种参数。

blob.png

blob.png

blob.png

blob.png

登录后方可回帖

登 录
信息栏
本站永久域名:HtmLayout.Cn
纯私人站,当笔记本用的,学到哪写到哪,目前正在学aardio+halcon机器视觉.
本 站 主 站:Stm32cube中文网
Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
黑猫Aar教程网:简码编程
C大Aardio论坛:Aar爱好者论坛
AARDIO语言QQ群:70517368
赞助商:才仁机械
下载站:非凡软件站
Loading...