RSS
StartseiteKnowledge LibraryTop 10Impressum

Flexible Formular Eigenschaften

Schreibgeschützte Form Eigenschaften, wie MinButton oder MaxButton zur Laufzeit ändern

War es Faulheit oder sah man einfach nur keine Notwendigkeit, die Eigenschaften MinButton, MaxButton und Borderstyle eines Formulars zur Laufzeit ändern zu können? Fest steht, es geht - sogar für MDI Formulare, die derartige Eigenschaften nicht mal zur Design-Zeit bieten.

Zur Design- Zeit können Sie nahezu alle Form Eigenschaften, wie BorderStyle fest oder änderbar, MinButton und MaxButton sichtbar oder nicht, festlegen. Einige Programmabläufe erfordern allerdings eine Änderung dieser Eigenschaften zur Laufzeit, doch hier unterbindet VB den schreibenden Zugriff. MDI Formulare bieten diese Eigenschaften weder zur Design-Zeit noch zur Laufzeit. Ein Zugriff auf den Zustand des Schließen- Menüs bieten beide Formulartypen nicht. Mit ein paar API Funktion kann diese Einschränkung jedoch umgangen werden, auch für MDI Formulare.

Die benötigten API Deklarationen und Konstanten:

Private 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 RemoveMenu Lib "user32" _
       (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" _
       (ByVal hWnd As Long) As Long

Private Const MF_BYCOMMAND = &H0&

Private Const SC_CLOSE = &HF060
Private Const SC_MAXIMIZE = &HF030
Private Const SC_MINIMIZE = &HF020
Private Const SC_MOVE = &HF010
Private Const SC_RESTORE = &HF120
Private Const SC_SIZE = &HF000

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 Const GWL_STYLE = (-16)

Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_THICKFRAME = &H40000

Die Schaltflächen in der Titelleiste des Formulars werden durch das Entfernen der entsprechenden Fensterstile WS_MAXIMIZEBOX bzw. WS_MINIMIZEBOX ausgeblendet. Für den Rahmen ist der Fensterstil WS_THICKFRAME zuständig. Wird er entfernt, hat das Fenster einen unveränderbaren Rahmen. Den aktuellen Fensterstil ermittelt die API Funktion GetWindowLong. GWL_STYLE gibt dabei an, das die einfachen Fensterstile ermittelt werden sollen. SetWindowLong weist den veränderten Fensterstil wieder zu.

Damit der Anwender diese Fensterstile nicht Mithilfe des Systemmenüs übergehen kann, müssen hier noch die entsprechenden Einträge entfernt werden. Den Handle des Systemmenüs ermittelt man mit der Funktion GetSystemMenu, die Menüeinträge werden mit der RemoveMenu- Funktion entfernt. Damit man nicht blind im Menü herumstochern muss und wahllos Einträge löscht, gibt man für den Parameter nPosition die dem Eintrag zugeordnete System Command - Konstante an. Zum Schluß informiert man das Fenster von der Änderung des Systemmenüs, mittels der DrawMenuBar- Funktion. Ggf. sorgt diese auch zugleich für das Aktualisieren des geänderten Rahmen.

Die Prozedur DynamicSysMenu isoliert alle API Aufrufe und erledigt das Beiwerk. In Ihrem Projekt eingesetzt, brauchen Sie nur noch das entsprechende Form- Objekt übergeben und legen fest, welche Funktionen des Systemmenüs deaktiviert werden soll. Übergeben Sie nur das Form- Objekt, wird das Systemmenü in den Ausgangszustand zurückgesetzt

.
Public Sub DynamicSysMenu(ByVal Form As Form, _
                 Optional ByVal NoMin As Boolean, _
                 Optional ByVal NoMax As Boolean, _
                 Optional ByVal NoClose As Boolean, _
                 Optional ByVal NoSize As Boolean)
  Dim hMenu    As Long
  Dim lngStyle As Long
  Dim bolMin   As Boolean
  Dim bolMax   As Boolean
  Dim bolSize  As Boolean
  
  With Form
    GetSystemMenu .hWnd, True
    lngStyle = GetWindowLong(.hWnd, GWL_STYLE)
    hMenu = GetSystemMenu(.hWnd, False)
  
    If Not TypeOf Form Is MDIForm Then
      bolMin = (((.BorderStyle = vbSizable) Or _
                 (.BorderStyle = vbFixedSingle)) _
                And .MinButton And (Not NoMin))
      bolMax = (((.BorderStyle = vbSizable) Or _
                 (.BorderStyle = vbFixedSingle)) _
                And .MaxButton And (Not NoMax))
      bolSize = (((.BorderStyle = vbSizable) Or _
                  (.BorderStyle = vbSizableToolWindow)) And _
                  (Not NoSize))
    Else
      bolMin = Not NoMin
      bolMax = Not NoMax
      bolSize = Not NoSize
    End If
  End With

  '// Zugesicherte Fensterstile wiederherstellen:
  If (bolMax) Then lngStyle = lngStyle Or WS_MAXIMIZEBOX
  If (bolMin) Then lngStyle = lngStyle Or WS_MINIMIZEBOX
  If (bolSize) Then lngStyle = lngStyle Or WS_THICKFRAME
  
  '// Überflüssige Menüeinträge entfernen:
  If Not (bolSize) Then RemoveMenu hMenu, SC_SIZE, MF_BYCOMMAND
  If Not (bolMin) Then RemoveMenu hMenu, SC_MINIMIZE, MF_BYCOMMAND
  If Not (bolMax) Then RemoveMenu hMenu, SC_MAXIMIZE, MF_BYCOMMAND
  If ((Not bolMin) And (Not bolMax)) Then RemoveMenu hMenu, SC_RESTORE, MF_BYCOMMAND
  If Not (Form.Moveable) Then RemoveMenu hMenu, SC_MOVE, MF_BYCOMMAND
  
  If GetMenuItemCount(hMenu) = 2 Then RemoveMenu hMenu, &H0, MF_BYCOMMAND
  
  If (NoClose) Then
    RemoveMenu hMenu, SC_CLOSE, MF_BYCOMMAND
    RemoveMenu hMenu, &H0, MF_BYCOMMAND
  End If
    
  '// Ggf. Schaltflächen ausblenden und Borderstyle ändern:
  If Not (bolMax) Then lngStyle = lngStyle And Not WS_MAXIMIZEBOX
  If Not (bolMin) Then lngStyle = lngStyle And Not WS_MINIMIZEBOX
  If Not (bolSize) Then lngStyle = lngStyle And Not WS_THICKFRAME

  With Form
    '// Neuen Fensterstil zuweisen/ Menü aktualisieren:
    SetWindowLong .hWnd, GWL_STYLE, lngStyle
    DrawMenuBar .hWnd
  End With
End Sub

Zwei Hinweise zum Schluss: