先说声对不起,让大家久等了。这个系列的贴子从上一课到现在已经隔了好几个月了,这期间变化也蛮大的,我换了工作,也换了地方,在山菊花版主和总版主的提拔以及各位版主的支持下,我也成了一名版主。这也意味着我的责任也大了,为了ExcelHome以及广大Excel爱好者,我会更加努力的为大家服务。 书接上回,上回已经向大家介绍了最基本如何在窗体中添加菜单,关于菜单还有很多的内容,比如在在菜单项中插入图片,插入分隔线等等。可是大家最想知道的还是如何实现菜单项的功能,这一课就先讲这个吧,其他的以后在慢慢说。
一、原理 如何让窗体菜单的每一项都实现相应的功能呢?我们都知道自定义Excel菜单的时候可以通过属性OnAction指定运行某个过程就ok了,那窗体菜单是不是类似呢?呵呵,完全不同。 首先,谈谈消息和窗口函数。消息是什么玩意?其实就是事件,所有的事件。比如你单击了鼠标,滚动滚轮或者按下了键盘上的某个键,都会触发相应的消息,它们由Windows传给窗口函数。而每个窗口都有一个窗口函数,它的作用是对消息进行处理。该函数就象一个特殊的VB程序,其中包含了对事件进行处理的代码。请求窗体执行特定的操作。 原理我们已经知道了,可是窗口函数是系统自己写好的,我们看不到它内部的代码,也不能修改。怎么办?没关系我们有api函数,我们可以自己写一个窗口函数,然后传递给窗体,就能让窗体执行我们想要的操作了。这是非常令人兴奋的事情。我们可以随心所欲的命令窗体了。比如很多控件都不支持滚轮,我们就可以拦截滚轮消息,自己写一个窗口函数,告诉窗体当滚动滚轮时应该干什么。 二、如何写窗口函数 先介绍一个api函数CallWindowProc。 声明:Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 功能:将消息传送给指定的窗口函数 参数: lpPrevWndFunc:指向前一个窗口函数的指针。如果该值是通过调用GetWindowLong函数,并将该函数中的nlndex参数设为 GWL_WNDPROC或DWL_DLGPROC而得到的,那么它实际上要么是窗口或者对话框的地址,要么就是代表该地址的句柄。 hWnd:指向接收消息的窗口函数的句柄。 Msg:指定消息类型。 wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。 IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。 返回值:返回值指定了消息处理结果,它与发送的消息有关。 下面开始介绍如何写窗口函数,就以下面的窗口函数为例: Function MyProcess(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Dim FileN If Msg = WM_COMMAND Then Select Case wParam Case 100 FileN = Application.GetOpenFilename() Case 101 MsgBox "哈哈" Case 102 MsgBox "呵呵" Case 103 MsgBox "口黑口黑" Case 104 UserForm2.Show Case Else End Select End If MyProcess = CallWindowProc(PreWinProc, hwnd, Msg, wParam, lParam) End Function 剖析:此例中我们定义了一个窗口函数MyProcess,其四个参数是固定的,一个都不能少。在此之前,还得做一项准备工作,就是先保存系统默认的窗口函数,可以通过GetWindowLong来获取,成功的话会返回其地址,我们将其放在变量PreWinProc中备用。 If Msg = WM_COMMAND,这句是判断消息是否是单击菜单项,所有的windows消息常量都是以WM开头的,就是WindowMessage的头两个字母,比如滚轮消息WM_MOUSEWHEEL。这里我们省略这个if判断也是可以的,wParam可以确定消息。 由于此时是单击菜单项,所有wParam的值就是菜单项的id,我们可以通过id号来判断单击了哪一个菜单项,然后就可以执行我们想要实现的功能了。在处理了我们自己想要的处理的消息后,一定要恢复窗口的默认函数,即MyProcess = CallWindowProc(PreWinProc, hwnd, Msg, wParam, lParam)这句,否则出错。 注意:1、窗口函数必须写在标准模块中,写在类模块或窗体里都无效。 2、写窗口函数时一定要小心,确保无误后在运行,如果有一点错误,就会导致IDE环境崩溃,程序死掉,最好先保存后在运行。 三、如何将自己的窗口函数传给窗体 在窗体初始化的时候,用SetWindowLong将自定义的窗口函数传递给窗体,此时传递的是函数的地址,因此要用AddressOf运算符。如下: SetWindowLong hwnd, GWL_WNDPROC, AddressOf MyProcess 第二个参数GWL_WNDPROC表示传递的是窗口函数。 最后,在窗体结束的时候要用SetWindowLong hwnd, GWL_WNDPROC, PreWinProc还原默认窗口函数,此时不需要AddressOf,因为PreWinProc存放的就是地址。 四、示例
LyWxw5aM.rar
(15.34 KB, 下载次数: 2065)
|