如何在窗口的系统菜单中添加“About”菜单项?

Wolfe 2003-01-08 10:27:00
在窗口的系统菜单中添加“About”菜单项,不用API可以吗?如果不可以,那么又怎么做?希望指点一下小弟啊!
...全文
17 点赞 收藏 11
写回复
11 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
zyl910 2003-01-12
GWL_WNDPROC 该窗口的窗口函数的地址
回复
zyl910 2003-01-12
VarPtr 返回变量的地址
StrPtr 返回变长字符串的字符串数据的址址
ObjPtr 返回对象的地址
用于获取变量地址,是函数

AddressOf 返回标准模块中的函数的地址
通常只用于回调,是运算符

作为参数,如果你用的是地址,那么通过byval可以得到地址本身;通过byfef得到的是地址的地址
回复
zyl910 2003-01-12
在窗体模块中
如果没有匹配定义的变量
则自动调用窗体模块的属性
hWnd与me.hWnd是等效的
回复
Wolfe 2003-01-12
ProcOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc) 这个函数能解释一下吗? "hWnd"是如何得到的?GWL_WNDPROC代表什么?AddressOf WindowProc如何表达? 能解释一下吗?
回复
zyl910 2003-01-12
SubClass(子类)!


Private Sub Form_Load()
……
ProcOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
Call SetWindowLong(hWnd, GWL_WNDPROC, ProcOld)
End Sub


Then, add the code below to a module


……

Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
'// ----WARNING----
'// do not attempt to debug this procedure!!
'// ----WARNING----

'// this is our implementation of the message handling routine
'// determine which message was recieved
Select Case iMsg
Case WM_SYSCOMMAND
If wParam = IDM_ABOUT Then
MsgBox "VB Web Append to System Menu Example", vbInformation, "About"
Exit Function
End If
End Select
'// pass all messages on to VB and then return the value to windows
WindowProc = CallWindowProc(ProcOld, hWnd, iMsg, wParam, lParam)
End Function
回复
Wolfe 2003-01-12
多谢啊,那么在VB中具体如何响应WM_SYSCOMMAND消息呢?
进一步的说,如何响应用户自定义消息呢?
回复
zyl910 2003-01-12
先用GetSystemMenu取得窗体系统菜单的句柄
再用AppendMenu、InsertMenu添加菜单
最后还要响应“WM_SYSCOMMAND”消息,以处理菜单点击




GetSystemMenu

VB声明
Declare Function GetSystemMenu Lib "user32" Alias "GetSystemMenu" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
说明
取得指定窗口的系统菜单的句柄。在vb环境,“系统菜单”的正式名称为“控制菜单”,即单击窗口左上角的控制框时出现的菜单
返回值
Long,如执行成功,返回系统菜单的句柄;零意味着出错。如bRevert设为TRUE,也会返回零(简单的恢复原始的系统菜单)
参数表
参数 类型及说明
hwnd Long,窗口的句柄
bRevert Long,如设为TRUE,表示接收原始的系统菜单
注解
在vb里使用:系统菜单会向窗口发送一条WM_SYSCOMMAND消息,而不是WM_COMMAND消息




AppendMenu

VB声明
Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
说明
在指定的菜单里添加一个菜单项
返回值
Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
hMenu Long,菜单句柄
wFlags Long,参考ModifyMenu函数中的菜单常数标志定义表,其中列出了允许使用的所有常数
wIDNewItem Long,指定菜单条目的新命令ID。如果在wFlags参数中指定了MF_POPUP字段,那么这应该是指向一个弹出式菜单的句柄
lpNewItem String(相应的vb声明见注解),如果在wFlags参数中指定了MF_STRING标志,这就代表在菜单中设置的字串。如设置了MF_BITMAP标志,这就代表一个Long型变量,其中包含了一个位图句柄。如设置了MF_OWNERDRAW,这个值就会包括在DRAWITEMSTRUCT和MEASUREITEMSTRUCT结构中,在条目需要重画的时候由windows发送出去
回复
zyl910 2003-01-12
原理:
先用GetSystemMenu取得窗体系统菜单的句柄
然后用GetSubMenu取得弹出式菜单的句柄
再用AppendMenu、InsertMenu添加菜单
最后还要响应“WM_COMMAND”消息,以处理菜单点击
回复
This example adds an About... item to the forms System Menu (shown by clicking the forms icon, or right clicking on its button on the taskbar)

Please note that this uses subclassing, so DO NOT use the Stop button on the VB toolbar, or attempt to debug the WindowProc procedure (unless you like VB crashing!).

First, add the following code to a form

'// form_load event. Catch all those messages!
Private Sub Form_Load()
Dim lhSysMenu As Long, lRet As Long
On Error Resume Next
'// add about menu
lhSysMenu = GetSystemMenu(hWnd, 0&)
lRet = AppendMenu(lhSysMenu, MF_SEPARATOR, 0&, vbNullString)
lRet = AppendMenu(lhSysMenu, MF_STRING, IDM_ABOUT, "About...")
Show
'// saves the previous window message handler. Always restore this value
'// AddressOf command sends the address of the WindowProc procedure
'// to windows
ProcOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

'// form_queryunload event. Return control to windows/vb
Private Sub Form_Unload(Cancel As Integer)
'// give message processing control back to VB
'// if you don't do this you WILL crash!!!
Call SetWindowLong(hWnd, GWL_WNDPROC, ProcOld)
End Sub

Then, add the code below to a module


'// variable that stores the previous message handler
Public ProcOld As Long
'// Windows API Call for catching messages
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
'// Windows API call for calling window procedures
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
'// menu windows api
Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As String) As Long
Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, ByVal bRevert As Long) As Long
'// windows api constants
Public Const WM_SYSCOMMAND = &H112
Public Const MF_SEPARATOR = &H800&
Public Const MF_STRING = &H0&
Public Const GWL_WNDPROC = (-4)
Public Const IDM_ABOUT As Long = 1010

Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
'// ----WARNING----
'// do not attempt to debug this procedure!!
'// ----WARNING----

'// this is our implementation of the message handling routine
'// determine which message was recieved
Select Case iMsg
Case WM_SYSCOMMAND
If wParam = IDM_ABOUT Then
MsgBox "VB Web Append to System Menu Example", vbInformation, "About"
Exit Function
End If
End Select
'// pass all messages on to VB and then return the value to windows
WindowProc = CallWindowProc(ProcOld, hWnd, iMsg, wParam, lParam)
End Function
回复
feixuehenshui 2003-01-08
先添加一个窗体,选择"关于窗体"
然后用菜单编辑器添加一项,
然后frmabout.show
回复
suntt 2003-01-08
楼上的大哥写得很清楚了
回复
发动态
发帖子
VB基础类
创建于2007-09-28

7453

社区成员

VB 基础类
申请成为版主
社区公告
暂无公告