VB 版 (精华区)

发信人: zxfsnow (别怕我伤心), 信区: VB
标  题: 针对API编程初学者的教程第五篇 
发信站: 哈工大紫丁香 (2000年05月31日12:19:12 星期三), 转信

发信人: Keri (呵呵2000), 信区: VB
标  题: 针对API编程初学者的教程第五篇
发信站: 虎踞龙蟠 (Fri Mar 31 09:29:14 2000), 转信

子类处理
当你一最大限度利用了VB所给你的并且还想知道更多的东西,或只是想更多地了解你自己
的窗口,你将会发现子类处理的优势.
子类处理是指用一个新的窗口函数来取代当前活动窗口函数.这个用户自定义函数能处理
任何需要的消息,并能调用原来的窗口函数,它将在原来的窗口函数之前收到各种消息.但
原来的那个窗口处理函数依然存在,并没有消失.如果你不想处理某条消息,你应该让原来
的窗口函数去处理它.
子类处理是通过调用SetWindowLong函数实现的,该函数将改变指定窗口的特殊属性.下面
是它的声明:
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA"(ByVal hwn
d As Long, ByVal nIndex As Long,ByVal dwNewLong As Long) As Long
第一个参数代表要进行子类处理的窗口,第二个参数应该是GWL_WNDPROC(-4),第三个参数
是新的窗口函数的地址.参见回调和窗口函数一节.
此函数将在窗口取得焦点,发生事件,或其他情况下(如其他进程改变了系统的某些参数)
被随时调用.
如果发生错误SetWindowLong函数将返回0,否则将返回原来的窗口函数的地址.这个地址
特别重要,你应该把它保存在一个变量中或其他地方.当你不处理某些消息时(实际上,你
可能只处理不到1%的消息,其他的都将由原窗口函数处理),调用原来的窗口函数就需要该
地址.
地址.
调用原窗口函数将由CallWindowProc来完成.这里是它的声明:
Declare Function CallWindowProc Lib "user32" Alias"CallWindowProcA"(ByVal lp
PrevWndFunc As Long,ByVal hWnd As Long,ByVal Msg As Long,ByVal wParam As Lon
g, ByVal lParam As Long) As Long
第一个参数是原窗口函数的地址,其他的同你接收到的四个参数一样.你可以改变其中的
值来控制对消息的处理.例如,当你收到了一条WM_MOUSEMOVE消息时,你从lParam中得到鼠
标所在位置的坐标并将其改成了其他的坐标.那么原窗口函数就会认为鼠标位于其他的位
置从而做出一些有趣的事如显示其他控件的Tooltip.
你指定的返回值也是有意义的,它依赖于发送的消息.
在结束你的程序时将控制权交回给原窗口函数是很重要的,通常在Form_Unload中完成如
下:
Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProcAddress)
如果你在VB中启动程序时忘掉了这一行,结果将是VB崩溃并会丢失尚未保存的数据.千万
要小心.
这里是子类处理的一个简单示例:
Dim oldWndProc As Long
Private Sub Form_Load()
oldWndProc = SetWindowLong(Me.Hwnd, GWL_WNDPROC, AddressOf MyWndProc)
End Sub
Private Sub Form_Unload()
Ret& = SetWindowLong(Me.Hwnd, GWL_WNDPROC, oldWndProc)
End Sub
End Sub
Function MyWndProc(ByVal Hwnd As Long,ByVal wMsg as Long,ByVal wParam As Lon
g,ByVal lParam As Long)
Debug.Print wMsg & " " & wParam & " " & lParam
Ret& = CallWindowProc(oldWndProc, Hwnd, wMsg, wParam, lParam)
End Function
处理参数
有时函数并不以你所需的方式返回信息.一个典型的例子是将两个代表鼠标位置的整形(
2 byte)数合并为一个4 Byte的数.还有一个例子是判断一个数的某位是否为1.你还可能
得到一个代表一个结构地址的Long型数.
合并和分离一个数并不需要过多的描述.你能在我们的网站(www.geocities.com/Silico
nValley/Lab/1632/)上找到APIMacro.bas,它包含了你需要的多种函数.
可以用一下方法检查一个数的第N位是否为1:
If Value and (2^N) then ...
置1
Value = Value Or 2^N
置0
Value = Value And Not 2^N
如果你想设定或取得预先知道的某位的信息,用1024代替2^10要快的多.因为这样VB无需
自己进行计算(VB憎恨 "^" ?).
如果你接收到一个类型的指针,你要做的工作将稍多一点.你可以使用CopyMem函数来取得
信息.下面是它的声明:
Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory"     (pDest As Any,

pSource As Any, ByVal ByteLen As Long)
如果你接收到了一个指向RECT 类型的指针并存在Long型变量Addr 中,可以这样处理:
Dim Info As Rect
Call CopyMem(Info, ByVal Addr, len(Info))
注意ByVal关键字.现在,如果你想把信息写回,使用:
Call CopyMem(ByVal Addr, Info, Len(Info))
结束语
我希望这份教程能帮助你理解如何控制API函数的威力和如何正确使用它们.但是要小心
!就像火,如果你让它失去控制,你就会玩蛋.当然,不要忘了VB是进行简单.安全程序设计
的语言,而API函数则正好相反.如果你想得到更多的控制功能,最好转移到VC++ 或者Del
phi.(这一点,洞主不敢苟同).
祝你在API探险中好运!


--
不写了,没什么可说的了.....

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.7.200]

--
-                          KeriKeriKeriKeriKeri
                          拥                  拒
                          有   不敢奢望太多   绝
                          友   只想珍惜现在   爱
                          情                  情
                           KeriKeriKeriKeriKeri


--

 以科计为本,以产业报国!
  超越自我,飞跃无限!
  

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.235.249]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.383毫秒