注册 登录
编程论坛 VB6论坛

微软没有发现的VB与VBA的BUG——关于窗体子类化

me4405801 发布于 2013-04-16 17:02, 1430 次点击
很多人认为理论上VB与VBA没有区别,可是事实真的如此吗?

 因为程序需要,我用WORD在VBA中插入了一个用户窗体USERFORM1,并且将该窗体子类化了。

  但是程序运行后,窗体的标题栏似乎是一个“禁区”,无论在标题栏鼠标左击、右击,或者左击窗体右上角的关闭按钮,都会导致程序停止响应,包括WORD,可是在VB环境中却不会出现这种现象……

 我实在就迷茫了,不知道为什么,怎么解决?

  跪求各位大神不吝赐教啊~!!~!


  相关代码如下:
  '在USERFORM1中
  Private Sub UserForm_Click()
  Unload UserForm1
  End Sub

  Private Sub UserForm_Initialize()
      FrmHwnd = FindWindow(vbNullString, UserForm1.Caption)
      lpPrevWndProc = SetWindowLong(FrmHwnd, GWL_WNDPROC, AddressOf WindowProcTest)

  End Sub

  Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
      SetWindowLong FrmHwnd, GWL_WNDPROC, lpPrevWndProc
  End Sub

  '在模块中
  Public Const GWL_WNDPROC = -4

  Public lpPrevWndProc   As Long

  Public FrmHwnd 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 Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

  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 Function WindowProcTest(ByVal hwnd As Long, _
                             ByVal uMsg As Long, _
                             ByVal wParam As Long, _
                             ByVal lParam As Long) As Long


      WindowProcTest = CallWindowProc(lpPrevWndProc, hwnd, uMsg, wParam, lParam)

  End
5 回复
#2
风吹过b2013-04-16 17:36
感觉是运行环境的造成的问题。

VBA ,消息传递,感觉是先到 WORD ,然后再到 你的窗体 。
VB ,是直接到你的窗体。

我不知道 VB6 是如何在 编辑环境 运行程序的,
但 VBA 是纯粹的 解释型的语言,它的运行环境是基本 宿主程序的,这里是 WORD ,

猜测:
有可能在你 重定义 消息响应函数,虽然 VBA 支持这种的方法
但可能与 WORD 的处理机制冲突,造成 重定位失败,消息无响应,消息死锁造成程序无响应情况。
#3
me44058012013-04-16 17:51
感谢2楼大大的回复~!

难道就没有好一点的解决方案吗?

而且VBA中的用户窗体和VB中还有很多不同,例如VBA中用户窗体好像无法设置为TOPMOST

SetWindowPos Frmhwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE Or SWP_SHOWWINDOW

测函数对VBA的用户窗体无效~!
#4
风吹过b2013-04-16 21:12
窗体置顶后,WORD 怎么办。VBA  定义为脚本,VB定义为语言,这些区别肯定是有的。VBA不可能 能完成VB的全部功能,WORD的价格也与VB的价格差好大好大。老老实实用VB 吧。
手机打字就是累。
#5
me44058012013-04-16 22:08
算了,还是我给一个解决方法吧,这个方法没有解决问题,而是逃避了问题,就是把窗体的标题栏隐藏。

具体代码如下,在窗体的Initialize事件中插入以下代码。(相应声明请自行补齐)
Private Sub UserForm_Initialize()
    FrmHwnd = FindWindow(vbNullString, UserForm1.Caption)
    Dim FrmStl As Long
    FrmStl = GetWindowLong(FrmHwnd, GWL_STYLE)
    FrmStl = FrmStl - WS_CAPTION + WS_EX_TOOLWINDOW
    SetWindowLong FrmHwnd, GWL_STYLE, FrmStl
    DrawMenuBar FrmHwnd
    lpPrevWndProc = SetWindowLong(FrmHwnd, GWL_WNDPROC, AddressOf WindowProc)
   
End Sub
#6
xbj_hyml2013-04-17 14:45
不懂VBA的飘过...
1