MyCfItem.xaml.vb 8.6 KB

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