Suche: Flat Controls

Ich suche eine Möglichkeit Command Buttons, List Box, Text Fields u.ä. „flach“ und mit Hottrack darzustellen (Wie bei Java Swing).

Über eine Quelle für solche Controls wäre ich sehr dankbar!

cu René

Hallo

Zunächst erstellst du ein neues Klassenmodul mit dem folgenden Code
und gibt ihm den Namen „clsFlatControl“:

Option Explicit

' Declare constants
Implements ISubclass
Private Const WM\_COMMAND = &H111
Private Const WM\_PAINT = &HF
Private Const WM\_TIMER = &H113
Private Const WM\_MOUSEMOVE = &H200
Private Const WM\_LBUTTONDOWN = &H201
Private Const WM\_LBUTTONUP = &H202
Private Const SM\_CXHTHUMB = 10
Private Const WM\_SETFOCUS = &H7
Private Const WM\_KillFileFOCUS = &H8
Private Const WM\_MOUSEACTIVATE = &H21
Private Const PS\_SOLID = 0
Private Const GWL\_EXSTYLE = (-20)
Private Const GWL\_STYLE = (-16)
Private Const WS\_EX\_CLIENTEDGE = &H200&
Private Const CBS\_DROPDOWN = &H2&
Private Const CBS\_DROPDOWNLIST = &H3&
Private Const CBN\_DROPDOWN = 7
Private Const CBN\_CLOSEUP = 8
Private Const CB\_GETDROPPEDSTATE = &H157
Private Const GW\_CHILD = 5

' Declare enums
Private Enum EDrawStyle
 FC\_DRAWNORMAL = &H1
 FC\_DRAWRAISED = &H2
 FC\_DRAWPRESSED = &H4
End Enum

' Declare types
Private Type POINTAPI
 X As Long
 Y As Long
End Type

Private Type RECT
 Left As Long
 Top As Long
 Right As Long
 Bottom As Long
End Type

' Declare functions
Private Declare Function GetClientRect Lib "user32.dll" (ByVal hwnd 
As Long, lpRect As RECT) As Long
Private Declare Function ScreenToClient Lib "user32.dll" (ByVal hwnd 
As Long, lpPoint As POINTAPI) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) 
As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) 
As Long
Private Declare Function GetParent Lib "user32.dll" (ByVal hwnd As 
Long) As Long
Private Declare Function InflateRect Lib "user32.dll" (lpRect As 
RECT, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function OffsetRect Lib "user32.dll" (lpRect As RECT, 
ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function IsWindowEnabled Lib "user32.dll" (ByVal hwnd 
As Long) As Long
Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal 
nIndex As Long) As Long
Private Declare Function InvalidateRect Lib "user32.dll" (ByVal hwnd 
As Long, lpRect As RECT, ByVal bErase As Long) As Long
Private Declare Function SetTimer Lib "user32.dll" (ByVal hwnd As 
Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal 
lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32.dll" (ByVal hwnd As 
Long, ByVal nIDEvent As Long) As Long
Private Declare Function GetCursorPos Lib "user32.dll" (lpPoint As 
POINTAPI) As Long
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd 
As Long, lpRect As RECT) As Long
Private Declare Function PtInRect Lib "user32.dll" (lpRect As RECT, 
ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function CreatePen Lib "gdi32.dll" (ByVal nPenStyle 
As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As 
Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject 
As Long) As Long
Private Declare Function MoveToEx Lib "gdi32.dll" (ByVal hdc As Long, 
ByVal X As Long, ByVal Y As Long, lpPoint As POINTAPI) As Long
Private Declare Function LineTo Lib "gdi32.dll" (ByVal hdc As Long, 
ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function OleTranslateColor Lib "olepro32.dll" (ByVal 
OLE\_COLOR As Long, ByVal HPALETTE As Long, pccolorref As Long) As 
Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias 
"GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex 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
Private Declare Function FindWindowEx Lib "user32.dll" Alias 
"FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal 
lpsz1 As String, lpsz2 As Any) As Long
Private Declare Function SendMessageLong Lib "user32.dll" Alias 
"SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam 
As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindow Lib "user32.dll" (ByVal hwnd As 
Long, ByVal wCmd As Long) As Long
Private Declare Function GetFocus Lib "user32.dll" () As Long

' Declare values
Private m\_bLBtnDown As Boolean
Private m\_bCombo As Boolean
Private m\_hWnd As Long
Private m\_hWndEdit As Long
Private m\_hWndParent As Long
Private m\_bSubclass As Boolean
Private m\_bMouseOver As Boolean

Public Sub Attach(ByRef objthis As Object)
 Dim lStyle As Long
 Dim lhWnd As Long
 pRelease
 On Error Resume Next
 lhWnd = objthis.hwnd
 If (Err.Number 0) Then
 Err.Raise vbObjectError + 1048 + 1, App.EXEName & 
".cFlatControl", "Incorrect control type passed to 'Attach' parameter 
- must be a control with a hWnd property."
 Exit Sub
 End If
 m\_bCombo = False
 If TypeName(objthis) = "ImageCombo" Then
 m\_hWndParent = lhWnd
 lhWnd = FindWindowEx(lhWnd, 0&, "ComboBox", ByVal 0&amp:wink:
 m\_bCombo = True
 ElseIf TypeName(objthis) = "ComboBox" Then
 m\_hWndParent = GetParent(objthis.hwnd)
 m\_bCombo = True
 ElseIf TypeName(objthis) = "OwnerDrawComboList" Then
 m\_hWndParent = lhWnd
 m\_bCombo = True
 Else
 lStyle = GetWindowLong(lhWnd, GWL\_STYLE)
 If ((lStyle And CBS\_DROPDOWN) = CBS\_DROPDOWN) Or ((lStyle And 
CBS\_DROPDOWNLIST) = CBS\_DROPDOWNLIST) Then
 m\_hWndParent = objthis.Parent.hwnd
 m\_bCombo = True
 Else
 With objthis
 .Move .Left + 2 \* Screen.TwipsPerPixelX, .Top + 2 \* 
Screen.TwipsPerPixelY, .Width - 4 \* Screen.TwipsPerPixelX, .Height - 
4 \* Screen.TwipsPerPixelY
 End With
 End If
 End If
 pAttach lhWnd
End Sub

Private Sub pAttach(ByRef hWndA As Long)
 Dim lStyle As Long
 m\_hWnd = hWndA
 If (m\_hWnd 0) Then
 lStyle = GetWindowLong(m\_hWnd, GWL\_STYLE)
 If (lStyle And CBS\_DROPDOWN) = CBS\_DROPDOWN Then
 m\_hWndEdit = GetWindow(m\_hWnd, GW\_CHILD)
 End If
 AttachMessage Me, m\_hWnd, WM\_PAINT
 AttachMessage Me, m\_hWnd, WM\_MOUSEACTIVATE
 AttachMessage Me, m\_hWnd, WM\_SETFOCUS
 AttachMessage Me, m\_hWnd, WM\_KillFileFOCUS
 AttachMessage Me, m\_hWnd, WM\_MOUSEMOVE
 AttachMessage Me, m\_hWnd, WM\_TIMER
 If (m\_hWndEdit 0) Then
 AttachMessage Me, m\_hWndEdit, WM\_MOUSEACTIVATE
 AttachMessage Me, m\_hWndEdit, WM\_SETFOCUS
 AttachMessage Me, m\_hWndEdit, WM\_KillFileFOCUS
 AttachMessage Me, m\_hWndEdit, WM\_MOUSEMOVE
 End If
 If (m\_bCombo) Then
 AttachMessage Me, m\_hWndParent, WM\_COMMAND
 End If
 m\_bSubclass = True
 End If
End Sub

Private Sub pRelease()
 If (m\_bSubclass) Then
 DetachMessage Me, m\_hWnd, WM\_PAINT
 DetachMessage Me, m\_hWnd, WM\_SETFOCUS
 DetachMessage Me, m\_hWnd, WM\_KillFileFOCUS
 DetachMessage Me, m\_hWnd, WM\_MOUSEACTIVATE
 DetachMessage Me, m\_hWnd, WM\_MOUSEMOVE
 DetachMessage Me, m\_hWnd, WM\_TIMER
 If (m\_hWndEdit 0) Then
 DetachMessage Me, m\_hWndEdit, WM\_MOUSEACTIVATE
 DetachMessage Me, m\_hWndEdit, WM\_SETFOCUS
 DetachMessage Me, m\_hWndEdit, WM\_KillFileFOCUS
 DetachMessage Me, m\_hWndEdit, WM\_MOUSEMOVE
 End If
 If (m\_bCombo) Then
 DetachMessage Me, m\_hWndParent, WM\_COMMAND
 End If
 End If
 m\_hWnd = 0
 m\_hWndEdit = 0
 m\_hWndParent = 0
End Sub

Private Sub Draw(ByVal dwStyle As EDrawStyle, clrTopLeft As 
OLE\_COLOR, clrBottomRight As OLE\_COLOR)
 If m\_hWnd = 0 Then Exit Sub
 If (m\_bCombo) Then
 DrawCombo dwStyle, clrTopLeft, clrBottomRight
 Else
 DrawEdit dwStyle, clrTopLeft, clrBottomRight
 End If
End Sub

Private Sub DrawEdit(ByVal dwStyle As EDrawStyle, clrTopLeft As 
OLE\_COLOR, clrBottomRight As OLE\_COLOR)
 Dim rcItem As RECT
 Dim rcItem2 As RECT
 Dim pDC As Long
 Dim hWndFocus As Long
 Dim tP As POINTAPI
 Dim hWndP As Long
 hWndP = GetParent(m\_hWnd)
 GetWindowRect m\_hWnd, rcItem
 tP.X = rcItem.Left: tP.Y = rcItem.Top
 ScreenToClient hWndP, tP
 rcItem.Left = tP.X: rcItem.Top = tP.Y
 tP.X = rcItem.Right: tP.Y = rcItem.Bottom
 ScreenToClient hWndP, tP
 rcItem.Right = tP.X: rcItem.Bottom = tP.Y
 InflateRect rcItem, 2, 2
 pDC = GetDC(hWndP)
 Draw3DRect pDC, rcItem, clrTopLeft, clrBottomRight
 InflateRect rcItem, -1, -1
 If (IsWindowEnabled(m\_hWnd) = 0) Then
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 Else
 Draw3DRect pDC, rcItem, vbButtonFace, vbButtonFace
 End If
 If (IsWindowEnabled(m\_hWnd) = 0) Then
 DeleteDC pDC
 Exit Sub
 End If
 Select Case dwStyle
 Case FC\_DRAWNORMAL
 Case FC\_DRAWRAISED, FC\_DRAWPRESSED
 InflateRect rcItem, -1, -1
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 InflateRect rcItem, -1, -1
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 InflateRect rcItem, -1, -1
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 End Select
 DeleteDC pDC
End Sub

Private Function Draw3DRect(ByVal hdc As Long, ByRef rcItem As RECT, 
ByVal oTopLeftColor As OLE\_COLOR, ByVal oBottomRightColor As 
OLE\_COLOR)
 Dim hPen As Long
 Dim hPenOld As Long
 Dim tP As POINTAPI
 hPen = CreatePen(PS\_SOLID, 1, TranslateColor(oTopLeftColor))
 hPenOld = SelectObject(hdc, hPen)
 MoveToEx hdc, rcItem.Left, rcItem.Bottom - 1, tP
 LineTo hdc, rcItem.Left, rcItem.Top
 LineTo hdc, rcItem.Right - 1, rcItem.Top
 SelectObject hdc, hPenOld
 DeleteObject hPen
 If (rcItem.Left rcItem.Right) Then
 hPen = CreatePen(PS\_SOLID, 1, TranslateColor(oBottomRightColor))
 hPenOld = SelectObject(hdc, hPen)
 LineTo hdc, rcItem.Right - 1, rcItem.Bottom - 1
 LineTo hdc, rcItem.Left, rcItem.Bottom - 1
 SelectObject hdc, hPenOld
 DeleteObject hPen
 End If
End Function

Private Function TranslateColor(ByVal clr As OLE\_COLOR, Optional hPal 
As Long = 0) As Long
 If OleTranslateColor(clr, hPal, TranslateColor) Then
 TranslateColor = -1
 End If
End Function

Private Sub DrawCombo(ByVal dwStyle As EDrawStyle, clrTopLeft As 
OLE\_COLOR, clrBottomRight As OLE\_COLOR)
 Dim rcItem As RECT
 Dim rcItem2 As RECT
 Dim pDC As Long
 Dim hWndFocus As Long
 Dim tP As POINTAPI
 GetClientRect m\_hWnd, rcItem
 pDC = GetDC(m\_hWnd)
 Draw3DRect pDC, rcItem, clrTopLeft, clrBottomRight
 InflateRect rcItem, -1, -1
 If (IsWindowEnabled(m\_hWnd) = 0) Then
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 Else
 Draw3DRect pDC, rcItem, vbButtonFace, vbButtonFace
 End If
 InflateRect rcItem, -1, -1
 rcItem.Left = rcItem.Right - Offset()
 Draw3DRect pDC, rcItem, vbButtonFace, vbButtonFace
 InflateRect rcItem, -1, -1
 Draw3DRect pDC, rcItem, vbButtonFace, vbButtonFace
 If (IsWindowEnabled(m\_hWnd) = 0) Then
 DeleteDC pDC
 Exit Sub
 End If
 Select Case dwStyle
 Case FC\_DRAWNORMAL
 rcItem.Top = rcItem.Top - 1
 rcItem.Bottom = rcItem.Bottom + 1
 Draw3DRect pDC, rcItem, vb3DHighlight, vb3DHighlight
 rcItem.Left = rcItem.Left - 1
 rcItem.Right = rcItem.Left
 Draw3DRect pDC, rcItem, vbWindowBackground, &H0
 Case FC\_DRAWRAISED
 rcItem.Top = rcItem.Top - 1
 rcItem.Bottom = rcItem.Bottom + 1
 rcItem.Right = rcItem.Right + 1
 Draw3DRect pDC, rcItem, vb3DHighlight, vbButtonShadow
 Case FC\_DRAWPRESSED
 rcItem.Left = rcItem.Left - 1
 rcItem.Top = rcItem.Top - 2
 OffsetRect rcItem, 1, 1
 Draw3DRect pDC, rcItem, vbButtonShadow, vb3DHighlight
 End Select
 DeleteDC pDC
End Sub

Private Function Offset() As Long
 Offset = GetSystemMetrics(SM\_CXHTHUMB)
End Function

Public Property Get DroppedDown() As Boolean
 If (m\_bCombo) And (m\_hWnd 0) Then
 DroppedDown = (SendMessageLong(m\_hWnd, CB\_GETDROPPEDSTATE, 0, 0) 
 0)
 End If
End Property

Private Sub OnPaint(ByVal bFocus As Boolean, ByVal bDropped As 
Boolean)
 If bFocus Then
 If (bDropped) Then
 Draw FC\_DRAWPRESSED, vbButtonShadow, vb3DHighlight
 Else
 Draw FC\_DRAWRAISED, vbButtonShadow, vb3DHighlight
 End If
 Else
 Draw FC\_DRAWNORMAL, vbButtonFace, vbButtonFace
 End If
End Sub

Private Sub Class\_Terminate()
 pRelease
End Sub

Private Sub OnTimer(ByVal bCheckMouse As Boolean)
 Dim bOver As Boolean
 Dim rcItem As RECT
 Dim tP As POINTAPI
 If (bCheckMouse) Then
 bOver = True
 GetCursorPos tP
 GetWindowRect m\_hWnd, rcItem
 If (PtInRect(rcItem, tP.X, tP.Y) = 0) Then
 bOver = False
 End If
 End If
 If Not (bOver) Then
 KillTimer m\_hWnd, 1
 m\_bMouseOver = False
 End If
End Sub

Private Property Let ISubclass\_MsgResponse(ByVal RHS As 
SSubTimer.EMsgResponse)
 ' do not remove this comment
End Property

Private Property Get ISubclass\_MsgResponse() As 
SSubTimer.EMsgResponse
 If (CurrentMessage = WM\_PAINT) Then
 ISubclass\_MsgResponse = emrPreprocess
 Else
 ISubclass\_MsgResponse = emrPostProcess
 End If
End Property

Private Function ISubclass\_WindowProc(ByVal hwnd As Long, ByVal iMsg 
As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 Dim bDown As Boolean
 Dim bFocus As Boolean
 Select Case iMsg
 Case WM\_COMMAND
 If (m\_hWnd = lParam) Then
 Select Case wParam \ &H10000
 Case CBN\_CLOSEUP
 OnPaint (m\_hWnd = GetFocus() Or m\_hWndEdit = GetFocus() Or 
bDown), bDown
 End Select
 OnTimer False
 End If
 Case WM\_PAINT
 bDown = DroppedDown()
 bFocus = (m\_hWnd = GetFocus() Or m\_hWndEdit = GetFocus() Or 
bDown)
 OnPaint (bFocus), bDown
 If (bFocus) Then
 OnTimer False
 End If
 Case WM\_SETFOCUS
 OnPaint True, False
 OnTimer False
 Case WM\_KillFileFOCUS
 OnPaint False, False
 Case WM\_MOUSEMOVE
 If Not (m\_bMouseOver) Then
 bDown = DroppedDown()
 If Not (m\_hWnd = GetFocus() Or m\_hWndEdit = GetFocus() Or 
bDown) Then
 OnPaint True, False
 m\_bMouseOver = True
 SetTimer m\_hWnd, 1, 10, 0
 End If
 End If
 Case WM\_TIMER
 OnTimer True
 If Not (m\_bMouseOver) Then
 OnPaint False, False
 End If
 End Select
End Function

Über „Projekt“ -> „Verweise“ musst du sicherstellen, dass die Datei
„Ssubtmr.dll“ in dein Projekt eingebunden wird. Die Datei findest du
unter anderem hier:
http://www.vbaccelerator.com/codelib/ssubtmr/ssubtmr…
(Kopiere die Datei „Ssubtmr.dll“ einfach ins Windows-System-
Verzeichnis!)

Um gewisse Controls nun flach aussehen zu lassen, musst du den
folgenden Code in ein entsprechendes Formmodul einfügen:

Private mclsFlat(2) As clsFlatControl

Private Sub Form\_Load()
 Set mclsFlat(0) = New clsFlatControl
 Call mclsFlat(0).Attach(Text1)
 Set mclsFlat(1) = New clsFlatControl
 Call mclsFlat(1).Attach(Combo1)
 Set mclsFlat(2) = New clsFlatControl
 Call mclsFlat(2).Attach(Combo2)
End Sub

Je nach Anzahl flacher Controls musst du den Index und die Anzahl der
Attach-Methoden anpassen.

Mit freundlichen Grüßen

Samuel

Team: Name entfernt