VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - 如何拦截ComboBox的mouse右键
发表评论(0)作者:不详, 平台:VB6.0+Win98, 阅读:9981, 日期:2001-09-17
 如何拦截ComboBox的mouse右键


作者: 王国荣 

在ComboBox上按右键时,会有一个popup menu出现,如何令之不出现呢?
在editBox中可用Subclassing的技巧check msg是否是WM_RBUTTONDOWN 来拦截mouse
是否按了右键而後吃掉该message(不Call CallWindowProc()),而使之不会出现
popup menu。但在ComboBox中,按了mouse右键,却仍出现Popup Menu,
查了一下按右键时,发现是 WM_PARENTNOTIFY的讯息,而不是
wm_rbuttondown, 这该如何才能使之不出现Popup menu

这是个有趣的问题,ComboBox 是由 "Edit"(TextBox 的前身) 及 "ListBox"
两种 Windows 的 control 所组成的,而在 ComboBox 上面按下滑鼠右钮是由
"Edit" 来处理,因此拦截的方法是:

  1. 呼叫 EnumChildWindows 取得 ComboBox 的 "Edit" 子视窗的 hWnd
  2. 拦截 "Edit" hWnd。

而取得ListBox的hWnd请叁考改变“ComboBox中ListBox的宽度”

注释:以下程式在form
Option Explicit
Private hwnd5 As Long

Private Sub Form_Load()
Dim ret As Long
注释:取得Combo内EditBox的hwnd
hwnd5 = FindEditInCombo(Combo1)
注释:记录原本的Window Procedure的位址
preWinProc = GetWindowLong(hwnd5, GWL_WNDPROC)
注释:设定EditBox的window Procedure到wndproc
ret = SetWindowLong(hwnd5, GWL_WNDPROC, AddressOf wndproc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
注释:取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(hwnd5, GWL_WNDPROC, preWinProc)
End Sub

注释:以下程式在.bas module
Option Explicit

Declare Function EnumChildWindows Lib "user32" _
   (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, _
   ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
       (ByVal hwnd As Long, ByVal lpClassName As String, _
        ByVal nMaxCount As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
  (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
  (ByVal hwnd As Long, ByVal nIndex As Long) As Long
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 Const GWL_WNDPROC = (-4)
Public Const WM_MOUSEMOVE = &H200
Public Const WM_RBUTTONDOWN = &H204
Public preWinProc As Long
Private hEditWnd As Long

Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, _
                         ByVal wParam As Long, ByVal lParam As Long) As Long
注释:以下会截取mouse Rbutton Down
If Msg = WM_RBUTTONDOWN Then
    Debug.Print "Combol Mouse RButton Down "
Else
注释:将之送往原来的Window Procedure
    wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End If
End Function
Public Function FindEditInCombo(ctl As ComboBox) As Long
Call EnumChildWindows(ctl.hwnd, AddressOf EnumFunc, 0)
FindEditInCombo = hEditWnd
End Function

Public Function EnumFunc(ByVal hwnd As Long, ByVal lParam As Long) As Long
Dim ClsName As String
Dim len5 As Long
If hwnd = 0 Then
   EnumFunc = 0
Else
   ClsName = String(255, 0)
   len5 = GetClassName(hwnd, ClsName, 256)
   ClsName = Left(ClsName, len5)
   If ClsName = "Edit" Then
      hEditWnd = hwnd
      EnumFunc = 0
   Else
      EnumFunc = 1
   End If
End If
End Function