📄 morphlcd.ctl
字号:
Private m_SegmentLitColor As OLE_COLOR ' the color of displayed (non burn-in) segments.
Private m_SegmentLitColorNeg As OLE_COLOR ' lit segment color when value is negative.
Private m_SegmentStyle As SegmentStyleOptions ' hexagonal, trapezoidal, or rectangular segments.
Private m_SegmentStyleExp As SegmentStyleOptions ' hexagonal, trapezoidal, or rectangular segments.
Private m_SegmentWidth As Long ' # of pixels in short dimension of main value segment.
Private m_SegmentWidthExp As Long ' # of pixels in short dimension of exponent segment.
Private m_ShowBurnIn As Boolean ' if True, simulated digit 'burn-in' is displayed.
Private m_ShowExponent As Boolean ' if True, exponent portion of value is shown.
Private m_ShowThousandsSeparator As Boolean ' display thousands separator? boolean.
Private m_Theme As LCDThemeOptions ' user-definable and selectable display theme.
Private m_ThousandsGrouping As Long ' how many digits between thousands separators.
Private m_ThousandsSeparator As SeparatorOptions ' thousands separator character ("," in U.S.).
Private m_Value As String ' the value to be displayed.
Private m_XOffset As Long ' # of pixels from left to display main value.
Private m_XOffsetExp As Long ' # of pixels from left to display exponent.
Private m_YOffset As Long ' # of pixels from top to display main value.
Private m_YOffsetExp As Long ' # of pixels from top to display exponent.
' declares for virtual background bitmap.
Private VirtualBackgroundDC As Long ' handle of the created DC.
Private mMemoryBitmap As Long ' Handle of the created bitmap.
Private mOrginalBitmap As Long ' used in destroying virtual DC.
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Events >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Private Sub UserControl_Initialize()
'*************************************************************************
'* initializes variables at the start of the control's existence. *
'*************************************************************************
' initialize the display patterns for the LCD segments. Segment
' positions on the 7-segment LCD start with #1 on top, go clockwise.
' The center segment is #7. A "1" means the segment is lit.
DisplayPattern(0) = "1111110" ' zero.
DisplayPattern(1) = "0110000" ' one.
DisplayPattern(2) = "1101101" ' two.
DisplayPattern(3) = "1111001" ' three.
DisplayPattern(4) = "0110011" ' four.
DisplayPattern(5) = "1011011" ' five.
DisplayPattern(6) = "1011111" ' six.
DisplayPattern(7) = "1110000" ' seven.
DisplayPattern(8) = "1111111" ' eight.
DisplayPattern(9) = "1111011" ' nine.
DisplayPattern(10) = "0000000" ' for display of 'burn-in' unused digits.
DisplayPattern(11) = "0000001" ' minus sign.
DisplayPattern(12) = "1110111" ' Hex "A".
DisplayPattern(13) = "0011111" ' Hex "b". (have to do it lowercase so as not to confuse it with "8".)
DisplayPattern(14) = "1001110" ' Hex "C".
DisplayPattern(15) = "0111101" ' Hex "d". (have to do it lowercase so as not to confuse it with "0".)
DisplayPattern(16) = "1001111" ' Hex "E".
DisplayPattern(17) = "1000111" ' Hex "F".
' initialize the decimal separator location to 'no decimal separator'.
DecimalSeparatorPos.x = -1
' initialize the colon location to 'no colon'.
ColonPos.TopPoint.x = -1
End Sub
Private Sub UserControl_Resize()
'*************************************************************************
'* just used in design mode at the moment. *
'*************************************************************************
CalculateBackGroundGradient
RedrawControl
End Sub
Private Sub UserControl_Show()
'*************************************************************************
'* dimension the thousands flag to match size of .NumDigits property. *
'*************************************************************************
ReDim ThousandsFlag(0 To m_NumDigits - 1)
' for showing the control when placed on form in design mode.
If Not Ambient.UserMode Then
InitLCDDisplayCharacteristics
RedrawControl
End If
End Sub
Private Sub UserControl_Terminate()
'*************************************************************************
'* destroys all active objects and regions prior to control termination. *
'*************************************************************************
Dim i As Long ' loop variable.
' delete digit segment region objects.
For i = 0 To 9
DeleteObject LCDSegment(i)
DeleteObject LCDSegmentExp(i)
Next i
' delete digit segment color brushes.
DeleteObject LCDLitColorBrush
DeleteObject LCDBurnInColorBrush
DeleteObject LCDLitColorBrushNeg
DeleteObject LCDBurnInColorBrushNeg
' destroy the virtual DC's used in background storage.
DestroyVirtualDC
DestroyPattern
End Sub
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Graphics >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Private Sub DisplayValue(sValue As String, ByVal ForceDisplay As Boolean)
'*************************************************************************
'* displays the value stored in the .Value property. The 'ForceDisplay' *
'* parameter is used to force a redisplay when a property is changed. *
'*************************************************************************
Dim sMainValue As String ' non-exponential, main value.
Dim sExponentValue As String ' up to n_NumDigitsExp long exponent (including sign).
Dim IsBase10 As Boolean ' not using this function return value now.
' just in case, so exponent "E" and hex digits get processed correctly.
sValue = UCase(sValue)
' a catch for if there isn't a 0 in front of the decimal separator in a
' fractional value. (That won't happen if control is used correctly.)
If Left(sValue, 1) = "." Then
sValue = "0" & sValue
End If
' determine the color brush to use when displaying the value.
If Val(sValue) < 0 Then
' value is negative; use negative value color brushes.
CurrentLitColorBrush = LCDLitColorBrushNeg
CurrentBurnInColorBrush = LCDBurnInColorBrushNeg
' a word about the PreviousNegative stuff... Normally individual display digits are drawn
' only if the digit has changed from the previous displayed digit in the same position.
' This saves a great deal of time in my timing tests. However, when the sign is changed
' when a new value is displayed, we have to force a redraw of every digit, even if they're
' the same as in previous display. That way a displayed value can't be a mishmash of
' positive and negative value colors.
If Not PreviousNegative Then
PreviousMainValue = String(m_NumDigits, "X")
PreviousExponentValue = String(m_NumDigitsExp, "X")
End If
PreviousNegative = True
Else
' value is positive; use regular (positive number) color brushes.
CurrentLitColorBrush = LCDLitColorBrush
CurrentBurnInColorBrush = LCDBurnInColorBrush
If PreviousNegative Then
PreviousMainValue = String(m_NumDigits, "X")
PreviousExponentValue = String(m_NumDigitsExp, "X")
End If
PreviousNegative = False
End If
' separate possible exponent from overall value.
IsBase10 = SeparateMainValueAndExponent(sValue, sMainValue, sExponentValue)
' display the main value, and also the exponent if permitted by the ShowExponent property.
DisplayMainValue sMainValue, ForceDisplay
If m_ShowExponent Then
DisplayExponentValue sExponentValue, ForceDisplay
End If
End Sub
Private Function SeparateMainValueAndExponent(ByVal sValue As String, ByRef sMainValue As String, ByRef ExponentValue As String) As Boolean
'*************************************************************************
'* if it's an exponential base-10 number, separates the exponent and the *
'* main value. Otherwise returns the value and spaces for exponent. *
'*************************************************************************
Dim ExpPos As Long ' position in value of exponent symbols E+ or E-.
Dim ExponentSign As String ' what sign the exponent is (+ or -).
If InStr(sValue, "E+") > 0 Or InStr(sValue, "E-") > 0 Then
' since we see an "E" followed by a "+" or "-" we know it's the base-10
' exponent "E", not hex "E". Separate the main value and exponent.
ExpPos = InStr(sValue, "E+")
If ExpPos = 0 Then
ExpPos = InStr(sValue, "E-")
End If
sMainValue = Left(sValue, ExpPos - 1)
ExponentSign = Mid(sValue, ExpPos + 1, 1)
ExponentValue = Right(sValue, Len(sValue) - ExpPos - 1)
' grab appropriate part of exponent depending on whether
' we're displaying calculation result exponent or seconds.
If InStr(sValue, ":") = 0 Then
ExponentValue = Right(String(m_NumDigitsExp - 1, "0") & ExponentValue, m_NumDigitsExp - 1)
Else
ExponentValue = Right(String(m_NumDigitsExp - 1, "0") & ExponentValue, m_NumDigitsExp)
End If
If ExponentSign = "-" Then
ExponentValue = ExponentSign & ExponentValue
Else
ExponentValue = " " & ExponentValue
End If
SeparateMainValueAndExponent = True
Else
' could be hex, or a non-exponential decimal value. Just return the original value.
sMainValue = sValue
ExponentValue = String(m_NumDigitsExp, " ")
End If
End Function
Private Sub DisplayMainValue(strValue As String, ByVal ForceDisplay As Boolean)
'*************************************************************************
'* displays non-exponent portion of value stored in .Value property. *
'*************************************************************************
Dim s As String ' right-justified version of value.
Dim i As Long ' loop variable.
Dim CurrentDigit As String ' the current digit being displayed.
s = strValue
' determine thousands separator placement, if they are to be displayed.
If m_ShowThousandsSeparator Then
DetermineThousandsSeparatorPlacement s
DisplayThousandsSeparators
End If
' erase old decimal separator if displayed; display new one if necessary.
ProcessDecimalSeparator s
' erase old colon if displayed; display new one if necessary.
ProcessColon s
' pad the value with leading spaces.
s = Right(Space(m_NumDigits) & s, m_NumDigits)
' display the main value. Only draw a digit if the particular digit being
' drawn is different from digit the previous time value was displayed.
Select Case m_SegmentStyle
Case [Hexagonal]
For i = 1 To m_NumDigits
CurrentDigit = Mid(s, i, 1)
If (CurrentDigit <> Mid(PreviousMainValue, i, 1)) Or ForceDisplay Then
DisplayHexagonalSegmentDigit CurrentDigit, LCDSegment(), _
DigitXPos(i - 1), m_YOffset, _
m_SegmentHeight, m_SegmentWidth, _
m_InterSegmentGap, DigitWidth, DigitHeight
End If
Next i
Case [Trapezoidal]
For i = 1 To m_NumDigits
CurrentDigit = Mid(s, i, 1)
If (CurrentDigit <> Mid(PreviousMainValue, i, 1)) Or ForceDisplay Then
DisplayTrapezoidalSegmentDigit CurrentDigit, LCDSegment(), _
DigitXPos(i - 1), m_YOffset, _
m_SegmentHeight, m_SegmentWidth, _
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -