Win32汇编让你的VB也支持滚轮

来源:互联网 发布:一页知秋 百川鱼海 编辑:程序博客网 时间:2024/04/26 03:53




本文作者: 壮士沈
文章出处: E代时光程序设计版面

  掐指一算,偶摆弄电脑时间也不短了.可一直没有出过什么见得了人的东东.实在惭愧的很.这不机会来了.偶很长时间来一直是用VB6来做一些编程的工作.自觉得其果然是上手快.效率也不错(纯粹为愚人之见,莫怪!^_^)可觉得VB中的代码一但多起来,要查找一行代码来不停的点击鼠标实在是一种很让人头痛的事(哪简直是一种摧残555~~~)谁叫VB6不支持鼠标的滚轮呢?无奈之下只好出此下策自己动手来改变这种生活方式啦!!!
1. 动手前的思考:
问:VB6为什么不支持鼠标滚轮呢?
答:大家都知道Windows是以事件驱动的操作系统。也就是说它在有什么样的事件发生时才会根据不同的事件而进行不同的操作。其实并不是VB6不支持鼠标滚轮事件,而是当在VB6发生一个鼠标滚轮事件时。VB6中的处理程序对这个事件并不理睬,也就是什么也不做。(它也会偷懒???).那么知道这一点也就好办了。我们可以通过编程‘逼’VB6对这一事件作出反应。偶有两种方法:A:重新打造VB6的核心程序,对VB6的DLL文件作出修改(偶是这么想的。但偶功力不足。所以舍之…..)B:编制一个程序对系统进行监视当发现VB6中有一个滚轮事件发生时。就对这个消息进行改造。把它改造成鼠标单击了滚动条事件。再把它重新发往VB6。因为VB6对滚动条的事件是会处理的。

问:那么什么样的消息代表的是鼠标滚动轮的消息呢?
答:这个消息通过查MSDN可知它为的标识符为WM_MOUSEWHELL.也可以通过打开VC的辅助工具spy++来对整个系统进行监视得知。


问:那么怎样才能得知并拦截WM_MOUSEWHELL消息并知道这个消息是由VB6产生而不是别的程序呢?
答:拦截一个消息可以通过Windows自有的功能钩子函数(SetWindowHookEx)。它相当于一个监视器。可以监视系统中发生的一切事件。至于怎样识别这个消息是否是由VB6产生可以通过对产生WM_MOUSEWHELL消息的窗口进行识别。因为大多窗口是由不同的类产生所以它们的窗口类名也不相同如VB6的代码窗口类名为:vbawindow.


问:那用什么样的程序来编制才合适呢?
答:偶觉得这不过是一个小程序。用一些如VB,VC,DELPHIN来编制觉得不太全程而且编制好的程序给别人用的时候还要安装实在很烦。所以偶还是觉得用汇编来写还是很合适的。


2. 动手准备
所谓”工欲善其事,必先利其器”。我们必须要有好的工具才能事半功倍。得心应手啊!为此我准备了RADRAM---汇编语言的编辑工具。在前几期的黑防光盘上有。VC6---主要用来进行一些资源文件的编译。Spy++---VC6中自有的工具主要用来进行一些窗口的分析。MASM32---汇编语言的编译程序。参考资料,《Windows环境下32位汇编语言程序设计》---罗云彬。MSDN2003---主要用来进行一此API的查询。


3. 我的程序思路
在系统中安装一个系统级的钩子函数,当发生WM_MOUSEWHELL事件时。再对发生事件的窗口进行别看是否是VB6窗口如果是,则向其发送改装过的消息。也就是发送一个虚假的消息骗VB6说刚才发生了一次鼠标单击滚动条的事件(嘻!不骗白不骗^_^)。


以下是对整个代码的分析:


>>>>>>>>>>>>>>>>>>>>>>文件:vbhook.asm>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none

;以下是一些引用文件夹的定义
include d:/masm32/include/windows.inc
include d:/masm32/include/user32.inc
include d:/masm32/include/shell32.inc
include d:/masm32/include/kernel32.inc
include d:/masm32/bin/hookdll.inc
includelib d:/masm32/lib/user32.lib
includelib d:/masm32/lib/kernel32.lib
includelib d:/masm32/bin/hookdll.lib
includelib d:/masm32/lib/shell32.lib

;以下是常量的定义
IDC_DLG equ 103 ;对话框的ID
IDC_DLGIMG equ 104 ;对话框中图片的ID
IDC_ICO equ 102 ;对话框图标的ID
hSubMenu1 equ 104 ;子菜单的ID
hSubMenu2 equ 105 ;子菜单的ID
WM_HOOK equ WM_USER + 100h ;自定义的消息ID


;;;;;;;;;以下是数据段的定义
.data?

hHook dd ? ;钩子的句柄
hInstance dd ? ;程序模块的句柄
hIco dd ? ;图标的句柄
hPopuMenu dd ? ;弹出式菜单的句柄
hDlgHwnd dd ? ;弹出式窗口的句柄
szClassNameBuf db 250 dup(?) ;存放窗口类名的缓冲区
hIntBufLen dd ?


;;;;;;;;;以下是一些常量的定义
.const
szClassName db 'VbaWindow',0
szSubMenu1 db '关于(&A)',0 ;子菜单的标题
szSubMenu2 db '退出(&Q)',0 ;子菜单的标题


;以下是代码段的定义
.code
;对话框消息处理函数
_ProcDialog proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @icoinfo:NOTIFYICONDATA ;一个ICON结构
LOCAL @cur:POINT

mov eax,wMsg

.if eax==WM_COMMAND
mov eax,wParam
.if eax==hSubMenu1 ;如果消息是由菜单1发过来那么就显示这个对话框
invoke ShowWindow,hWnd,SW_SHOW
.elseif eax==hSubMenu2 ;如果消息是由菜单2发来那么将任务栏上的图标删除,并卸载一个钩子函数
invoke Shell_NotifyIcon,NIM_DELETE,addr @icoinfo;删除任务栏图标
invoke UnhookWindowsHookEx,hHook ;卸载一个钩子函数
invoke EndDialog,hWnd,NULL ;结束程序
.else
invoke DefWindowProc,hWnd,wMsg,wParam,lParam ;将消息发往默认消息处理函数
.endif
.elseif eax==WM_RBUTTONDOWN
.if lParam==WM_RBUTTONDOWN ;如果消息是由右击图标产生那么弹出一个弹出式菜单
invoke GetCursorPos,addr @cur ;取得鼠标的坐标
invoke TrackPopupMenu,hPopuMenu,TPM_LEFTALIGN,@cur.x,@cur.y,NULL,hWnd,NULL
;弹出一个弹出式菜单函数
.endif
.elseif eax==WM_LBUTTONDOWN ;如果是鼠标左键被按下那么将对话框隐藏
invoke ShowWindow,hWnd,SW_HIDE


;;;;;;;;;向任务栏添加图标过程
.elseif eax==WM_INITDIALOG ;如果是对话框的初始化消息
mov eax,hWnd
mov hDlgHwnd,eax ;将对话框架的句柄保存起来
invoke LoadIcon,hInstance,IDC_ICO ;加载一个图标
mov hIco,eax ;保存图标的句柄
invoke RtlZeroMemory,addr @icoinfo,sizeof NOTIFYICONDATA ;将@icoinfo结构清0
mov @icoinfo.cbSize,sizeof NOTIFYICONDATA ;保存图标结构的字节数
mov eax,hWnd
mov @icoinfo.hwnd,eax ;要加载到任务栏的图标句柄
mov @icoinfo.uFlags,NIF_ICON Or NIF_MESSAGE Or NIF_TIP ;图标可以处理的信息
mov @icoinfo.uCallbackMessage,WM_RBUTTONDOWN ; 有信息产生进图标向处理函数所发送的消息
mov eax,hIco
mov @icoinfo.hIcon,eax ;图标的标识
invoke Shell_NotifyIcon,NIM_ADD,addr @icoinfo ;添加图标到任务栏

;;;;;;;;;;;加载一个弹出式菜单
invoke CreatePopupMenu ;创建一个弹出式菜单
mov hPopuMenu,eax ;保存这个弹出式菜单的句柄
invoke AppendMenu,hPopuMenu,0,hSubMenu1,addr szSubMenu1 ;向这个弹出式菜单添加菜单项
invoke AppendMenu,hPopuMenu,MF_SEPARATOR,0,NULL ;向这个弹出式菜单添加一个横线
invoke AppendMenu,hPopuMenu,0,hSubMenu2,addr szSubMenu2 ; 向这个弹出式菜单添加菜单项


;;;;;;;;;;;;;;;;;;;安装一个钩子函数
invoke InstallHook,hWnd,WM_HOOK ;这个函数是调用hookdll.dll文件的的函数
.if !eax
invoke MessageBeep,MB_ICONASTERISK
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDialog endp


start:

invoke GetModuleHandle,NULL ;取得当前模块的句柄
mov hInstance,eax ;保存取得的句柄
invoke DialogBoxParam,hInstance,IDC_DLG,NULL,addr _ProcDialog,NULL ;创
;建一个模态对话框,它的所有消息由_ProcDialog处理
invoke ExitProcess,NULL
end start



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;以下是hookdll.asm的源文件;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 鼠标钩子使用的 dll 程序
; 用来设置钩子过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Hookdll.asm
; Link /subsystem:windows /section:.bss,S /Def:Hookdll.def /Dll Hookdll.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include d:/masm32/include/windows.inc
include d:/masm32/include/user32.inc
includelib d:/masm32/lib/user32.lib
include d:/masm32/include/kernel32.inc
includelib d:/masm32/lib/kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
hInstance dd ?

.data?
hWnd dd ?
hHook dd ?
dwMessage dd ?
szAscii db 4 dup (?)
hScoolHwnd dd ?
szClassName db 256 dup (?)

.const
szWinClassName db 'VbaWindow',0
szScrollName db 'ScrollBar',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; dll 的入口函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DllEntry proc _hInstance,_dwReason,_dwReserved

push _hInstance
pop hInstance
mov eax,TRUE
ret

DllEntry Endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 键盘钩子回调函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;本程序的主体:钩子函数的回调函数;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HookProc proc nCode,wParam,lParam
LOCAL @scollInfo:SCROLLINFO
invoke CallNextHookEx,hHook,nCode,wParam,lParam

.if nCode==HC_ACTION
mov ebx,lParam
assume ebx:ptr MSG
.if [ebx].message==WM_MOUSEWHEEL
invoke GetWindow,[ebx].hwnd,GW_CHILD
.while eax
mov hScoolHwnd,eax
xor eax,eax
invoke GetWindowLong,hScoolHwnd,GWL_STYLE
and eax,WS_CHILDWINDOW or WS_VISIBLE or SBS_VERT
.break .if eax==WS_CHILDWINDOW or WS_VISIBLE or SBS_VERT
invoke GetWindow,hScoolHwnd,GW_HWNDNEXT
.endw
invoke GetClassName,[ebx].hwnd,addr szClassName,256
invoke lstrcmp,addr szClassName,addr szWinClassName
.if eax==0
mov eax,[ebx].wParam
shr eax,30
.if eax>0
invoke SendMessage,[ebx].hwnd,WM_VSCROLL,SB_LINEDOWN,hScoolHwnd
.else
invoke SendMessage,[ebx].hwnd,WM_VSCROLL,SB_LINEUP,hScoolHwnd
.endif
.endif
.endif
.endif



xor eax,eax
ret

HookProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 安装钩子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
InstallHook proc _hWnd,_dwMessage

push _hWnd
pop hWnd
push _dwMessage
pop dwMessage
invoke SetWindowsHookEx,WH_GETMESSAGE,addr HookProc,hInstance,NULL
mov hHook,eax
ret

InstallHook endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 卸载钩子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
UninstallHook proc

invoke UnhookWindowsHookEx,hHook
ret

UninstallHook endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
End DllEntry


由于本文不是教会大家怎么去学会和使用32位汇编语言所以,在不懂的地方各位只好去查一些资料了.本来就是一些基础的东东.没有太高深的地方相信大家只相去查相关的资料就什么都明白了.
 
原创粉丝点击