|
|
|
|
|
Dicas
|
|
Visual Basic (ActiveX/Controles/DLL)
|
|
|
Título da Dica: como habilitar e desabilitar os itens Minimize, Maximize e Close do system menu
|
|
|
|
Postada em 5/4/2006 por Geronimo
Esse exemplo mostra como habilitar e desabilitar os itens Minimize, Maximize e Close do system menu e por consequencia os botões do canto superior direito. Para testar crie um projeto com um MDIForm e um módulo e cole o código a seguir:
No módulo:
Option Explicit
Private Const SC_CLOSE As Long = &HF060& Private Const SC_MAXIMIZE As Long = &HF030& Private Const SC_MINIMIZE As Long = &HF020&
Private Const xSC_CLOSE As Long = -10& Private Const xSC_MAXIMIZE As Long = -11& Private Const xSC_MINIMIZE As Long = -12&
Private Const GWL_STYLE = (-16) Private Const WS_MAXIMIZEBOX = &H10000 Private Const WS_MINIMIZEBOX = &H20000
Private Const hWnd_NOTOPMOST = -2 Private Const SWP_NOZORDER = &H4 Private Const SWP_NOSIZE = &H1 Private Const SWP_NOMOVE = &H2 Private Const SWP_FRAMECHANGED = &H20
Private Const MIIM_STATE As Long = &H1& Private Const MIIM_ID As Long = &H2& Private Const MFS_GRAYED As Long = &H3& Private Const WM_NCACTIVATE As Long = &H86
Private Type MENUITEMINFO cbSize As Long fMask As Long fType As Long fState As Long wID As Long hSubMenu As Long hbmpChecked As Long hbmpUnchecked As Long dwItemData As Long dwTypeData As String cch As Long End Type
Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, ByVal bRevert As Long) As Long Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Boolean, lpMenuItemInfo As MENUITEMINFO) As Long Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal bool As Boolean, lpcMenuItemInfo As MENUITEMINFO) 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 Declare Function IsWindow Lib "user32" (ByVal hWnd 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 SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function GetParent Lib "user32" (ByVal hWnd As Long) As Long Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Public Function EnableCloseButton(ByVal hWnd As Long, Enable As Boolean) _
EnableSystemMenuItem hWnd, SC_CLOSE, xSC_CLOSE, Enable, "EnableCloseButton" End Function
Public Sub EnableMinButton(ByVal hWnd As Long, Enable As Boolean)
Dim lngFormStyle As Long
' Enable / Disable System Menu Item EnableSystemMenuItem hWnd, SC_MINIMIZE, xSC_MINIMIZE, Enable, "EnableMinButton" ' Enable / Disable TitleBar button lngFormStyle = GetWindowLong(hWnd, GWL_STYLE) If Enable Then lngFormStyle = lngFormStyle Or WS_MINIMIZEBOX Else lngFormStyle = lngFormStyle And Not WS_MINIMIZEBOX End If SetWindowLong hWnd, GWL_STYLE, lngFormStyle ' Dirty, slimy, devious hack to ensure that the changes to the ' window's style take immediate effect before the form is shown SetParent hWnd, GetParent(hWnd) SetWindowPos hWnd, hWnd_NOTOPMOST, 0, 0, 0, 0, SWP_NOZORDER Or SWP_NOSIZE Or SWP_NOMOVE Or SWP_FRAMECHANGED End Sub
Public Sub EnableMaxButton(ByVal hWnd As Long, Enable As Boolean)
Dim lngFormStyle As Long
' Enable / Disable System Menu Item EnableSystemMenuItem hWnd, SC_MAXIMIZE, xSC_MAXIMIZE, Enable, "EnableMaxButton" ' Enable / Disable TitleBar button lngFormStyle = GetWindowLong(hWnd, GWL_STYLE) If Enable Then lngFormStyle = lngFormStyle Or WS_MAXIMIZEBOX Else lngFormStyle = lngFormStyle And Not WS_MAXIMIZEBOX End If SetWindowLong hWnd, GWL_STYLE, lngFormStyle ' Dirty, slimy, devious hack to ensure that the changes to the ' window's style take immediate effect before the form is shown SetParent hWnd, GetParent(hWnd) SetWindowPos hWnd, hWnd_NOTOPMOST, 0, 0, 0, 0, SWP_NOZORDER Or SWP_NOSIZE Or SWP_NOMOVE Or SWP_FRAMECHANGED
End Sub
Private Sub EnableSystemMenuItem(hWnd As Long, Item As Long, Dummy As Long, Enable As Boolean, FuncName As String)
Dim hMenu As Long Dim MII As MENUITEMINFO Dim lngMenuID As Long If IsWindow(hWnd) = 0 Then Err.Raise vbObjectError, "modCloseBtn::" & FuncName, "modCloseBtn::" & FuncName & "() - Invalid Window Handle" Exit Sub End If ' Retrieve a handle to the window's system menu hMenu = GetSystemMenu(hWnd, 0) ' Retrieve the menu item information for the Max menu item/button MII.cbSize = Len(MII) MII.dwTypeData = String$(80, 0) MII.cch = Len(MII.dwTypeData) MII.fMask = MIIM_STATE If Enable Then MII.wID = Dummy Else MII.wID = Item End If If GetMenuItemInfo(hMenu, MII.wID, False, MII) = 0 Then Err.Raise vbObjectError, "modCloseBtn::" & FuncName, "modCloseBtn::" & FuncName & "() - Menu Item Not Found" Exit Sub End If ' Switch the ID of the menu item so that VB can not undo the action itself lngMenuID = MII.wID If Enable Then MII.wID = Item Else MII.wID = Dummy End If MII.fMask = MIIM_ID If SetMenuItemInfo(hMenu, lngMenuID, False, MII) = 0 Then Err.Raise vbObjectError, "modCloseBtn::" & FuncName, "modCloseBtn::" & FuncName & "() - Error encountered " & "changing ID" Exit Sub End If ' Set the enabled / disabled state of the menu item If Enable Then MII.fState = MII.fState And Not MFS_GRAYED Else MII.fState = MII.fState Or MFS_GRAYED End If MII.fMask = MIIM_STATE If SetMenuItemInfo(hMenu, MII.wID, False, MII) = 0 Then Err.Raise vbObjectError, "modCloseBtn::" & FuncName, "modCloseBtn::" & FuncName & "() - Error encountered " & "changing state" Exit Sub End If ' Activate the non-client area of the window to update the titlebar, and ' draw the Max button in its new state. SendMessage hWnd, WM_NCACTIVATE, True, 0 End Sub
No MDIForm:
Dim bMaxButton As Boolean Dim bMinButton As Boolean Dim bCloseButton As Boolean
Private Sub MDIForm_Load()
bMaxButton = True bMinButton = True bCloseButton = True MsgBox "Clique com o Esquerdo para o Botão Minimizar" & vbCrLf & "Clique com o Direito para o Botão Maximizar" & vbCrLf & "Clique qualquer botão + CTRL para Botão Fechar", vbInformation End Sub
Private Sub MDIForm_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Select Case True Case (Button <> 0) And Shift = 2 ' Click com qualquer botão + CTRL = Botão Fechar bCloseButton = Not bCloseButton EnableCloseButton Me.hWnd, bCloseButton ' Click com o esquerdo = Botão Minimizar Case Button = 1 bMinButton = Not bMinButton EnableMinButton Me.hWnd, bMinButton Case Button = 2 ' Click com o direito = Botão Maximizar bMaxButton = Not bMaxButton EnableMaxButton Me.hWnd, bMaxButton End Select End Sub
PS.: Este exemplo deve funcionar com qualquer tipo de form, seja mdi, sdi ou mdichild
|
|
|
|
|