It’s a coolbutton. 🙂 Those flat things that MS uses now.
This one supports setting images for mouse over, mouse down, mouse up, drawing bevels for those 3 states, setting the colours of the bevel, automatically generating the mousedown and mouseup images by varying the brightness of the original, setting text positioning… lots of stuff.
Original Author: Dave Hng
Assumptions
Sometimes it doesn’t update automatically, like when you enter text, sometimes the text won’t be renedered. Update the usercontrol, or reload the form to resolve the change.
Side Effects
Warning!
If you do use this code, either use the activex control, or switch on compile on demand! If you ever come up with an error message that reads something like VB cannot read a temp file, close VB immediately without saving, and load it up again.
Seems there’s as glitch in VB, if you write code that pops up an error, and you use a usercontrol that needs to execute to work, VB can loose project data! Be extremely cautious about this!
(I have compiled it to an activex control, and stuck it in a zip file if anyone wants to be safe)
Tooltips don’t work with this control too, due to the way it works.
API Declarations
(see code below)
Code
'
' Instead of doing a very big cut and paste job, you can download this control
' as source code, and compiled to an activex control in this zip file:
'
' http://users.wantree.com.au/~paulhng/files/cSFCoolbutton.zip
'
' Details of the properties and such are in the readme included in the zip file.
'
' It's 31kb, and could save a lot of headaches piecing it together again :)
'
' If you are unfamiliar with UserControls, or are working on a mission critical
' application, i don't recommend you using the UserControl, unless you
' definately know what you're doing (and can understand the code entirely).
'
' Note: This code comes completely unwarranted. If it does damage in any way,
' i am not responsible. If you use this code, you agree to these terms.
'
' Cut and paste beginning at "VERSION 5.00" to the end, and save
' it as cSFCoolButton.ctl.
' Then load it up in VB, and everything should work fine:
'
'
' Enjoy!
' [ I hope the code formatter here doesn't screw it up too much :) ]
VERSION 5.00
Begin VB.UserControl cSfCb
AutoRedraw = -1 'True
ClientHeight = 1395
ClientLeft = 0
ClientTop = 0
ClientWidth = 2205
FillStyle = 0 'Solid
BeginProperty Font
Name = "Arial"
Size = 8.25
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
FontTransparent = 0 'False
ForeColor = &H00FFFFFF&
KeyPreview = -1 'True
ScaleHeight = 93
ScaleMode = 3 'Pixel
ScaleWidth = 147
End
Attribute VB_Name = "cSfCb"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
'----------------------------------------------------------
' CoolButton control, ver 2.2
'
' (C) Dave Hng '99 ryuunosuke@earthcorp.com
'
' http://www.earthcorp.com/ryuunosuke/
'----------------------------------------------------------
'
'A lot nicer with regards to system resources and CPU time,
'using SetCapture and ReleaseCapture instead of a timer,
'though a lot more confusing, especially the DrawBevel sub. :)
'
'Files for this usercontrol:
'----------------------------------------------------------
'cSfCoolButton.ctl
'
'Nothing else! Add it, and off you go!
'
'Known problems:
'----------------------------------------------------------
'Tooltips don't agree with SetCapture, it doesn't display them.
' -Can be rectified through subclassing, but that's a lot of work.
'Bevels are not drawn when in design mode, because i don't want to change lots of subs and functions.
' -it works, i'm not going to break it again.. :)
'Never name a property TextFont, it won't work for some reason.. :P
' -Causes problems, property is never saved.. odd.
'AutoDim doesn't work all the time
' -Don't know why.
'----------------------------------------------------------
'You shouldn't need to modify anything below here...
'(You shouldn't need to modify anything at all.. :) )
Option Explicit
'Constants for AutoDim.
Private Const csDimPercent As Single = 0.9 'Dim to 90%
Private Const csBriPercent As Single = 1.2 'Brighten to 120%
Private Const cbMaxValue As Byte = 255 'Max value for a byte
'API Declares
'----------------------------------------------------------
Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectPalette Lib "gdi32" (ByVal hdc As Long, ByVal hPalette As Long, ByVal bForceBackground As Long) As Long
Private Declare Function RealizePalette Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hdc As Long) As Long
Private Declare Function CreateHalftonePalette Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
Private Declare Function SetTextAlign Lib "gdi32" (ByVal hdc As Long, ByVal wFlags As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'You might like to use this function instead of CreateCompatibleBitmap, if it doesn't work for some reason.
'Private Declare Function CreateDiscardableBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Type BITMAPINFOHEADER '40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Private Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As RGBQUAD
End Type
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
'Constants for API calls
'----------------------------------------------------------
Private Const TA_CENTER = 6
Private Const TA_LEFT = 0
Private Const TA_RIGHT = 2
Private Const TA_BASELINE = 24
Private Const DT_BOTTOM = &H8
Private Const DT_CALCRECT = &H400
Private Const DT_CENTER = &H1
Private Const DT_EXPANDTABS = &H40
Private Const DT_EXTERNALLEADING = &H200
Private Const DT_LEFT = &H0
Private Const DT_NOCLIP = &H100
Private Const DT_NOPREFIX = &H800
Private Const DT_RIGHT = &H2
Private Const DT_SINGLELINE = &H20
Private Const DT_TABSTOP = &H80
Private Const DT_TOP = &H0
Private Const DT_VCENTER = &H4
Private Const DT_WORDBREAK = &H10
Private Const TRANSPARENT = 1
Private Const BI_RGB = 0&
Private Const DIB_RGB_COLORS = 0& ' color table in RGBs
'TypeDef Structs that this control uses
'----------------------------------------------------------
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Enum eBevelType
'----------------------------------------------------------
'Do not change these values, they are set for specific reasons,
'as i do some bit operations on them to change settings.
'It works like this, each value is two bits:
'
' 1 1
' Mouse Up or Down Mouse in area?
' -0 if Up, 1 if Down -0 if Out, 1 if In
'
'Heh, and you thought VB programmers never knew what bits were.. :)
'----------------------------------------------------------
UpIn = 1
DownIn = 3
UpOut = 0
DownOut = 2
End Enum
'Bevel width constant
Private Const ciBevelWidth As Integer = 1
Public Enum eVTextPosition
cTop = 0
cMiddle = 1
cBottom = 2
c3Quarters = 3
End Enum
Public Enum eHTextPosition
ciLeft = 0
ciCenter = 1
ciRight = 2
End Enum
'Property variables
Private bLoaded As Boolean
Private bUnderlineFocus As Boolean
Private bUsePictures As Boolean
Private bUseBevels As Boolean
Private bDipControls As Boolean
Private iBevelType As eBevelType
Private bDeviated As Boolean
Private iInitialScaleMode As Integer
Private bAutoSize As Boolean
Private sCaption As String
Private bEnabled As Boolean
Private bButtonsAlwaysUp As Boolean
Private bAutoDim As Boolean
Private lvTextPosition As Long
Private lhTextPosition As Long
Private bAutoColour As Boolean
Private hMouseOverBitmap As Long
Private hMouseDownBitmap As Long
'Pictures
Private picNormal As StdPicture
Private picMouseOver As StdPicture
Private picMouseDown As StdPicture
'Colours!
Private colour_Highlight As OLE_COLOR
Private colour_LowLight As OLE_COLOR
Private colour_BackColour As OLE_COLOR
Private colour_TextStdColour As OLE_COLOR
Private colour_TextOverColour As OLE_COLOR
Private colour_Ignore As OLE_COLOR
'Working variables
Private ti As Integer
Private ti2 As Integer
Private bClick As Boolean
Private bMouseDowned As Boolean
'Events
'----------------------------------------------------------
Public Event Click()
Public Event MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
Public Event MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Public Event MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
Public Event MouseEnter()
Public Event MouseExit()
Private Sub AutoSizeControl()
Dim result As Long, bmp As BITMAP
'Find bitmap's dimensions. I don't know what picture
'object width and height is measured in... something weird.
result = GetObject(picNormal.Handle, Len(bmp), bmp)
UserControl.ScaleMode = vbPixels
'Leave room for bevels if needed
If bUseBevels Then
UserControl.Height = (bmp.bmHeight + 2) * Screen.TwipsPerPixelY
UserControl.Width = (bmp.bmWidth + 2) * Screen.TwipsPerPixelX
Else
UserControl.Height = bmp.bmHeight * Screen.TwipsPerPixelY
UserControl.Width = bmp.bmWidth * Screen.TwipsPerPixelX
End If
End Sub
Private Sub DrawBevel(ByVal nBevelType As Integer)
On Error GoTo ErrorHandler
'Exit this sub if things aren't loaded, otherwise trouble will arise
If Not bLoaded Then Exit Sub
'Manual bitmap drawing, and text output!
'Sheesh, what a waste of time :)
'You can't use image and label controls, because they receive
'mouse events, rather than the control, which messes things up.
'------------------------------------------------------------------
Dim result As Long, ts As String
Dim picDraw As StdPicture
Dim hBitmapHack As Long
Dim bInnerBevel As Boolean
Dim bBevel As Boolean
UserControl.ScaleMode = vbPixels
UserControl.Cls
'Set vars appropriately
'------------------------------------------------------------------
Select Case nBevelType
Case DownOut
bInnerBevel = True
bBevel = True
If bUsePictures Then Set picDraw = picNormal
UserControl.ForeColor = colour_TextStdColour
hBitmapHack = picNormal.Handle
Case DownIn
bInnerBevel = True
bBevel = True
If bUsePictures Then Set picDraw = picMouseDown
UserControl.ForeColor = colour_TextOverColour
hBitmapHack = hMouseDownBitmap
Case UpIn
DrawUp:
UserControl.Cls
bInnerBevel = False
bBevel = bUseBevels
If (bUsePictures And Not (picMouseOver Is Nothing)) Then Set picDraw = picMouseOver
UserControl.ForeColor = colour_TextOverColour
hBitmapHack = hMouseOverBitmap
Case UpOut
If bButtonsAlwaysUp Then GoTo DrawUp
bBevel = False
UserControl.Cls
If bUsePictures Then Set picDraw = picNormal
UserControl.ForeColor = colour_TextStdColour
hBitmapHack = picNormal.Handle
End Select
'Check in case there's no picture, if not, bail.
If picDraw Is Nothing Then Set picDraw = picNormal
If picDraw.Handle = 0 Then Exit Sub
'This next part draws the image and text to the usercontrol
'I seriously hope there are no memory leaks here.
'------------------------------------------------------------------
Dim dcDesktop As Long, palHalfTone As Long
Dim dcTemp As Long, palOld As Long
Dim bmpOld As Long, bmp As BITMAP, rt As RECT
Dim XPos As Long, YPos As Long
Dim oldTextAlign As Long
Dim oldTextDrawMode As Long
'Create a halftone palette to dither to, if needed.
palHalfTone = CreateHalftonePalette(UserControl.hdc)
'Create off screen DC to draw to
dcDesktop = GetDC(ByVal 0&)
dcTemp = CreateCompatibleDC(dcDesktop)
palOld = SelectPalette(dcTemp, palHalfTone, True)
RealizePalette dcTemp
'Associate picture with dc, including self generated dimmed bitmaps
If bAutoDim Then
bmpOld = SelectObject(dcTemp, hBitmapHack)
Else
bmpOld = SelectObject(dcTemp, picDraw.Handle)
End If
'Blit picture to usercontrol's center
result = GetObject(picDraw.Handle, Len(bmp), bmp)
XPos = UserControl.ScaleWidth / 2 - bmp.bmWidth / 2
YPos = UserControl.ScaleHeight / 2 - bmp.bmHeight / 2
BitBlt UserControl.hdc, XPos, YPos, XPos + picDraw.Width, YPos + picDraw.Height, dcTemp, 0, 0, vbSrcCopy
'Clean up
GoSub CleanUp
'------------------------------------------------------------------
DrawText:
'Since TextOut won't align, and DrawText doesn't work :P,
'combine both to make something that does! :)
'Use DrawText to return the text's height, and textout accordingly!
'------------------------------------------------------------------
If bUseBevels And bBevel Then
If bInnerBevel Then
FormInnerBevel
Else
FormOuterBevel
End If
End If
'Set transparent text rendering
oldTextDrawMode = SetBkMode(UserControl.hdc, TRANSPARENT)
'Find out the bounds of the usercontrol's rectangle
result = GetWindowRect(UserControl.hWnd, rt)
'Asks DrawText to calculate the height of the text, stick it in result
result = DrawText(UserControl.hdc, sCaption, Len(sCaption), rt, DT_CALCRECT)
Select Case lhTextPosition
Case ciLeft
XPos = 1
oldTextAlign = SetTextAlign(UserControl.hdc, TA_LEFT)
Case ciCenter
XPos = UserControl.ScaleWidth / 2
oldTextAlign = SetTextAlign(UserControl.hdc, TA_CENTER)
Case ciRight
XPos = UserControl.ScaleWidth - 1
oldTextAlign = SetTextAlign(UserControl.hdc, TA_RIGHT)
End Select
Select Case lvTextPosition
Case cTop
YPos = 1
Case cBottom
YPos = UserControl.ScaleHeight - result - 1
Case cMiddle
YPos = UserControl.ScaleHeight / 2 - result / 2
Case c3Quarters
YPos = UserControl.ScaleHeight * (3 / 4) - result / 2 - 1
End Select
result = TextOut(UserControl.hdc, XPos, YPos, sCaption, Len(sCaption))
'Put back the old text alignment style
SetTextAlign UserControl.hdc, oldTextAlign
'Put back the old text drawing mode
SetBkMode UserControl.hdc, oldTextDrawMode
'Ask the control to repaint itself, since i've changed it's looks.
UserControl.Refresh
Exit Sub
'Error handling
'If we hit an error 91, which will usually mean that picview didn't
'point to anything, skip blitting image, render text.
'------------------------------------------------------------------
ErrorHandler:
If Err.Number = 91 Then GoTo DrawText: GoSub CleanUp: Exit Sub
MsgBox "Error in Coolbutton UserControl, DrawBevel sub!" & vbCrLf & CStr(Err.Number) & vbCrLf & Err.Description, vbCritical, "Error!"
GoSub CleanUp
Exit Sub
Resume Next
'Frees objects and memory
'------------------------------------------------------------------
CleanUp:
SelectObject dcTemp, bmpOld
SelectPalette dcTemp, palOld, True
RealizePalette dcTemp
DeleteDC dcTemp
ReleaseDC ByVal 0&, dcDesktop
DeleteObject palHalfTone
Return
End Sub
Public Sub ForceRedraw()
DrawBevel iBevelType
End Sub
Private Sub FormBevelLines(ByVal side As Integer, ByVal wid As Integer, ByVal Color As Long)
'This is from www.planet-source-code.com's extensive vb code
'library.
'Unfortunately, the code would never cut and paste right for me,
'so i've forgotten the author's name.
Dim x1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer
Dim rightX As Integer, bottomY As Integer
Dim dx1 As Integer, dx2 As Integer, dy1 As Integer, dy2 As Integer
Dim i As Integer
rightX = UserControl.ScaleWidth - 1
bottomY = UserControl.ScaleHeight - 1
Select Case side
Case 0
'Left side
x1 = 0
dx1 = 1
X2 = 0
dx2 = 1
Y1 = 0
dy1 = 1
Y2 = bottomY + 1
dy2 = -1
Case 1
'Right side
x1 = rightX
dx1 = -1
X2 = x1
dx2 = dx1
Y1 = 0
dy1 = 1
Y2 = bottomY + 1
dy2 = -1
Case 2
'Top side
x1 = 0
dx1 = 1
X2 = rightX
dx2 = -1
Y1 = 0
dy1 = 1
Y2 = 0
dy2 = 1
Case 3
'Bottom side
x1 = 1
dx1 = 1
X2 = rightX + 1
dx2 = -1
Y1 = bottomY
dy1 = -1
Y2 = Y1
dy2 = dy1
End Select
For i = 1 To wid
UserControl.Line (x1, Y1)-(X2, Y2), Color
x1 = x1 + dx1
X2 = X2 + dx2
Y1 = Y1 + dy1
Y2 = Y2 + dy2
Next i
End Sub
Private Sub FormOuterBevel()
UserControl.ScaleMode = vbPixels
FormBevelLines 0, ciBevelWidth, colour_Highlight
FormBevelLines 1, ciBevelWidth, colour_LowLight
FormBevelLines 2, ciBevelWidth, colour_Highlight
FormBevelLines 3, ciBevelWidth, colour_LowLight
End Sub
Private Sub FormInnerBevel()
UserControl.ScaleMode = vbPixels
FormBevelLines 0, ciBevelWidth, colour_LowLight
FormBevelLines 1, ciBevelWidth, colour_Highlight
FormBevelLines 2, ciBevelWidth, colour_LowLight
FormBevelLines 3, ciBevelWidth, colour_Highlight
End Sub
Private Sub FreeDimmedBitmaps()
If hMouseOverBitmap Then DeleteObject hMouseOverBitmap: hMouseOverBitmap = 0
If hMouseDownBitmap Then DeleteObject hMouseDownBitmap: hMouseDownBitmap = 0
End Sub
Private Sub GenerateDimmedPictures()
If picNormal Is Nothing Then Exit Sub
'i hope there's no bugs here!
Screen.MousePointer = vbHourglass
DoEvents
'Declare variables
Dim Quads() As RGBQUAD, LongColours() As Long
Dim result As Long, bmp As BITMAP
Dim lSize As Long
Dim i As Long
Dim hTempDC As Long
Dim oldBitmap As Long
Dim bmpinfo As BITMAPINFO
Dim ti As Integer
Dim tCol As Long
Dim srcPtr As Long, dstPtr As Long
Dim colIgnore As Long
'VB stores colours in a differnet order of what windows does.
'which is hell annoying. Alignment and order is different, so
'i have to rearrange to get it right.
colIgnore = CLng(colour_Ignore)
Dim bArray1(3) As Byte
Dim bArray2(3) As Byte
srcPtr = VarPtr(colIgnore)
dstPtr = VarPtr(bArray1(0))
CopyMemory ByVal dstPtr, ByVal srcPtr, Len(colIgnore)
bArray2(0) = bArray1(2)
bArray2(1) = bArray1(1)
bArray2(2) = bArray1(0)
bArray2(3) = 0
srcPtr = VarPtr(bArray2(0))
dstPtr = VarPtr(colIgnore)
CopyMemory ByVal dstPtr, ByVal srcPtr, Len(colIgnore)
'ColIgnore has the colour to ignore in API nice terms.
'Get the bitmap's dimensions
result = GetObject(picNormal.Handle, Len(bmp), bmp)
'Find out the size of the array i need
lSize = bmp.bmWidth * bmp.bmHeight
'Make a DC so i can use GetDIBits, SetDIBits
hTempDC = CreateCompatibleDC(ByVal 0&)
'Select the bitmap to the DC
oldBitmap = SelectObject(hTempDC, picNormal.Handle)
'Alloc mem
ReDim Quads(lSize)
ReDim LongColours(lSize)
'Create info struct, to read raw data in RGB format
'Asking for the data in RLE format might be a lot faster to
'process, there's an idea for a speedup.
With bmpinfo.bmiHeader
.biSize = Len(bmpinfo.bmiHeader)
.biWidth = bmp.bmWidth
.biHeight = bmp.bmHeight
.biPlanes = bmp.bmPlanes
.biBitCount = 32
.biCompression = BI_RGB
End With
'Get the data, in Quad and Long form.
result = GetDIBits(hTempDC, picNormal.Handle, 0&, bmp.bmHeight, Quads(0), bmpinfo, DIB_RGB_COLORS)
result = GetDIBits(hTempDC, picNormal.Handle, 0&, bmp.bmHeight, LongColours(0), bmpinfo, DIB_RGB_COLORS)
'Decrease brightness of the bitmap
For i = LBound(Quads, 1) To UBound(Quads, 1)
If Not LongColours(i) = colIgnore Then
With Quads(i)
.rgbBlue = .rgbBlue * csDimPercent
.rgbGreen = .rgbGreen * csDimPercent
.rgbRed = .rgbRed * csDimPercent
End With
End If
Next i
'Delete any bitmap if already created
If hMouseDownBitmap Then DeleteObject hMouseDownBitmap
'Create a bitmap
hMouseDownBitmap = CreateCompatibleBitmap(UserControl.hdc, bmp.bmWidth, bmp.bmHeight)
'Select new bitmap
result = SelectObject(hTempDC, hMouseDownBitmap)
'Write bits to it
result = SetDIBits(hTempDC, hMouseDownBitmap, 0, bmp.bmHeight, Quads(0), bmpinfo, DIB_RGB_COLORS)
'Part 1 done.
'------------------------------------------------------------------
'Select original image
SelectObject hTempDC, picNormal.Handle
'Get original data again
result = GetDIBits(hTempDC, picNormal.Handle, 0, bmp.bmHeight, Quads(0), bmpinfo, DIB_RGB_COLORS)
'Brighten, watching for overflows
For i = LBound(Quads, 1) To UBound(Quads, 1)
If Not LongColours(i) = colIgnore Then
With Quads(i)
ti = .rgbBlue * csBriPercent
If ti < cbMaxValue Then
.rgbBlue = ti
Else
.rgbBlue = cbMaxValue
End If
ti = .rgbGreen * csBriPercent
If ti < cbMaxValue Then
.rgbGreen = ti
Else
.rgbGreen = cbMaxValue
End If
ti = .rgbRed * csBriPercent
If ti < cbMaxValue Then
.rgbRed = ti
Else
.rgbRed = cbMaxValue
End If
End With
End If
Next i
'Delete old bitmap if present
If hMouseOverBitmap Then DeleteObject hMouseOverBitmap
'Create new bitmap
hMouseOverBitmap = CreateCompatibleBitmap(UserControl.hdc, bmp.bmWidth, bmp.bmHeight)
'Select bitmap to DC
SelectObject hTempDC, hMouseOverBitmap
'Copy data over
result = SetDIBits(hTempDC, hMouseOverBitmap, 0, bmp.bmHeight, Quads(0), bmpinfo, DIB_RGB_COLORS)
'Part 2 done
'------------------------------------------------------------------
DoEvents
'Clean up
'------------------------------------------------------------------
'Dealloc memory
Erase Quads()
Erase LongColours
'Select back old bitmap
SelectObject hTempDC, oldBitmap
'Delete the DC
result = DeleteDC(hTempDC)
Screen.MousePointer = vbNormal
End Sub
Private Function HasBackColourProperty(ByVal ctrl As Object) As Boolean
On Error GoTo ErrorHandler
Dim colourTemp As OLE_COLOR
colourTemp = ctrl.BackColor
HasBackColourProperty = True
Exit Function
ErrorHandler:
Exit Function
End Function
Private Sub UserControl_EnterFocus()
UserControl.FontUnderline = bUnderlineFocus
End Sub
Private Sub UserControl_ExitFocus()
UserControl.FontUnderline = False
If bUnderlineFocus Then
DrawBevel iBevelType
End If
End Sub
Private Sub UserControl_Initialize()
'Set initial values for variables that i can.
'----------------------------------------------------------
iBevelType = UpOut
iInitialScaleMode = UserControl.ScaleMode
colourHighlight = QBColor(15)
colourLowLight = QBColor(8)
colourBackColour = vbButtonFace
colourTextStdColour = QBColor(0)
colourTextOverColour = QBColor(1)
UseBevels = True
UsePictures = True
bDipControls = False
AutoSize = False
UseUnderlineOnFocus = True
bEnabled = True
End Sub
Private Sub UserControl_KeyDown(KeyCode As Integer, Shift As Integer)
If Not bEnabled Then Exit Sub
'Traps for spacebar, if it's pushed, then behave like a button
'----------------------------------------------------------
If KeyCode = ti2 Then Exit Sub
If KeyCode = vbKeySpace Then
ti = iBevelType
iBevelType = DownIn
DrawBevel iBevelType
UserControl.Refresh
End If
ti2 = KeyCode
End Sub
Private Sub UserControl_KeyPress(KeyAscii As Integer)
If Not bEnabled Then Exit Sub
'If enter / return 's pressed, then simulate the button going
'up, then down.
'----------------------------------------------------------
If KeyAscii = vbKeyReturn Then
Dim iPrevBeveltype
iPrevBeveltype = iBevelType
iBevelType = DownIn
DrawBevel iBevelType
UserControl.Refresh
Sleep 50
iBevelType = UpIn
DrawBevel iBevelType
UserControl.Refresh
Sleep 50
RaiseEvent Click
iBevelType = iPrevBeveltype
DrawBevel iBevelType
End If
End Sub
Private Sub UserControl_KeyUp(KeyCode As Integer, Shift As Integer)
If Not bEnabled Then Exit Sub
'Accompanying part for the KeyDown sub
'----------------------------------------------------------
If KeyCode = vbKeySpace And ti2 = vbKeySpace Then
iBevelType = UpIn
DrawBevel (iBevelType)
UserControl.Refresh
Sleep 50
RaiseEvent Click
iBevelType = ti
ti = 0
DrawBevel (iBevelType)
ti2 = 0
End If
End Sub
Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
If Not bEnabled Then Exit Sub
Dim result As Long
Dim bInArea As Boolean
bInArea = ((x >= UserControl.ScaleLeft And x <= UserControl.ScaleWidth) And (y >= UserControl.ScaleTop And y <= UserControl.ScaleHeight))
bClick = False
If Button = vbLeftButton Then
bMouseDowned = True
'Mouse down, in area
iBevelType = iBevelType Or 2
DrawBevel iBevelType
If (iBevelType = UpIn Or iBevelType = DownIn) Then
result = SetCapture(UserControl.hWnd)
End If
bClick = (iBevelType And 1 = 1)
bDeviated = True
ElseIf Button = vbRightButton Then
'Redraw with the mouse out.
'iBevelType = UpOut
'DrawBevel iBevelType
End If
If bInArea Then
RaiseEvent MouseDown(Button, Shift, x, y)
End If
End Sub
Private Sub UserControl_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
If Not bEnabled Then Exit Sub
Dim result As Long
Dim iPrevBevel As Integer
Dim bInArea As Boolean
'Bug / Glitch: VB doesn't update X and Y for a scalemode
'If you change scalemode in the sub, X and Y are not changed, ever!
UserControl.ScaleMode = iInitialScaleMode
If Button = 0 Then
iBevelType = iBevelType And 1
ElseIf Button = vbLeftButton And bMouseDowned Then
iBevelType = iBevelType Or 2
End If
iPrevBevel = iBevelType
bInArea = ((x >= UserControl.ScaleLeft And x <= UserControl.ScaleWidth) And (y >= UserControl.ScaleTop And y <= UserControl.ScaleHeight))
If bInArea Then
'Set iBevelType to reflect that the mouse is in
iBevelType = iBevelType Or 1
Else
'Set iBeveltype to reflect that the mouse is out
iBevelType = iBevelType And 2
End If
If (iBevelType And 1) Then
'Debug.Print "mouse in area"
If iPrevBevel <> iBevelType Then
DrawBevel iBevelType
'MouseEnter is raised here, only occurs once.
RaiseEvent MouseEnter
result = SetCapture(UserControl.hWnd)
End If
RaiseEvent MouseMove(Button, Shift, x, y)
Else
'I can raise the event here, because it'll only get called
'once, before the usercontrol releases capture of mouse events.
RaiseEvent MouseExit
iBevelType = UpOut
DrawBevel iBevelType
result = ReleaseCapture()
End If
End Sub
Private Sub UserControl_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
If Not bEnabled Then Exit Sub
Dim result As Long
Dim bInArea As Boolean
bInArea = ((x >= UserControl.ScaleLeft And x <= UserControl.ScaleWidth) And (y >= UserControl.ScaleTop And y <= UserControl.ScaleHeight))
'VB releases capture on mouseup somehow...,
'might be how it's coded.
If Button = vbRightButton Then
result = SetCapture(UserControl.hWnd)
End If
If Button = vbLeftButton Then
iBevelType = iBevelType And 1
DrawBevel iBevelType
result = SetCapture(UserControl.hWnd)
bDeviated = False
End If
If bClick And (iBevelType And 1 = 1) And bMouseDowned Then
bClick = False
RaiseEvent Click
End If
If bInArea Then
RaiseEvent MouseUp(Button, Shift, x, y)
End If
If Button = vbLeftButton Then result = SetCapture(UserControl.hWnd)
bMouseDowned = False
End Sub
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
Dim picTemp As StdPicture
With PropBag
Set picNormal = .ReadProperty("Picture", picTemp)
Set picMouseDown = .ReadProperty("PictureDown", picTemp)
Set picMouseOver = .ReadProperty("PictureOver", picTemp)
colourHighlight = .ReadProperty("colourHighlight", QBColor(15))
colourLowLight = .ReadProperty("colourLowlight", QBColor(8))
colourBackColour = .ReadProperty("colourBackColour", vbButtonFace)
colourTextStdColour = .ReadProperty("colourTextStdColour", QBColor(0))
colourTextOverColour = .ReadProperty("colourTextOverColour", colour_TextStdColour)
colourIgnore = .ReadProperty("colourIgnore", vbBlack)
Caption = .ReadProperty("Caption", "")
UseBevels = .ReadProperty("UseBevels", True)
UsePictures = .ReadProperty("UsePictures", True)
UseDippedControls = .ReadProperty("UseDippedControls", False)
AutoSize = .ReadProperty("AutoSize", False)
UseUnderlineOnFocus = .ReadProperty("UseUnderlineOnFocus", True)
Enabled = .ReadProperty("Enabled", True)
Set UserControl.Font = .ReadProperty("CaptionFont", UserControl.Font)
bButtonsAlwaysUp = .ReadProperty("AlwaysDrawBevel", False)
AutoDim = .ReadProperty("AutoDim", False)
TextPositionV = .ReadProperty("TextPositionV", cMiddle)
TextPositionH = .ReadProperty("TextPositionH", ciCenter)
AutoColour = .ReadProperty("AutoColour", False)
End With
UserControl.BackColor = colour_BackColour
bLoaded = True
End Sub
Private Sub UserControl_Resize()
DrawBevel iBevelType
End Sub
Private Sub UserControl_Show()
DrawBevel iBevelType
End Sub
Public Property Get Picture() As StdPicture
Set Picture = picNormal
End Property
Public Property Set Picture(ByVal pNewValue As StdPicture)
Set picNormal = pNewValue
PropertyChanged "Picture"
If bAutoSize Then AutoSizeControl
If bAutoDim Then GenerateDimmedPictures
DrawBevel iBevelType
End Property
Public Property Get PictureOver() As StdPicture
Set PictureOver = picMouseOver
End Property
Public Property Set PictureOver(ByVal pNewValue As StdPicture)
Set picMouseOver = pNewValue
PropertyChanged "PictureOver"
End Property
Public Property Get PictureDown() As StdPicture
Set PictureDown = picMouseDown
End Property
Public Property Set PictureDown(ByVal pNewValue As StdPicture)
Set picMouseDown = pNewValue
PropertyChanged "PictureDown"
End Property
Public Property Get colourHighlight() As OLE_COLOR
colourHighlight = colour_Highlight
End Property
Public Property Let colourHighlight(ByVal cNewValue As OLE_COLOR)
colour_Highlight = cNewValue
PropertyChanged "colourHighlight"
End Property
Public Property Get colourLowLight() As OLE_COLOR
colourLowLight = colour_LowLight
End Property
Public Property Let colourLowLight(ByVal cNewValue As OLE_COLOR)
colour_LowLight = cNewValue
PropertyChanged "colourLowLight"
End Property
Public Property Get colourBackColour() As OLE_COLOR
colourBackColour = colour_BackColour
End Property
Public Property Let colourBackColour(ByVal cNewValue As OLE_COLOR)
colour_BackColour = cNewValue
PropertyChanged "colourBackColour"
UserControl.BackColor = cNewValue
DrawBevel iBevelType
End Property
Public Property Get colourTextStdColour() As OLE_COLOR
colourTextStdColour = colour_TextStdColour
End Property
Public Property Let colourTextStdColour(ByVal cNewValue As OLE_COLOR)
colour_TextStdColour = cNewValue
PropertyChanged "colourTextStdColour"
DrawBevel iBevelType
End Property
Public Property Get colourTextOverColour() As OLE_COLOR
colourTextOverColour = colour_TextOverColour
End Property
Public Property Let colourTextOverColour(ByVal cNewValue As OLE_COLOR)
colour_TextOverColour = cNewValue
PropertyChanged "colourTextOverColour"
End Property
Private Sub UserControl_Terminate()
FreeDimmedBitmaps
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Dim picTemp As StdPicture, fntTemp As Font
With PropBag
.WriteProperty "CaptionFont", UserControl.Font, fntTemp
.WriteProperty "Picture", picNormal, picTemp
.WriteProperty "PictureDown", picMouseDown, picTemp
.WriteProperty "PictureOver", picMouseOver, picTemp
.WriteProperty "colourHighlight", colour_Highlight, QBColor(15)
.WriteProperty "colourLowlight", colour_LowLight, QBColor(8)
.WriteProperty "colourBackColour", colour_BackColour, &H8000000F
.WriteProperty "colourTextStdColour", colour_TextStdColour, QBColor(0)
.WriteProperty "colourTextOverColour", colour_TextOverColour, colour_TextStdColour
.WriteProperty "colourIgnore", colourIgnore, vbBlack
.WriteProperty "Caption", sCaption, ""
.WriteProperty "UseBevels", UseBevels, True
.WriteProperty "UsePictures", UsePictures, True
.WriteProperty "UseDippedControls", UseDippedControls, False
.WriteProperty "AutoSize", AutoSize, False
.WriteProperty "Enabled", Enabled, True
.WriteProperty "UseUnderlineOnFocus", UseUnderlineOnFocus, True
.WriteProperty "AlwaysDrawBevel", bButtonsAlwaysUp, False
.WriteProperty "AutoDim", AutoDim, False
.WriteProperty "TextPositionV", TextPositionV, cMiddle
.WriteProperty "TextPositionH", TextPositionH, ciCenter
.WriteProperty "AutoColour", AutoColour, False
End With
End Sub
Public Property Get Caption() As String
Caption = sCaption
End Property
Public Property Let Caption(ByVal sNewValue As String)
sCaption = sNewValue
PropertyChanged "Caption"
Dim i As Integer, ts As String
i = InStr(1, sNewValue, "&", vbBinaryCompare)
If i <> 0 And i <> Len(sNewValue) Then
ts = Mid$(sNewValue, i + 1, 1)
UserControl.AccessKeys = ts
End If
DrawBevel iBevelType
End Property
Public Property Get UsePictures() As Boolean
UsePictures = bUsePictures
End Property
Public Property Let UsePictures(ByVal bNewValue As Boolean)
bUsePictures = bNewValue
PropertyChanged "UsePictures"
DrawBevel iBevelType
End Property
Public Property Get UseBevels() As Boolean
UseBevels = bUseBevels
End Property
Public Property Let UseBevels(ByVal bNewValue As Boolean)
bUseBevels = bNewValue
PropertyChanged "UseBevels"
DrawBevel iBevelType
End Property
Public Property Get UseDippedControls() As Boolean
UseDippedControls = bDipControls
End Property
Public Property Let UseDippedControls(ByVal bNewValue As Boolean)
bDipControls = bNewValue
PropertyChanged "UseDippedControls"
End Property
Public Property Get AutoSize() As Boolean
AutoSize = bAutoSize
End Property
Public Property Let AutoSize(ByVal bNewValue As Boolean)
bAutoSize = bNewValue
PropertyChanged "AutoSize"
If bAutoSize Then AutoSizeControl
End Property
Public Property Get UseUnderlineOnFocus() As Boolean
UseUnderlineOnFocus = bUnderlineFocus
End Property
Public Property Let UseUnderlineOnFocus(ByVal bNewValue As Boolean)
bUnderlineFocus = bNewValue
PropertyChanged "UseUnderlineOnFocus"
End Property
Public Property Get CaptionFont() As Font
Set CaptionFont = UserControl.Font
End Property
Public Property Set CaptionFont(ByVal fNewValue As Font)
Set UserControl.Font = fNewValue
PropertyChanged "CaptionFont"
DrawBevel iBevelType
End Property
Public Property Get Enabled() As Boolean
Enabled = bEnabled
End Property
Public Property Let Enabled(ByVal bNewValue As Boolean)
bEnabled = bNewValue
PropertyChanged "Enabled"
End Property
Public Property Get hWnd() As Long
hWnd = UserControl.hWnd
End Property
Public Property Let hWnd(ByVal lnewValue As Long)
'Do nothing
End Property
Public Property Get AlwaysDrawBevel() As Boolean
AlwaysDrawBevel = bButtonsAlwaysUp
End Property
Public Property Let AlwaysDrawBevel(ByVal bNewValue As Boolean)
bButtonsAlwaysUp = bNewValue
PropertyChanged "AlwaysDrawBevel"
ForceRedraw
End Property
Public Property Get AutoDim() As Boolean
AutoDim = bAutoDim
End Property
Public Property Let AutoDim(ByVal bNewValue As Boolean)
bAutoDim = bNewValue
PropertyChanged "AutoDim"
If bAutoDim Then
If Ambient.UserMode Then GenerateDimmedPictures
Else
FreeDimmedBitmaps
End If
End Property
Public Property Get TextPositionV() As eVTextPosition
TextPositionV = lvTextPosition
End Property
Public Property Let TextPositionV(ByVal iNewValue As eVTextPosition)
lvTextPosition = iNewValue
PropertyChanged "TextPositionV"
DrawBevel iBevelType
End Property
Public Property Get TextPositionH() As eHTextPosition
TextPositionH = lhTextPosition
End Property
Public Property Let TextPositionH(ByVal iNewValue As eHTextPosition)
lhTextPosition = iNewValue
PropertyChanged "TextPositionH"
DrawBevel iBevelType
End Property
Public Property Get colourIgnore() As OLE_COLOR
colourIgnore = colour_Ignore
End Property
Public Property Let colourIgnore(ByVal cNewValue As OLE_COLOR)
colour_Ignore = cNewValue
PropertyChanged "colourIgnore"
End Property
Public Property Get AutoColour() As Boolean
AutoColour = bAutoColour
End Property
Public Property Let AutoColour(ByVal bNewValue As Boolean)
Static bUsingOldColour As Boolean
Static colourOld As OLE_COLOR
If HasBackColourProperty(UserControl.Extender.Container) Then
If bNewValue Then
colourOld = colourBackColour
colourBackColour = UserControl.Extender.Container.BackColor
bUsingOldColour = True
Else
If bUsingOldColour Then colourBackColour = colourOld
End If
bAutoColour = bNewValue
PropertyChanged "AutoColour"
Else
bNewValue = False
bAutoColour = False
VBA.MsgBox "Sorry, AutoColour can't be changed, because the container doesn't support a BackColor property!", vbExclamation
End If
End Property