PageLaunchLeft.xaml.vb 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. Public Class PageLaunchLeft
  2. '加载当前版本
  3. Private IsLoad As Boolean = False
  4. Private IsLoadFinished As Boolean = False
  5. Public Sub PageLaunchLeft_Loaded() Handles Me.Loaded
  6. If IsLoad Then RefreshPage(True, False)
  7. AprilPosTrans.X = 0
  8. AprilPosTrans.Y = 0
  9. If IsLoad Then Exit Sub
  10. IsLoad = True
  11. AniControlEnabled += 1
  12. '开始按钮
  13. AddHandler McVersionListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
  14. AddHandler McFolderListLoader.LoadingStateChanged, AddressOf RefreshButtonsUI
  15. RefreshButtonsUI()
  16. '加载版本
  17. RunInNewThread(
  18. Sub()
  19. '自动整合包安装:准备
  20. Dim PackInstallPath As String = Nothing
  21. If File.Exists(Path & "modpack.zip") Then PackInstallPath = Path & "modpack.zip"
  22. If File.Exists(Path & "modpack.mrpack") Then PackInstallPath = Path & "modpack.mrpack"
  23. If PackInstallPath IsNot Nothing Then
  24. Log("[Launch] 需自动安装整合包:" & PackInstallPath, LogLevel.Debug)
  25. Setup.Set("LaunchFolderSelect", "$.minecraft\")
  26. If Not Directory.Exists(Path & ".minecraft\") Then
  27. Directory.CreateDirectory(Path & ".minecraft\")
  28. Directory.CreateDirectory(Path & ".minecraft\versions\")
  29. McFolderLauncherProfilesJsonCreate(Path & ".minecraft\")
  30. End If
  31. PageSelectLeft.AddFolder(Path & ".minecraft\", GetFolderNameFromPath(Path), False)
  32. McFolderListLoader.WaitForExit()
  33. End If
  34. '确认 Minecraft 文件夹存在
  35. PathMcFolder = Setup.Get("LaunchFolderSelect").ToString.Replace("$", Path)
  36. If PathMcFolder = "" OrElse Not Directory.Exists(PathMcFolder) Then
  37. '无效的文件夹
  38. If PathMcFolder = "" Then
  39. Log("[Launch] 没有已储存的 Minecraft 文件夹")
  40. Else
  41. Log("[Launch] Minecraft 文件夹无效,该文件夹已不存在:" & PathMcFolder, LogLevel.Debug)
  42. End If
  43. McFolderListLoader.WaitForExit(IsForceRestart:=True)
  44. Setup.Set("LaunchFolderSelect", McFolderList(0).Path.Replace(Path, "$"))
  45. End If
  46. Log("[Launch] Minecraft 文件夹:" & PathMcFolder)
  47. If Setup.Get("SystemDebugDelay") Then Thread.Sleep(RandomInteger(500, 3000))
  48. '自动整合包安装
  49. If PackInstallPath IsNot Nothing Then
  50. Try
  51. Dim InstallLoader = ModpackInstall(PackInstallPath)
  52. Log("[Launch] 自动安装整合包已开始:" & PackInstallPath)
  53. InstallLoader.WaitForExit()
  54. If InstallLoader.State = LoadState.Finished Then
  55. Log("[Launch] 自动安装整合包成功,清理安装包:" & PackInstallPath)
  56. If File.Exists(PackInstallPath) Then File.Delete(PackInstallPath)
  57. End If
  58. Catch ex As CancelledException
  59. Log(ex, "自动安装整合包被用户取消:" & PackInstallPath)
  60. Catch ex As Exception
  61. Log(ex, "自动安装整合包失败:" & PackInstallPath, LogLevel.Msgbox)
  62. End Try
  63. End If
  64. '确认 Minecraft 版本存在
  65. Dim Selection As String = Setup.Get("LaunchVersionSelect")
  66. Dim Version As McVersion = If(Selection = "", Nothing, New McVersion(Selection))
  67. If Version Is Nothing OrElse Not Version.Path.StartsWithF(PathMcFolder) OrElse Not Version.Check() Then
  68. '无效的版本
  69. Log("[Launch] 当前选择的 Minecraft 版本无效:" & If(Version Is Nothing, "null", Version.Path), If(IsNothing(Version), LogLevel.Normal, LogLevel.Debug))
  70. If Not McVersionListLoader.State = LoadState.Finished Then LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
  71. If Not McVersionList.Any() OrElse McVersionList.First.Value(0).Logo.Contains("RedstoneBlock") Then
  72. Version = Nothing
  73. Setup.Set("LaunchVersionSelect", "")
  74. Log("[Launch] 无可用 Minecraft 版本")
  75. Else
  76. Version = McVersionList.First.Value(0)
  77. Setup.Set("LaunchVersionSelect", Version.Name)
  78. Log("[Launch] 自动选择 Minecraft 版本:" & Version.Path)
  79. End If
  80. End If
  81. RunInUi(
  82. Sub()
  83. McVersionCurrent = Version '绕这一圈是为了避免 McVersionCheck 触发第二次版本改变
  84. IsLoadFinished = True
  85. RefreshButtonsUI()
  86. RefreshPage(False, False) '有可能选择的版本变化了,需要重新刷新
  87. If McLoginAble() = "" Then McLoginLoader.Start() '自动登录
  88. End Sub)
  89. End Sub, "Version Check", ThreadPriority.AboveNormal)
  90. '改变页面
  91. Dim LoginType As McLoginType = Setup.Get("LoginType")
  92. If LoginType = McLoginType.Legacy OrElse LoginType = McLoginType.Ms Then CType(FindName("RadioLoginType" & LoginType), MyRadioButton).Checked = True
  93. RefreshPage(False, False)
  94. AniControlEnabled -= 1
  95. End Sub
  96. #Region "切换大页面"
  97. ''' <summary>
  98. ''' 切换至启动中页面。
  99. ''' </summary>
  100. Public Sub PageChangeToLaunching()
  101. '修改登陆方式
  102. Select Case Setup.Get("LoginType")
  103. Case McLoginType.Legacy
  104. If PageLinkHiper.HiperState = LoadState.Finished Then
  105. LabLaunchingMethod.Text = "联机离线登录"
  106. Else
  107. LabLaunchingMethod.Text = "离线登录"
  108. End If
  109. Case McLoginType.Ms
  110. LabLaunchingMethod.Text = "正版登录"
  111. Case McLoginType.Nide
  112. LabLaunchingMethod.Text = "统一通行证"
  113. Case McLoginType.Auth
  114. LabLaunchingMethod.Text = "Authlib-Injector"
  115. End Select
  116. '初始化页面
  117. LabLaunchingName.Text = McVersionCurrent.Name
  118. LabLaunchingStage.Text = "初始化"
  119. LabLaunchingTitle.Text = If(CurrentLaunchOptions?.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本")
  120. LabLaunchingProgress.Text = "0.00 %"
  121. LabLaunchingProgress.Opacity = 1
  122. LabLaunchingDownload.Visibility = Visibility.Visible
  123. LabLaunchingProgressLeft.Opacity = 0.6
  124. LabLaunchingDownload.Visibility = Visibility.Visible
  125. LabLaunchingDownload.Text = "0 B/s"
  126. LabLaunchingDownload.Opacity = 0
  127. LabLaunchingDownload.Visibility = Visibility.Collapsed
  128. LabLaunchingDownloadLeft.Opacity = 0
  129. LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
  130. ProgressLaunchingFinished.Width = New GridLength(0, GridUnitType.Star)
  131. ProgressLaunchingUnfinished.Width = New GridLength(1, GridUnitType.Star)
  132. PanLaunchingHint.Opacity = 0
  133. PanLaunchingHint.Visibility = Visibility.Collapsed
  134. PanLaunchingInfo.Width = Double.NaN '重置宽度改变动画
  135. McLaunchProcess = Nothing
  136. McLaunchWatcher = Nothing
  137. '获取 “你知道吗” 提示
  138. LabLaunchingHint.Text = PageOtherTest.GetRandomHint()
  139. '初始化其他页面
  140. PanInput.IsHitTestVisible = False
  141. PanLaunching.IsHitTestVisible = False
  142. LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Run
  143. PanLaunching.Visibility = Visibility.Visible
  144. AniStart({
  145. AaOpacity(PanInput, 0, 50), '略作延迟,这样如果预检测失败,不会出现奇怪的弹一下的动画
  146. AaOpacity(PanInput, -PanInput.Opacity, 110, , New AniEaseInFluent, True),
  147. AaScaleTransform(PanInput, 1.2 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 160),
  148. AaOpacity(PanLaunching, 1 - PanLaunching.Opacity, 150, 100),
  149. AaScaleTransform(PanLaunching, 1 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 500, 100, New AniEaseOutBack(AniEasePower.Weak)),
  150. AaCode(Sub() PanLaunching.IsHitTestVisible = True, 150)
  151. }, "Launch State Page")
  152. End Sub
  153. ''' <summary>
  154. ''' 切换至登录页面。
  155. ''' </summary>
  156. Public Sub PageChangeToLogin()
  157. PageGet(PageCurrent).Reload(KeepInput:=False)
  158. PanInput.IsHitTestVisible = False
  159. PanLaunching.IsHitTestVisible = False
  160. LoadLaunching.State.LoadingState = MyLoading.MyLoadingState.Stop
  161. PanInput.Visibility = Visibility.Visible
  162. AniStart({
  163. AaOpacity(PanLaunching, -PanLaunching.Opacity, 150),
  164. AaScaleTransform(PanLaunching, 0.8 - CType(PanLaunching.RenderTransform, ScaleTransform).ScaleX, 150,, New AniEaseOutFluent(AniEasePower.Weak)),
  165. AaOpacity(PanInput, 1 - PanInput.Opacity, 250, 50),
  166. AaScaleTransform(PanInput, 1 - CType(PanInput.RenderTransform, ScaleTransform).ScaleX, 300, 50, New AniEaseOutBack(AniEasePower.Weak)),
  167. AaCode(Sub() PanInput.IsHitTestVisible = True, 200)
  168. }, "Launch State Page", True)
  169. End Sub
  170. #End Region
  171. #Region "切换登录页面"
  172. Private Enum PageType
  173. None
  174. Legacy
  175. Nide
  176. NideSkin
  177. Auth
  178. AuthSkin
  179. Ms
  180. MsSkin
  181. End Enum
  182. ''' <summary>
  183. ''' 当前页面的种类。
  184. ''' </summary>
  185. Private PageCurrent As PageType = PageType.None
  186. Private Function PageGet(Type As PageType)
  187. Select Case Type
  188. Case PageType.Legacy
  189. If IsNothing(FrmLoginLegacy) Then FrmLoginLegacy = New PageLoginLegacy
  190. Return FrmLoginLegacy
  191. Case PageType.Nide
  192. If IsNothing(FrmLoginNide) Then FrmLoginNide = New PageLoginNide
  193. Return FrmLoginNide
  194. Case PageType.NideSkin
  195. If IsNothing(FrmLoginNideSkin) Then FrmLoginNideSkin = New PageLoginNideSkin
  196. Return FrmLoginNideSkin
  197. Case PageType.Auth
  198. If IsNothing(FrmLoginAuth) Then FrmLoginAuth = New PageLoginAuth
  199. Return FrmLoginAuth
  200. Case PageType.AuthSkin
  201. If IsNothing(FrmLoginAuthSkin) Then FrmLoginAuthSkin = New PageLoginAuthSkin
  202. Return FrmLoginAuthSkin
  203. Case PageType.Ms
  204. If IsNothing(FrmLoginMs) Then FrmLoginMs = New PageLoginMs
  205. Return FrmLoginMs
  206. Case PageType.MsSkin
  207. If IsNothing(FrmLoginMsSkin) Then FrmLoginMsSkin = New PageLoginMsSkin
  208. Return FrmLoginMsSkin
  209. Case Else
  210. Throw New ArgumentOutOfRangeException("Type", "即将切换的登录分页编号越界")
  211. End Select
  212. End Function
  213. ''' <summary>
  214. ''' 切换现有登录页面种类,返回新页面的实例。
  215. ''' </summary>
  216. ''' <param name="Type">新页面的种类。</param>
  217. ''' <param name="Anim">是否显示动画。</param>
  218. Private Function PageChange(Type As PageType, Anim As Boolean)
  219. Dim PageNew As Object = FrmLoginMs '初始化一个东西,避免在执行时出现异常导致雪崩
  220. Try
  221. #Region "确定更改的页面实例并实例化"
  222. If PageCurrent = Type Then Return PageNew
  223. PageNew = PageGet(Type)
  224. #End Region
  225. #Region "切换页面"
  226. AniStop("FrmLogin PageChange")
  227. '清除页面关联性
  228. If Not IsNothing(PageNew) AndAlso Not IsNothing(PageNew.Parent) Then PageNew.SetValue(ContentPresenter.ContentProperty, Nothing)
  229. If Anim Then
  230. '动画
  231. Dispatcher.Invoke(Sub()
  232. '执行动画
  233. AniStart({
  234. AaOpacity(PanLogin, -PanLogin.Opacity, 100,, New AniEaseOutFluent),
  235. AaCode(Sub()
  236. AniControlEnabled += 1
  237. PanLogin.Children.Clear()
  238. PanLogin.Children.Add(PageNew)
  239. AniControlEnabled -= 1
  240. End Sub, 100),
  241. AaOpacity(PanLogin, 1, 100, 120, New AniEaseInFluent)
  242. }, "FrmLogin PageChange")
  243. End Sub, Threading.DispatcherPriority.Render)
  244. Else
  245. '无动画
  246. AniControlEnabled += 1
  247. PanLogin.Children.Clear()
  248. PanLogin.Children.Add(PageNew)
  249. AniControlEnabled -= 1
  250. End If
  251. #End Region
  252. PageCurrent = Type
  253. Return PageNew
  254. Catch ex As Exception
  255. Log(ex, "切换登录分页失败(" & GetStringFromEnum(CType(Type, [Enum])) & ")", LogLevel.Feedback)
  256. Return PageNew
  257. End Try
  258. End Function
  259. ''' <summary>
  260. ''' 确认当前显示的子页面正确,并刷新该页面。
  261. ''' </summary>
  262. Public Sub RefreshPage(KeepInput As Boolean, Anim As Boolean)
  263. '获取页面的可用种类并回写缓存
  264. Dim Type As PageType
  265. Dim LoginPageType As Integer
  266. If McVersionCurrent IsNot Nothing Then
  267. LoginPageType = Setup.Get("VersionServerLogin", Version:=McVersionCurrent)
  268. '缓存当前版本的页面种类,下一次打开 McVersionCurrent 为空时才能加载出正确的页面
  269. Setup.Set("LoginPageType", LoginPageType)
  270. Else
  271. LoginPageType = Setup.Get("LoginPageType")
  272. End If
  273. Select Case LoginPageType
  274. Case 0 '正版或离线
  275. UnknownType:
  276. If RadioLoginType5.Checked Then
  277. If Setup.Get("CacheMsV2Access") = "" Then
  278. Type = PageType.Ms
  279. Else
  280. Type = PageType.MsSkin
  281. End If
  282. Setup.Set("LoginType", McLoginType.Ms)
  283. Else
  284. Type = PageType.Legacy
  285. Setup.Set("LoginType", McLoginType.Legacy)
  286. End If
  287. PanType.Visibility = Visibility.Visible
  288. PanTypeOne.Visibility = Visibility.Collapsed
  289. RadioLoginType5.Visibility = Visibility.Visible
  290. RadioLoginType0.Visibility = Visibility.Visible
  291. Case 1 '仅正版
  292. If Setup.Get("CacheMsV2Access") = "" Then
  293. Type = PageType.Ms
  294. Else
  295. Type = PageType.MsSkin
  296. End If
  297. Setup.Set("LoginType", McLoginType.Ms)
  298. PanType.Visibility = Visibility.Collapsed
  299. PanTypeOne.Visibility = Visibility.Visible
  300. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonShield)
  301. LabTypeOne.Text = "正版登录"
  302. RadioLoginType5.Visibility = Visibility.Visible
  303. RadioLoginType0.Visibility = Visibility.Collapsed
  304. Case 2 '仅离线
  305. Type = PageType.Legacy
  306. Setup.Set("LoginType", McLoginType.Legacy)
  307. PanType.Visibility = Visibility.Collapsed
  308. PanTypeOne.Visibility = Visibility.Visible
  309. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonOffline)
  310. LabTypeOne.Text = "离线登录"
  311. Case 3 '统一通行证
  312. If Setup.Get("CacheNideAccess") = "" Then
  313. Type = PageType.Nide
  314. Else
  315. Type = PageType.NideSkin
  316. End If
  317. Setup.Set("LoginType", McLoginType.Nide)
  318. PanType.Visibility = Visibility.Collapsed
  319. PanTypeOne.Visibility = Visibility.Visible
  320. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
  321. LabTypeOne.Text = "统一通行证登录"
  322. Case 4 'Authlib-Injector
  323. If Setup.Get("CacheAuthAccess") = "" Then
  324. Type = PageType.Auth
  325. Else
  326. Type = PageType.AuthSkin
  327. End If
  328. Setup.Set("LoginType", McLoginType.Auth)
  329. PanType.Visibility = Visibility.Collapsed
  330. PanTypeOne.Visibility = Visibility.Visible
  331. PathTypeOne.Data = (New GeometryConverter).ConvertFromString(Logo.IconButtonCard)
  332. LabTypeOne.Text = If(McVersionCurrent Is Nothing, Setup.Get("CacheAuthServerName"), Setup.Get("VersionServerAuthName", Version:=McVersionCurrent))
  333. If LabTypeOne.Text = "" Then LabTypeOne.Text = "第三方登录"
  334. Case Else
  335. Log("[Control] 未知的登录页面:" & LoginPageType, LogLevel.Hint)
  336. GoTo UnknownType
  337. End Select
  338. '刷新页面
  339. If PageCurrent = Type Then Exit Sub
  340. PageChange(Type, Anim).Reload(KeepInput)
  341. Dim Control As MyRadioButton = FindName("RadioLoginType" & Setup.Get("LoginType"))
  342. If Control IsNot Nothing Then Control.Checked = True
  343. End Sub
  344. Private Sub RadioLoginType_Change(sender As Object, raiseByMouse As Boolean) Handles RadioLoginType0.Check, RadioLoginType5.Check
  345. If raiseByMouse Then RefreshPage(True, True)
  346. End Sub
  347. #End Region
  348. #Region "皮肤"
  349. '微软正版皮肤
  350. Public Shared SkinMs As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Ms", AddressOf SkinMsLoad, AddressOf SkinMsInput, ThreadPriority.AboveNormal)
  351. Private Shared Function SkinMsInput() As EqualableList(Of String)
  352. '获取名称
  353. Return New EqualableList(Of String) From {Setup.Get("CacheMsV2Name"), Setup.Get("CacheMsV2Uuid")}
  354. End Function
  355. Private Shared Sub SkinMsLoad(Data As LoaderTask(Of EqualableList(Of String), String))
  356. '清空已有皮肤
  357. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  358. RunInUi(Sub() If FrmLoginMsSkin IsNot Nothing AndAlso FrmLoginMsSkin.Skin IsNot Nothing Then FrmLoginMsSkin.Skin.Clear())
  359. '获取 Url
  360. Dim UserName As String = Data.Input(0)
  361. Dim Uuid As String = Data.Input(1)
  362. If UserName = "" Then
  363. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  364. Log("[Minecraft] 获取微软正版皮肤失败,ID 为空")
  365. GoTo Finish
  366. End If
  367. Try
  368. Dim Result As String = McSkinGetAddress(Uuid, "Ms")
  369. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  370. Result = McSkinDownload(Result)
  371. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  372. Data.Output = Result
  373. Catch ex As Exception
  374. If ex.GetType.Name = "ThreadInterruptedException" Then
  375. Data.Output = ""
  376. Exit Sub
  377. ElseIf GetExceptionSummary(ex).Contains("429") Then
  378. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  379. Log("[Minecraft] 获取正版皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
  380. ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
  381. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  382. Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
  383. Else
  384. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  385. Log(ex, "获取微软正版皮肤失败(" & UserName & ")", LogLevel.Hint)
  386. End If
  387. End Try
  388. Finish:
  389. '刷新显示
  390. If FrmLoginMsSkin IsNot Nothing Then
  391. RunInUi(AddressOf FrmLoginMsSkin.Skin.Load)
  392. ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
  393. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  394. End If
  395. End Sub
  396. '离线皮肤
  397. Public Shared SkinLegacy As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Legacy", AddressOf SkinLegacyLoad, AddressOf SkinLegacyInput, ThreadPriority.AboveNormal)
  398. Private Shared Function SkinLegacyInput() As EqualableList(Of String)
  399. '根据类型判断输入
  400. Dim Type As Integer = Setup.Get("LaunchSkinType")
  401. Select Case Type
  402. Case 0
  403. If FrmLoginLegacy IsNot Nothing AndAlso FrmLoginLegacy.IsReloaded Then
  404. Return New EqualableList(Of String) From {0, If(FrmLoginLegacy.ComboName.Text.Trim, "")}
  405. ElseIf Setup.Get("LoginLegacyName") = "" Then
  406. Return New EqualableList(Of String) From {0, ""}
  407. Else
  408. Return New EqualableList(Of String) From {0, If(Setup.Get("LoginLegacyName").ToString.BeforeFirst("¨"), "")}
  409. End If
  410. Case 3
  411. Return New EqualableList(Of String) From {3, Setup.Get("LaunchSkinID")}
  412. Case Else
  413. Return New EqualableList(Of String) From {Type}
  414. End Select
  415. End Function
  416. Private Shared Sub SkinLegacyLoad(Data As LoaderTask(Of EqualableList(Of String), String))
  417. '清空已有皮肤
  418. RunInUi(Sub() If FrmLoginLegacy IsNot Nothing AndAlso FrmLoginLegacy.Skin IsNot Nothing Then FrmLoginLegacy.Skin.Clear())
  419. '获取 Url
  420. Select Case Data.Input(0)
  421. Case 0 '默认
  422. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(Data.Input(1))) & ".png"
  423. Case 1 'Steve
  424. UseDefault:
  425. Data.Output = PathImage & "Skins/Steve.png"
  426. Case 2 'Alex
  427. Data.Output = PathImage & "Skins/Alex.png"
  428. Case 3 '正版
  429. Dim ID As String = Data.Input(1)
  430. Try
  431. If ID.Count < 2 Then
  432. Data.Output = PathImage & "Skins/Steve.png"
  433. Else
  434. Dim Result As String = McLoginMojangUuid(ID, True)
  435. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
  436. Result = McSkinGetAddress(Result, "Mojang")
  437. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
  438. Result = McSkinDownload(Result)
  439. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & ID)
  440. Data.Output = Result
  441. End If
  442. Catch ex As Exception
  443. If ex.GetType.Name = "ThreadInterruptedException" Then
  444. Data.Output = ""
  445. Exit Sub
  446. ElseIf GetExceptionSummary(ex).Contains("429") Then
  447. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
  448. Log("获取离线登录使用的正版皮肤失败(" & ID & "):获取皮肤太过频繁,请 5 分钟后再试!")
  449. Else
  450. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(ID)) & ".png"
  451. Log(ex, "获取离线登录使用的正版皮肤失败(" & ID & ")")
  452. End If
  453. End Try
  454. Case 4 '自定义
  455. If Not File.Exists(PathAppdata & "CustomSkin.png") Then
  456. Hint("未找到离线皮肤自定义文件,可能它已被删除。PCL 将使用默认的 Steve 皮肤!")
  457. Setup.Set("LaunchSkinType", 1)
  458. GoTo UseDefault
  459. End If
  460. Data.Output = PathAppdata & "CustomSkin.png"
  461. End Select
  462. '刷新显示
  463. If FrmLoginLegacy IsNot Nothing Then
  464. RunInUi(AddressOf FrmLoginLegacy.Skin.Load)
  465. ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
  466. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  467. End If
  468. End Sub
  469. '统一通行证皮肤
  470. Public Shared SkinNide As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Nide", AddressOf SkinNideLoad, AddressOf SkinNideInput, ThreadPriority.AboveNormal)
  471. Private Shared Function SkinNideInput() As EqualableList(Of String)
  472. '获取名称
  473. Return New EqualableList(Of String) From {Setup.Get("CacheNideName"), Setup.Get("CacheNideUuid")}
  474. End Function
  475. Private Shared Sub SkinNideLoad(Data As LoaderTask(Of EqualableList(Of String), String))
  476. '清空已有皮肤
  477. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  478. RunInUi(Sub() If FrmLoginNideSkin IsNot Nothing AndAlso FrmLoginNideSkin.Skin IsNot Nothing Then FrmLoginNideSkin.Skin.Clear())
  479. '获取 Url
  480. Dim UserName As String = Data.Input(0)
  481. Dim Uuid As String = Data.Input(1)
  482. If UserName = "" Then
  483. Data.Output = PathImage & "Skins/" & McSkinSex(McLoginLegacyUuid(UserName)) & ".png"
  484. Log("[Minecraft] 获取统一通行证皮肤失败,ID 为空")
  485. GoTo Finish
  486. End If
  487. Try
  488. Dim Result As String = McSkinGetAddress(Uuid, "Nide")
  489. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  490. Result = McSkinDownload(Result)
  491. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  492. Data.Output = Result
  493. Catch ex As Exception
  494. If ex.GetType.Name = "ThreadInterruptedException" Then
  495. Data.Output = ""
  496. Exit Sub
  497. ElseIf GetExceptionSummary(ex).Contains("429") Then
  498. Data.Output = PathImage & "Skins/Steve.png"
  499. Log("[Minecraft] 获取统一通行证皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
  500. ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
  501. Data.Output = PathImage & "Skins/Steve.png"
  502. Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
  503. Else
  504. Data.Output = PathImage & "Skins/Steve.png"
  505. Log(ex, "获取统一通行证皮肤失败(" & UserName & ")", LogLevel.Hint)
  506. End If
  507. End Try
  508. Finish:
  509. '刷新显示
  510. If FrmLoginNideSkin IsNot Nothing Then
  511. RunInUi(AddressOf FrmLoginNideSkin.Skin.Load)
  512. ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
  513. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  514. End If
  515. End Sub
  516. 'Authlib-Injector 皮肤
  517. Public Shared SkinAuth As New LoaderTask(Of EqualableList(Of String), String)("Loader Skin Auth", AddressOf SkinAuthLoad, AddressOf SkinAuthInput, ThreadPriority.AboveNormal)
  518. Private Shared Function SkinAuthInput() As EqualableList(Of String)
  519. '获取名称
  520. Return New EqualableList(Of String) From {Setup.Get("CacheAuthName"), Setup.Get("CacheAuthUuid")}
  521. End Function
  522. Private Shared Sub SkinAuthLoad(Data As LoaderTask(Of EqualableList(Of String), String))
  523. '清空已有皮肤
  524. '如果在输入时清空皮肤,若输入内容一样则不会执行 Load 方法,导致皮肤不被加载
  525. RunInUi(Sub() If FrmLoginAuthSkin IsNot Nothing AndAlso FrmLoginAuthSkin.Skin IsNot Nothing Then FrmLoginAuthSkin.Skin.Clear())
  526. '获取 Url
  527. Dim UserName As String = Data.Input(0)
  528. Dim Uuid As String = Data.Input(1)
  529. If UserName = "" Then
  530. Data.Output = PathImage & "Skins/Steve.png"
  531. Log("[Minecraft] 获取 Authlib-Injector 皮肤失败,ID 为空")
  532. GoTo Finish
  533. End If
  534. Try
  535. Dim Result As String = McSkinGetAddress(Uuid, "Auth")
  536. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  537. Result = McSkinDownload(Result)
  538. If Data.IsAborted Then Throw New ThreadInterruptedException("当前任务已取消:" & UserName)
  539. Data.Output = Result
  540. Catch ex As Exception
  541. If ex.GetType.Name = "ThreadInterruptedException" Then
  542. Data.Output = ""
  543. Exit Sub
  544. ElseIf GetExceptionSummary(ex).Contains("429") Then
  545. Data.Output = PathImage & "Skins/Steve.png"
  546. Log("[Minecraft] 获取 Authlib-Injector 皮肤失败(" & UserName & "):获取皮肤太过频繁,请 5 分钟后再试!", LogLevel.Hint)
  547. ElseIf GetExceptionSummary(ex).Contains("未设置自定义皮肤") Then
  548. Data.Output = PathImage & "Skins/Steve.png"
  549. Log("[Minecraft] 用户未设置自定义皮肤,跳过皮肤加载")
  550. Else
  551. Data.Output = PathImage & "Skins/Steve.png"
  552. Log(ex, "获取 Authlib-Injector 皮肤失败(" & UserName & ")", LogLevel.Hint)
  553. End If
  554. End Try
  555. Finish:
  556. '刷新显示
  557. If FrmLoginAuthSkin IsNot Nothing Then
  558. RunInUi(AddressOf FrmLoginAuthSkin.Skin.Load)
  559. ElseIf Not Data.IsAborted Then '如果已经中断,Input 也被清空,就不会再次刷新
  560. Data.Input = Nothing '清空输入,因为皮肤实际上没有被渲染,如果不清空切换到页面的 Start 会由于输入相同而不渲染
  561. End If
  562. End Sub
  563. '全部皮肤加载器
  564. '需要放在其中元素的后面,否则会因为它提前被加载而莫名其妙变成 Nothing
  565. Public Shared SkinLoaders As New List(Of LoaderTask(Of EqualableList(Of String), String)) From {SkinMs, SkinLegacy, SkinNide, SkinAuth}
  566. #End Region
  567. '版本选择按钮
  568. Private Sub BtnVersion_Click(sender As Object, e As EventArgs) Handles BtnVersion.Click
  569. If McLaunchLoader.State = LoadState.Loading Then Exit Sub
  570. FrmMain.PageChange(FormMain.PageType.VersionSelect)
  571. End Sub
  572. '启动按钮
  573. Public Sub LaunchButtonClick() Handles BtnLaunch.Click
  574. If McLaunchLoader.State = LoadState.Loading OrElse Not BtnLaunch.IsEnabled OrElse
  575. (FrmMain.PageRight IsNot Nothing AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentStay AndAlso FrmMain.PageRight.PageState <> MyPageRight.PageStates.ContentEnter) Then Exit Sub
  576. '愚人节处理
  577. If IsAprilEnabled AndAlso Not IsAprilGiveup Then
  578. ThemeUnlock(12, False, "隐藏主题 滑稽彩 已解锁!")
  579. IsAprilGiveup = True
  580. FrmLaunchLeft.AprilScaleTrans.ScaleX = 1
  581. FrmLaunchLeft.AprilScaleTrans.ScaleY = 1
  582. FrmLaunchLeft.AprilPosTrans.X = 0
  583. FrmLaunchLeft.AprilPosTrans.Y = 0
  584. FrmMain.BtnExtraApril.ShowRefresh()
  585. End If
  586. '实际的启动
  587. If BtnLaunch.Text = "启动游戏" Then
  588. McLaunchStart()
  589. ElseIf BtnLaunch.Text = "下载游戏" Then
  590. FrmMain.PageChange(FormMain.PageType.Download, FormMain.PageSubType.DownloadInstall)
  591. End If
  592. End Sub
  593. Private BtnLaunchState As Integer = 0
  594. Private BtnLaunchVersion As McVersion = Nothing
  595. Public Sub RefreshButtonsUI() Handles BtnLaunch.Loaded
  596. If Not BtnLaunch.IsLoaded Then Exit Sub
  597. '获取当前状态
  598. Dim CurrentState As Integer
  599. If (Not IsLoadFinished) OrElse McVersionListLoader.State = LoadState.Loading OrElse McFolderListLoader.State = LoadState.Loading Then
  600. CurrentState = 0
  601. Else
  602. If McVersionCurrent Is Nothing Then
  603. If Setup.Get("UiHiddenPageDownload") AndAlso Not PageSetupUI.HiddenForceShow Then
  604. CurrentState = 1
  605. Else
  606. CurrentState = 2
  607. End If
  608. Else
  609. CurrentState = 3
  610. End If
  611. End If
  612. '更新状态
  613. If CurrentState = BtnLaunchState AndAlso
  614. If(McVersionCurrent Is Nothing, "", McVersionCurrent.Path) = If(BtnLaunchVersion Is Nothing, "", BtnLaunchVersion.Path) Then GoTo ExitRefresh
  615. BtnLaunchVersion = McVersionCurrent
  616. BtnLaunchState = CurrentState
  617. Select Case CurrentState
  618. Case 0
  619. Log("[Minecraft] 启动按钮:正在加载 Minecraft 版本")
  620. FrmLaunchLeft.BtnLaunch.Text = "正在加载"
  621. FrmLaunchLeft.BtnLaunch.IsEnabled = False
  622. FrmLaunchLeft.LabVersion.Text = "正在加载中,请稍候"
  623. FrmLaunchLeft.BtnVersion.IsEnabled = False
  624. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  625. Case 1
  626. Log("[Minecraft] 启动按钮:无 Minecraft 版本,下载已禁用")
  627. FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
  628. FrmLaunchLeft.BtnLaunch.IsEnabled = False
  629. FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
  630. FrmLaunchLeft.BtnVersion.IsEnabled = True
  631. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  632. Case 2
  633. Log("[Minecraft] 启动按钮:无 Minecraft 版本,要求下载")
  634. FrmLaunchLeft.BtnLaunch.Text = "下载游戏"
  635. FrmLaunchLeft.BtnLaunch.IsEnabled = True
  636. FrmLaunchLeft.LabVersion.Text = "未找到可用的游戏版本"
  637. FrmLaunchLeft.BtnVersion.IsEnabled = True
  638. FrmLaunchLeft.BtnMore.Visibility = Visibility.Collapsed
  639. Case 3
  640. Log("[Minecraft] 启动按钮:Minecraft 版本:" & McVersionCurrent.Path)
  641. FrmLaunchLeft.BtnLaunch.Text = "启动游戏"
  642. FrmLaunchLeft.BtnVersion.IsEnabled = True
  643. FrmLaunchLeft.BtnLaunch.IsEnabled = True
  644. FrmLaunchLeft.LabVersion.Text = McVersionCurrent.Name
  645. 'FrmLaunchLeft.BtnMore.Visibility = Visibility.Visible '由功能隐藏设置修改
  646. End Select
  647. ExitRefresh:
  648. '功能隐藏
  649. FrmLaunchLeft.BtnVersion.Visibility = If(Not PageSetupUI.HiddenForceShow AndAlso Setup.Get("UiHiddenFunctionSelect"), Visibility.Collapsed, Visibility.Visible)
  650. If CurrentState = 3 Then
  651. FrmLaunchLeft.BtnMore.Visibility = FrmLaunchLeft.BtnVersion.Visibility
  652. End If
  653. End Sub
  654. '取消按钮
  655. Private Sub BtnCancel_Click() Handles BtnCancel.Click
  656. If McLaunchLoaderReal IsNot Nothing Then
  657. McLaunchLoaderReal.Abort()
  658. McLaunchLog("已取消启动")
  659. Try
  660. If McLaunchWatcher IsNot Nothing Then
  661. McLaunchWatcher.Kill()
  662. ElseIf McLaunchProcess IsNot Nothing Then
  663. If Not McLaunchProcess.HasExited Then McLaunchProcess.Kill()
  664. End If
  665. Catch ex As Exception
  666. Log(ex, "取消启动结束进程失败", LogLevel.Hint)
  667. End Try
  668. End If
  669. End Sub
  670. '版本设置按钮
  671. Private Sub BtnMore_Click(sender As Object, e As EventArgs) Handles BtnMore.Click
  672. If McLaunchLoader.State = LoadState.Loading Then Exit Sub
  673. McVersionCurrent.Load()
  674. PageVersionLeft.Version = McVersionCurrent
  675. FrmMain.PageChange(FormMain.PageType.VersionSetup, 0)
  676. End Sub
  677. ''' <summary>
  678. ''' 每 0.2s 执行一次,刷新启动的数据 UI 显示。
  679. ''' </summary>
  680. Public Sub LaunchingRefresh()
  681. Try
  682. If McLaunchLoaderReal.State = LoadState.Aborted Then Exit Sub
  683. '阶段状态获取
  684. Dim IsLaunched As Boolean = False '是否已经启动游戏,只是在等待窗口
  685. Try
  686. For Each Loader In McLaunchLoaderReal.GetLoaderList(False)
  687. If Loader.State = LoadState.Loading OrElse Loader.State = LoadState.Waiting Then
  688. LabLaunchingStage.Text = Loader.Name
  689. IsLaunched = Loader.Name = "等待游戏窗口出现" OrElse Loader.Name = "结束处理"
  690. Exit Try
  691. End If
  692. Next
  693. LabLaunchingStage.Text = "已完成"
  694. Catch ex As Exception
  695. Log(ex, "获取是否启动完成失败,可能是由于启动状态改变导致集合已修改")
  696. Exit Sub
  697. End Try
  698. If AniIsRun("Launch State Page") Then IsLaunched = False '等待页面切换动画完成
  699. '计算应显示的进度
  700. Dim ActualProgress = McLaunchLoaderReal.Progress
  701. If ActualProgress >= ShowProgress Then ShowProgress += (ActualProgress - ShowProgress) * 0.2 + 0.005 '向实际进度靠一点
  702. If ActualProgress <= ShowProgress Then ShowProgress = ActualProgress '原来或处理后变得比实际进度高,直接回退
  703. If IsLaunched Then ShowProgress = 1 '如果已经完成了,就不卖关子了
  704. '文本
  705. LabLaunchingTitle.Text = If(IsLaunched, "已启动游戏", If(CurrentLaunchOptions.SaveBatch Is Nothing, "正在启动游戏", "正在导出启动脚本"))
  706. LabLaunchingProgress.Text = StrFillNum(ShowProgress * 100, 2) & " %"
  707. Dim HasLaunchDownloader As Boolean = False
  708. Try
  709. For Each Loader In NetManager.Tasks
  710. If Loader.RealParent IsNot Nothing AndAlso Loader.RealParent.Name = "Minecraft 启动" AndAlso Loader.State = LoadState.Loading Then HasLaunchDownloader = True
  711. Next
  712. Catch ex As Exception
  713. Log(ex, "获取 Minecraft 启动下载器失败,可能是因为启动被取消")
  714. HasLaunchDownloader = False
  715. End Try
  716. LabLaunchingDownload.Text = GetString(NetManager.Speed) & "/s"
  717. '进度改变动画
  718. Dim AnimList As New List(Of AniData) From {
  719. AaGridLengthWidth(ProgressLaunchingFinished, ShowProgress - ProgressLaunchingFinished.Width.Value, 260,, New AniEaseOutFluent),
  720. AaGridLengthWidth(ProgressLaunchingUnfinished, 1 - ShowProgress - ProgressLaunchingUnfinished.Width.Value, 260,, New AniEaseOutFluent)
  721. }
  722. Dim IsDownloadStateChanged As Boolean = HasLaunchDownloader = (LabLaunchingDownload.Visibility = Visibility.Collapsed)
  723. If IsDownloadStateChanged Then
  724. LabLaunchingDownload.Visibility = Visibility.Visible
  725. LabLaunchingDownloadLeft.Visibility = Visibility.Visible
  726. AnimList.AddRange({
  727. AaOpacity(LabLaunchingDownload, If(HasLaunchDownloader, 1, 0) - LabLaunchingDownload.Opacity, 100),
  728. AaOpacity(LabLaunchingDownloadLeft, If(HasLaunchDownloader, 0.5, 0) - LabLaunchingDownloadLeft.Opacity, 100),
  729. AaCode(Sub()
  730. If Not HasLaunchDownloader Then
  731. LabLaunchingDownload.Visibility = Visibility.Collapsed
  732. LabLaunchingDownloadLeft.Visibility = Visibility.Collapsed
  733. End If
  734. End Sub, 110)
  735. })
  736. End If
  737. Dim IsProgressStateChanged As Boolean = (Not IsLaunched) = (LabLaunchingProgress.Visibility = Visibility.Collapsed)
  738. If IsProgressStateChanged Then
  739. LabLaunchingProgress.Visibility = Visibility.Visible
  740. LabLaunchingProgressLeft.Visibility = Visibility.Visible
  741. If IsLaunched Then
  742. 'IsWidthAnimating = True
  743. PanLaunchingHint.Visibility = Visibility.Visible
  744. 'AniStop("Launching Info Width")
  745. 'PanLaunchingInfo.Width = 260
  746. 'ActualUsedWidth = 260
  747. 'IsWidthAnimating = False
  748. End If
  749. AnimList.AddRange({
  750. AaOpacity(LabLaunchingProgress, If(Not IsLaunched, 1, 0) - LabLaunchingProgress.Opacity, 100),
  751. AaOpacity(LabLaunchingProgressLeft, If(Not IsLaunched, 0.5, 0) - LabLaunchingProgressLeft.Opacity, 100),
  752. AaOpacity(PanLaunchingHint, If(IsLaunched, 1, 0) - PanLaunchingHint.Opacity, 100)
  753. })
  754. End If
  755. AniStart(AnimList, "Launching Progress")
  756. Catch ex As Exception
  757. Log(ex, "刷新启动信息失败", LogLevel.Feedback)
  758. End Try
  759. End Sub
  760. Private ShowProgress As Double = 0
  761. '尺寸改变动画
  762. Private IsWidthAnimating As Boolean = False
  763. Private ActualUsedWidth As Double
  764. Private Sub PanLaunchingInfo_SizeChangedW(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
  765. Dim DeltaWidth As Double = e.NewSize.Width - e.PreviousSize.Width
  766. If e.PreviousSize.Width = 0 OrElse IsWidthAnimating OrElse Math.Abs(DeltaWidth) < 1 OrElse PanLaunchingInfo.ActualWidth = 0 Then Exit Sub
  767. AniStart({
  768. AaWidth(PanLaunchingInfo, DeltaWidth, 180,, New AniEaseOutFluent),
  769. AaCode(Sub()
  770. IsWidthAnimating = False
  771. PanLaunchingInfo.Width = ActualUsedWidth
  772. End Sub,, True)
  773. }, "Launching Info Width")
  774. IsWidthAnimating = True
  775. ActualUsedWidth = PanLaunchingInfo.Width
  776. PanLaunchingInfo.Width = e.PreviousSize.Width
  777. End Sub
  778. Private IsHeightAnimating As Boolean = False
  779. Private ActualUsedHeight As Double
  780. Private Sub PanLaunchingInfo_SizeChangedH(sender As Object, e As SizeChangedEventArgs) Handles PanLaunchingInfo.SizeChanged
  781. Dim DeltaHeight As Double = e.NewSize.Height - e.PreviousSize.Height
  782. If e.PreviousSize.Height = 0 OrElse IsHeightAnimating OrElse Math.Abs(DeltaHeight) < 1 OrElse PanLaunchingInfo.ActualHeight = 0 Then Exit Sub
  783. AniStart({
  784. AaHeight(PanLaunchingInfo, DeltaHeight, 180,, New AniEaseOutFluent),
  785. AaCode(Sub()
  786. IsHeightAnimating = False
  787. PanLaunchingInfo.Height = ActualUsedHeight
  788. End Sub,, True)
  789. }, "Launching Info Height")
  790. IsHeightAnimating = True
  791. ActualUsedHeight = PanLaunchingInfo.Height
  792. PanLaunchingInfo.Height = e.PreviousSize.Height
  793. End Sub
  794. End Class