|
|
@@ -0,0 +1,877 @@
|
|
|
+Imports System.Windows.Interop
|
|
|
+Imports System.Windows.Threading
|
|
|
+
|
|
|
+Public Module ModMain
|
|
|
+
|
|
|
+#Region "弹出提示"
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 提示信息的种类。
|
|
|
+ ''' </summary>
|
|
|
+ Public Enum HintType
|
|
|
+ ''' <summary>
|
|
|
+ ''' 信息,通常是蓝色的“i”。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <remarks></remarks>
|
|
|
+ Info
|
|
|
+ ''' <summary>
|
|
|
+ ''' 已完成,通常是绿色的“√”。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <remarks></remarks>
|
|
|
+ Finish
|
|
|
+ ''' <summary>
|
|
|
+ ''' 错误,通常是红色的“×”。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <remarks></remarks>
|
|
|
+ Critical
|
|
|
+ End Enum
|
|
|
+ Private Structure HintMessage
|
|
|
+ Public Text As String
|
|
|
+ Public Type As HintType
|
|
|
+ Public Log As Boolean
|
|
|
+ End Structure
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 等待弹出的提示列表。以 {String, HintType, Log As Boolean} 形式存储为数组。
|
|
|
+ ''' </summary>
|
|
|
+ Private HintWaiting As List(Of HintMessage) = If(HintWaiting, New List(Of HintMessage))
|
|
|
+ ''' <summary>
|
|
|
+ ''' 在窗口左下角弹出提示文本。
|
|
|
+ ''' </summary>
|
|
|
+ Public Sub Hint(Text As String, Optional Type As HintType = HintType.Info, Optional Log As Boolean = True)
|
|
|
+ If HintWaiting Is Nothing Then HintWaiting = New List(Of HintMessage)
|
|
|
+ HintWaiting.Add(New HintMessage With {.Text = If(Text, ""), .Type = Type, .Log = Log})
|
|
|
+ End Sub
|
|
|
+
|
|
|
+ Private Sub HintTick()
|
|
|
+ Try
|
|
|
+
|
|
|
+ 'Tag 存储了:{ 是否可以重用, Uuid }
|
|
|
+ If Not HintWaiting.Any() Then Exit Sub
|
|
|
+ Do While HintWaiting.Any
|
|
|
+ ''清除空提示
|
|
|
+ 'If IsNothing(HintWaiting(0)) OrElse IsNothing(HintWaiting(0)(0)) Then
|
|
|
+ ' HintWaiting.RemoveAt(0)
|
|
|
+ ' Continue Do
|
|
|
+ 'End If
|
|
|
+ Dim CurrentHint = HintWaiting(0)
|
|
|
+ '去回车
|
|
|
+ CurrentHint.Text = CurrentHint.Text.Replace(vbCrLf, " ").Replace(vbCr, " ").Replace(vbLf, " ")
|
|
|
+ '超量提示直接忽略
|
|
|
+ If FrmMain.PanHint.Children.Count >= 20 Then GoTo EndHint
|
|
|
+ '检查是否有重复提示
|
|
|
+ Dim DoubleStack As Border = Nothing
|
|
|
+ For Each stack As Border In FrmMain.PanHint.Children
|
|
|
+ If stack.Tag(0) AndAlso CType(stack.Child, TextBlock).Text = CurrentHint.Text Then DoubleStack = stack
|
|
|
+ Next
|
|
|
+ '获取渐变颜色
|
|
|
+ Dim TargetColor0, TargetColor1 As MyColor
|
|
|
+ Dim Percent As Double = 0.3
|
|
|
+ Select Case CurrentHint.Type
|
|
|
+ Case HintType.Info
|
|
|
+ TargetColor0 = New MyColor(37, 155, 252)
|
|
|
+ TargetColor1 = New MyColor(10, 142, 252)
|
|
|
+ Case HintType.Finish
|
|
|
+ TargetColor0 = New MyColor(33, 177, 33)
|
|
|
+ TargetColor1 = New MyColor(29, 160, 29)
|
|
|
+ Case Else 'HintType.Critical
|
|
|
+ TargetColor0 = New MyColor(255, 53, 11)
|
|
|
+ TargetColor1 = New MyColor(255, 43, 0)
|
|
|
+ End Select
|
|
|
+ If Not IsNothing(DoubleStack) Then
|
|
|
+ '有重复提示,且该提示的进入动画已播放
|
|
|
+ If Not AniIsRun("Hint Show " & DoubleStack.Tag(1)) Then
|
|
|
+ AniStop("Hint Hide " & DoubleStack.Tag(1))
|
|
|
+ Dim Delay As Double = (800 + MathClamp(CurrentHint.Text.Length, 5, 23) * 180) * AniSpeed
|
|
|
+ AniStart({
|
|
|
+ AaX(DoubleStack, -12 - DoubleStack.Margin.Left, 50,, New AniEaseOutFluent),
|
|
|
+ AaX(DoubleStack, -8, 50, 50, New AniEaseInFluent),
|
|
|
+ AaX(DoubleStack, 8, 50, 100, New AniEaseOutFluent),
|
|
|
+ AaX(DoubleStack, -8, 50, 150, New AniEaseInFluent),
|
|
|
+ AaDouble(Sub(i)
|
|
|
+ Percent += i
|
|
|
+ Dim Gradient As LinearGradientBrush = DoubleStack.Background
|
|
|
+ Gradient.GradientStops(0).Color = TargetColor0 * Percent + New MyColor(255, 255, 255) * (1 - Percent)
|
|
|
+ Gradient.GradientStops(1).Color = TargetColor1 * Percent + New MyColor(255, 255, 255) * (1 - Percent)
|
|
|
+ End Sub, 0.7, 250),
|
|
|
+ AaX(DoubleStack, -50, 200, Delay, New AniEaseInFluent),
|
|
|
+ AaOpacity(DoubleStack, -1, 150, Delay),
|
|
|
+ AaCode(Sub() DoubleStack.Tag(0) = False, Delay),
|
|
|
+ AaHeight(DoubleStack, -26, 100,, New AniEaseOutFluent, True),
|
|
|
+ AaCode(Sub() FrmMain.PanHint.Children.Remove(DoubleStack), , True)
|
|
|
+ }, "Hint Hide " & DoubleStack.Tag(1))
|
|
|
+ End If
|
|
|
+ Else
|
|
|
+ '准备控件
|
|
|
+ Dim NewHintControl As New Border With {.Tag = {True, GetUuid()}, .Margin = New Thickness(-70, 0, 20, 0), .Opacity = 0, .Height = 0, .HorizontalAlignment = HorizontalAlignment.Left, .CornerRadius = New CornerRadius(0, 6, 6, 0)}
|
|
|
+ NewHintControl.Background = New LinearGradientBrush(New GradientStopCollection(New List(Of GradientStop) From {
|
|
|
+ New GradientStop(TargetColor0 * Percent + New MyColor(255, 255, 255) * (1 - Percent), 0),
|
|
|
+ New GradientStop(TargetColor1 * Percent + New MyColor(255, 255, 255) * (1 - Percent), 1)}), 90)
|
|
|
+ NewHintControl.Child = New TextBlock With {.TextTrimming = TextTrimming.CharacterEllipsis, .FontSize = 13, .Text = CurrentHint.Text, .Foreground = New MyColor(255, 255, 255), .Margin = New Thickness(33, 5, 8, 5)}
|
|
|
+ 'AddHandler NewHintControl.MouseLeftButtonDown, AddressOf HideAllHint
|
|
|
+ FrmMain.PanHint.Children.Add(NewHintControl)
|
|
|
+ '控件动画
|
|
|
+ Dim Animations As New List(Of AniData)
|
|
|
+ If FrmMain.PanHint.Children.Count > 1 Then
|
|
|
+ '已有提示
|
|
|
+ Animations.Add(AaHeight(NewHintControl, 26, 150, , New AniEaseOutFluent))
|
|
|
+ Else
|
|
|
+ '是唯一提示
|
|
|
+ NewHintControl.Height = 26
|
|
|
+ End If
|
|
|
+ '开始动画
|
|
|
+ Animations.AddRange({
|
|
|
+ AaX(NewHintControl, 30, 400, , New AniEaseOutElastic(AniEasePower.Weak)),
|
|
|
+ AaX(NewHintControl, 20, 200, , New AniEaseOutFluent),
|
|
|
+ AaOpacity(NewHintControl, 1, 100),
|
|
|
+ AaDouble(Sub(i)
|
|
|
+ Percent += i
|
|
|
+ Dim Gradient As LinearGradientBrush = NewHintControl.Background
|
|
|
+ Gradient.GradientStops(0).Color = TargetColor0 * Percent + New MyColor(255, 255, 255) * (1 - Percent)
|
|
|
+ Gradient.GradientStops(1).Color = TargetColor1 * Percent + New MyColor(255, 255, 255) * (1 - Percent)
|
|
|
+ End Sub, 0.7, 250, 100)
|
|
|
+ })
|
|
|
+ AniStart(Animations, "Hint Show " & NewHintControl.Tag(1))
|
|
|
+ '结束动画
|
|
|
+ Dim Delay As Double = (800 + MathClamp(CurrentHint.Text.Length, 5, 23) * 180) * AniSpeed
|
|
|
+ AniStart({
|
|
|
+ AaX(NewHintControl, -50, 200, Delay, New AniEaseInFluent),
|
|
|
+ AaOpacity(NewHintControl, -1, 150, Delay),
|
|
|
+ AaCode(Sub() NewHintControl.Tag(0) = False, Delay),
|
|
|
+ AaHeight(NewHintControl, -26, 100,, New AniEaseOutFluent, True),
|
|
|
+ AaCode(Sub() FrmMain.PanHint.Children.Remove(NewHintControl), , True)
|
|
|
+ }, "Hint Hide " & NewHintControl.Tag(1))
|
|
|
+ End If
|
|
|
+ '结束处理
|
|
|
+EndHint:
|
|
|
+ If CurrentHint.Log Then Log("[UI] 弹出提示:" & CurrentHint.Text)
|
|
|
+ HintWaiting.RemoveAt(0)
|
|
|
+ Loop
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "显示弹出提示失败", LogLevel.Normal)
|
|
|
+ End Try
|
|
|
+ End Sub
|
|
|
+ Private Sub HideAllHint()
|
|
|
+ For Each Control As Border In FrmMain.PanHint.Children
|
|
|
+ Control.IsHitTestVisible = False
|
|
|
+ AniStart({
|
|
|
+ AaX(Control, -50, 200, , New AniEaseInFluent),
|
|
|
+ AaOpacity(Control, -1, 150, , New AniEaseInFluent),
|
|
|
+ AaCode(Sub() Control.Tag(0) = False),
|
|
|
+ AaHeight(Control, -26, 100,, New AniEaseOutFluent, True),
|
|
|
+ AaCode(Sub() FrmMain.PanHint.Children.Remove(Control), , True)
|
|
|
+ }, "Hint Hide " & Control.Tag(1))
|
|
|
+ Next
|
|
|
+ End Sub
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+#Region "弹窗"
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 存储弹窗信息的转换器。
|
|
|
+ ''' </summary>
|
|
|
+ Public Class MyMsgBoxConverter
|
|
|
+ Public Type As MyMsgBoxType
|
|
|
+ Public Title As String
|
|
|
+ Public Text As String
|
|
|
+ ''' <summary>
|
|
|
+ ''' 输入框模式:文本框的文本;选择模式:需要放进去的 List(Of MyListItem)。
|
|
|
+ ''' </summary>
|
|
|
+ Public Content As Object
|
|
|
+ ''' <summary>
|
|
|
+ ''' 仅输入框模式:输入验证规则。
|
|
|
+ ''' </summary>
|
|
|
+ Public ValidateRules As ObjectModel.Collection(Of Validate)
|
|
|
+ ''' <summary>
|
|
|
+ ''' 仅输入框模式:提示文本。
|
|
|
+ ''' </summary>
|
|
|
+ Public HintText As String = ""
|
|
|
+ ''' <summary>
|
|
|
+ ''' 有多个按钮时,是否给第一个按钮加高亮。
|
|
|
+ ''' </summary>
|
|
|
+ Public HighLight As Boolean
|
|
|
+ Public Button1 As String = "确定"
|
|
|
+ Public Button2 As String = ""
|
|
|
+ Public Button3 As String = ""
|
|
|
+ ''' <summary>
|
|
|
+ ''' 点击第一个按钮将执行该方法,不关闭弹窗。
|
|
|
+ ''' </summary>
|
|
|
+ Public Button1Action As Action = Nothing
|
|
|
+ ''' <summary>
|
|
|
+ ''' 点击第二个按钮将执行该方法,不关闭弹窗。
|
|
|
+ ''' </summary>
|
|
|
+ Public Button2Action As Action = Nothing
|
|
|
+ ''' <summary>
|
|
|
+ ''' 点击第三个按钮将执行该方法,不关闭弹窗。
|
|
|
+ ''' </summary>
|
|
|
+ Public Button3Action As Action = Nothing
|
|
|
+ Public IsWarn As Boolean = False
|
|
|
+ Public ForceWait As Boolean = False
|
|
|
+ Public WaitFrame As New DispatcherFrame(True)
|
|
|
+ ''' <summary>
|
|
|
+ ''' 弹窗是否已经关闭。
|
|
|
+ ''' </summary>
|
|
|
+ Public IsExited As Boolean = False
|
|
|
+ ''' <summary>
|
|
|
+ ''' 点击的按钮编号或输入的文本。若输入弹窗点击了非第一个按钮,则为 Nothing。
|
|
|
+ ''' </summary>
|
|
|
+ Public Result As Object
|
|
|
+ End Class
|
|
|
+ Public Enum MyMsgBoxType
|
|
|
+ Text
|
|
|
+ [Select]
|
|
|
+ Input
|
|
|
+ End Enum
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 显示弹窗,返回点击按钮的编号(从 1 开始)。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <param name="Title">弹窗的标题。</param>
|
|
|
+ ''' <param name="Caption">弹窗的内容。</param>
|
|
|
+ ''' <param name="Button1">显示的第一个按钮,默认为“确定”。</param>
|
|
|
+ ''' <param name="Button2">显示的第二个按钮,默认为空。</param>
|
|
|
+ ''' <param name="Button3">显示的第三个按钮,默认为空。</param>
|
|
|
+ ''' <param name="Button1Action">点击第一个按钮将执行该方法,不关闭弹窗。</param>
|
|
|
+ ''' <param name="Button2Action">点击第二个按钮将执行该方法,不关闭弹窗。</param>
|
|
|
+ ''' <param name="Button3Action">点击第三个按钮将执行该方法,不关闭弹窗。</param>
|
|
|
+ ''' <param name="IsWarn">是否为警告弹窗,若为 True,弹窗配色和背景会变为红色。</param>
|
|
|
+ Public Function MyMsgBox(Caption As String, Optional Title As String = "提示",
|
|
|
+ Optional Button1 As String = "确定", Optional Button2 As String = "", Optional Button3 As String = "",
|
|
|
+ Optional IsWarn As Boolean = False, Optional HighLight As Boolean = True, Optional ForceWait As Boolean = False,
|
|
|
+ Optional Button1Action As Action = Nothing, Optional Button2Action As Action = Nothing, Optional Button3Action As Action = Nothing) As Integer
|
|
|
+ '将弹窗列入队列
|
|
|
+ Dim Converter As New MyMsgBoxConverter With {.Type = MyMsgBoxType.Text, .Button1 = Button1, .Button2 = Button2, .Button3 = Button3, .Text = Caption, .IsWarn = IsWarn, .Title = Title, .HighLight = HighLight, .ForceWait = True, .Button1Action = Button1Action, .Button2Action = Button2Action, .Button3Action = Button3Action}
|
|
|
+ WaitingMyMsgBox.Add(Converter)
|
|
|
+ If RunInUi() Then
|
|
|
+ '若为 UI 线程,立即执行弹窗刻, 避免快速(连点器)点击时多次弹窗
|
|
|
+ MyMsgBoxTick()
|
|
|
+ End If
|
|
|
+ If Button2.Length > 0 OrElse ForceWait Then
|
|
|
+ '若有多个按钮则开始等待
|
|
|
+ If FrmMain Is Nothing OrElse FrmMain.PanMsg Is Nothing AndAlso RunInUi() Then
|
|
|
+ '主窗体尚未加载,用老土的弹窗来替代
|
|
|
+ WaitingMyMsgBox.Remove(Converter)
|
|
|
+ If Button2.Length > 0 Then
|
|
|
+ Dim RawResult As MsgBoxResult = MsgBox(Caption, If(Button3.Length > 0, MsgBoxStyle.YesNoCancel, MsgBoxStyle.YesNo) + If(IsWarn, MsgBoxStyle.Critical, MsgBoxStyle.Question), Title)
|
|
|
+ Select Case RawResult
|
|
|
+ Case MsgBoxResult.Yes
|
|
|
+ Converter.Result = 1
|
|
|
+ Case MsgBoxResult.No
|
|
|
+ Converter.Result = 2
|
|
|
+ Case MsgBoxResult.Cancel
|
|
|
+ Converter.Result = 3
|
|
|
+ End Select
|
|
|
+ Else
|
|
|
+ MsgBox(Caption, MsgBoxStyle.OkOnly + If(IsWarn, MsgBoxStyle.Critical, MsgBoxStyle.Question), Title)
|
|
|
+ Converter.Result = 1
|
|
|
+ End If
|
|
|
+ Log("[Control] 主窗体加载完成前出现意料外的等待弹窗:" & Button1 & "," & Button2 & "," & Button3, LogLevel.Debug)
|
|
|
+ Else
|
|
|
+ Try
|
|
|
+ FrmMain.DragStop()
|
|
|
+ ComponentDispatcher.PushModal()
|
|
|
+ Dispatcher.PushFrame(Converter.WaitFrame)
|
|
|
+ Finally
|
|
|
+ ComponentDispatcher.PopModal()
|
|
|
+ End Try
|
|
|
+ End If
|
|
|
+ Log("[Control] 普通弹框返回:" & If(Converter.Result, "null"))
|
|
|
+ Return Converter.Result
|
|
|
+ Else
|
|
|
+ '不进行等待,直接返回
|
|
|
+ Return 1
|
|
|
+ End If
|
|
|
+ End Function
|
|
|
+ ''' <summary>
|
|
|
+ ''' 显示输入框并返回输入的文本。若点击第二个按钮,则返回 Nothing。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <param name="Title">弹窗的标题。</param>
|
|
|
+ ''' <param name="ValidateRules">文本框的输入检测。</param>
|
|
|
+ ''' <param name="Text">弹窗的介绍文本。</param>
|
|
|
+ ''' <param name="DefaultInput">文本框的默认内容。</param>
|
|
|
+ ''' <param name="HintText">文本框的提示内容。</param>
|
|
|
+ ''' <param name="Button1">显示的第一个按钮,默认为“确定”。</param>
|
|
|
+ ''' <param name="Button2">显示的第二个按钮,默认为“取消”。</param>
|
|
|
+ ''' <param name="IsWarn">是否为警告弹窗,若为 True,弹窗配色和背景会变为红色。</param>
|
|
|
+ Public Function MyMsgBoxInput(Title As String, Optional Text As String = "", Optional DefaultInput As String = "", Optional ValidateRules As ObjectModel.Collection(Of Validate) = Nothing, Optional HintText As String = "", Optional Button1 As String = "确定", Optional Button2 As String = "取消", Optional IsWarn As Boolean = False) As String
|
|
|
+ '将弹窗列入队列
|
|
|
+ Dim Converter As New MyMsgBoxConverter With {.Text = Text, .HintText = HintText, .Type = MyMsgBoxType.Input, .ValidateRules = If(ValidateRules, New ObjectModel.Collection(Of Validate)), .Button1 = Button1, .Button2 = Button2, .Content = DefaultInput, .IsWarn = IsWarn, .Title = Title}
|
|
|
+ WaitingMyMsgBox.Add(Converter)
|
|
|
+ '虽然我也不知道这是啥但是能用就成了 :)
|
|
|
+ Try
|
|
|
+ If FrmMain IsNot Nothing Then FrmMain.DragStop()
|
|
|
+ ComponentDispatcher.PushModal()
|
|
|
+ Dispatcher.PushFrame(Converter.WaitFrame)
|
|
|
+ Finally
|
|
|
+ ComponentDispatcher.PopModal()
|
|
|
+ End Try
|
|
|
+ Log("[Control] 输入弹框返回:" & If(Converter.Result, "null"))
|
|
|
+ Return Converter.Result
|
|
|
+ End Function
|
|
|
+ ''' <summary>
|
|
|
+ ''' 显示选择框并返回选择的第几项(从 0 开始)。若点击第二个按钮,则返回 Nothing。
|
|
|
+ ''' </summary>
|
|
|
+ ''' <param name="Title">弹窗的标题。</param>
|
|
|
+ ''' <param name="Button1">显示的第一个按钮,默认为 “确定”。</param>
|
|
|
+ ''' <param name="Button2">显示的第二个按钮,默认为空。</param>
|
|
|
+ ''' <param name="IsWarn">是否为警告弹窗,若为 True,弹窗配色和背景会变为红色。</param>
|
|
|
+ Public Function MyMsgBoxSelect(Selections As List(Of IMyRadio), Optional Title As String = "提示", Optional Button1 As String = "确定", Optional Button2 As String = "", Optional IsWarn As Boolean = False) As Integer?
|
|
|
+ '将弹窗列入队列
|
|
|
+ Dim Converter As New MyMsgBoxConverter With {.Type = MyMsgBoxType.Select, .Button1 = Button1, .Button2 = Button2, .Content = Selections, .IsWarn = IsWarn, .Title = Title}
|
|
|
+ WaitingMyMsgBox.Add(Converter)
|
|
|
+ '虽然我也不知道这是啥但是能用就成了 :)
|
|
|
+ Try
|
|
|
+ If FrmMain IsNot Nothing Then FrmMain.DragStop()
|
|
|
+ ComponentDispatcher.PushModal()
|
|
|
+ Dispatcher.PushFrame(Converter.WaitFrame)
|
|
|
+ Finally
|
|
|
+ ComponentDispatcher.PopModal()
|
|
|
+ End Try
|
|
|
+ Log("[Control] 选择弹框返回:" & If(Converter.Result, "null"))
|
|
|
+ Return Converter.Result
|
|
|
+ End Function
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 等待显示的弹窗。
|
|
|
+ ''' </summary>
|
|
|
+ Public WaitingMyMsgBox As List(Of MyMsgBoxConverter) = If(WaitingMyMsgBox, New List(Of MyMsgBoxConverter))
|
|
|
+ Public Sub MyMsgBoxTick()
|
|
|
+ Try
|
|
|
+ If FrmMain Is Nothing OrElse FrmMain.PanMsg Is Nothing OrElse FrmMain.WindowState = WindowState.Minimized Then Exit Sub
|
|
|
+ If FrmMain.PanMsg.Children.Count > 0 Then
|
|
|
+ '弹窗中
|
|
|
+ FrmMain.PanMsg.Visibility = Visibility.Visible
|
|
|
+ ElseIf WaitingMyMsgBox.Any Then
|
|
|
+ '没有弹窗,显示一个等待的弹窗
|
|
|
+ FrmMain.PanMsg.Visibility = Visibility.Visible
|
|
|
+ Select Case CType(WaitingMyMsgBox(0), MyMsgBoxConverter).Type
|
|
|
+ Case MyMsgBoxType.Input
|
|
|
+ FrmMain.PanMsg.Children.Add(New MyMsgInput(WaitingMyMsgBox(0)))
|
|
|
+ Case MyMsgBoxType.Select
|
|
|
+ FrmMain.PanMsg.Children.Add(New MyMsgSelect(WaitingMyMsgBox(0)))
|
|
|
+ Case MyMsgBoxType.Text
|
|
|
+ FrmMain.PanMsg.Children.Add(New MyMsgText(WaitingMyMsgBox(0)))
|
|
|
+ End Select
|
|
|
+ WaitingMyMsgBox.RemoveAt(0)
|
|
|
+ Else
|
|
|
+ '没有弹窗,没有等待的弹窗
|
|
|
+ If Not FrmMain.PanMsg.Visibility = Visibility.Collapsed Then FrmMain.PanMsg.Visibility = Visibility.Collapsed
|
|
|
+ End If
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "处理等待中的弹窗失败", LogLevel.Feedback)
|
|
|
+ End Try
|
|
|
+ End Sub
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+#Region "页面声明"
|
|
|
+ '在最后进行页面声明,避免颜色尚未加载完毕
|
|
|
+
|
|
|
+ '窗体声明
|
|
|
+ Public FrmMain As FormMain
|
|
|
+ Public FrmStart As SplashScreen
|
|
|
+
|
|
|
+ '页面声明(出于单元测试考虑,初始化页面已转入 FormMain 中)
|
|
|
+ Public FrmLaunchLeft As PageLaunchLeft
|
|
|
+ Public FrmLaunchRight As PageLaunchRight
|
|
|
+ Public FrmSelectLeft As PageSelectLeft
|
|
|
+ Public FrmSelectRight As PageSelectRight
|
|
|
+ Public FrmSpeedLeft As PageSpeedLeft
|
|
|
+ Public FrmSpeedRight As PageSpeedRight
|
|
|
+
|
|
|
+ '联机页面声明
|
|
|
+ Public FrmLinkLeft As PageLinkLeft
|
|
|
+ Public FrmLinkIoi As PageLinkIoi
|
|
|
+ Public FrmLinkHiper As PageLinkHiper
|
|
|
+ Public FrmLinkHelp As PageOtherHelpDetail
|
|
|
+ Public FrmLinkFeedback As PageLinkFeedback
|
|
|
+
|
|
|
+ '下载页面声明
|
|
|
+ Public FrmDownloadLeft As PageDownloadLeft
|
|
|
+ Public FrmDownloadInstall As PageDownloadInstall
|
|
|
+ Public FrmDownloadClient As PageDownloadClient
|
|
|
+ Public FrmDownloadOptiFine As PageDownloadOptiFine
|
|
|
+ Public FrmDownloadLiteLoader As PageDownloadLiteLoader
|
|
|
+ Public FrmDownloadForge As PageDownloadForge
|
|
|
+ Public FrmDownloadFabric As PageDownloadFabric
|
|
|
+ Public FrmDownloadMod As PageDownloadMod
|
|
|
+ Public FrmDownloadPack As PageDownloadPack
|
|
|
+
|
|
|
+ '设置页面声明
|
|
|
+ Public FrmSetupLeft As PageSetupLeft
|
|
|
+ Public FrmSetupLaunch As PageSetupLaunch
|
|
|
+ Public FrmSetupUI As PageSetupUI
|
|
|
+ Public FrmSetupSystem As PageSetupSystem
|
|
|
+ Public FrmSetupLink As PageSetupLink
|
|
|
+
|
|
|
+ '其他页面声明
|
|
|
+ Public FrmOtherLeft As PageOtherLeft
|
|
|
+ Public FrmOtherHelp As PageOtherHelp
|
|
|
+ Public FrmOtherAbout As PageOtherAbout
|
|
|
+ Public FrmOtherTest As PageOtherTest
|
|
|
+
|
|
|
+ '登录页面声明
|
|
|
+ Public FrmLoginLegacy As PageLoginLegacy
|
|
|
+ Public FrmLoginNide As PageLoginNide
|
|
|
+ Public FrmLoginNideSkin As PageLoginNideSkin
|
|
|
+ Public FrmLoginAuth As PageLoginAuth
|
|
|
+ Public FrmLoginAuthSkin As PageLoginAuthSkin
|
|
|
+ Public FrmLoginMs As PageLoginMs
|
|
|
+ Public FrmLoginMsSkin As PageLoginMsSkin
|
|
|
+
|
|
|
+ '版本设置页面声明
|
|
|
+ Public FrmVersionLeft As PageVersionLeft
|
|
|
+ Public FrmVersionOverall As PageVersionOverall
|
|
|
+ Public FrmVersionMod As PageVersionMod
|
|
|
+ Public FrmVersionModDisabled As PageVersionModDisabled
|
|
|
+ Public FrmVersionSetup As PageVersionSetup
|
|
|
+
|
|
|
+ '资源信息分页声明
|
|
|
+ Public FrmDownloadCompDetail As PageDownloadCompDetail
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+#Region "帮助"
|
|
|
+
|
|
|
+ Public Class HelpEntry
|
|
|
+
|
|
|
+ '基础
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 显示标题。
|
|
|
+ ''' </summary>
|
|
|
+ Public Title As String
|
|
|
+ ''' <summary>
|
|
|
+ ''' 显示描述。
|
|
|
+ ''' </summary>
|
|
|
+ Public Desc As String
|
|
|
+ ''' <summary>
|
|
|
+ ''' 检索关键字。
|
|
|
+ ''' </summary>
|
|
|
+ Public Search As String
|
|
|
+ ''' <summary>
|
|
|
+ ''' 用于分类的标签列表。
|
|
|
+ ''' </summary>
|
|
|
+ Public Types As List(Of String)
|
|
|
+
|
|
|
+ '显示(可选)
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 帮助项的自定义图标。可能为 Nothing。
|
|
|
+ ''' </summary>
|
|
|
+ Public Logo As String = Nothing
|
|
|
+ ''' <summary>
|
|
|
+ ''' 是否显示在搜索结果。默认为 True。
|
|
|
+ ''' </summary>
|
|
|
+ Public ShowInSearch As Boolean = True
|
|
|
+ ''' <summary>
|
|
|
+ ''' 是否在公开版的 PCL 中显示(这会影响主页与搜索)。默认为 True。
|
|
|
+ ''' </summary>
|
|
|
+ Public ShowInPublic As Boolean = True
|
|
|
+ ''' <summary>
|
|
|
+ ''' 是否在快照版的 PCL 中显示(这会影响主页与搜索)。默认为 True。
|
|
|
+ ''' </summary>
|
|
|
+ Public ShowInSnapshot As Boolean = True
|
|
|
+
|
|
|
+ '动作
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 是否为 “执行事件”。
|
|
|
+ ''' </summary>
|
|
|
+ Public IsEvent As Boolean
|
|
|
+ Public EventType As String
|
|
|
+ Public EventData As String
|
|
|
+ ''' <summary>
|
|
|
+ ''' 若非执行事件,其对应的 .xaml 本地文件内容。
|
|
|
+ ''' </summary>
|
|
|
+ Public XamlContent As String
|
|
|
+
|
|
|
+ '转换
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 从文件初始化 HelpEntry 对象,失败会抛出异常。
|
|
|
+ ''' </summary>
|
|
|
+ Public Sub New(FilePath As String)
|
|
|
+ Dim JsonData As JObject = GetJson(HelpArgumentReplace(ReadFile(FilePath)))
|
|
|
+ If JsonData Is Nothing Then Throw New FileNotFoundException("未找到帮助文件:" & FilePath, FilePath)
|
|
|
+ '加载常规信息
|
|
|
+ If JsonData("Title") IsNot Nothing Then
|
|
|
+ Title = JsonData("Title")
|
|
|
+ Else
|
|
|
+ Throw New ArgumentException("未找到 Title 项")
|
|
|
+ End If
|
|
|
+ Desc = If(JsonData("Description"), "")
|
|
|
+ Search = If(JsonData("Keywords"), "")
|
|
|
+ Logo = JsonData("Logo") '为保持 Nothing,不要加 If
|
|
|
+ ShowInSearch = If(JsonData("ShowInSearch"), ShowInSearch)
|
|
|
+ ShowInPublic = If(JsonData("ShowInPublic"), ShowInPublic)
|
|
|
+ ShowInSnapshot = If(JsonData("ShowInSnapshot"), ShowInSnapshot)
|
|
|
+ Types = New List(Of String)
|
|
|
+ For Each NameOfType In If(JsonData("Types"), GetJson("[]"))
|
|
|
+ Types.Add(NameOfType)
|
|
|
+ Next
|
|
|
+ '加载事件信息
|
|
|
+ If If(JsonData("IsEvent"), False) Then
|
|
|
+ EventType = JsonData("EventType")
|
|
|
+ If EventType Is Nothing Then Throw New ArgumentException("未找到 EventType 项")
|
|
|
+ EventData = If(JsonData("EventData"), "")
|
|
|
+ IsEvent = True
|
|
|
+ Else
|
|
|
+ Dim XamlAddress As String = FilePath.ToLower.Replace(".json", ".xaml")
|
|
|
+ If File.Exists(XamlAddress) Then
|
|
|
+ XamlContent = ReadFile(XamlAddress)
|
|
|
+ IsEvent = False
|
|
|
+ Else
|
|
|
+ Throw New FileNotFoundException("未找到帮助条目 .json 对应的 .xaml 文件(" & XamlAddress & ")")
|
|
|
+ End If
|
|
|
+ End If
|
|
|
+ End Sub
|
|
|
+ ''' <summary>
|
|
|
+ ''' 获取该 HelpEntry 对应的 MyListItem。
|
|
|
+ ''' </summary>
|
|
|
+ Public Function ToListItem() As MyListItem
|
|
|
+ Return SetToListItem(New MyListItem)
|
|
|
+ End Function
|
|
|
+ ''' <summary>
|
|
|
+ ''' 将属性设置入一个现有的 ListItem。
|
|
|
+ ''' </summary>
|
|
|
+ Public Function SetToListItem(Item As MyListItem) As MyListItem
|
|
|
+ Dim Logo As String
|
|
|
+ If IsEvent Then
|
|
|
+ If EventType = "弹出窗口" Then
|
|
|
+ Logo = PathImage & "Blocks/GrassPath.png"
|
|
|
+ Else
|
|
|
+ Logo = PathImage & "Blocks/CommandBlock.png"
|
|
|
+ End If
|
|
|
+ Else
|
|
|
+ Logo = PathImage & "Blocks/Grass.png"
|
|
|
+ End If
|
|
|
+ '设置属性
|
|
|
+ With Item
|
|
|
+ .SnapsToDevicePixels = True
|
|
|
+ .Title = Title
|
|
|
+ .Info = Desc
|
|
|
+ .Logo = If(Me.Logo, Logo)
|
|
|
+ .Height = 42
|
|
|
+ .Type = MyListItem.CheckType.Clickable
|
|
|
+ .Tag = Me
|
|
|
+ .EventType = Nothing
|
|
|
+ .EventData = Nothing
|
|
|
+ End With
|
|
|
+ '项目的点击事件
|
|
|
+ AddHandler Item.Click, Sub(sender, e) PageOtherHelp.OnItemClick(sender.Tag)
|
|
|
+ Return Item
|
|
|
+ End Function
|
|
|
+
|
|
|
+ End Class
|
|
|
+
|
|
|
+ Public HelpLoader As New LoaderTask(Of Integer, List(Of HelpEntry))("Help Page", AddressOf HelpLoad,, ThreadPriority.BelowNormal)
|
|
|
+ Private ReadOnly HelpLoadLock As New Object
|
|
|
+ ''' <summary>
|
|
|
+ ''' 初始化帮助列表对象。
|
|
|
+ ''' </summary>
|
|
|
+ Private Sub HelpLoad(Loader As LoaderTask(Of Integer, List(Of HelpEntry)))
|
|
|
+ SyncLock HelpLoadLock '避免重复解压文件导致出错
|
|
|
+ Try
|
|
|
+
|
|
|
+ '解压内置文件
|
|
|
+ HelpTryExtract()
|
|
|
+
|
|
|
+ '遍历文件
|
|
|
+ Dim FileList As New List(Of String)
|
|
|
+ Try
|
|
|
+ Dim IgnoreList As New List(Of String)
|
|
|
+ '读取自定义文件
|
|
|
+ If Directory.Exists(Path & "PCL\Help\") Then
|
|
|
+ For Each File In EnumerateFiles(Path & "PCL\Help\")
|
|
|
+ Select Case File.Extension.ToLower
|
|
|
+ Case ".helpignore"
|
|
|
+ '加载忽略列表
|
|
|
+ Log("[Help] 发现 .helpignore 文件:" & File.FullName)
|
|
|
+ For Each Line In ReadFile(File.FullName).Split(vbCrLf.ToCharArray)
|
|
|
+ Dim RealString As String = Line.Before("#").Trim
|
|
|
+ If String.IsNullOrWhiteSpace(RealString) Then Continue For
|
|
|
+ IgnoreList.Add(RealString)
|
|
|
+ If ModeDebug Then Log("[Help] > " & RealString)
|
|
|
+ Next
|
|
|
+ Case ".json"
|
|
|
+ FileList.Add(File.FullName)
|
|
|
+ End Select
|
|
|
+ Next
|
|
|
+ End If
|
|
|
+ Log("[Help] 已扫描 PCL 文件夹下的帮助文件,目前总计 " & FileList.Count & " 条")
|
|
|
+ '读取自带文件
|
|
|
+ For Each File In EnumerateFiles(PathTemp & "Help")
|
|
|
+ '跳过非 json 文件与以 . 开头的文件夹
|
|
|
+ If File.Extension.ToLower <> ".json" OrElse File.Directory.FullName.Replace(PathTemp & "Help", "").Contains("\.") Then Continue For
|
|
|
+ '检查忽略列表
|
|
|
+ Dim RealPath As String = File.FullName.Replace(PathTemp & "Help\", "")
|
|
|
+ For Each Ignore In IgnoreList
|
|
|
+ If RegexCheck(RealPath, Ignore) Then
|
|
|
+ If ModeDebug Then Log("[Help] 已忽略 " & RealPath & ":" & Ignore)
|
|
|
+ GoTo NextFile
|
|
|
+ End If
|
|
|
+ Next
|
|
|
+ FileList.Add(File.FullName)
|
|
|
+NextFile:
|
|
|
+ Next
|
|
|
+ Log("[Help] 已扫描缓存文件夹下的帮助文件,目前总计 " & FileList.Count & " 条")
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "检查帮助文件夹失败", LogLevel.Msgbox)
|
|
|
+ End Try
|
|
|
+ If Loader.IsAborted Then Exit Sub
|
|
|
+
|
|
|
+ '将文件实例化
|
|
|
+ Dim Dict As New List(Of HelpEntry)
|
|
|
+ For Each FilePath As String In FileList
|
|
|
+ Try
|
|
|
+ Dim Entry As New HelpEntry(FilePath)
|
|
|
+ Dict.Add(Entry)
|
|
|
+ If ModeDebug Then Log("[Help] 已加载的帮助条目:" & Entry.Title & " ← " & FilePath)
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "初始化帮助条目失败(" & FilePath & ")", LogLevel.Msgbox)
|
|
|
+ End Try
|
|
|
+ Next
|
|
|
+
|
|
|
+ '回设
|
|
|
+ If Not Dict.Any() Then Throw New Exception("未找到可用的帮助;若不需要帮助页面,可以在 设置 → 个性化 → 功能隐藏 中将其隐藏")
|
|
|
+ If Loader.IsAborted Then Exit Sub
|
|
|
+ Loader.Output = Dict
|
|
|
+
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "帮助列表初始化失败")
|
|
|
+ Throw
|
|
|
+ End Try
|
|
|
+ End SyncLock
|
|
|
+ End Sub
|
|
|
+ ''' <summary>
|
|
|
+ ''' 尝试解压内置帮助文件。
|
|
|
+ ''' </summary>
|
|
|
+ Public Sub HelpTryExtract()
|
|
|
+ If Setup.Get("SystemHelpVersion") <> VersionCode OrElse Not File.Exists(PathTemp & "Help\启动器\备份设置.xaml") Then
|
|
|
+ DeleteDirectory(PathTemp & "Help")
|
|
|
+ Directory.CreateDirectory(PathTemp & "Help")
|
|
|
+ WriteFile(PathTemp & "Cache\Help.zip", GetResources("Help"))
|
|
|
+ ExtractFile(PathTemp & "Cache\Help.zip", PathTemp & "Help", Encoding.UTF8)
|
|
|
+ Setup.Set("SystemHelpVersion", VersionCode)
|
|
|
+ Log("[Help] 已解压内置帮助文件,目前状态:" & File.Exists(PathTemp & "Help\启动器\备份设置.xaml"), LogLevel.Debug)
|
|
|
+ End If
|
|
|
+ End Sub
|
|
|
+ ''' <summary>
|
|
|
+ ''' 对帮助文件约定的替换标记进行处理,如果遇到需要转义的字符会进行转义。
|
|
|
+ ''' </summary>
|
|
|
+ Public Function HelpArgumentReplace(Xaml As String) As String
|
|
|
+ Dim Result = Xaml.Replace("{path}", EscapeXML(Path))
|
|
|
+ Result = RegexReplaceEach(Result, Function() EscapeXML(PageOtherTest.GetRandomHint()), "\{hint\}")
|
|
|
+ Result = RegexReplaceEach(Result, Function() EscapeXML(PageOtherTest.GetRandomCave()), "\{cave\}")
|
|
|
+ Return Result
|
|
|
+ End Function
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+#Region "愚人节"
|
|
|
+
|
|
|
+ Public IsAprilEnabled As Boolean = Date.Now.Month = 4 AndAlso Date.Now.Day = 1
|
|
|
+ Public IsAprilGiveup As Boolean = False
|
|
|
+ Private AprilSpeed As New Vector(0, 0)
|
|
|
+ Private AprilIdieCount As Integer = 0, AprilMousePosLast As New Point(0, 0)
|
|
|
+ Private AprilDistance As Integer = 0
|
|
|
+ Private Sub TimerFool()
|
|
|
+ Try
|
|
|
+ If FrmLaunchLeft Is Nothing OrElse FrmLaunchLeft.AprilPosTrans Is Nothing OrElse FrmMain.lastMouseArg Is Nothing Then Exit Sub
|
|
|
+ If IsAprilGiveup OrElse FrmMain.PageCurrent <> FormMain.PageType.Launch OrElse AniControlEnabled <> 0 OrElse Not FrmLaunchLeft.BtnLaunch.IsLoaded Then Exit Sub
|
|
|
+
|
|
|
+ '计算是否空闲
|
|
|
+ Dim MousePos = FrmMain.lastMouseArg.GetPosition(FrmMain)
|
|
|
+ If MousePos = AprilMousePosLast Then
|
|
|
+ AprilIdieCount += 1
|
|
|
+ Else
|
|
|
+ AprilMousePosLast = MousePos
|
|
|
+ AprilIdieCount = 0
|
|
|
+ End If
|
|
|
+ '计算躲避移动
|
|
|
+ Dim Direction As Vector
|
|
|
+ Dim Distance As Double
|
|
|
+ Dim ButtonWidth = FrmLaunchLeft.BtnLaunch.ActualWidth / 2, ButtonHeight = FrmLaunchLeft.BtnLaunch.ActualHeight / 2
|
|
|
+ Dim Vec As Vector = FrmMain.lastMouseArg.GetPosition(FrmLaunchLeft.BtnLaunch) - New Vector(ButtonWidth, ButtonHeight)
|
|
|
+ Dim Dir As New Vector(Vec.X, Vec.Y)
|
|
|
+ Dir.Normalize()
|
|
|
+ Direction = -Dir
|
|
|
+ Distance = New Vector(Math.Max(0, Math.Abs(Vec.X) - ButtonWidth), Math.Max(0, Math.Abs(Vec.Y) - ButtonHeight)).Length
|
|
|
+ Dim BreathScale = Math.Sin(Timer150Count / 37.5 * Math.PI)
|
|
|
+ Dim Acc = Math.Max(0, BreathScale * 0.25 - 0.65 - Math.Log((Distance + 0.4) / 200)) * Direction '加速度
|
|
|
+ '计算回归移动
|
|
|
+ If AprilIdieCount >= 64 * 5 Then
|
|
|
+ Dim SafeDist As Vector = FrmMain.lastMouseArg.GetPosition(FrmMain.PanMain) - New Vector(ButtonWidth, FrmMain.PanMain.ActualHeight - ButtonHeight * 3)
|
|
|
+ Dim Back As New Vector(FrmLaunchLeft.AprilPosTrans.X, FrmLaunchLeft.AprilPosTrans.Y)
|
|
|
+ If SafeDist.Length > 250 AndAlso Back.Length > 0.4 Then
|
|
|
+ Acc -= Back * 0.0005
|
|
|
+ Back.Normalize()
|
|
|
+ Acc -= Back * 0.15
|
|
|
+ End If
|
|
|
+ End If
|
|
|
+ '回到边界
|
|
|
+ Dim Relative As Point = FrmLaunchLeft.BtnLaunch.TranslatePoint(New Point(0, 0), FrmMain.PanForm)
|
|
|
+ If Relative.X < -ButtonWidth * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X += FrmMain.PanForm.ActualWidth + ButtonWidth * 2 '离开左边界
|
|
|
+ AprilSpeed.X -= 80
|
|
|
+ If Relative.Y < 0 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y += ButtonHeight * 2.5
|
|
|
+ ElseIf Relative.Y > FrmMain.PanForm.ActualHeight - ButtonHeight * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y -= ButtonHeight * 2.5
|
|
|
+ End If
|
|
|
+ ElseIf Relative.X > FrmMain.PanForm.ActualWidth Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X -= FrmMain.PanForm.ActualWidth + ButtonWidth * 2 '离开右边界
|
|
|
+ AprilSpeed.X += 80
|
|
|
+ If Relative.Y < 0 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y += ButtonHeight * 2.5
|
|
|
+ ElseIf Relative.Y > FrmMain.PanForm.ActualHeight - ButtonHeight * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y -= ButtonHeight * 2.5
|
|
|
+ End If
|
|
|
+ ElseIf Relative.Y < -ButtonHeight * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y += FrmMain.PanForm.ActualHeight + ButtonHeight * 2 '离开上边界
|
|
|
+ AprilSpeed.Y -= 25
|
|
|
+ If Relative.X < 0 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X += ButtonWidth * 2
|
|
|
+ ElseIf Relative.X > FrmMain.PanForm.ActualWidth - ButtonWidth * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X -= ButtonWidth * 2
|
|
|
+ End If
|
|
|
+ ElseIf Relative.Y > FrmMain.PanForm.ActualHeight Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y -= FrmMain.PanForm.ActualHeight + ButtonHeight * 2 '离开下边界
|
|
|
+ AprilSpeed.Y += 25
|
|
|
+ If Relative.X < 0 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X += ButtonWidth * 2
|
|
|
+ ElseIf Relative.X > FrmMain.PanForm.ActualWidth - ButtonWidth * 2 Then
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X -= ButtonWidth * 2
|
|
|
+ End If
|
|
|
+ End If
|
|
|
+ '移动
|
|
|
+ AprilSpeed = AprilSpeed * 0.8 + Acc
|
|
|
+ Dim SpeedValue = Math.Min(60, AprilSpeed.Length)
|
|
|
+ If SpeedValue < 0.01 Then Exit Sub
|
|
|
+ AprilSpeed.Normalize()
|
|
|
+ AprilSpeed *= SpeedValue
|
|
|
+ AprilDistance += SpeedValue
|
|
|
+ FrmLaunchLeft.AprilPosTrans.X += AprilSpeed.X
|
|
|
+ FrmLaunchLeft.AprilPosTrans.Y += AprilSpeed.Y
|
|
|
+ '大小改变
|
|
|
+ FrmLaunchLeft.AprilScaleTrans.ScaleX = MathClamp(1 - (Math.Abs(Direction.X) - Math.Abs(Direction.Y)) * (SpeedValue / 160), 0.2, 1.8)
|
|
|
+ FrmLaunchLeft.AprilScaleTrans.ScaleY = MathClamp(1 - (Math.Abs(Direction.Y) - Math.Abs(Direction.X)) * (SpeedValue / 100), 0.2, 1.8)
|
|
|
+ '放弃提示
|
|
|
+ If AprilDistance > 4000 Then
|
|
|
+ AprilDistance = -4000
|
|
|
+ Select Case RandomInteger(0, 3)
|
|
|
+ Case 0
|
|
|
+ Hint("放弃吧!只需要点一下右下角的小白旗……")
|
|
|
+ Case 1
|
|
|
+ Hint("看到右下角的那面小白旗了吗?")
|
|
|
+ Case 2
|
|
|
+ Hint("这里建议点一下右下角的小白旗投降呢.jpg")
|
|
|
+ Case 3
|
|
|
+ Hint("右下角的小白旗永远等着你……")
|
|
|
+ End Select
|
|
|
+ End If
|
|
|
+
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "愚人节移动出错", LogLevel.Feedback)
|
|
|
+ End Try
|
|
|
+ End Sub
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+#Region "系统"
|
|
|
+
|
|
|
+ ''' <summary>
|
|
|
+ ''' 把某个 PCL 窗口拖到最前面。
|
|
|
+ ''' </summary>
|
|
|
+ Public Sub ShowWindowToTop(Handle As IntPtr)
|
|
|
+ Try
|
|
|
+ PostMessage(Handle, 400 * 16 + 2, 0, 0)
|
|
|
+ SetForegroundWindow(Handle) '不在这里放不行,神秘 WinAPI,建议别动
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "设置窗口置顶失败", LogLevel.Hint)
|
|
|
+ End Try
|
|
|
+ End Sub
|
|
|
+ Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ClassName As String, WindowName As String) As IntPtr
|
|
|
+ Public Declare Function SetForegroundWindow Lib "user32" (hWnd As IntPtr) As Integer
|
|
|
+ Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (hWnd As IntPtr, msg As UInteger, wParam As Long, lParam As Long) As Boolean
|
|
|
+
|
|
|
+#End Region
|
|
|
+
|
|
|
+ Public DragControl = Nothing
|
|
|
+ Private Timer4Count As Integer = 0
|
|
|
+ Private Timer150Count As Integer = 0
|
|
|
+ Private Sub TimerMain()
|
|
|
+ Try
|
|
|
+#Region "每 50ms 执行一次的代码"
|
|
|
+ HintTick()
|
|
|
+ MyMsgBoxTick()
|
|
|
+ FrmMain.DragTick()
|
|
|
+ LoaderTaskbarProgressRefresh()
|
|
|
+ If ThemeDontClick = 2 Then ThemeRefresh()
|
|
|
+#End Region
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "短程主时钟执行异常", LogLevel.Assert)
|
|
|
+ End Try
|
|
|
+ Timer4Count += 1
|
|
|
+ If Timer4Count = 4 Then
|
|
|
+ Timer4Count = 0
|
|
|
+ Try
|
|
|
+#Region "每 250ms 执行一次的代码"
|
|
|
+ If ThemeNow = 12 Then ThemeRefresh()
|
|
|
+#End Region
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "中程主时钟执行异常", LogLevel.Debug)
|
|
|
+ End Try
|
|
|
+ End If
|
|
|
+ Timer150Count += 1
|
|
|
+ If Timer150Count = 150 Then
|
|
|
+ Timer150Count = 0
|
|
|
+ Try
|
|
|
+#Region "每 7.5s 执行一次的代码"
|
|
|
+ If FrmMain.BtnExtraApril_ShowCheck AndAlso AprilDistance <> 0 Then FrmMain.BtnExtraApril.Ribble()
|
|
|
+ '以未知原因窗口被丢到一边去的修复(Top、Left = -25600),还有 #745
|
|
|
+ RunInUi(Sub()
|
|
|
+ If Not FrmMain.Hidden Then
|
|
|
+ If FrmMain.Top < -9000 Then FrmMain.Top = 100
|
|
|
+ If FrmMain.Left < -9000 Then FrmMain.Left = 100 '窗口拉至最大时 Left = -18.8
|
|
|
+ End If
|
|
|
+ End Sub)
|
|
|
+#End Region
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "长程主时钟执行异常", LogLevel.Assert)
|
|
|
+ End Try
|
|
|
+ End If
|
|
|
+ End Sub
|
|
|
+ Public Sub TimerMainStart()
|
|
|
+ RunInNewThread(
|
|
|
+ Sub()
|
|
|
+ Try
|
|
|
+ Do While True
|
|
|
+ RunInUiWait(AddressOf TimerMain)
|
|
|
+ Thread.Sleep(50 * 0.98)
|
|
|
+ Loop
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "程序主时钟出错", LogLevel.Feedback)
|
|
|
+ End Try
|
|
|
+ End Sub, "Timer Main")
|
|
|
+ If Not IsAprilEnabled Then Exit Sub
|
|
|
+ RunInNewThread(
|
|
|
+ Sub()
|
|
|
+ Try
|
|
|
+ Dim LastTime = My.Computer.Clock.TickCount
|
|
|
+ Do While True
|
|
|
+ If LastTime <> My.Computer.Clock.TickCount Then
|
|
|
+ LastTime = My.Computer.Clock.TickCount
|
|
|
+ RunInUiWait(AddressOf TimerFool)
|
|
|
+ End If
|
|
|
+ Thread.Sleep(1)
|
|
|
+ Loop
|
|
|
+ Catch ex As Exception
|
|
|
+ Log(ex, "愚人节主时钟出错", LogLevel.Feedback)
|
|
|
+ End Try
|
|
|
+ End Sub, "Timer Main Fool")
|
|
|
+ End Sub
|
|
|
+
|
|
|
+End Module
|