制作可以自动隐藏的弹出式菜单

王朝vb·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

关键在于对WM_ENTERIDLE消息的处理

在菜单状态下移动鼠标会产生WM_ENTERIDLE消息

这时用TempPoint、WindowFromPoint可以取得当前鼠标所指窗体的句柄

再用GetClassName取得类名,与"#32768"(菜单窗体的类名)进行比较

再等待1秒钟,用keybd_event发送VK_ESCAPE取消菜单状态

但是还是有一个的缺点:无法在鼠标不移动的时候自动隐藏

这时需要Timer控件的帮忙

将下列文件粘贴到记事本,并保存为相应文件

AutoHidePopupMenu.vbp

====================================================================

Type=Exe

Form=Form1.frm

Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\WINDOWS\SYSTEM\stdole2.tlb#OLE Automation

Module=Module1; Module1.bas

Startup="Form1"

ExeName32="AutoHidePopupMenu.exe"

Command32=""

Name="AutoHidePopupMenu"

HelpContextID="0"

CompatibleMode="0"

MajorVer=1

MinorVer=0

RevisionVer=0

AutoIncrementVer=0

ServerSupportFiles=0

VersionCompanyName="zyl910"

CompilationType=0

OptimizationType=0

FavorPentiumPro(tm)=0

CodeViewDebugInfo=0

NoAliasing=0

BoundsCheck=0

OverflowCheck=0

FlPointCheck=0

FDIVCheck=0

UnroundedFP=0

StartMode=0

Unattended=0

Retained=0

ThreadPerObject=0

MaxNumberOfThreads=1

Form1.frm

====================================================================

VERSION 5.00

Begin VB.Form Form1

BorderStyle = 1 'Fixed Single

Caption = "AutoHidePopupMenu"

ClientHeight = 3225

ClientLeft = 45

ClientTop = 330

ClientWidth = 4710

LinkTopic = "Form1"

MaxButton = 0 'False

ScaleHeight = 3225

ScaleWidth = 4710

StartUpPosition = 3 '窗口缺省

Begin VB.Timer Timer1

Interval = 1000

Left = 2580

Top = 360

End

Begin VB.Label LblNow

AutoSize = -1 'True

Caption = "LblNow"

Height = 180

Left = 1410

TabIndex = 1

Top = 210

Width = 540

End

Begin VB.Label LblClick

AutoSize = -1 'True

Caption = "点击鼠标右键"

BeginProperty Font

Name = "宋体"

Size = 26.25

Charset = 134

Weight = 400

Underline = 0 'False

Italic = 0 'False

Strikethrough = 0 'False

EndProperty

Height = 525

Left = 720

TabIndex = 0

Top = 1200

Width = 3150

End

Begin VB.Menu mnuPopup

Caption = "Popup"

Visible = 0 'False

Begin VB.Menu mnuItem1

Caption = "Item&1"

End

Begin VB.Menu mnuItem2

Caption = "Item&2"

End

Begin VB.Menu mnuItem3

Caption = "Item&3"

End

End

End

Attribute VB_Name = "Form1"

Attribute VB_GlobalNameSpace = False

Attribute VB_Creatable = False

Attribute VB_PredeclaredId = True

Attribute VB_Exposed = False

Option Explicit

Private Sub Form_Load()

'MsgBox ClassName(Me.hWnd)

LblNow.Caption = Now

Hook Me.hWnd

End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)

LblClick_MouseUp Button, Shift, X, Y

End Sub

Private Sub Form_Unload(Cancel As Integer)

UnHook Me.hWnd

End Sub

Private Sub LblClick_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)

If Button And vbKeyRButton Then

'ShowMsg = True

PopupMenu mnuPopup

'ShowMsg = False

End If

End Sub

Private Sub Timer1_Timer()

LblNow.Caption = Now

'这样即使不移动鼠标,菜单也会自动隐藏

If ChkTime Then

ChkExit

End If

End Sub

Module1.bas

====================================================================

Attribute VB_Name = "Module1"

Option Explicit

'## API ########################################

'== 硬件与系统函数 =============================

Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Public Declare Function GetTickCount Lib "kernel32" () As Long

Public Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

Public Const VK_ESCAPE = &H1B

Public Const KEYEVENTF_KEYUP = &H2

Type POINTAPI

X As Long

Y As Long

End Type

'== 控件与消息函数 =============================

'CallWindowProc 把消息信息传递给指定的窗体过程

'GetClassName 为指定的窗口取得类名

'SetWindowLong 在窗体结构中为指定的窗体设置信息。返回值:Long,指定数据的前一个值。

'WindowFromPoint 返回包含了指定点的窗口的句柄。

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 Declare Function GetClassNameA Lib "user32" (ByVal hWnd As Long, lpClassName As Any, ByVal nMaxCount As Long) 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 WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long

'-- SetWindowLong ------------------------------

Public Const GWL_WNDPROC = -4

'===============================================

Public Const WM_ENTERIDLE = &H121

'===============================================

Public MeOldWndProc As Long '旧的窗体消息处理程序地址

Public ShowMsg As Boolean

Public OldIn As Boolean

Public OldTime As Long

Public ChkTime As Boolean

Public Function ClassName(ByVal hWnd As Long) As String

Dim StrData(0 To &H100) As Byte

Dim Rc As Long

Rc = GetClassNameA(hWnd, StrData(0), &H100)

If Rc > 0 Then

ClassName = StrConv(LeftB(StrData, Rc), vbUnicode)

Else

ClassName = vbNullString

End If

End Function

Public Sub Hook(ByVal hWnd As Long)

MeOldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)

End Sub

Public Sub UnHook(ByVal hWnd As Long)

Call SetWindowLong(hWnd, GWL_WNDPROC, MeOldWndProc)

End Sub

'消息处理

Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Select Case uMsg

Case WM_ENTERIDLE

'Debug.Print "WM_ENTERIDLE"

ChkExit

Case Else

'If ShowMsg Then Debug.Print uMsg

'下级传递消息

WindowProc = CallWindowProc(MeOldWndProc, hWnd, uMsg, wParam, lParam)

End Select

End Function

Public Sub ChkExit()

Dim TempPoint As POINTAPI

Dim TemphWnd As Long

Dim TempBool As Boolean

GetCursorPos TempPoint

TemphWnd = WindowFromPoint(TempPoint.X, TempPoint.Y)

If TemphWnd Then

TempBool = (ClassName(TemphWnd) = "#32768")

Else

TempBool = False

End If

'Debug.Print TempBool

If TempBool <> OldIn Then

If TempBool Then

OldTime = 0

ChkTime = False

Else

OldTime = GetTickCount

ChkTime = True

End If

OldIn = TempBool

End If

If ChkTime Then

If GetTickCount - OldTime > 1000 Then '大于1秒就退出

'Debug.Print "Exit"

keybd_event VK_ESCAPE, 0, 0, 0

keybd_event VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0

ChkTime = False

End If

End If

End Sub

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航