[ZsUI]一步一步写个DirectUI.[连载贴]
vb吧
全部回复
仅看楼主
level 11
Zatans 楼主
趁着今天六一,这么欢乐的节日里,开个连载贴.
这个贴酝酿了有几天了,现在发出来看看反响.如果大家都不怎么感兴趣的话,我果断TJ掉.[抛媚眼]
贴吧的帖子偶尔会抽,或者排版问题影响阅读,所以我每一章都会在博客里也发一次.
看正版高清**连载请点:http://hi.baidu.com/zatansvb/blog/category/Visual%20Basic
2012年05月31日 18点05分 1
level 11
Zatans 楼主
ZsUI - 前言
提起DirectUI或者Windowsless相信很多人都会感到陌生.
先来看看百度百科:
http://baike.baidu.com/view/3102587.htm
如果还觉得概念模糊.可以找点参照.
VB中其实也有一些这样的控件,比如Label Image,这些都是直接画在窗体上,SPY+找不到句柄.
现在,开始一步一步的写一个自己的DirectUI.
由于此连载内容只是教学,为了简介方便,使用了效率一般的GDI+.大量地方未做优化.
(工程内引用了vIstaswx的GDI+ 声明模块)
每一步的代码都会打包放在百度的网盘里.
http://pan.baidu.com/netdisk/singlepublic?fid=295000_3835340436

2012年05月31日 18点05分 2
1
2021年05月20日 03点05分
链接没了
2024年10月16日 03点10分
level 11
Zatans 楼主
ZsUI - 第一个例子
第一步,我们找个容器.
在VB里,Form或者PictureBox又或者其它那些有句柄的可视控件都能胜任.
接着,在脑子想象一个控件应该有的样子. 位置和尺寸(x.y.width.height).各种属性和状态.(image.status).
我们先用一个Type来描述它.
Type Zs_UI_Button '想象中的简陋按钮.
X As Integer
Y As Integer
Width As Integer
Height As Integer
Image As Long
Status As Long
End Type
第二部,给它来点实际的东西.
Dim ZButton1 As Zs_UI_Button
With ZButton1
.X = 30
.Y = 30
.Width = 92
.Height = 40
Call GdipLoadImageFromFile(StrPtr(App.Path & "/res/button.png"), pImage)
.Image = pImage
.Status = C_Status_Leave
End With
第三部,我们为它弄点"事件"并把它显示出来.
"事件"不可能凭空出现,这事得靠依附的那个容器了.
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) '容器的MouseMove事件
With ZButton1
If X > .X And X < .X + .Width And Y > .Y And Y < .Y + .Height Then '看看是不是轮到我出场了.MouseEnter和MouseLeave都是靠这句了.
If .Status And C_Status_Leave Then '为了防止一直重画,设置个状态标志.
Me.Cls '因为我们要做的控件是透明的,所以先要把容器背景重画一次.
Call GdipDrawImageRectRect(pGraphics, .Image, .X, .Y, .Width, .Height, 92, 0, 92, 40, UnitPixel) '根据一个状态画出对应的图.
.Status = C_Status_Hover '标记一下
End If
Else
If .Status = C_Status_Hover Then
Me.Cls
Call GdipDrawImageRectRect(pGraphics, .Image, .X, .Y, .Width, .Height, 0, 0, 92, 40, UnitPixel)
.Status = C_Status_Leave
End If
End If
End With
End Sub
Private Sub Form_Click() '处理容器的单击事件.
If ZButton1.Status = C_Status_Hover Then '如果鼠标还在虚拟控件的范围内,就吱一声.
MsgBox "ZButton_Click"
End If
End Sub
写完这些,运行来张效果图看看.
嘿,可爱的"控件"出现了.
不过这样的代码明显是各种BUG,糟糕透顶了.
一两个"控件"还好,多了就是一团糟.
下期我们开始把这些封装起来.让它更像"控件"一点.
本期代码下载地址:http://pan.baidu.com/netdisk/singlepublic?fid=295000_4071038647

2012年05月31日 18点05分 3
level 11
Zatans 楼主
ZsUI - 初步封装
封装可以使代码变得简洁,方便,可复用.
我们先简单的封装一下.
新建一个Zs_h模块.
把一些常数和自定义类型的声明放在里面.
新建一个Zs_Graphics_GdiPlus类模块.
负责GDIPlus的初始化和善后.
新建一个Zs_UI_Container类模块.
负责管理子控件,处理父容器的消息分发给对应的子控件.并声明一些接口给子控件调用.
新建一个Zs_UI_ImageButton类模块.
替代原先那个简陋的Type Zs_UI_Button.
封装后的效果图.
本期源码下载地址:http://pan.baidu.com/netdisk/singlepublic?fid=295000_3794599589

2012年05月31日 19点05分 4
level 13
顶顶更健康,来支持下!顺祝节日快乐[傻笑]
2012年05月31日 19点05分 5
level 11
Zatans 楼主
ZsUI - 思考已出现的问题
上一期的代码里,把所有的UI对象都放进一个数组,通过轮询数组来找出触发事件的对象,数组的中对象的顺序既是对象的Z序.
重绘的时候从数组第一个对象开始,也就是最底层.触发事件的时候从数组最后一个对象开始,也就是最顶层.
VB中数组很方便,可是用数组保存对象,这对于增删改对象的时候却非常的低效.个人觉得链表才是更好的选择.虽然链表在VB中实现也很麻烦.
关于重绘,上一期的代码重绘时有很严重的闪烁.而且系统的内存占用很大.
可以更改重绘方式为双缓冲定时重绘,即每50MS重绘一次.VB中多线程不稳定,用Timer代替.
(因UI对象都有透明度,这里重绘时选择全部重绘,而没有做裁剪优化.有心的可以自己去写一个)
在想象中,写一个Zs_UI_Base这样的基类,然后继承和重载是最好的选择,可以省去很多精力和劳力,可惜VB在类的继承上太脆弱了.
导致每写一个UI对象就要重新写一遍那些X,Y,Width,Height...之类的属性和方法.代码的臃肿可想而知.
这个暂时无解.或又谁知道取巧的可以指点下我.~.~.

2012年05月31日 19点05分 6
level 11
Zatans 楼主
[奸笑]年年有今日,岁岁有今朝.
2012年05月31日 19点05分 7
level 9
大概20天或者一个月前也在弄directui,语言选了go,现在有点后悔了。(go有接口,但没有继承)
控件只写了个按钮类和半个文本框(cleartype不会处理,再加上考试所以停滞到了现在..)
实现的事件:
go和vb一样,没有头文件,只能自己去写声明:
抛开语言,说下经验:
重绘问题是大家都比较关心的,我的实现方法是父控件生成bitmap,然后向下传递从该bitmap创建的graphics。最终所有图像都存在于顶层控件创建的bitmap上,由顶层控件(窗体)实施绘制。重绘效率:
大概每次15ms。提高重绘效率的一个技巧是使用cachedbitmap(不使用cachedbitmap的效率大概是200ms)。
贴张图(上面的图都是以前截的,刚重装完系统...)
为了风格统一,我实现的时候除了beginpaint和endpaint算是gdi函数外,其余全部使用gdi+函数。
支持楼主[Yeah]此贴不会TJ[顶]
2012年05月31日 20点05分 8
level 8

2012年06月01日 00点06分 9
吧务
level 10
节日快乐,此贴该加精
2012年06月01日 00点06分 10
吧务
level 10
好像已经是精品了,哈哈
2012年06月01日 00点06分 11
level 7
好贴要顶 支持
lz
继续发下去 祝lz节日快乐
2012年06月01日 00点06分 12
对不起,我摸了你的签名档做了桌面
2012年06月14日 15点06分
level 13
[顶]
2012年06月01日 00点06分 13
level 11
Zatans 楼主
[哈哈]谢谢大家支持.六一快乐.
2012年06月01日 01点06分 14
level 9
厉害[开心]
2012年06月01日 01点06分 15
level 11
Zatans 楼主
很早前用PowerBasic写了一个框架,现在再看看发现以前写的实在有够烂,准备推翻重写了.
贴图部分最好是用自己写的函数,抛弃GDI+,那玩意儿实在是慢.
GDI+在这教程里用只是为了方便和简洁.效率什么的暂时不做考虑.[哈哈]
2012年06月01日 02点06分 16
level 9
混个
前排
!~~~~~~~~~~~~~~~[抛媚眼]
2012年06月01日 04点06分 17
level 11
好神奇...学习了.
@WWEERR
2012年06月01日 04点06分 18
level 12
x
2012年06月01日 05点06分 19
level 7
谢谢@Zatans。。难得一见的技术好贴~
2012年06月01日 08点06分 21
1 2 3 4 5 6 尾页