完全采用 VB 自身功能实现对 Windows 消息的拦截!

Phoenix2000 2001-08-03 06:29:16
众所周知,VB 的功能没有 VC++、Delphi 这样的全功能开发平台强大,但她也足以完成我们绝大部分的工作,
只要你开动脑筋,敢想敢干,我们可以让 VB 发挥最大的效能,做出许多令人惊叹的软件。开发高难度软件,
并不只是 VC++ 和 Delphi 的专利!

过去普遍认为 VB 无法自定义拦截 Windows 的消息,只能靠 VB 本身提供的几个有限的事件来编程,这有很
大的局限性。缺少消息捕获,同时又被认为不支持回调函数机制(主要是因为 VB 没有指针,更谈不上函数指
针),这造成了 VB 编程的很大局限性。事实上,VB 可以采用别的办法变相地实现这一机制。从 VB 5.0 开始
就提供了 AddressOf 操作符,利用这个操作符可以获取 VB 自定义函数的地址。有了函数地址就可以采用回调
函数的机制了。当然,VB 仍然无法实现 VB 函数之间的地址传递,她只支持 VB 函数到 DLL 的函数抵制传递。
但是,这已经足够了。下面这个程序,就是采用了这一方法,程序中只有一个主窗体,通过设置属性,使得主窗
体没有边框,没有标题栏,不能改变大小,不能通过标题栏托动。但是通过拦截 Windows 消息可以使得鼠标处在
窗体中的任意位置都可以托动它,就像按住标题栏托动一样。这个程序没有用到任何附加的控件,全部采用 VB 代
码完成。注意,请增加一个公共模块,以便声明一些函数和常数。以下代码在 VB 6.0 中通过。

' ===================================
' 这是公共模块的代码
Attribute VB_Name = "Module1"
Option Explicit

Public Const WM_NCHITTEST = &H84
Public Const VK_LBUTTON = &H1
Public Const HTCAPTION = 2
Public Const HTCLIENT = 1


Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Public 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
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Const GWL_WNDPROC = -4
Global lpPrevWndProc As Long
Global gHW As Long

' 这里是关键,我自定义了一个窗口函数(回调函数),以替代 VB 窗体自己的默认窗口函数。
' 窗口函数是干什么的?它就是负责处理 Windows 发送给它的消息,并加以过滤,筛选出它感兴趣
' 的消息,映射成为事件供我们使用。VB 中每个窗口都有一个默认的窗口函数,我们是看不到的。
' 有很多消息都被 VB 的默认窗口函数过滤掉了。了解 C/C++/Delphi 程序设计的朋友应该知道这些。
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
' 我们也进行消息过滤,不过我们指拦截我们感兴趣的消息
' 其他消息我们懒得处理,交给 VB 默认的窗口函数去处理吧。
Select Case uMsg
Case WM_NCHITTEST ' 拦截 WM_NCHITTEST 消息
If GetAsyncKeyState(VK_LBUTTON) < 0 Then ' 是否有鼠标左键在窗体客户区按下?
' 如果是,函数返回值被设置为 HTCAPTION,欺骗 Windows,让它以为鼠标是按在标题栏
' Windows 是通过窗口函数的返回值进行判断处理的
WindowProc = HTCAPTION
Exit Function
Else
' 其他的我们不管,还是规规矩矩的该怎么样就怎么样
WindowProc = HTCLIENT
Exit Function
End If
End Select
' 这里又是关键,因为其他我们不关心的消息我们自己不处理,所以必须由 VB 的默认处理函数处理
' lpPrevWndProc 其实就是一个函数指针,它指向 VB 默认窗口函数
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End Function

' ===================================
' 这是窗体的代码
VERSION 5.00
Begin VB.Form Form1
BorderStyle = 0 'None
ClientHeight = 3195
ClientLeft = 0
ClientTop = 0
ClientWidth = 4680
LinkTopic = "Form1"
MaxButton = 0 'False
MinButton = 0 'False
ScaleHeight = 3195
ScaleWidth = 4680
ShowInTaskbar = 0 'False
StartUpPosition = 3 '窗口缺省
Begin VB.CommandButton Command1
Caption = "Command1"
Height = 375
Left = 2160
TabIndex = 0
Top = 720
Width = 1575
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

Private Sub Command1_Click()
Unload Me ' 按下这个按钮就退出了
End Sub

Private Sub Form_Load()
gHW = Me.hwnd ' 保存窗体的句柄
' 下面是关键,完成两个工作:1、将我们自己的全局函数替换为新的窗体回调函数
' 2、保存原来的 VB 默认窗户口函数地址
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
End Sub

其实,一切就这么简单。有了这种办法,Windows 中需要回调函数的 API 函数我们都可以调用了,有很多的
功能我们都可以用 VB 来实现了。注意,我们自定义的回调函数只能是模块中定义的全局函数!不能在窗体中
定义。

写出来只是想抛砖引玉,其实有很多功能不需要到处去找控件的。我现在在研究用 VB 6 + DirectX 7/8 写游
戏。游戏速度当然不可能达到 C++ 的程度,但是足够应付一些中小型的游戏题材了,比如 RPG 的。这又有很
多值得写出来的了。虽然不是什么新鲜的话题,但是其中仍不乏许多的技巧和编程思想。希望对此有研究的朋
友能够多多出来交流指点一二。
...全文
231 7 打赏 收藏 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
WQ771211 2002-06-30
  • 打赏
  • 举报
回复
不用API,就用ASM去写VXD去吧
heyijpn 2001-08-05
  • 打赏
  • 举报
回复
vb调用API怎么了?!!!
vc其实不也是直接调用API(SDK编程)或者间接调用API(MFC编程)吗?
只不过有些API函数VB不能调用罢了(VB没有指针),但VB。NET据说已经
具有指针的概念了,到那时,呵呵。。。。。
sunsatan 2001-08-04
  • 打赏
  • 举报
回复
又是API VB离开api不能活吗
aikill 2001-08-04
  • 打赏
  • 举报
回复
还有别的方法吗?
bucher 2001-08-04
  • 打赏
  • 举报
回复
是指没有使用第三方控件
windows底层编程不用API能行么?
xyjdn 2001-08-03
  • 打赏
  • 举报
回复
good! ^_^
littleholly 2001-08-03
  • 打赏
  • 举报
回复
我没仔细看,不过好象调用了API,不知道算不算你说的用VB自身功能解决!
交个朋友!
(
|
(
内容概要:本文围绕基于物理场的动态模式分解(piDMD)展开研究,重点探讨其在流体力学、热传导及多物理耦合系统中的建模与应用。通过Matlab代码实现,将传统的动态模式分解(DMD)方法与物理场控制方程相结合,引入物理约束以增强数据驱动模型的物理一致性,从而提升对复杂非线性系统的模态提取精度与长期预测能力。文章系统阐述了piDMD的理论基础、数学推导过程与算法实现步骤,并结合典型物理场仿真案例(如Navier-Stokes方程驱动的流场演化)进行验证,展示了其在降阶建模、主导模态识别和时空动态可视化方面的优越性能,适用于高维、强耦合、非平稳系统的分析与优化。; 适合人群:具备一定数值计算、流体力学、控制理论或数据驱动建模背景,熟悉Matlab编程与线性代数运算,从事科学研究、工程仿真或系统辨识工作的研究生、科研人员及工程师。; 使用场景及目标:①实现对流场、温度场等物理场的高效降阶建模与动态行为预测;②提取符合物理规律的关键模态,用于系统稳定性分析与控制设计;③支撑复杂系统的状态估计、异常检测与优化调控等下游任务。; 阅读建议:建议读者结合提供的Matlab代码逐行调试与运行,深入理解piDMD算法中物理约束的嵌入方式及其对模态质量的影响,同时可尝试将其迁移至其他偏微分方程描述的物理系统中进行拓展验证与应用。
内容概要:本文研究了在峰谷分时电价引导下,基于多目标优化遗传算法NSGA-II的电动汽车充电负荷优化问题。通过构建以电网负荷波动最小化和用户充电成本最低为核心的多目标优化模型,利用NSGA-II算法求解获得帕累托最优解集,实现对大规模电动汽车充电行为的有序引导。文中系统阐述了峰谷电价激励机制的设计原理、电动汽车充电负荷的数学建模方法、多目标优化问题的形式化表达以及NSGA-II算法的具体实现流程,并借助Matlab平台进行仿真验证,结果表明该策略能有效平抑电网负荷峰谷差、降低用户充电支出并提升电力系统的运行效率与稳定性。; 适合人群:具备一定电力系统基础知识和Matlab编程能力,从事智能电网、电动汽车调度、需求侧管理等相关领域的研究生或科研人员。; 使用场景及目标:①研究峰谷电价政策对电动汽车充电行为的影响机制;②掌握NSGA-II算法在电力系统多目标优化中的具体应用;③实现电动汽车集群的有序充电调度以改善电网负荷曲线; 阅读建议:此资源结合了电力经济学与智能优化算法,建议读者在学习过程中重点关注模型构建与算法实现的衔接部分,动手复现仿真代码以深入理解参数设置与结果分析过程。

743

社区成员

发帖
与我相关
我的任务
社区描述
VB 版八卦、闲侃,联络感情地盘,禁广告帖、作业帖
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧