换句话说,我想之到目前被鼠标(或键盘)点亮的(选中)的菜单项的名称或id

解决方案 »

  1.   

    我是想让鼠标移动到菜单项时就获得菜单项的有关信息,而不是点击时才知道。
    这可以实现“写字板”的状态栏的功能,它可以随时显示被点亮的菜单项的功能。
    也就是说用API函数为菜单项模拟出一个MouseMove事件
    顺便在文一句,那位可以用API函数为菜单项模拟出KeyDown事件呢?
    我之所以问这两个问题,是因为菜单项只有Click事件,而且菜单弹出时,我无法获得Keydown事件。我的信箱[email protected] ,请各位高手帮帮忙!
      

  2.   

    很高深阿,我的水平实在是很差,不知有没有相关的事例?KeyDown事件也能模拟出来么?
      

  3.   

    实现代码如下:Option ExplicitPublic Const MF_BYCOMMAND = &H0&
    Public Const MF_BYPOSITION = &H400&
    Public Const MF_POPUP = &H10&
    Declare Function GetMenuString Lib "user32" Alias "GetMenuStringA" (ByVal hMenu As Long, ByVal wIDItem As Long, ByVal lpString As String, ByVal nMaxCount As Long, ByVal wFlag As Long) As LongPrivate Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private 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
    Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As LongPrivate oldwndproc As Long
    Private subclassedhWnd As LongPublic Const WM_MENUSELECT = &H11F
    Public Const WM_NCDESTROY = &H82
    Public Const GWL_WNDPROC = (-4)Public Sub HookWindow(SubClassForm As Form)' if something is already subclassed, don't subclass anything else
    If oldwndproc <> 0 Then Exit SubsubclassedhWnd = SubClassForm.hwnd'Get the handle for the old window procedure so it can be replaced and used later
    oldwndproc = GetWindowLong(SubClassForm.hwnd, GWL_WNDPROC)'Install custom window procedure for this window
    SetWindowLong SubClassForm.hwnd, GWL_WNDPROC, AddressOf WndProcEnd SubPrivate Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'Does control want this message?
    If Msg = WM_MENUSELECT Then
       
      ' This occurs when the menu is being closed
      If lParam = 0 Then Exit Function
      
      Dim MenuItemStr As String * 128
      Dim MenuHandle As Integer
      
      ' Get the low word from wParam: this contains the command ID or position of the menu entry
      MenuHandle = GetLowWord(wParam)
      
      'If the highlighted menu is the top of a poup menu, pass menu item by position
      If (GetHighWord(wParam) And MF_POPUP) = MF_POPUP Then
        
        'Get the caption of the menu item
        If GetMenuString(lParam, MenuHandle, MenuItemStr, 127, MF_BYPOSITION) = 0 Then Exit Function
      
      Else    ' Otherwise pass it by command ID
        
        'Get the caption of the menu item
        If GetMenuString(lParam, MenuHandle, MenuItemStr, 127, MF_BYCOMMAND) = 0 Then Exit Function
      
      End If
      
      ' Add status bar message here!
      frmMenu.lblSelItem = Trim$(MenuItemStr)Else
      
      'Otherwise, just call default window handler
      WndProc = CallWindowProc(oldwndproc, hwnd, Msg, wParam, lParam)End If'Unhook this window if it is being destroyed
    If Msg = WM_NCDESTROY Then
      UnHookWindow
    End If
    End FunctionPublic Sub UnHookWindow()
    ' If there is nothing subclassed, there is nothing to unsubclass!
    If oldwndproc = 0 Then Exit Sub'Return to default window handler
    SetWindowLong subclassedhWnd, GWL_WNDPROC, oldwndproc
    oldwndproc = 0
    End SubPublic Function GetLowWord(Word As Long)
    GetLowWord = CInt("&H" & Right$(Hex$(Word), 4))
    End FunctionPublic Function GetHighWord(Word As Long)
    GetHighWord = CInt("&H" & Left$(Hex$(Word), 4))
    End Function
      

  4.   

    看不太懂,使用这个模块,怎样实现相应菜单项的mousemove或keydown事件?
    或者具体地,现在怎样将Form1的点亮的菜单项的信息写在Label1.Caption中?
      

  5.   

    Option Explicit
    '添加一个lblSelItem标签控件Private Sub Form_Load()
    HookWindow MeEnd SubPrivate Sub Form_Unload(Cancel As Integer)
    UnHookWindow
    End Sub
      

  6.   

    运行时直接退出!
    我将上面的代码复制到了一个模块中,
    然后建了一个Form1窗体,建立若干菜单
    在Form1中写下
    Option Explicit
    Private Sub Form_Load()
    HookWindow Me
    End SubPrivate Sub Form_Unload(Cancel As Integer)
    UnHookWindow
    End Sub
    并添加一个名为lblSelItem的Label控件。以上操作有误吗?那里出错了?
    好像还应该有个时钟之类的控件来监视菜单项的状态阿?
      

  7.   

    给你一个有中文注释的子分类例子.希望对你有帮助'API函数
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private 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'定义常数
    Private Const GWL_WNDPROC = (-4)Private Const WM_MOUSEMOVE = &H200 '鼠标移动
    Private Const WM_RBUTTONDOWN = &H204 '右键按下'全局变量,存放控件标志性数据
    Private preWinProc As Long
        
    '本函数就是用来接收子分类时截取的消息的
    Private Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long    '截取下来的消息存放在msg参数中.
        If Msg = WM_RBUTTONDOWN Then
          '检测到鼠标右击消息,这里就可以加入我们的处理代码如:
           MsgBox "你好!"
           '需要注意,如果这儿不加入任何代码,则相当于吃掉了这条消息.
        ElseIf Msg = WM_MOUSEMOVE Then
           '吃掉
        Else
           '如果我们不是我们需要处理的消息,则将之送回原来的程序.
           wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
        End If
    End Function
    Public Sub subclass(m_hwnd As Long)
    Dim ret As Long
        '记录Window Procedure的地址
        preWinProc = GetWindowLong(m_hwnd, GWL_WNDPROC)
        '开始截取消息,并将消息交给wndproc过程处理.
        ret = SetWindowLong(m_hwnd, GWL_WNDPROC, AddressOf wndproc)
    End Sub
        
    Public Sub EndSubclass(m_hwnd As Long)
        Dim ret As Long
        '取消消息截取,结束子分类过程.
        ret = SetWindowLong(m_hwnd, GWL_WNDPROC, preWinProc)
    End Sub
    下面在窗体部分  
    Private Sub Form_Load()
        subclass Me.hwnd
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        EndSubclass Me.hwnd
    End Sub
      

  8.   

    很有用的代码!
    不过我怎样写类似“Msg = WM_RBUTTONDOWN”这句代码呢?
    哪里有关于这些消息常数的含义的说明,我怎样知道我现在的行为得到的MSG是多少呢?(我将MSG赋给了Text,可是他的变化实在是太快了!)