此文章献给想美化程序界面的pb程序员。
一.载入位图资源并创建PatternBrush作为填充背景图的刷子 long ll_bmp long h_deskdc long ll_memDc
if ih_BkBrush>0 then deleteObject(ih_BkBrush) ih_BkBrush=0 end if
h_deskdc =GetDc(0) //载入图片 ll_bmp = LoadImage(0,BMPBkName,0,0,0,16) //失败 if ll_bmp = 0 then releaseDc(0,h_deskdc) return end if ll_memDC = CreateCompatibleDC(h_deskdc) //选入到场景 SelectObject(ll_memDC,ll_bmp) //创建绘制背景图的刷子 ih_BkBrush =CreatePatternBrush(ll_bmp) //释放不需要的资源 releaseDc(0,h_deskdc) Deleteobject(ll_bmp) DeleteDc(ll_memDC)
二.给listview加背景图 1.得到listview客户区域矩形 getClientRect(handle(this),lvclientRect)
2.在listview中以pbm_erasebkgnd为事件id,自定义事件ue_erasebkgnd ,script如下 if ih_BkBrush>0 then FillRect(hdc,lvClientrect,ih_BkBrush) return 1 end if
3.当listview的显示风格为listviewreport!,listviewlist!时候,拖动滚动条时候会出现挤压需要以pbm_vscroll和pbm_hscroll作为eventid自定义事件ue_vscroll,ue_hscroll。 if ih_BkBrush>0 and (View=listviewreport! or View=listviewlist!) then if (scrollcode<>SB_ENDSCROLL) and (scrollcode<>SB_THUMBPOSITION) then InvalidateRect(handle(this),lvclientRect,1) end if end if 尽管如此,在上述两种风格中拖动滚动条依然有闪烁的情况,我还没有能够解决,欢迎大家提出意见。
4.如果想要listview中item的文本和图片背景透明,只需调用以下代码 Constant Long CLR_NONE = 4294967295 Constant Long LVM_FIRST =4096 Constant Long LVM_SETTEXTBKCOLOR = (LVM_FIRST + 38) Constant Long LVM_GETIMAGELIST = (LVM_FIRST + 2) Constant Long LVM_SETBKCOLOR = (LVM_FIRST + 1) Constant Long LVSIL_NORMAL= 0 Constant Long LVSIL_SMALL=1 Constant Long LVSIL_STATE=2 //让文本的背景色透明 Send(handle(this),LVM_SETTEXTBKCOLOR,0,CLR_NONE) //让图片的背景色透明 Send(handle(this),LVM_SETBKCOLOR,0,CLR_NONE)
此外,如果使用pb自带的图片,需要将PictureMaskColor设置为Silver。
三.给treeview加背景图 如果按照上述listview的方法给treeview控件添加背景图,也可以基本实现,但是在树的子项展开,收缩时候以及拖动滚动条时会挤压图形,如果用setredraw控制会出现严重的闪烁情况。此外树的子项的文本和图片背景也不能透明。
1.我参考了其他程序语言实现的例程,基本都会在WM_PAINT事件中处理,因此我以pbm_paint作为eventid自定义事件ue_paint。但由于此事件的参数Hdc在任何情况下均为0,所以我猜测在pb中,此事件只是在调用WindowProc处理WM_PAINT消息前执行,并没有使用beginPaint开始进行绘图操作。 要让树的子项的文本和图片背景透明,只需要做一些光栅运算就可以了 相关代码如下: if ih_BkBrush>0 then
if message.WordParm >0 then //由send函数带WordParm参数触发,不执行下面的操作 return 0 end if tagPAINTSTRUCT ps //开始paint操作 HDC=BEGINPAINT(handle(this),ps) long memdc,maskdc,ResultDc; long hbitmap; long li_RCWidth,li_RCHeight li_RCWidth=tvclientRect.right -tvclientRect.left li_RCHeight=tvclientRect.bottom -tvclientRect.top ResultDc=CreateCompatibleDC(hdc); hbitmap=CreateCompatibleBitmap(hdc,li_RCWidth,li_RCHeight); SelectObject(ResultDc, hbitmap ); deleteObject(hbitmap) //将背景图绘制到设备场景ResultDc上 FillRect(ResultDc,tvclientRect,ih_BkBrush) // create a compatible memory dc memdc=CreateCompatibleDC(hdc); hbitmap=CreateCompatibleBitmap(hdc,li_RCWidth,li_RCHeight); SelectObject(memdc, hbitmap ); deleteObject(hbitmap) //将tv的内容绘制到设备场景memdc上 send(handle(this),WM_PAINT,memdc, 0) // create mask dc maskdc=CreateCompatibleDC(hdc); hbitmap=CreateBitmap(li_RCWidth,li_RCHeight,1, 1,0); SelectObject(maskdc, hbitmap ); deleteObject(hbitmap) //只有单色 BitBlt(maskdc,0,0,li_RCWidth,li_RCHeight,memdc,0,0,SRCCOPY); SetBkColor(memdc,RGB(0,0,0)); SetTextColor(memdc,RGB(255,255,255)) //白色替换为黑色 BitBlt(memdc,0,0,li_RCWidth,li_RCHeight,maskdc,0,0,SRCAND); //通过and操作,将item和文本置为黑色添加到背景图上 BitBlt(ResultDc,0,0,li_RCWidth,li_RCHeight,maskdc,0,0,SRCAND); //通过or操作,将treeitem替换为原有颜色 BitBlt(ResultDc,0,0,li_RCWidth,li_RCHeight,memdc,0,0,SRCPAINT); //将合并后的图copy到hdc上 BitBlt(hDc,0,0,li_RCWidth,li_RCHeight,ResultDc,0,0,SRCCOPY);
deleteDc(memdc) deleteDc(maskdc) deleteDc(ResultDc) //结束paint操作 endpaint(handle(this),ps) end if
由于做了多次的位图处理操作,在配置较低的机器上可能会有延迟的现象,所以treeview控件的长度和宽度不要太大,子项的数目应该控制在合理的范围内。
2、由于我们在ue_paint事件中已经对背景进行了绘制,因此需要屏蔽默认的刷新背景操作。 ue_erasebkgnd: if ih_BkBrush>0 then //不执行默认的消息处理程序 return 1 end if
3.对于treeview由于子项展开,收缩时候会挤压图形,需要itemcollapsin、itemexpanding和selectchanging事件控制从而使整个控件重画。 if ih_BkBrush>0 then InvalidateRect(handle(this),tvclientRect,0) 4、对于由于滚动条拖动产生的图形积压,也需要做类似处理。 pbm_vscroll和pbm_hscroll: if ih_BkBrush>0 and (scrollcode<>SB_ENDSCROLL) and (scrollcode<>SB_THUMBPOSITION) then InvalidateRect(handle(this),tvclientRect,0) end if
在这里我只对程序的关键实现部分作了说明,省略了相关的变量、外部函数、结构声明和其他部分。完整的pb8例程可在 http://www.tiantiansoft.com/dispbbs.asp?boardID=23&ID=934下载,欢迎大家作进一步探讨:)
[常用软件]TreeView 控件应用详解 [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(二) [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(一) [Delphi程序]Delphi中为TreeView添加单选和复选框 [Delphi程序]Object TreeView简要说明 [Delphi程序]Delphi下Treeview控件基于节点编号的访问 [VB.NET程序]将listview中显示出来的记录拖到treeview中去 [VB.NET程序]vbscript版的TreeView,也就是树 [VB.NET程序]TreeView 控件树状控件的填充VB以及 VS.NET C#源代… [VB.NET程序]Treeview 控件的使用方法
|