ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 15774|回复: 33

千奇百怪的窗体(六)-窗体菜单(2)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2007-5-20 21:38 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:窗体

先说声对不起,让大家久等了。这个系列的贴子从上一课到现在已经隔了好几个月了,这期间变化也蛮大的,我换了工作,也换了地方,在山菊花版主和总版主的提拔以及各位版主的支持下,我也成了一名版主。这也意味着我的责任也大了,为了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, 下载次数: 2052)

TA的精华主题

TA的得分主题

发表于 2007-5-20 21:41 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
紧跟版主学习窗体的制作,谢谢分享!

TA的精华主题

TA的得分主题

发表于 2007-5-20 21:43 | 显示全部楼层
终于抢到第三楼!
[此贴子已经被作者于2007-5-20 21:43:29编辑过]

TA的精华主题

TA的得分主题

发表于 2007-5-20 21:45 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
谢谢agstick斑竹

TA的精华主题

TA的得分主题

发表于 2007-5-20 21:46 | 显示全部楼层
亦不知第七回何时再分解[em04]

TA的精华主题

TA的得分主题

发表于 2007-5-20 22:15 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2007-5-21 08:16 | 显示全部楼层
agstick版主:为何我将窗体显示为无模态会当机(userform1.show 0)

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-5-21 08:49 | 显示全部楼层
QUOTE:
以下是引用DJFN在2007-5-21 8:16:56的发言:
agstick版主:为何我将窗体显示为无模态会当机(userform1.show 0)

无模式时,窗口函数会出错。任何一点的错误都会使VBE崩溃。

TA的精华主题

TA的得分主题

发表于 2007-5-21 09:44 | 显示全部楼层
原来如此,谢谢版主!!!
[此贴子已经被作者于2007-5-21 9:44:49编辑过]

TA的精华主题

TA的得分主题

发表于 2007-5-24 13:19 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-27 03:03 , Processed in 0.041115 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表