ZsUI - 抛弃原生事件改用子类化
VB自身高度封装的事件驱动给了我们很多便利,可是也制约了我们的自由.
随着我们需求的旺盛,容器妹纸自身已经满足不了我们了.
像MouseLeave,MouseWheel,Activate...等等,都是她无法给我们的爱.
是时候找个野蛮女友了.我那又爱又恨的...SubClass!!
开始调教第一步.
SetProp(ContainerObject.hWnd, C_Prop_UI_Container, ObjPtr(Me))
先把对象指针放到容器的属性表中,这样子类函数里就可以找到并且调用了.
SetWindowLong(ContainerObject.hWnd, GWL_WNDPROC, AddressOf Zs_UI_ObjectWndProc)
子类化容器对象,处理交给Zs_Proc模块的Zs_UI_ObjectWndProc函数.
SetTimer(ContainerObject.hWnd, Zs_Const_RefreshTimerId, RefreshCycle, AddressOf Zs_UI_ObjectTimerProc)
创建一个定时器替代原本的定时器控件,回调函数Zs_Proc模块的Zs_UI_ObjectTimerProc.
第二步就是在回调函数中把消息映射到对象的事件了.
Dim objX As Object
Call CopyMemory(objX, GetProp(hwnd, C_Prop_UI_Container), 4)
这样就获得了容器对象.
Dim dwSZ As Dword 'Dword是一个Type,用来取出lParam的高低位.
Case WM_SIZE
Call CopyMemory(dwSZ, lParam, 4)
Zs_UI_ObjectWndProc = objX.EventResize(dwSZ.Hi, dwSZ.Lo) '按消息执行对象的方法
Call CopyMemory(lParam, dwSZ, 4)
对象中有如下的方法.
Public Function EventResize(w As Integer, h As Integer) As Long
RaiseEvent Resize(w, h) '映射到对象的事件Resize
End Function
回调函数末尾需要用Call CopyMemory(objX, 0&, 4)来还原对象指针,
这样,一个映射机制基本实现,扩展的时候代码也不用做太大改动,需要什么事件只需添加相应的消息,再映射到对象上就可以了.
再把那些依赖容器属性的对象属性改为用API实现,从容器对象的捆绑中解脱出来.
一切搞定之后.
现在,我们的容器已经不局限于窗体.可以是PictureBox,可以是Frame...只要是有hWnd的对象都可以.

本期源码下载地址:
http://pan.baidu.com/netdisk/singlepublic?fid=295000_3144764738