Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0652: Größenänderungen in MDI-Parent-Formularen unterbinden

 von 

Beschreibung 

Dieser Tipp macht es möglich, auch bei MDI-Parent-Formularen die Schaltflächen zum Minimieren und Maximieren des Fensters zu deaktivieren. Zusätzlich kann gleichzeitg das Ändern der Größe unterbunden werden.

Schwierigkeitsgrad:

Schwierigkeitsgrad 3

Verwendete API-Aufrufe:

DrawMenuBar, EnableMenuItem, GetMenuItemCount, GetMenuItemInfoA (GetMenuItemInfo), GetSystemMenu, GetWindowLongA (GetWindowLong), RemoveMenu, SetWindowLongA (SetWindowLong)

Download:

Download des Beispielprojektes [5,35 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------------- Anfang Projektdatei Projekt1.vbp -------------
'--------- Anfang Formular "Form1" alias Form1.frm  ---------
' Steuerelement: Kontrollkästchen-Steuerelement "chkBlockResize"
' Steuerelement: Schaltfläche "Command3"
' Steuerelement: Schaltfläche "Command2"
' Steuerelement: Schaltfläche "Command1"

Option Explicit

Private Sub Command1_Click()
    SetMinMaxButtons Me.hWnd, False, True, (chkBlockResize.Value = 1)
End Sub

Private Sub Command2_Click()
    SetMinMaxButtons Me.hWnd, True, False, (chkBlockResize.Value = 1)
End Sub

Private Sub Command3_Click()
    SetMinMaxButtons Me.hWnd, False, False, (chkBlockResize.Value = 1)
End Sub



'---------- Ende Formular "Form1" alias Form1.frm  ----------
'--- Anfang Modul "mod_ButtonState" alias mod_Buttonstate.bas ---


'   ********************************************************************
'   Modul        :  mod_ButtonState
'   Beschreibung :  Dieses Modul setzt einige WindowStyles neu, damit
'                   ein Dialog nicht mehr maximiert oder minimiert
'                   werden kann. Optional kann auch gleich das Ändern
'                   der Größe verhindert werden.
'   Autor        :  Helge Rex
'   Email        :  helge@activevb.de
'   Datum        :  07.10.2004 (1. Version)
'                   25.11.2004 (BugFix: Menubar muß neu gezeichnet
'                               werden, wenn das Systemmenü geändert
'                               wird)
'                   04.01.2005 (BugFix: Bei mehrmaligem Aufruf der
'                               Funktion wird kein falscher Menüpunkt
'                               mehr entfernt)
'                   06.01.2005 (BugFix: Schließen wird nicht mehr
'                               deaktiviert, außerdem kann nun
'                               festgelegt werden, ob Resize noch
'                               möglich ist)
'                   09.01.2005 (BugFix durch Udo Schmidt: Funktioniert
'                               nun auch unter Windows 98)
'   Anmerkungen  :  Artikel Q137033 in der Microsoft Knowledge Base
'                   (http://support.microsoft.com/?kbid=137033) diente
'                   als Grundlage für die Entwicklung dieses Codes.
'                   Der Code im besagten Artikel hat jedoch den
'                   Nachteil, daß das Systemmenü unangetastet bleibt
'                   und so die Funktionalität dem Anwender weiterhin
'                   zur Verfügung steht. Es ist jetzt nur noch möglich,
'                   den Dialog per Code zu maxi- oder minimieren.
'                   Die Konstanten für die Menüpunkte "Minimieren" und
'                   "Maximieren" sind von mir auf einem deutschen
'                   XP-System ermittelt worden. Sollten die Werte der
'                   Konstanten in anderen Windows-Versionen (auch
'                   anderen Sprachen) davon abweichen, bitte ich um eine
'                   Information diesbezüglich, damit der Code
'                   dahingehend angepaßt werden kann.
'   ********************************************************************

'   ********************************************************************
'   Einstellungen
Option Explicit

'   ********************************************************************
'   lokale (private) Konstanten
Private Const GWL_STYLE As Long = (-16)
Private Const MF_FIRST As Long = 0&         '   MenuFlagEnum
Private Const MIIM_FIRST As Long = 0&       '   MenuItemInfoEnum
Private Const MFS_FIRST As Long = 0&        '   MenuFlagStyleEnum
Private Const MFT_FIRST As Long = 0&        '   MenuFlagTypeEnum
Private Const SMI_FIRST As Long = &HF000&   '   SysMenuItemIDEnum
Private Const WS_FIRST As Long = 0&         '   WindowStyleEnum

'   ********************************************************************
'   lokale (private) Auflistungen
Private Enum MenuFlagEnum
    MF_INSERT = (MF_FIRST + &H0&)
    MF_CHANGE = (MF_FIRST + &H80&)
    MF_APPEND = (MF_FIRST + &H100&)
    MF_DELETE = (MF_FIRST + &H200&)
    MF_REMOVE = (MF_FIRST + &H1000&)
    MF_BYCOMMAND = (MF_FIRST + &H0&)
    MF_BYPOSITION = (MF_FIRST + &H400&)
    MF_SEPARATOR = (MF_FIRST + &H800&)
    MF_ENABLED = (MF_FIRST + &H0&)
    MF_GRAYED = (MF_FIRST + &H1&)
    MF_DISABLED = (MF_FIRST + &H2&)
    MF_UNCHECKED = (MF_FIRST + &H0&)
    MF_CHECKED = (MF_FIRST + &H8&)
    MF_USECHECKBITMAPS = (MF_FIRST + &H200&)
    MF_STRING = (MF_FIRST + &H0&)
    MF_BITMAP = (MF_FIRST + &H4&)
    MF_OWNERDRAW = (MF_FIRST + &H100&)
    MF_POPUP = (MF_FIRST + &H10&)
    MF_MENUBARBREAK = (MF_FIRST + &H20&)
    MF_MENUBREAK = (MF_FIRST + &H40&)
    MF_UNHILITE = (MF_FIRST + &H0&)
    MF_HILITE = (MF_FIRST + &H80&)
    MF_DEFAULT = (MF_FIRST + &H1000&)
    MF_SYSMENU = (MF_FIRST + &H2000&)
    MF_HELP = (MF_FIRST + &H4000&)
    MF_RIGHTJUSITFY = (MF_FIRST + &H4000&)
    MF_MOUSESELECT = (MF_FIRST + &H8000&)
    MF_END = (MF_FIRST + &H80&)
End Enum

Private Enum MenuItemInfoMaskEnum
    MIIM_STATE = (MIIM_FIRST + &H1&)
    MIIM_ID = (MIIM_FIRST + &H2&)
    MIIM_SUBMENU = (MIIM_FIRST + &H4&)
    MIIM_CHECKMARKS = (MIIM_FIRST + &H8&)
    MIIM_TYPE = (MIIM_FIRST + &H10&)
    MIIM_DATA = (MIIM_FIRST + &H20&)
    MIIM_STRING = (MIIM_FIRST + &H40&)
    MIIM_BITMAP = (MIIM_FIRST + &H80&)
    MIIM_FTYPE = (MIIM_FIRST + &H100&)
End Enum

Private Enum MenuFlagStyleEnum
    MFS_GRAYED = (MFS_FIRST + &H3&)
    MFS_DISABLED = MenuFlagStyleEnum.MFS_GRAYED
    MFS_CHECKED = MenuFlagEnum.MF_CHECKED
    MFS_HILITE = MenuFlagEnum.MF_HILITE
    MFS_ENABLED = MenuFlagEnum.MF_ENABLED
    MFS_UNCHECKED = MenuFlagEnum.MF_UNCHECKED
    MFS_UNHILITE = MenuFlagEnum.MF_UNHILITE
    MFS_DEFAULT = MenuFlagEnum.MF_DEFAULT
    MFS_MASK = (MFS_FIRST + &H108B&)
    MFS_HOTTRACKDRAWN = (MFS_FIRST + &H10000000)
    MFS_CACHEDBMP = (MFS_FIRST + &H20000000)
    MFS_BOTTOMGAPDROP = (MFS_FIRST + &H40000000)
    MGS_TOPGAPDROP = (MFS_FIRST + &H80000000)
    MFS_GAPDROP = MFS_BOTTOMGAPDROP Or MGS_TOPGAPDROP
End Enum

Private Enum MenuFlagTypeEnum
    MFT_STRING = MenuFlagEnum.MF_STRING
    MFT_BITMAP = MenuFlagEnum.MF_BITMAP
    MFT_MENUBARBREAK = MenuFlagEnum.MF_MENUBARBREAK
    MFT_MENUBREAK = MenuFlagEnum.MF_MENUBREAK
    MFT_OWNERDRAW = MenuFlagEnum.MF_OWNERDRAW
    MFT_RADIOCHECK = (MFT_FIRST + &H200&)
    MFT_SEPARATOR = MenuFlagEnum.MF_SEPARATOR
    MFT_RIGHTORDER = (MFT_FIRST + &H2000&)
    MFT_RIGHTJUSTIFY = MenuFlagEnum.MF_RIGHTJUSITFY
End Enum

Private Enum SysMenuItemIDEnum
    SMI_RESTORE = (SMI_FIRST + &H120&)
    SMI_MOVE = (SMI_FIRST + &H10&)
    SMI_RESIZE = (SMI_FIRST + &H0&)
    SMI_MINIMIZE = (SMI_FIRST + &H20&)
    SMI_MAXIMIZE = (SMI_FIRST + &H30&)
    SMI_CLOSE = (SMI_FIRST + &H60&)
End Enum

Private Enum WindowStyleEnum
    WS_MAXIMIZEBOX = (WS_FIRST + &H10000)
    WS_MINIMIZEBOX = (WS_FIRST + &H20000)
    WS_THICKFRAME = (WS_FIRST + &H40000)
End Enum

'   ********************************************************************
'   lokale (private) Datentypen
Private Type MenuItemInfoType
    cbSize As Long
    fMask As MenuItemInfoMaskEnum
    fType As MenuFlagTypeEnum
    fState As MenuFlagStyleEnum
    wID As Long
    hSubMenu As Long
    hbmpChecked As Long
    hbmpUnchecked As Long
    dwItemData As Long
    dwTypeData As String
    cch As Long
End Type

'   ********************************************************************
'   lokale (private) API-Funktionen
Private Declare Function DrawMenuBar Lib "user32.dll" ( _
                ByVal hMenu As Long) As Long

Private Declare Function EnableMenuItem Lib "user32.dll" ( _
                ByVal hMenu As Long, _
                ByVal wIDEnableItem As Long, _
                ByVal wEnable As Long) As Long

Private Declare Function GetMenuItemCount Lib "user32.dll" ( _
                ByVal hWnd As Long) As Long
                
Private Declare Function GetMenuItemInfo Lib "user32.dll" _
                Alias "GetMenuItemInfoA" ( _
                ByVal hMenu As Long, _
                ByVal uItem As Long, _
                ByVal fByPosition As Long, _
                ByRef lpMenuItemInfo As MenuItemInfoType) As Long
                
Private Declare Function GetSystemMenu Lib "user32.dll" ( _
                ByVal hWnd As Long, _
                ByVal bRevert As Long) As Long

Private Declare Function GetWindowLong Lib "user32" _
                Alias "GetWindowLongA" ( _
                ByVal hWnd As Long, _
                ByVal wIndx As Long) As Long

Private Declare Function RemoveMenu Lib "user32.dll" ( _
                ByVal hMenu As Long, _
                ByVal nPosition As Long, _
                ByVal wFlags As Long) As Long

Private Declare Function SetWindowLong Lib "user32.dll" _
                Alias "SetWindowLongA" ( _
                ByVal hWnd As Long, _
                ByVal nIndex As Long, _
                ByVal dwNewLong As Long) As Long

'   ********************************************************************
'   globale (öffentliche) Methoden
Public Sub SetMinMaxButtons(ByVal hWnd As Long, _
                            ByVal CanMinimize As Boolean, _
                            ByVal CanMaximize As Boolean, _
                            Optional ByVal BlockResize As Boolean = True)
    
    Const ErrPart1 As String = "Folgender Fehlercode wurde gemeldet: "
    Const ErrPart2 As String = vbNewLine & "Die Bedeutung dieses " & _
                               "Fehlercodes ist in der MSDN " & _
                               "Library nachzulesen."
    
    Dim WindowStyle As Long
    Dim hMenu As Long
    Dim Result As Long
    Dim lngMinimize As Long
    Dim lngMaximize As Long
    Dim lngResize As Long
    Dim lngMenuItems As Long
    Dim i As Long
    Dim MenuItemInfo As MenuItemInfoType
    
    '   Positionen der Menüpunkte "Maximize" und "Minimize" festlegen
    lngMaximize = 0
    lngMinimize = 0
    lngResize = 0
    
    '   Aktuelle Eigenschaften des Fensters auslesen
    WindowStyle = GetWindowLong(hWnd, GWL_STYLE)
    
    '   Fehler ins Debug-Fenster schreiben
    If (WindowStyle = 0) Then
        Debug.Print ErrPart1 & CStr(Err.LastDllError) & ErrPart2
    Else
        '   Systemmenü referenzieren
        hMenu = GetSystemMenu(hWnd, 0)
        
        If (hMenu <> 0) Then
            '   Anzahl Einträge im Menü ermitteln
            lngMenuItems = GetMenuItemCount(hMenu)
            
            '   Alle MenuItems durchlaufen (null-basiert!)
            For i = 0 To lngMenuItems - 1
                '   Struktur für den Aufruf vorbereiten
                With MenuItemInfo
                    .cbSize = Len(MenuItemInfo)
                    .fMask = MenuItemInfoMaskEnum.MIIM_ID
                    .fState = MenuFlagStyleEnum.MFS_DEFAULT
                End With
                
                '   MenuItemInfo auslesen
                Result = GetMenuItemInfo(hMenu, i, 1, MenuItemInfo)
                
                If (Result <> 0) Then
                    '   Minimieren und Maximieren heraussuchen
                    Select Case MenuItemInfo.wID
                        Case SysMenuItemIDEnum.SMI_MAXIMIZE
                            lngMaximize = i
                            
                        Case SysMenuItemIDEnum.SMI_MINIMIZE
                            lngMinimize = i
                        
                        Case SysMenuItemIDEnum.SMI_RESIZE
                            lngResize = i
                            
                    End Select
                End If
            Next i
        End If
        
        If (Not (CanMaximize)) And (lngMaximize <> 0) Then
            '   Maximize-Button entfernen
            WindowStyle = WindowStyle And Not (WS_MAXIMIZEBOX)
            
            '   "Maximize" aus dem Systemmenü entfernen
            If (hMenu <> 0) Then
                Result = RemoveMenu(hMenu, lngMaximize, MF_BYPOSITION)
                
                Result = EnableMenuItem(hMenu, lngMaximize, _
                                        MF_BYPOSITION Or MF_DISABLED)
                If (Result = &HFFFFFFFF) Then
                    Debug.Print ErrPart1 & CStr(Err.LastDllError) & _
                                                                ErrPart2
                End If
            End If
        End If
        
        If (Not (CanMinimize)) And (lngMinimize <> 0) Then
            '   Minimize-Button entfernen
            WindowStyle = WindowStyle And Not (WS_MINIMIZEBOX)
            
            '   "Minimize" aus dem Systemmenü entfernen
            If (hMenu <> 0) Then
                Result = RemoveMenu(hMenu, lngMinimize, MF_BYPOSITION)
                
                Result = EnableMenuItem(hMenu, lngMinimize, _
                                        MF_BYPOSITION Or MF_DISABLED)
                If (Result = &HFFFFFFFF) Then
                    Debug.Print ErrPart1 & CStr(Err.LastDllError) & _
                                                                ErrPart2
                End If
            End If
        End If
        
        '   Resize setzen
        If (Not (CanMinimize And CanMaximize)) And (BlockResize) And _
                                                (lngResize <> 0) Then
            WindowStyle = WindowStyle And Not (WS_THICKFRAME)
                
            '   "Resize" aus dem Systemmenü entfernen
            If (hMenu <> 0) Then
                Result = RemoveMenu(hMenu, lngResize, MF_BYPOSITION)
                
                Result = EnableMenuItem(hMenu, lngResize, _
                                        MF_BYPOSITION Or MF_DISABLED)
                If (Result = &HFFFFFFFF) Then
                    Debug.Print ErrPart1 & CStr(Err.LastDllError) & _
                                                                ErrPart2
                End If
            End If
        End If
        
        '   Eigenschaften neu setzen
        WindowStyle = SetWindowLong(hWnd, GWL_STYLE, WindowStyle)
        If (WindowStyle = 0) Then
            Debug.Print ErrPart1 & CStr(Err.LastDllError) & ErrPart2
        End If
        
        '   Systemmenü neu zeichnen lassen
        If (hMenu <> 0) Then
            Call DrawMenuBar(hWnd)
        End If
    End If
End Sub

'--- Ende Modul "mod_ButtonState" alias mod_Buttonstate.bas ---
'-------------- Ende Projektdatei Projekt1.vbp --------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 2 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von hedgehog am 16.03.2006 um 09:56

Hallo,

ich habe den Bedarf, das "X" auszublenden oder zu disablen. Die Minimize- und Maximize-Buttons können in meiner Anwednung erhalten bleiben. Dieser Tipp kann das nicht (noch nicht). Möglich? Wenn ja, wie?

Kommentar von Henning Klein am 20.09.2005 um 15:13

Der Tip ist ja ganz nett, aber so aufwendig.
Schlieslich kann mit mit Tip 213 (Fensterstile zur Laufzeit ändern) auch jeder MDI-Parent-Form die Min/Max-Buttons entziehen.
Von den anderen Möglichkeiten zur Fenstergestaltung des Tips 213 mal ganz abgesehen.

Henning