MyCfItem.xaml.vb 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. Public Class MyCfItem
  2. Public Uuid As Integer = GetUuid()
  3. #Region "Logo"
  4. Private _Logo As String = ""
  5. Public Property Logo As String
  6. Get
  7. Return _Logo
  8. End Get
  9. Set(value As String)
  10. If _Logo = value OrElse value Is Nothing Then Exit Property
  11. _Logo = value
  12. Dim FileAddress = PathTemp & "CFLogo\" & GetHash(_Logo) & ".png"
  13. Try
  14. If _Logo.ToLower.StartsWith("http") Then
  15. '网络图片
  16. If File.Exists(FileAddress) Then
  17. PathLogo.Source = New MyBitmap(FileAddress)
  18. Else
  19. PathLogo.Source = New MyBitmap("pack://application:,,,/images/Icons/NoIcon.png")
  20. RunInNewThread(Sub() LogoLoader(FileAddress), "CurseForge Logo Loader " & Uuid & "#", ThreadPriority.BelowNormal)
  21. End If
  22. Else
  23. '位图
  24. PathLogo.Source = New MyBitmap(_Logo)
  25. End If
  26. Catch ex As IOException
  27. Log(ex, "加载 CurseForge 工程图标时读取失败(" & FileAddress & ")")
  28. Catch ex As ArgumentException
  29. '考虑缓存的图片本身可能有误
  30. Log(ex, "可视化 CurseForge 工程图标失败(" & FileAddress & ")")
  31. Try
  32. File.Delete(FileAddress)
  33. Log("[Download] 已清理损坏的 CurseForge 工程图标:" & FileAddress)
  34. Catch exx As Exception
  35. Log(exx, "清理损坏的 CurseForge 工程图标缓存失败(" & FileAddress & ")", LogLevel.Hint)
  36. End Try
  37. Catch ex As Exception
  38. Log(ex, "加载 CurseForge 工程图标失败(" & value & ")")
  39. End Try
  40. End Set
  41. End Property
  42. Private Sub LogoLoader(Address As String)
  43. Dim Retry As Boolean = False
  44. Dim DownloadEnd As String = GetUuid()
  45. RetryStart:
  46. Try
  47. NetDownload(_Logo, Address & DownloadEnd)
  48. RunInUiWait(Sub()
  49. Try
  50. '在地址更换时取消加载
  51. If Not Address = PathTemp & "CFLogo\" & GetHash(_Logo) & ".png" Then Exit Sub
  52. '在完成正常加载后才保存缓存图片
  53. PathLogo.Source = New MyBitmap(Address & DownloadEnd)
  54. Catch ex As Exception
  55. Log(ex, "读取 CurseForge 工程图标失败(" & Address & ")", LogLevel.Hint)
  56. End Try
  57. End Sub)
  58. If File.Exists(Address) Then
  59. File.Delete(Address & DownloadEnd)
  60. Else
  61. FileIO.FileSystem.MoveFile(Address & DownloadEnd, Address)
  62. End If
  63. Catch ex As Exception
  64. If Not Retry Then
  65. Retry = True
  66. GoTo RetryStart
  67. Else
  68. Log(ex, "下载 CurseForge 工程图标失败")
  69. End If
  70. End Try
  71. End Sub
  72. #End Region
  73. #Region "点击"
  74. '触发点击事件
  75. Public Event Click(sender As Object, e As MouseButtonEventArgs)
  76. Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonUp
  77. If IsMouseDown Then
  78. RaiseEvent Click(sender, e)
  79. If e.Handled Then Exit Sub
  80. Log("[Control] 按下 CurseForge 工程列表项:" & LabTitle.Text)
  81. End If
  82. End Sub
  83. '鼠标点击判定
  84. Private IsMouseDown As Boolean = False
  85. Private Sub Button_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonDown
  86. If IsMouseOver Then IsMouseDown = True
  87. End Sub
  88. Private Sub Button_MouseLeave(sender As Object, e As Object) Handles Me.MouseLeave, Me.PreviewMouseLeftButtonUp
  89. IsMouseDown = False
  90. End Sub
  91. #End Region
  92. #Region "后加载指向背景"
  93. Private _RectBack As Border = Nothing
  94. Public ReadOnly Property RectBack As Border
  95. Get
  96. If _RectBack Is Nothing Then
  97. Dim Rect As New Border With {
  98. .Name = "RectBack",
  99. .CornerRadius = New CornerRadius(3),
  100. .RenderTransform = New ScaleTransform(0.8, 0.8),
  101. .RenderTransformOrigin = New Point(0.5, 0.5),
  102. .BorderThickness = New Thickness(GetWPFSize(1)),
  103. .SnapsToDevicePixels = True,
  104. .IsHitTestVisible = False,
  105. .Opacity = 0
  106. }
  107. Rect.SetResourceReference(Border.BackgroundProperty, "ColorBrush7")
  108. Rect.SetResourceReference(Border.BorderBrushProperty, "ColorBrush6")
  109. SetColumnSpan(Rect, 999)
  110. SetRowSpan(Rect, 999)
  111. Children.Insert(0, Rect)
  112. _RectBack = Rect
  113. '<!--<Border x:Name = "RectBack" CornerRadius="3" RenderTransformOrigin="0.5,0.5" SnapsToDevicePixels="True"
  114. 'IsHitTestVisible = "False" Opacity="0" BorderThickness="1"
  115. 'Grid.ColumnSpan = "4" Background="{DynamicResource ColorBrush7}" BorderBrush="{DynamicResource ColorBrush6}"/>-->
  116. End If
  117. Return _RectBack
  118. End Get
  119. End Property
  120. #End Region
  121. Private StateLast As String
  122. Public HasAnimation As Boolean = True
  123. Public Sub RefreshColor(sender As Object, e As EventArgs) Handles Me.MouseEnter, Me.MouseLeave, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp
  124. If Not HasAnimation Then Exit Sub
  125. '判断当前颜色
  126. Dim StateNew As String, Time As Integer
  127. If IsMouseOver Then
  128. If IsMouseDown Then
  129. StateNew = "MouseDown"
  130. Time = 120
  131. Else
  132. StateNew = "MouseOver"
  133. Time = 120
  134. End If
  135. Else
  136. StateNew = "Idle"
  137. Time = 180
  138. End If
  139. If StateLast = StateNew Then Exit Sub
  140. StateLast = StateNew
  141. '触发颜色动画
  142. If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
  143. '有动画
  144. Dim Ani As New List(Of AniData)
  145. If IsMouseOver Then
  146. Ani.AddRange({
  147. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrushBg1"), Time),
  148. AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
  149. })
  150. If IsMouseDown Then
  151. Ani.Add(AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  152. Else
  153. Ani.Add(AaScaleTransform(RectBack, 1 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  154. End If
  155. Else
  156. Ani.AddRange({
  157. AaOpacity(RectBack, -RectBack.Opacity, Time),
  158. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush7"), Time),
  159. AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time,, New AniEaseOutFluent),
  160. AaScaleTransform(RectBack, -0.196, 1,,, True)
  161. })
  162. End If
  163. AniStart(Ani, "CfItem Color " & Uuid)
  164. Else
  165. '无动画
  166. AniStop("CfItem Color " & Uuid)
  167. If _RectBack IsNot Nothing Then RectBack.Opacity = 0
  168. End If
  169. End Sub
  170. '指向时扩展描述
  171. Private Sub LabInfo_MouseEnter(sender As Object, e As MouseEventArgs) Handles LabInfo.MouseEnter
  172. If IsTextTrimmed(LabInfo) Then
  173. ToolTipInfo.Content = LabInfo.Text
  174. ToolTipInfo.Width = LabInfo.ActualWidth + 25
  175. LabInfo.ToolTip = ToolTipInfo
  176. Else
  177. LabInfo.ToolTip = Nothing
  178. End If
  179. End Sub
  180. Private Function IsTextTrimmed(textBlock As TextBlock) As Boolean
  181. Dim typeface As New Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch)
  182. Dim formattedText As New FormattedText(textBlock.Text, Thread.CurrentThread.CurrentCulture, textBlock.FlowDirection, typeface, textBlock.FontSize, textBlock.Foreground, DPI)
  183. Return formattedText.Width > textBlock.ActualWidth
  184. End Function
  185. End Class