能否在excel中用vba代码实现禁用调试按钮

taideng666 2012-03-25 07:38:07
版本:excel2003。
不想设置vba密码,也不想设置共享工作簿,也不想用错误跳转,如何能在代码出错后弹出的对话框中使调试按钮不可用?谢谢关注!如下图:(调试按钮的id=4801?)

[/img]
...全文
464 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
taideng666 2012-03-29
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
因为你截获不到这个窗口什么时候弹出。

我这里有段代码,是当程序调用DialogBoxParamA裝入4070对话框(密码对话框)时的操作,当程序裝入4021对话框(就是上面那个错误对话框)是不是也可以操作呢?调试按钮的id是4801.代码如下:

Option Explicit
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Long, Source As Long, ByVal Length As Long)
Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, ByVal pTemplateName As Long, ByVal hWndParent As Long, ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As Long
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As Long) As Long
'獲得函數的地址
GetPtr = Value
End Function
Public Sub RecoverBytes()
'若已經hook,則恢復原API開頭的6字節,也就是恢復原來函數的功能
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 5) As Byte
Dim p As Long
Dim OriginProtect As Long
Hook = False
'VBE6.dll調用DialogBoxParamA顯示VB6INTL.dll資源中的第4070號對話框(就是輸入密碼的窗口)
'若DialogBoxParamA返回值非0,則VBE會認為密碼正確,所以我們要hook DialogBoxParamA函數
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
'標準api hook過程之一: 修改內存屬性,使其可寫
If VirtualProtect(ByVal pFunc, 6, &H40, OriginProtect) <> 0 Then
'標準api hook過程之二: 判斷是否已經hook,看看API的第一個字節是否為&H68,
'若是則說明已經Hook
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
'標準api hook過程之三: 保存原函數開頭字節,這裡是6個字節,以備後面恢復
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
'用AddressOf獲取MyDialogBoxParam的地址
'因為語法不允許寫成p = AddressOf MyDialogBoxParam,這裡我們寫一個函數
'GetPtr,作用僅僅是返回AddressOf MyDialogBoxParam的值,從而實現將
'MyDialogBoxParam的地址付給p的目的
p = GetPtr(AddressOf MyDialogBoxParam)
'標準api hook過程之四: 組裝API入口的新代碼
'HookBytes 組成如下彙編
'push MyDialogBoxParam的地址
'ret
'作用是跳轉到MyDialogBoxParam函數
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
'標準api hook過程之五: 用HookBytes的內容改寫API前6個字節
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
'設置hook成功標誌
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As Long, ByVal pTemplateName As Long, ByVal hWndParent As Long, ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
If pTemplateName = 4070 Then
'有程序調用DialogBoxParamA裝入4070號對話框,這裡我們直接返回1,讓
'VBE以為密碼正確了
MyDialogBoxParam = 1
Else
'有程序調用DialogBoxParamA,但裝入的不是4070號對話框,這裡我們調用
'RecoverBytes函數恢復原來函數的功能,在進行原來的函數
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, hWndParent, lpDialogFunc, dwInitParam)
'原來的函數執行完畢,再次hook
Hook
End If
End Function
dsd999 2012-03-27
  • 打赏
  • 举报
回复
看到了,估计是不行。

因为你截获不到这个窗口什么时候弹出。

也许用很底层的方法可以做到,但这就高难度了。
taideng666 2012-03-27
  • 打赏
  • 举报
回复
谢dsd999!看来可能是比较困难。我也是想作为一种知识了解。再谢!
taideng666 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 dsd999 的回复:]
看不到图啊.
你好。看不到图就自己写句代码,比如 a=1/0 ,除数为零肯定出错的,就是那个错误弹窗。谢谢!
dsd999 2012-03-26
  • 打赏
  • 举报
回复
看不到图啊.

5,139

社区成员

发帖
与我相关
我的任务
社区描述
其他开发语言 Office开发/ VBA
社区管理员
  • Office开发/ VBA社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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