combobox自绘试验
看到论坛上有人问combobox这个控件可以自绘吗?
于是去看了下控件属性里面
貌似有个自绘选项,那么开启之后应该怎么操作呢,
于是我打开了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 { } } //无返回值则继续调用默认回调函数 }
运行后效果和想象的不一样。但是也能看出来有那么一点点的变化了。
后面继续测试。
仔细看了几篇文章,发现还是style没设置好。
虽然我里面用了
winform.combobox.modifyStyle(,0x20/*_CBS_OWNERDRAWVARIABLE*/);
但是貌似没写进图,于是,我先跳转到combobox.aardio这个库里面,在
在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这个还是没有。
虽然这样,但是至少是迈出了一大步。
这里我再次考虑,如果修改了标准库,那么以后所有的项目都会受到影响,这样显然不行。
那么就应该考虑怎么最低的消除隐患。
看到combobox这个库里面,生成控件的时候其实写了很多属性进去,那么从上图可以看出,这些红色框中的属性,对应的来自哪里??
我们打开界面的代码
原来这些属性是这里的。。。。
那么我是不是可以直接写入这里?
我在后面增加
style=0x20;
再次运行,效果和修改库是一样的,猜测正确。
根据如上的改动,增加代码:
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(); }
效果如下:
上面没有显示字,是因为还没调用绘制字的函数,下次继续修改。
我在aardio的全部文件中搜索ownerDraw
对比listbox和tab等等,发现combobox库里是不是少写了一句代码,因为少了下面这句,那么创建控件的时候,这个ownerDraw=1 这个参数就毫无用处。
于是我在库中增加:
if(tParam.ownerDraw) tParam.style |= ( 0x20/*_LBS_OWNERDRAWVARIABLE*/|0x40/*_LBS_HASSTRINGS*/ )
然后删除掉上面界面中添加的style=0x20,重新运行界面,发现完全和预想的一样了。
列表中的字没显示,还是因为开启了自绘,但是我没对字进行绘制。
把字体画出来。
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(); }
增加隔行显示,增加焦点背景显示,单行字后移
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(); }
附上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 。
增加位图到下拉。
//从文件创建位图 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();
http://www.aiuxian.com/article/p-425117.html
组合框控件(combobox)
组合框把一个编辑框和一个单选择列表框结合在了一起.用户既可以在编辑框中输入,也可以从列表框中选择一个列表项来完成输入。组合框分为简易式(Simple combo box)、下拉式(Drop-down combo box)和下拉列表式(Drop-down list box)三种.简易式组合框包含一个编辑框和一个总是显示的列表框。下拉式组合框同简易式组合框类似,二者的区别在于仅当单击下滚箭头后列表框才会弹出。下拉列表式组合框也有一个下拉的列表框,但它的编辑框是只读的,不能输入字符。
应用程序用CreateWindowEx创建组合框控件时,可根据控件的用途在下表中选择部份常数来设定其风格属性(style)。
应用程序可以通过调用SendMessage向控件发送如下消息来设定和查询控件各种参数。
登录后方可回帖
https://blog.csdn.net/u012372584/article/details/78111980
ComboBox控件自绘操作