combobox自绘试验

By admin at 2018-08-04 • 1人收藏 • 2560人看过

看到论坛上有人问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

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...