In den Eigenschaften eines Forms können sie zwar dessen
Abmessungen (Eigenschaften Height und Width) festlegen. Doch ist es
nicht ganz so einfach, dafür zu sorgen, dass die eigentliche
Arbeitsfläche des Forms, der so genannte Client-Bereich, eine
bestimmte Größe erhält. Dies ist zum Beispiel dann erforderlich,
wenn die Größe des Forms exakt an ein Hintergrundbild angepasst
werden soll.
Die notwendigen Abmessungen dazu können Sie von der API-Funktion
AdjustWindowRectEx
berechnen lassen. Etwas ungewöhnlich erscheint auf den ersten
Blick, dass Sie dieser Funktion kein konkretes Fenster(-Handle)
übergeben. Vielmehr übergeben Sie die gewünschte Größe der
Arbeitsfläche in einer benutzerdefinierten Variablen (RECT) und
dazu Angaben zu den Fensterstilen und die Angabe, ob das Fenster ein
sichtbares Menü hat. Nach dem Aufruf der Funktion sind dann die
Elemente Right und Bottom der RECT-Variablen lediglich entsprechend
angepasst, ohne dass die Formgröße bereits geändert wäre. Dieses
Prinzip hat wohl darin seinen Sinn, dass Sie so die Größe bereits
vorab kalkulieren und gegebenenfalls noch diverse andere Anpassungen
vornehmen könnten, ehe Sie die Größe eines Forms endgültig
setzen.
Die Angaben zu den Fensterstilen ermitteln Sie mit Hilfe der
API-Funktion GetWindowLong
und den Index-Angaben GW_STYLE und GW_EXSTYLE. Anhand dieser
Fensterstil-Angaben kann die Funktion AdjustWindowRectEx die in den
Bildschirm-Eigenschaften eingestellte Stärke des Fensterrahmen und
Höhe der Titelleiste ermitteln.
Ob das Form ein sichtbares Menü hat, kann die Funktion jedoch
nicht selbst ermitteln. Dazu ist die Angabe gedacht, ob das Form ein
Menü hat. Allerdings reicht die reine Angabe tatsächlich nicht
aus, wenn es sich um eine längere Menüzeile handelt, die bei einem
schmalen Form mehrzeilig umbrochen wird. Sie können aber über die
API-Funktionen GetMenu,
GetMenuItemCount
und GetMenuItemRect
die aktuelle Höhe der Menüleiste auch in umbrochenem Zustand
ermitteln. Doch falls die Menüzeile erst nach der Anpassung an eine
geringere Breite umbrochen werden sollte, stimmt das Ergebnis so
noch nicht. Sie müssen erneut die Höhe der Menüzeile ermitteln
und die Anpassung erneut vornehmen - so lange, bis die gewünschte
Größe erreicht ist. Das ganze Procedere packen wir daher am besten
in Hilfsprozeduren.
Mit der Prozedur CalcAdjustedFormSize werden Breite und/oder
Höhe ermittelt. Die gewünschten Maße für ClientWidth und
ClientHeight übergeben Sie in der aktuellen Maßeinheit (ScaleMode-Einstellung)
des betreffenden Forms, während die neue Breite und Höhe in Twips
zurückgegeben werden. Diese Prozedur können Sie natürlich auch
separat zu reinen Ermittlungszwecken verwenden.
Zum Setzen der neuen Breite und/oder Höhe dient die
Prozedur AdjustFormSize. Ihr übergeben Sie das betreffende Form und
optional die gewünschte Breite und/oder Höhe der Arbeitsfläche in
der aktuellen Maßeinheit des Forms. In dieser Prozedur werden die
notwendigen Abmessungen des Forms so lange ermittelt und gesetzt,
bis sich die Größe des Forms nicht mehr ändert.
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Declare Function AdjustWindowRectEx Lib "user32" _
(lpRect As RECT, ByVal dsStyle As Long, ByVal bMenu As Long, _
ByVal dwEsStyle As Long) As Long
Private Declare Function GetMenu Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" _
(ByVal hMenu As Long) As Long
Private Declare Function GetMenuItemRect Lib "user32" _
(ByVal hwnd As Long, ByVal hMenu As Long, ByVal uItem As Long, _
lprcItem As RECT) As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) _
As Long
Public Sub CalcAdjustedFormSize(Form As Form, _
Optional ByVal ClientWidth As Single = -1, _
Optional NewWidth As Single, _
Optional ByVal ClientHeight As Single = -1, _
Optional NewHeight As Single)
Dim nStyle As Long
Dim nExStyle As Long
Dim nRect As RECT
Dim nHasMenu As Long
Dim nControl As Control
Dim nWidth As Single
Dim nHeight As Single
Dim nMenuItemRect As RECT
Dim nMenu As Long
Dim nMenuItemCount As Long
Dim l As Long
Dim nMaxBottom As Long
Dim nMinTop As Long
Const GWL_EXSTYLE = (-20)
Const GWL_STYLE = (-16)
With Form
nStyle = GetWindowLong(.hwnd, GWL_STYLE)
nExStyle = GetWindowLong(.hwnd, GWL_EXSTYLE)
If ClientWidth >= 0 Then
nRect.Right = .ScaleX(ClientWidth, .ScaleMode, vbPixels)
End If
If ClientHeight >= 0 Then
nRect.Bottom = .ScaleY(ClientHeight, .ScaleMode, vbPixels)
End If
nMenu = GetMenu(.hwnd)
If nMenu Then
nMenuItemCount = GetMenuItemCount(nMenu)
nMinTop = .ScaleY(Screen.Height, vbTwips, vbPixels) * 2
For l = 1 To nMenuItemCount
GetMenuItemRect .hwnd, nMenu, l - 1, nMenuItemRect
With nMenuItemRect
If .Top < nMinTop Then
nMinTop = .Top
End If
If .Bottom > nMaxBottom Then
nMaxBottom = .Bottom
End If
End With
Next 'l
With nRect
.Bottom = .Bottom + (nMaxBottom - nMinTop)
End With
End If
AdjustWindowRectEx nRect, nStyle, 0, nExStyle
If ClientWidth >= 0 Then
NewWidth = (nRect.Right - nRect.Left) * Screen.TwipsPerPixelX
Else
NewWidth = .Width
End If
If ClientHeight >= 0 Then
NewHeight = (nRect.Bottom - nRect.Top) * Screen.TwipsPerPixelY
Else
NewHeight = .Height
End If
End With
End Sub
Public Sub AdjustFormSize(Form As Form, _
Optional ByVal ClientWidth As Single = -1, _
Optional ByVal ClientHeight As Single = -1)
Dim nNewWidth As Single
Dim nNewHeight As Single
Dim nLastNewWidth As Single
Dim nLastNewHeight As Single
With Form
Do
CalcAdjustedFormSize Form, _
ClientWidth, nNewWidth, ClientHeight, nNewHeight
If (nNewWidth <> nLastNewWidth) Or _
(nNewHeight <> nLastNewHeight) Then
.Move .Left, .Top, nNewWidth, nNewHeight
nLastNewWidth = nNewWidth
nLastNewHeight = nNewHeight
Else
Exit Do
End If
Loop
.Refresh
End With
End Sub
|