//以上都错了,应该是Form的 ControlBox属性设为FLASE!这样的话,缺少楼主所说的关闭按纽现在的问题是如果移除systemmenu的话,关闭按纽将失效,这是一个矛盾: Option ExplicitPrivate Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long 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 SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Const WM_SYSCOMMAND = &H112 Private Const SC_MOVE = &HF010& Private Const GWL_STYLE = (-16) Private Const WS_MAXIMIZE = &H1000000 Private Const WS_MAXIMIZEBOX = &H10000 Private Const WS_MINIMIZE = &H20000000 Private Const WS_MINIMIZEBOX = &H20000 Private Const MF_BYPOSITION = &H400& Private Sub Command1_Click() End End SubPrivate Sub Form_Load() '移除窗体的系统菜单 Dim i As Long Dim hSysMenu As Long, nCnt As Long hSysMenu = GetSystemMenu(Me.hwnd, False) If hSysMenu Then nCnt = GetMenuItemCount(hSysMenu) If nCnt Then For i = 0 To nCnt - 1 RemoveMenu hSysMenu, 0, MF_BYPOSITION Next End If End If '移除最大化?最小化按纽 Dim style As Long style = GetWindowLong(Me.hwnd, GWL_STYLE) style = style And Not WS_MAXIMIZEBOX style = style And Not WS_MINIMIZEBOX Call SetWindowLong(Me.hwnd, GWL_STYLE, style) End Sub
最后方案:用setwindowlong去掉窗体的最大,最小化按钮(当然,重绘标题栏也可以实现),在子类中拦截WM_SYSCOMMAND消息 模块: Option Explicit 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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Public Const GWL_WNDPROC = -4 Public Const WM_SYSCOMMAND = &H112 Public Const SC_CLOSE = &HF060& Global lpPrevWndProc As LongPublic Sub Hook(ByVal hwnd As Long) lpPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc) End SubPublic Sub UnHook(ByVal hwnd As Long) Dim lngReturnValue As Long lngReturnValue = SetWindowLong(hwnd, GWL_WNDPROC, lpPrevWndProc) End SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If uMsg = WM_SYSCOMMAND Then If wParam = 61587 Then'这个61587是我拦截下来的,是不是适用于所有的操作系统我还不敢肯定,希望大家测试一下 Debug.Print "呵呵" Else WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam) End If Else WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam) End If End Function窗体: Option Explicit 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 Const GWL_STYLE = (-16) Private Const WS_MAXIMIZEBOX = &H10000 Private Const WS_MINIMIZEBOX = &H20000 Private Sub Form_Load() '移除最大化,最小化按纽 Dim style As Long style = GetWindowLong(Me.hwnd, GWL_STYLE) style = style And Not WS_MAXIMIZEBOX style = style And Not WS_MINIMIZEBOX Call SetWindowLong(Me.hwnd, GWL_STYLE, style) Hook Me.hwnd End SubPrivate Sub Form_Unload(Cancel As Integer) UnHook Me.hwnd End Sub 自我评价:比将窗体的BorderStyle设成4或者5的标题栏好看些
发现bug,在标题栏上点击右键还可以出现菜单,修改下模块代码: Option Explicit 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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Public Const GWL_WNDPROC = -4 Public Const WM_SYSCOMMAND = &H112 Public Const WM_NCRBUTTONDOWN = &HA4 Public Const SC_CLOSE = &HF060& Global lpPrevWndProc As LongPublic Sub Hook(ByVal hwnd As Long) lpPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc) End SubPublic Sub UnHook(ByVal hwnd As Long) Dim lngReturnValue As Long lngReturnValue = SetWindowLong(hwnd, GWL_WNDPROC, lpPrevWndProc) End SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If uMsg = WM_SYSCOMMAND Then If wParam = 61587 Then Debug.Print "呵呵" Else Debug.Print wParam WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam) End If ElseIf uMsg = WM_NCRBUTTONDOWN Then Debug.Print "哈哈" Else WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam) End If End Function
现在才有时间,可是发现不用写了,这有一个用户控件(http://www.vbaspnew.com/ziyuan/y/ct/vbpj0399bb_p.zip),你用它就可以了(调用时设置Capbar控件的NumButtons为0,设置窗体的ControlBox为false)并加入如下代码:Private Sub Capbar1_Click() Unload Me End Sub
Me.BorderStyle = 4
//么实现,用属性或者API实现都可以,请问该怎么实现,先谢过了!
是系统菜单,无法做到取消窗体左上角的菜单,准确地说应该是关闭菜单,但在右上角又要留有一个关闭(X)按钮设置Me.BorderStyle = 1
以上都错了,应该是Form的 ControlBox属性设为FLASE!
ControlBox属性设为FLASE,
Option ExplicitPrivate Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
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 SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_SYSCOMMAND = &H112
Private Const SC_MOVE = &HF010&
Private Const GWL_STYLE = (-16)
Private Const WS_MAXIMIZE = &H1000000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZE = &H20000000
Private Const WS_MINIMIZEBOX = &H20000
Private Const MF_BYPOSITION = &H400&
Private Sub Command1_Click()
End
End SubPrivate Sub Form_Load()
'移除窗体的系统菜单
Dim i As Long
Dim hSysMenu As Long, nCnt As Long
hSysMenu = GetSystemMenu(Me.hwnd, False)
If hSysMenu Then
nCnt = GetMenuItemCount(hSysMenu)
If nCnt Then
For i = 0 To nCnt - 1
RemoveMenu hSysMenu, 0, MF_BYPOSITION
Next
End If
End If
'移除最大化?最小化按纽
Dim style As Long
style = GetWindowLong(Me.hwnd, GWL_STYLE)
style = style And Not WS_MAXIMIZEBOX
style = style And Not WS_MINIMIZEBOX
Call SetWindowLong(Me.hwnd, GWL_STYLE, style)
End Sub
模块:
Option Explicit
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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = -4
Public Const WM_SYSCOMMAND = &H112
Public Const SC_CLOSE = &HF060&
Global lpPrevWndProc As LongPublic Sub Hook(ByVal hwnd As Long)
lpPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End SubPublic Sub UnHook(ByVal hwnd As Long)
Dim lngReturnValue As Long
lngReturnValue = SetWindowLong(hwnd, GWL_WNDPROC, lpPrevWndProc)
End SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_SYSCOMMAND Then
If wParam = 61587 Then'这个61587是我拦截下来的,是不是适用于所有的操作系统我还不敢肯定,希望大家测试一下
Debug.Print "呵呵"
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End If
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End If
End Function窗体:
Option Explicit
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 Const GWL_STYLE = (-16)
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Sub Form_Load()
'移除最大化,最小化按纽
Dim style As Long
style = GetWindowLong(Me.hwnd, GWL_STYLE)
style = style And Not WS_MAXIMIZEBOX
style = style And Not WS_MINIMIZEBOX
Call SetWindowLong(Me.hwnd, GWL_STYLE, style)
Hook Me.hwnd
End SubPrivate Sub Form_Unload(Cancel As Integer)
UnHook Me.hwnd
End Sub
自我评价:比将窗体的BorderStyle设成4或者5的标题栏好看些
Option Explicit
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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = -4
Public Const WM_SYSCOMMAND = &H112
Public Const WM_NCRBUTTONDOWN = &HA4
Public Const SC_CLOSE = &HF060&
Global lpPrevWndProc As LongPublic Sub Hook(ByVal hwnd As Long)
lpPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End SubPublic Sub UnHook(ByVal hwnd As Long)
Dim lngReturnValue As Long
lngReturnValue = SetWindowLong(hwnd, GWL_WNDPROC, lpPrevWndProc)
End SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_SYSCOMMAND Then
If wParam = 61587 Then
Debug.Print "呵呵"
Else
Debug.Print wParam
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End If
ElseIf uMsg = WM_NCRBUTTONDOWN Then
Debug.Print "哈哈"
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End If
End Function
ControlBox属性设为FLASE,
===========================================================再拦截WM_NCRBUTTONDOWN消息就行了
==========================================有两种方法:
A:干脆不要标题栏,将BorderStyle设为0,自己用控件模拟标题栏,就是控件坐标定位麻烦一点
B:自绘非客户区,可以做出很完美的界面效果,但是技术难度超过方案A太多
1.新建标准窗体;
2.选择Icon属性,把Icon属性删除一下,变成(None);
3.设置BorderStyle属性为3;注:如果你还需要最大化按钮和最小化按钮,可以将MaxButton和MinButton设置为True
可将ShowInTaskbar设置回True人家让把左上角的菜单去掉,你管它任务栏上会不会点出来干嘛,呵呵!
Unload Me
End Sub