Modules.vb 169 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957
  1. Imports System.Drawing.Imaging
  2. Imports System.Reflection
  3. Imports System.Security.Cryptography
  4. Imports System.Windows.Threading
  5. Imports Ionic.Zip
  6. Public Module Modules
  7. #Region "Review完成 | 声明"
  8. ''' <summary>
  9. ''' 程序的启动路径,以“\”结尾。
  10. ''' </summary>
  11. ''' <remarks></remarks>
  12. Public PATH As String = GetPathFromFullPath(System.Windows.Forms.Application.ExecutablePath)
  13. ''' <summary>
  14. ''' 随机数。
  15. ''' </summary>
  16. ''' <remarks></remarks>
  17. Public Rnd As New Random
  18. ''' <summary>
  19. ''' 正在拖动的滚动条。
  20. ''' </summary>
  21. ''' <remarks></remarks>
  22. Public DragingScroll As VScroll = Nothing
  23. ''' <summary>
  24. ''' 位图缓存。
  25. ''' </summary>
  26. ''' <remarks></remarks>
  27. Public BitmapCache As New Dictionary(Of String, MyBitmap)
  28. #End Region
  29. #Region "Review完成 | API"
  30. ''' <summary>
  31. ''' 获取指定窗口的句柄。返回查找到的第一个窗口的句柄。
  32. ''' </summary>
  33. ''' <param name="lpClassName">窗口的类名,使用Spy++可以查看。</param>
  34. ''' <param name="lpWindowName">窗口的标题。</param>
  35. ''' <returns>查找到的第一个窗口的句柄。</returns>
  36. ''' <remarks></remarks>
  37. Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
  38. ''' <summary>
  39. ''' 彻底释放某个句柄对应项目的资源。
  40. ''' </summary>
  41. ''' <param name="hObject">需要释放资源的句柄。</param>
  42. ''' <returns></returns>
  43. ''' <remarks></remarks>
  44. Public Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject" (ByVal hObject As IntPtr) As Boolean
  45. ''' <summary>
  46. ''' 根据句柄设置对应窗口的标题。
  47. ''' </summary>
  48. ''' <param name="hwnd">窗口句柄。</param>
  49. ''' <param name="lpString">要设置的标题。</param>
  50. ''' <returns></returns>
  51. ''' <remarks></remarks>
  52. Public Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As String) As Integer
  53. ''' <summary>
  54. ''' 获取某个句柄对应的窗口的所属进程ID。
  55. ''' </summary>
  56. ''' <param name="hwnd">窗口句柄。</param>
  57. ''' <param name="lpdwProcessId">获取到的ID。需要变量承载。</param>
  58. ''' <returns></returns>
  59. ''' <remarks></remarks>
  60. Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Integer, ByVal lpdwProcessId As Integer) As Integer
  61. ''' <summary>
  62. ''' 设置某个句柄对应的窗口的属性。
  63. ''' </summary>
  64. ''' <param name="hwnd">窗口句柄。</param>
  65. ''' <param name="hWndInsertAfter">置顶标记。-1 为置顶,-2 为不置顶。</param>
  66. ''' <param name="x">窗口的 X 坐标。</param>
  67. ''' <param name="y">窗口的 Y 坐标。</param>
  68. ''' <param name="cx">窗口的宽度。</param>
  69. ''' <param name="cy">窗口的高度。</param>
  70. ''' <param name="wFlags">利用 Or 连接的参数。
  71. ''' SWP_HIDEWINDOW:隐藏窗口。
  72. ''' SWP_SHOWWINDOW:显示窗口。
  73. ''' SWP_NOMOVE:维持当前位置(忽略 X 和 Y 参数)。
  74. ''' SWP_NOSIZE:维持当前尺寸(忽略 cx 和 cy 参数)。</param>
  75. ''' <returns></returns>
  76. ''' <remarks></remarks>
  77. Public Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
  78. ''' <summary>
  79. ''' 播放 BGM。
  80. ''' </summary>
  81. ''' <param name="lpszSoundName">音乐文件的完整路径。</param>
  82. ''' <param name="hModule">填写“0”。</param>
  83. ''' <param name="dwFlags">填写“131072 Or 1 Or 8”。</param>
  84. ''' <returns></returns>
  85. ''' <remarks></remarks>
  86. Public Declare Function PlaySound Lib "winmm.dll" (ByVal lpszSoundName As String, ByVal hModule As Integer, ByVal dwFlags As Integer) As Integer
  87. ''' <summary>
  88. ''' 播放 MP3 相关项。
  89. ''' </summary>
  90. ''' <param name="lpstrCommand"></param>
  91. ''' <param name="lpstrRetumString"></param>
  92. ''' <param name="uReturnLength"></param>
  93. ''' <param name="hwndCallback"></param>
  94. ''' <returns></returns>
  95. ''' <remarks></remarks>
  96. Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrRetumString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
  97. Public Const SWP_HIDEWINDOW As Integer = 8 * 16 '0x0080
  98. Public Const SWP_SHOWWINDOW As Integer = 4 * 16 '0x0040
  99. Public Const SWP_NOMOVE As Integer = 2 '0x0002
  100. Public Const SWP_NOSIZE As Integer = 1 '0x0001
  101. #End Region
  102. #Region "类"
  103. ''' <summary>
  104. ''' 支持浮点数与常见类型隐式转换的颜色。
  105. ''' </summary>
  106. ''' <remarks></remarks>
  107. Public Class MyColor
  108. '属性
  109. Public A As Double = 0
  110. Public R As Double = 0
  111. Public G As Double = 0
  112. Public B As Double = 0
  113. '类型转换
  114. Public Shared Widening Operator CType(ByVal col As Color) As MyColor
  115. Return New MyColor(col)
  116. End Operator
  117. Public Shared Widening Operator CType(ByVal conv As MyColor) As Color
  118. Return Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B))
  119. End Operator
  120. Public Shared Widening Operator CType(ByVal conv As MyColor) As System.Drawing.Color
  121. Return System.Drawing.Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B))
  122. End Operator
  123. Public Shared Widening Operator CType(ByVal bru As SolidColorBrush) As MyColor
  124. Return New MyColor(bru.Color)
  125. End Operator
  126. Public Shared Widening Operator CType(ByVal conv As MyColor) As SolidColorBrush
  127. Return New SolidColorBrush(Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B)))
  128. End Operator
  129. Public Shared Widening Operator CType(ByVal bru As Brush) As MyColor
  130. Return New MyColor(ColorConverter.ConvertFromString(bru.ToString))
  131. End Operator
  132. Public Shared Widening Operator CType(ByVal conv As MyColor) As Brush
  133. Return New SolidColorBrush(Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B)))
  134. End Operator
  135. '颜色运算
  136. Shared Operator +(ByVal a As MyColor, ByVal b As MyColor) As MyColor
  137. Return New MyColor With {.A = a.A + b.A, .B = a.B + b.B, .G = a.G + b.G, .R = a.R + b.R}
  138. End Operator
  139. Shared Operator -(ByVal a As MyColor, ByVal b As MyColor) As MyColor
  140. Return New MyColor With {.A = a.A - b.A, .B = a.B - b.B, .G = a.G - b.G, .R = a.R - b.R}
  141. End Operator
  142. Shared Operator *(ByVal a As MyColor, ByVal b As Double) As MyColor
  143. Return New MyColor With {.A = a.A * b, .B = a.B * b, .G = a.G * b, .R = a.R * b}
  144. End Operator
  145. Shared Operator /(ByVal a As MyColor, ByVal b As Double) As MyColor
  146. Return New MyColor With {.A = a.A / b, .B = a.B / b, .G = a.G / b, .R = a.R / b}
  147. End Operator
  148. '构造函数
  149. Public Sub New()
  150. End Sub
  151. Public Sub New(ByVal col As Color)
  152. Me.A = col.A
  153. Me.R = col.R
  154. Me.G = col.G
  155. Me.B = col.B
  156. End Sub
  157. Public Sub New(ByVal newA As Double, ByVal col As Color)
  158. Me.A = newA
  159. Me.R = col.R
  160. Me.G = col.G
  161. Me.B = col.B
  162. End Sub
  163. Public Sub New(ByVal newR As Double, ByVal newG As Double, ByVal newB As Double)
  164. Me.A = 255
  165. Me.R = newR
  166. Me.G = newG
  167. Me.B = newB
  168. End Sub
  169. Public Sub New(ByVal newA As Double, ByVal newR As Double, ByVal newG As Double, ByVal newB As Double)
  170. Me.A = newA
  171. Me.R = newR
  172. Me.G = newG
  173. Me.B = newB
  174. End Sub
  175. '复写
  176. Public Shadows Function toString() As String
  177. Return "(" & A & "," & R & "," & G & "," & B & ")"
  178. End Function
  179. End Class
  180. Public Class AdvancedRect
  181. '属性
  182. Public Property Width As Double = 0
  183. Public Property Height As Double = 0
  184. Public Property Left As Double = 0
  185. Public Property Top As Double = 0
  186. '构造函数
  187. Public Sub New()
  188. End Sub
  189. Public Sub New(ByVal left As Double, ByVal top As Double, ByVal width As Double, ByVal height As Double)
  190. Me.Left = left
  191. Me.Top = top
  192. Me.Width = width
  193. Me.Height = height
  194. End Sub
  195. End Class '浮点矩形
  196. Public Class FileSize
  197. Public Value As Integer = 0
  198. '类型转换
  199. Public Shared Widening Operator CType(ByVal value As Long) As FileSize
  200. Return New FileSize(value)
  201. End Operator
  202. Public Shared Widening Operator CType(ByVal value As FileSize) As Long
  203. Return value.Value
  204. End Operator
  205. Public Shared Widening Operator CType(ByVal value As Integer) As FileSize
  206. Return New FileSize(value)
  207. End Operator
  208. Public Shared Widening Operator CType(ByVal value As FileSize) As Integer
  209. Return value.Value
  210. End Operator
  211. '运算
  212. Shared Operator +(ByVal a As FileSize, ByVal b As FileSize) As FileSize
  213. Return a.Value + b.Value
  214. End Operator
  215. Shared Operator -(ByVal a As FileSize, ByVal b As FileSize) As FileSize
  216. Return a.Value - b.Value
  217. End Operator
  218. Shared Operator *(ByVal a As FileSize, ByVal b As FileSize) As Integer
  219. Return a.Value * b.Value
  220. End Operator
  221. Shared Operator /(ByVal a As FileSize, ByVal b As FileSize) As Double
  222. Return MathRange(a.Value / b.Value, 0)
  223. End Operator
  224. Shared Operator =(ByVal a As FileSize, ByVal b As FileSize) As Boolean
  225. Return a.Value = b.Value
  226. End Operator
  227. Shared Operator <>(ByVal a As FileSize, ByVal b As FileSize) As Boolean
  228. Return Not a.Value = b.Value
  229. End Operator
  230. Shared Operator >(ByVal a As FileSize, ByVal b As FileSize) As Boolean
  231. Return a.Value > b.Value
  232. End Operator
  233. Shared Operator <(ByVal a As FileSize, ByVal b As FileSize) As Boolean
  234. Return a.Value < b.Value
  235. End Operator
  236. Shared Operator &(ByVal a As FileSize, ByVal b As String) As String
  237. Return a.ToString & b
  238. End Operator
  239. Shared Operator &(ByVal a As String, ByVal b As FileSize) As String
  240. Return a & b.ToString
  241. End Operator
  242. '构造函数
  243. Public Sub New()
  244. End Sub
  245. Public Sub New(ByVal value As Integer)
  246. Me.Value = value
  247. End Sub
  248. '复写
  249. Public Shadows Function ToString() As String
  250. Select Case Me.Value
  251. Case Is < 0
  252. Return "未知"
  253. Case Is < 1024
  254. Return Me.Value & "B"
  255. Case Is < 1024 ^ 2
  256. Return Math.Round(Me.Value / 1024, 1) & "K"
  257. Case Is < 1024 ^ 3
  258. Return Math.Round(Me.Value / 1024 ^ 2, 2) & "M"
  259. Case Else
  260. Return Math.Round(Me.Value / 1024 ^ 3, 2) & "G"
  261. End Select
  262. End Function
  263. End Class '文件大小
  264. Public Class Time
  265. Private Property Value As Integer = 0
  266. '类型转换
  267. Public Shared Widening Operator CType(ByVal value As Integer) As Time
  268. Return New Time(value)
  269. End Operator
  270. Public Shared Widening Operator CType(ByVal value As Time) As Integer
  271. Return value.Value
  272. End Operator
  273. Public Shared Widening Operator CType(ByVal value As Int64) As Time
  274. Return New Time(value)
  275. End Operator
  276. Public Shared Widening Operator CType(ByVal value As Time) As Int64
  277. Return value.Value
  278. End Operator
  279. '运算
  280. Shared Operator +(ByVal a As Time, ByVal b As Time) As Time
  281. Return a.Value + b.Value
  282. End Operator
  283. Shared Operator -(ByVal a As Time, ByVal b As Time) As Time
  284. Return a.Value - b.Value
  285. End Operator
  286. Shared Operator *(ByVal a As Time, ByVal b As Time) As Integer
  287. Return a.Value * b.Value
  288. End Operator
  289. Shared Operator /(ByVal a As Time, ByVal b As Time) As Double
  290. Return MathRange(a.Value / b.Value, 0)
  291. End Operator
  292. Shared Operator =(ByVal a As Time, ByVal b As Time) As Boolean
  293. Return a.Value = b.Value
  294. End Operator
  295. Shared Operator <>(ByVal a As Time, ByVal b As Time) As Boolean
  296. Return Not a.Value = b.Value
  297. End Operator
  298. Shared Operator >(ByVal a As Time, ByVal b As Time) As Boolean
  299. Return a.Value > b.Value
  300. End Operator
  301. Shared Operator <(ByVal a As Time, ByVal b As Time) As Boolean
  302. Return a.Value < b.Value
  303. End Operator
  304. Shared Operator &(ByVal a As Time, ByVal b As String) As String
  305. Return a.toString & b
  306. End Operator
  307. Shared Operator &(ByVal a As String, ByVal b As Time) As String
  308. Return a & b.toString
  309. End Operator
  310. '构造函数
  311. Public Sub New()
  312. End Sub
  313. Public Sub New(ByVal value As Integer)
  314. Me.Value = value
  315. End Sub
  316. '复写
  317. Public Shadows Function toString() As String
  318. Dim left As Integer = Me.Value
  319. Dim a As Integer
  320. a = Math.Floor(left / 3600)
  321. toString = FillLength(a.ToString, "0", 2)
  322. left = left - a * 3600
  323. a = Math.Floor(left / 60)
  324. toString = toString & ":" & FillLength(a.ToString, "0", 2) & ":" & FillLength((left - a * 60), "0", 2)
  325. End Function
  326. End Class '时间
  327. #End Region
  328. #Region "控件"
  329. ''' <summary>
  330. ''' 获取控件或窗体的左边距。无视Alignment。
  331. ''' </summary>
  332. ''' <param name="control"></param>
  333. ''' <returns></returns>
  334. ''' <remarks></remarks>
  335. Public Function GetLeft(ByVal control) As Double
  336. GetLeft = 0
  337. If control.GetType.BaseType.Name.Equals("Window") Then
  338. Return control.Left
  339. Else
  340. Select Case control.HorizontalAlignment
  341. Case HorizontalAlignment.Left, HorizontalAlignment.Stretch, HorizontalAlignment.Center
  342. Return control.Margin.Left
  343. Case HorizontalAlignment.Right
  344. Return CType(control.Parent, Object).ActualWidth - control.ActualWidth - control.Margin.Right
  345. 'Case HorizontalAlignment.Stretch
  346. ' Dim MaxWidth As Double = CType(control.Parent, Object).ActualWidth - control.Margin.Left - control.Margin.Right
  347. ' Return If(control.ActualWidth >= MaxWidth, control.Margin.Left, control.Margin.Left + (MaxWidth - control.ActualWidth) / 2)
  348. 'Case HorizontalAlignment.Center
  349. ' Dim CenterPos As Double = control.Margin.Left + (CType(control.Parent, Object).ActualWidth - control.Margin.Left - control.Margin.Right) / 2
  350. ' Return CenterPos - control.ActualWidth / 2
  351. End Select
  352. End If
  353. End Function
  354. ''' <summary>
  355. ''' 获取控件或窗体的顶边距。无视Alignment。
  356. ''' </summary>
  357. ''' <param name="control"></param>
  358. ''' <returns></returns>
  359. ''' <remarks></remarks>
  360. Public Function GetTop(ByVal control) As Double
  361. GetTop = 0
  362. If control.GetType.BaseType.Name.Equals("Window") Then
  363. Return control.Top
  364. Else
  365. Select Case control.VerticalAlignment
  366. Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
  367. Return control.Margin.Top
  368. Case VerticalAlignment.Bottom
  369. Return -control.Margin.Bottom
  370. 'Return CType(control.Parent, Object).ActualHeight - control.ActualHeight - control.Margin.Bottom
  371. 'Case VerticalAlignment.Stretch
  372. ' Dim MaxHeight As Double = CType(control.Parent, Object).ActualHeight - control.Margin.Top - control.Margin.Bottom
  373. ' Return If(control.ActualHeight >= MaxHeight, control.Margin.Top, control.Margin.Top + (MaxHeight - control.ActualHeight) / 2)
  374. 'Case VerticalAlignment.Center
  375. ' Dim CenterPos As Double = control.Margin.Top + (CType(control.Parent, Object).ActualHeight - control.Margin.Top - control.Margin.Bottom) / 2
  376. ' Return CenterPos - control.ActualHeight / 2
  377. End Select
  378. End If
  379. End Function
  380. ''' <summary>
  381. ''' 将一个IList中的内容添加到另外一个IList。
  382. ''' </summary>
  383. ''' <remarks></remarks>
  384. Public Sub IListCopy(ByVal list As IList, ByVal arr As IList)
  385. For Each item In arr
  386. list.Add(item)
  387. Next
  388. End Sub
  389. Public Sub SetLeft(ByVal control As Object, ByVal newValue As Double)
  390. If Double.IsNaN(newValue) Or Double.IsInfinity(newValue) Then Exit Sub '安全性检查
  391. If control.GetType.BaseType.Name.Equals("Window") Then
  392. control.Left = newValue
  393. Else
  394. Select Case control.HorizontalAlignment
  395. Case HorizontalAlignment.Left, HorizontalAlignment.Stretch, HorizontalAlignment.Center
  396. control.Margin = New Thickness(newValue, control.Margin.Top, control.Margin.Right, control.Margin.Bottom)
  397. Case HorizontalAlignment.Right
  398. control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
  399. End Select
  400. End If
  401. End Sub '设置Left
  402. Public Sub SetTop(ByVal control As Object, ByVal newValue As Double)
  403. If Double.IsNaN(newValue) Or Double.IsInfinity(newValue) Then Exit Sub '安全性检查
  404. If control.GetType.BaseType.Name.Equals("Window") Then
  405. control.Top = newValue
  406. Else
  407. Select Case control.VerticalAlignment
  408. Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
  409. control.Margin = New Thickness(control.Margin.Left, newValue, control.Margin.Right, control.Margin.Bottom)
  410. Case VerticalAlignment.Bottom
  411. control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, -newValue)
  412. 'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, CType(control.Parent, Object).ActualHeight - control.ActualHeight - newValue)
  413. End Select
  414. End If
  415. End Sub '设置Top
  416. ''' <summary>
  417. ''' 拖动滚动条。
  418. ''' </summary>
  419. ''' <remarks></remarks>
  420. Public Sub ControlStartRun()
  421. Dim timer As New DispatcherTimer()
  422. timer.Interval = TimeSpan.FromMilliseconds(20)
  423. AddHandler timer.Tick, Sub()
  424. If IsNothing(DragingScroll) Then Exit Sub
  425. If Mouse.LeftButton = MouseButtonState.Pressed Then
  426. DragingScroll.Draging(Mouse.GetPosition(DragingScroll.btnDrag).Y)
  427. Else
  428. '鼠标放下
  429. If Not DragingScroll.IsMouseOver Then DragingScroll.DragMouseLeave()
  430. DragingScroll = Nothing
  431. End If
  432. End Sub
  433. timer.Start()
  434. End Sub
  435. #End Region
  436. #Region "数学"
  437. ''' <summary>
  438. ''' 获取两数间的百分比。小数点精确到6位。
  439. ''' </summary>
  440. ''' <returns></returns>
  441. ''' <remarks></remarks>
  442. Public Function MathPercent(ByVal ValueA As Double, ByVal ValueB As Double, ByVal Percent As Object) As Double
  443. Return Math.Round(ValueA * (1 - Percent) + ValueB * Percent, 6) '解决Double计算错误
  444. End Function
  445. ''' <summary>
  446. ''' 获取两颜色间的百分比,根据RGB计算。小数点精确到6位。
  447. ''' </summary>
  448. ''' <returns></returns>
  449. ''' <remarks></remarks>
  450. Public Function MathPercent(ByVal ValueA As MyColor, ByVal ValueB As MyColor, ByVal Percent As Object) As MyColor
  451. Return MathRound(ValueA * (1 - Percent) + ValueB * Percent, 6) '解决Double计算错误
  452. End Function
  453. ''' <summary>
  454. ''' 检查一个数字是否正确(如检查无限、NaN等)。
  455. ''' </summary>
  456. ''' <param name="Num">需要检查的数字。</param>
  457. ''' <returns>是否正确。</returns>
  458. ''' <remarks></remarks>
  459. Public Function MathCheck(ByVal Num As Double) As Boolean
  460. Return Not (Double.IsInfinity(Num) Or Double.IsNaN(Num))
  461. End Function
  462. '贝塞尔曲线计算
  463. Public Function MathBezier(ByVal t As Double, ByVal x1 As Double, ByVal y1 As Double, ByVal x2 As Double, ByVal y2 As Double) As Double
  464. Dim a, b
  465. a = t
  466. Do
  467. b = 3 * a * ((1 / 3 + x1 - x2) * a * a + (x2 - 2 * x1) * a + x1)
  468. a = a + (t - b) * 0.5
  469. Loop Until Math.Abs(b - t) < 0.01 '精度1%
  470. Return 3 * a * ((1 / 3 + y1 - y2) * a * a + (y2 - 2 * y1) * a + y1)
  471. End Function
  472. 'Byte合理化
  473. Public Function MathByte(ByVal d As Double) As Byte
  474. If d < 0 Then d = 0
  475. If d > 255 Then d = 255
  476. Return Math.Round(d)
  477. End Function
  478. '提供扩展类支持的Round
  479. Public Function MathRound(ByVal col As MyColor, Optional ByVal w As Integer = 0) As MyColor
  480. Return New MyColor With {.A = Math.Round(col.A, w), .R = Math.Round(col.R, w), .G = Math.Round(col.G, w), .B = Math.Round(col.B, w)}
  481. End Function
  482. '把数值限定范围
  483. Public Function MathRange(ByVal value As Double, ByVal min As Double, Optional ByVal max As Double = Double.MaxValue) As Double
  484. Return Math.Max(min, Math.Min(max, value))
  485. End Function
  486. 'Byte类溢出处理
  487. Public Function ByteOverflow(ByVal int As Integer) As Byte
  488. Dim Original = int
  489. Dim ReturnValue As Byte
  490. Try
  491. If int < 0 Then
  492. Do Until int >= 0
  493. int = int + 256
  494. Loop
  495. ReturnValue = int
  496. Else
  497. ReturnValue = int Mod 256
  498. End If
  499. Return ReturnValue
  500. Catch ex As Exception
  501. ExShow(ex, "Byte 溢出处理出错:" & int)
  502. Return 0
  503. End Try
  504. End Function
  505. #End Region
  506. #Region "文本"
  507. '填充长度
  508. Public Function FillLength(ByVal str As String, ByVal code As String, ByVal length As Byte)
  509. If (Len(str) > length) Then Return Mid(str, 1, length)
  510. Return Mid(str.Replace(" ", "-").PadRight(length), str.Length + 1).Replace(" ", code) & str
  511. End Function
  512. '选择其一
  513. Public Function OneOf(ByVal objects As Array)
  514. Return objects.GetValue(RandomInteger(0, objects.Length - 1))
  515. End Function
  516. Public Function OneOf(ByVal objects As ArrayList)
  517. Return objects(RandomInteger(0, objects.Count - 1))
  518. End Function
  519. '正则搜索
  520. Public Function RegexSearch(ByVal str As String, ByVal regex As String) As ArrayList
  521. Try
  522. RegexSearch = New ArrayList
  523. Dim RegexSearchRes = (New RegularExpressions.Regex(regex)).Matches(str)
  524. If IsNothing(RegexSearchRes) Then Return RegexSearch
  525. For Each item As RegularExpressions.Match In RegexSearchRes
  526. RegexSearch.Add(item.Value)
  527. Next
  528. Catch
  529. Return New ArrayList
  530. End Try
  531. End Function
  532. '加密解密
  533. Public Function SerAdd(ByVal str As String) As String
  534. Dim text As Byte() = Encoding.Unicode.GetBytes(str)
  535. '-----------------------------------------------1
  536. Array.Reverse(text)
  537. '-----------------------------------------------2
  538. Dim out(text.Length - 1) As Byte
  539. For i As Integer = 0 To text.Length - 4 Step 4
  540. out(i) = text(i + 2)
  541. out(i + 1) = text(i + 1)
  542. out(i + 2) = text(i + 3)
  543. out(i + 3) = text(i)
  544. Next i
  545. If text.Length Mod 4 = 2 Then
  546. out(text.Length - 2) = text(text.Length - 1)
  547. out(text.Length - 1) = text(text.Length - 2)
  548. End If
  549. text = out
  550. '-----------------------------------------------3
  551. ReDim out(text.Length - 1)
  552. For i As Integer = 0 To text.Length - 3 Step 3
  553. out(i) = ByteOverflow(text(i + 2) + 12)
  554. out(i + 1) = ByteOverflow(text(i) - 85)
  555. out(i + 2) = ByteOverflow(text(i + 1) + 36)
  556. Next i
  557. Select Case text.Length Mod 3
  558. Case 1
  559. out(text.Length - 1) = ByteOverflow(text(text.Length - 1) - 52)
  560. Case 2
  561. out(text.Length - 1) = ByteOverflow(text(text.Length - 1) + 16)
  562. out(text.Length - 2) = ByteOverflow(text(text.Length - 2) + 48)
  563. End Select
  564. text = out
  565. '-----------------------------------------------4
  566. For i As Integer = 0 To text.Length - 1
  567. text(i) = ByteOverflow(text(i) + i)
  568. Next i
  569. '-----------------------------------------------E
  570. SerAdd = ""
  571. For Each bt As Byte In text
  572. SerAdd = SerAdd & BitConverter.ToString({bt})
  573. Next
  574. End Function
  575. Public Function SerRemove(ByVal str As String) As String
  576. Dim line1 As String, line2 As String
  577. line1 = "这就是解密函数……自己写的……很口胡很辣鸡……做一个加密只是为了防那些脑残熊孩子,既然都能搞到这函数了,那加密也没用,所以就别吐槽这辣鸡加密了吧233"
  578. line2 = "by 龙腾猫跃"
  579. Dim text(Len(str) / 2 - 1) As Byte
  580. For i As Integer = 0 To Len(str) - 2 Step 2
  581. text(i / 2) = Byte.Parse(Mid(str, i + 1, 2), Globalization.NumberStyles.AllowHexSpecifier)
  582. Next
  583. '-----------------------------------------------4
  584. For i As Integer = 0 To text.Length - 1
  585. text(i) = ByteOverflow(text(i) - i)
  586. Next i
  587. '-----------------------------------------------3
  588. Dim out(text.Length - 1) As Byte
  589. For i As Integer = 0 To text.Length - 3 Step 3
  590. out(i) = ByteOverflow(text(i + 1) + 85)
  591. out(i + 1) = ByteOverflow(text(i + 2) - 36)
  592. out(i + 2) = ByteOverflow(text(i) - 12)
  593. Next i
  594. Select Case text.Length Mod 3
  595. Case 1
  596. out(text.Length - 1) = ByteOverflow(text(text.Length - 1) + 52)
  597. Case 2
  598. out(text.Length - 1) = ByteOverflow(text(text.Length - 1) - 16)
  599. out(text.Length - 2) = ByteOverflow(text(text.Length - 2) - 48)
  600. End Select
  601. text = out
  602. '-----------------------------------------------2
  603. ReDim out(text.Length - 1)
  604. For i As Integer = 0 To text.Length - 4 Step 4
  605. out(i) = text(i + 3)
  606. out(i + 1) = text(i + 1)
  607. out(i + 2) = text(i)
  608. out(i + 3) = text(i + 2)
  609. Next i
  610. If text.Length Mod 4 = 2 Then
  611. out(text.Length - 2) = text(text.Length - 1)
  612. out(text.Length - 1) = text(text.Length - 2)
  613. End If
  614. text = out
  615. '-----------------------------------------------1
  616. Array.Reverse(text)
  617. '-----------------------------------------------E
  618. SerRemove = Encoding.Unicode.GetString(text)
  619. End Function
  620. ''' <summary>
  621. ''' 从用户输入的字符串中提取数字
  622. ''' </summary>
  623. ''' <param name="str">用户输入的字符串</param>
  624. ''' <returns>字符串中的数字,没有任何数字返回0</returns>
  625. ''' <remarks></remarks>
  626. Public Function GetDoubleFromString(ByVal str As String) As Double
  627. Dim regResult As ArrayList = RegexSearch(str, "(-?[0-9]\d*)?\.?[0-9]\d*")
  628. If regResult.Count = 0 Then
  629. Return 0
  630. Else
  631. Return Val(regResult(0))
  632. End If
  633. End Function
  634. '把Exception转为字符串
  635. Public Function GetStringFromException(ByVal ex As Exception, Optional ByVal isLong As Boolean = False) As String
  636. '构造基本信息与InnerException信息
  637. GetStringFromException = ex.Message.Replace(vbCrLf, "")
  638. If Not IsNothing(ex.InnerException) Then
  639. GetStringFromException = GetStringFromException & vbCrLf & "InnerException: " & ex.InnerException.Message.Replace(vbCrLf, "")
  640. If Not IsNothing(ex.InnerException.InnerException) Then
  641. GetStringFromException = GetStringFromException & vbCrLf & "InnerException: " & ex.InnerException.InnerException.Message.Replace(vbCrLf, "")
  642. End If
  643. End If
  644. '添加堆栈信息
  645. If isLong Then
  646. GetStringFromException = GetStringFromException & vbCrLf
  647. For Each Stack As String In ex.StackTrace.Split(vbCrLf)
  648. If Stack.Contains("pcl.") Then GetStringFromException = GetStringFromException & vbCrLf & Stack
  649. Next
  650. End If
  651. '清除双回车
  652. GetStringFromException = GetStringFromException.Replace(vbCrLf & vbCrLf, vbCrLf).Replace(vbCrLf & vbCrLf, vbCrLf)
  653. End Function
  654. #End Region
  655. #Region "Review完成 | 图片"
  656. ''' <summary>
  657. ''' 裁剪一个 BitmapSource。
  658. ''' </summary>
  659. ''' <param name="img">源图片。</param>
  660. Public Function CutBitmap(ByVal img As BitmapSource, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer) As BitmapSource
  661. Try
  662. Return New CroppedBitmap(img, New Int32Rect(x, y, width, height))
  663. Catch ex As Exception
  664. ExShow(ex, "裁剪图片失败", ErrorLevel.AllUsers)
  665. Return Nothing
  666. End Try
  667. End Function
  668. #End Region
  669. #Region "文件"
  670. ''' <summary>
  671. ''' 从应用资源释放文件。
  672. ''' </summary>
  673. ''' <param name="FileName">需要释放的文件在应用资源中的名称。</param>
  674. ''' <param name="OutputPath">释放的路径,包含文件名。</param>
  675. ''' <remarks></remarks>
  676. Public Sub OutputFileInResource(ByVal FileName As String, ByVal OutputPath As String, ByVal PassOnExists As Boolean)
  677. Try
  678. Dim Res = My.Resources.ResourceManager.GetObject(FileName)
  679. If IsNothing(Res) Then Throw New FileNotFoundException("没有找到名为" & FileName & "的资源")
  680. If PassOnExists And File.Exists(OutputPath) Then
  681. If GetFileSize(OutputPath) = Res.Length Then Exit Sub
  682. End If
  683. Directory.CreateDirectory(Mid(OutputPath, 1, OutputPath.LastIndexOf("\")))
  684. Using OutputStream As New FileStream(OutputPath, FileMode.OpenOrCreate, FileAccess.Write)
  685. OutputStream.Write(Res, 0, Res.Length)
  686. OutputStream.Flush()
  687. End Using
  688. log("[System] 释放文件:" & FileName)
  689. Catch ex As Exception
  690. ExShow(ex, "释放文件失败", ErrorLevel.DebugOnly)
  691. Throw ex
  692. End Try
  693. End Sub
  694. ''' <summary>
  695. ''' 解压文件。
  696. ''' </summary>
  697. ''' <param name="SourceFile">需要解压的文件的完整路径。</param>
  698. ''' <param name="UnzipDir">解压的目标文件夹。</param>
  699. ''' <param name="RunThread">解压结束后(无论成功还是失败)执行的方法。</param>
  700. ''' <remarks></remarks>
  701. Public Sub UnzipFile(ByVal SourceFile As String, ByVal UnzipDir As String, Optional ByVal RunThread As ParameterizedThreadStart = Nothing)
  702. Dim th As New Thread(Sub()
  703. Try
  704. Directory.CreateDirectory(UnzipDir)
  705. Using zip As New ZipFile(SourceFile)
  706. zip.ExtractAll(UnzipDir)
  707. End Using
  708. Catch ex As Exception
  709. ExShow(ex, "解压文件失败:" & SourceFile)
  710. End Try
  711. If Not IsNothing(RunThread) Then RunThread.Method.Invoke(Nothing, {Nothing})
  712. End Sub)
  713. th.Start()
  714. End Sub '解压ZIP文件
  715. ''' <summary>
  716. ''' 弹出选取文件对话框并且要求选取文件。
  717. ''' </summary>
  718. ''' <param name="FileFilter">要求的格式。如:“常用图片文件(*.png;*.jpeg)|*.png;*.jpg;*.jpeg”。</param>
  719. ''' <param name="Title">弹窗的标题。</param>
  720. ''' <returns>选择的唯一文件的完整路径,如果没有选择可能为空字符串。</returns>
  721. ''' <remarks></remarks>
  722. Public Function SelectFile(ByVal FileFilter As String, ByVal Title As String) As String
  723. Using fileDialog As New Forms.OpenFileDialog
  724. fileDialog.AddExtension = True
  725. fileDialog.AutoUpgradeEnabled = True
  726. fileDialog.CheckFileExists = True
  727. fileDialog.Filter = FileFilter
  728. fileDialog.Multiselect = False
  729. fileDialog.Title = Title
  730. fileDialog.ShowDialog()
  731. Return fileDialog.FileName
  732. End Using
  733. End Function
  734. ''' <summary>
  735. ''' 弹出选取文件夹对话框并且要求选取文件夹。
  736. ''' </summary>
  737. ''' <param name="Title">弹窗的标题。</param>
  738. ''' <returns>选择的唯一文件夹的完整路径,如果没有选择可能为空字符串。</returns>
  739. ''' <remarks></remarks>
  740. Public Function SelectFolder(ByVal Title As String) As String
  741. Using folderDialog As New Forms.FolderBrowserDialog
  742. folderDialog.Description = Title
  743. folderDialog.ShowNewFolderButton = True
  744. folderDialog.ShowDialog()
  745. Return folderDialog.SelectedPath
  746. End Using
  747. End Function
  748. ''' <summary>
  749. ''' 从文件路径或者URL获取不包含文件名的路径。不包含路径将会抛出异常。
  750. ''' </summary>
  751. ''' <param name="FilePath">文件路径,以标识符结尾。如果不包含文件名则必须以标识符结尾。</param>
  752. ''' <returns></returns>
  753. ''' <remarks></remarks>
  754. Public Function GetPathFromFullPath(ByVal FilePath As String) As String
  755. If Not (FilePath.Contains("\") Or FilePath.Contains("/")) Then Throw New FileFormatException("不包含路径:" & FilePath)
  756. If FilePath.EndsWith("\") Or FilePath.EndsWith("/") Then Return FilePath
  757. GetPathFromFullPath = Left(FilePath, FilePath.LastIndexOfAny({"\", "/"}) + 1)
  758. If GetPathFromFullPath = "" Then Throw New FileFormatException("不包含路径:" & FilePath)
  759. End Function
  760. ''' <summary>
  761. ''' 从文件路径或者URL获取不包含路径的文件名。不包含文件名将会抛出异常。
  762. ''' </summary>
  763. ''' <param name="FilePath">文件路径。可以不完整。</param>
  764. ''' <returns></returns>
  765. ''' <remarks></remarks>
  766. Public Function GetFileNameFromPath(ByVal FilePath As String) As String
  767. If FilePath.EndsWith("\") Or FilePath.EndsWith("/") Then Throw New FileFormatException("不包含文件名:" & FilePath)
  768. If Not (FilePath.Contains("\") Or FilePath.Contains("/")) Then Return FilePath
  769. GetFileNameFromPath = Mid(FilePath, FilePath.LastIndexOfAny({"\", "/"}) + 2)
  770. If GetFileNameFromPath.Contains("\\") And GetFileNameFromPath.Contains("?") Then
  771. '包含网络参数
  772. GetFileNameFromPath = Left(GetFileNameFromPath, FilePath.LastIndexOf("?"))
  773. End If
  774. If GetFileNameFromPath = "" Then Throw New FileFormatException("不包含文件名:" & FilePath)
  775. End Function
  776. ''' <summary>
  777. ''' 获取文件的版本信息。
  778. ''' </summary>
  779. ''' <param name="Path">文件目录。</param>
  780. ''' <returns></returns>
  781. ''' <remarks></remarks>
  782. Public Function GetFileVersion(ByVal Path As String) As String
  783. Try
  784. Return Diagnostics.FileVersionInfo.GetVersionInfo(Path).FileVersion
  785. Catch ex As Exception
  786. ExShow(ex, "获取文件版本失败:" & Path, ErrorLevel.Slient)
  787. Return ""
  788. End Try
  789. End Function
  790. ''' <summary>
  791. ''' 获取一个文件夹下的所有文件的完整路径。
  792. ''' </summary>
  793. ''' <param name="SourcePath">源文件夹,不以“\”结尾。</param>
  794. ''' <returns></returns>
  795. ''' <remarks></remarks>
  796. Public Function GetFilesFromPath(ByVal SourcePath As String) As ArrayList
  797. GetFilesFromPath = New ArrayList
  798. GetFilesFromPath(SourcePath, GetFilesFromPath)
  799. End Function
  800. Private Function GetFilesFromPath(ByVal SourcePath As String, ByRef CurrentList As ArrayList) As ArrayList
  801. Try
  802. If Not Directory.Exists(SourcePath) Then Return New ArrayList
  803. '列举文件
  804. For Each File As FileInfo In (New DirectoryInfo(SourcePath)).GetFiles
  805. CurrentList.Add(File.FullName)
  806. Next
  807. '列举目录
  808. For Each Folder As DirectoryInfo In (New DirectoryInfo(SourcePath)).GetDirectories
  809. GetFilesFromPath(Folder.FullName, CurrentList)
  810. Next
  811. Catch ex As Exception
  812. ExShow(ex, "列举文件失败:" & SourcePath, ErrorLevel.Slient)
  813. End Try
  814. '返回
  815. Return CurrentList
  816. End Function
  817. '获取文件大小(HTTP URL或文件路径)
  818. Public Function GetFileSize(ByVal Path As String, Optional ByRef FileMission As WebFile = Nothing) As Integer
  819. Try
  820. If Path.StartsWith("http") Then
  821. If MODE_OFFLINE Then Return 0
  822. '获取网络文件大小
  823. Dim Res As Net.WebRequest = Net.WebRequest.Create(Path)
  824. Dim Response As WebResponse = Res.GetResponse
  825. Dim Size As Integer = Response.ContentLength()
  826. If Not IsNothing(FileMission) Then
  827. '用Ref返回实际地址
  828. If Not FileMission.AllWebAddress(0) = Response.ResponseUri.ToString Then
  829. If FileMission.RefreshName Then FileMission.LocalName = GetFileNameFromPath(Response.ResponseUri.ToString)
  830. FileMission.AllWebAddress(0) = Response.ResponseUri.ToString
  831. End If
  832. End If
  833. '释放资源
  834. Response.Close()
  835. Res.Abort()
  836. Return Size
  837. Else
  838. If File.Exists(Path) Then
  839. Return New FileInfo(Path).Length
  840. Else
  841. Return 0
  842. End If
  843. End If
  844. Catch ex As Exception
  845. ExShow(ex, "获取文件大小失败:" & Path, ErrorLevel.Slient)
  846. Return 0
  847. End Try
  848. End Function
  849. '获取MD5
  850. Public Function GetFileMD5(ByVal filepath As String) As String
  851. Try
  852. '网上抄的啊,自己改了改而已XD
  853. Dim result As String = ""
  854. Using fstream As New FileStream(filepath, FileMode.Open, FileAccess.Read)
  855. Dim dataToHash(fstream.Length - 1) As Byte
  856. fstream.Read(dataToHash, 0, fstream.Length)
  857. Dim hashvalue As Byte() = CType(CryptoConfig.CreateFromName("MD5"), HashAlgorithm).ComputeHash(dataToHash)
  858. Dim i As Double
  859. For i = 0 To hashvalue.Length - 1
  860. result += FillLength(Hex(hashvalue(i)).ToLower, "0", 2)
  861. Next
  862. End Using
  863. Return result
  864. Catch ex As Exception
  865. ExShow(ex, "获取文件MD5失败:" & filepath, ErrorLevel.Slient)
  866. Return ""
  867. End Try
  868. End Function
  869. '读取文件
  870. Public Function ReadFileToEnd(ByVal filePath As String, Optional ByVal encode As Encoding = Nothing, Optional ByVal isFullPath As Boolean = True) As String
  871. Try
  872. Dim actualPath As String = If(isFullPath, "", PATH) & filePath
  873. If File.Exists(actualPath) Then
  874. encode = If(IsNothing(encode), New UTF8Encoding(False), encode)
  875. Using reader As New StreamReader(actualPath, encode)
  876. ReadFileToEnd = reader.ReadToEnd
  877. End Using
  878. Else
  879. Return ""
  880. End If
  881. Catch ex As Exception
  882. ExShow(ex, "读取文件出错:" & filePath)
  883. Return ""
  884. End Try
  885. End Function
  886. '写入文件
  887. Public Sub WriteFile(ByVal filePath As String, ByVal text As String, Optional ByVal add As Boolean = False, Optional ByVal encode As Encoding = Nothing, Optional ByVal isFullPath As Boolean = True)
  888. Try
  889. Dim actualpath As String = If(isFullPath, "", PATH) & filePath
  890. If Not File.Exists(actualpath) Then
  891. Directory.CreateDirectory(GetPathFromFullPath(actualpath))
  892. File.Create(actualpath).Dispose()
  893. End If
  894. encode = If(IsNothing(encode), New UTF8Encoding(False), encode)
  895. Using writer As New StreamWriter(actualpath, add, encode)
  896. writer.Write(text)
  897. writer.Flush()
  898. End Using
  899. Catch ex As Exception
  900. ExShow(ex, "写入文件时出错:" & filePath)
  901. End Try
  902. End Sub
  903. Private Class IniCache
  904. Public content As String = ""
  905. Public cache As New Dictionary(Of String, String)
  906. End Class
  907. Private CacheIni As New Dictionary(Of String, IniCache)
  908. ''' <summary>
  909. ''' 获取Ini文件内容,这可能会使用到缓存。
  910. ''' </summary>
  911. ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
  912. ''' <returns></returns>
  913. ''' <remarks></remarks>
  914. Private Function GetIni(ByVal FileName As String) As IniCache
  915. If Not FileName.Contains(":\") Then FileName = PATH & "PCL\" & FileName & ".ini"
  916. If CacheIni.ContainsKey(FileName) Then
  917. '返回缓存中的信息
  918. Dim Cache As New IniCache
  919. CacheIni.TryGetValue(FileName, Cache)
  920. Return Cache '防止ByRef导致缓存变更
  921. Else
  922. If File.Exists(FileName) Then
  923. '返回文件信息并且记入缓存
  924. Dim Cache As String = (vbCrLf & ReadFileToEnd(FileName) & vbCrLf).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf).Replace(vbCrLf & vbCrLf, vbCrLf)
  925. Dim Ini As New IniCache With {.content = Cache}
  926. CacheIni.Add(FileName, Ini)
  927. Return Ini
  928. Else
  929. '返回空信息
  930. Dim Ini As New IniCache With {.content = ""}
  931. CacheIni.Add(FileName, Ini)
  932. Return Ini
  933. End If
  934. End If
  935. End Function
  936. ''' <summary>
  937. ''' 读取Ini文件,这可能会使用到缓存。
  938. ''' </summary>
  939. ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
  940. ''' <param name="Key">键。</param>
  941. ''' <param name="DefaultValue">没有找到键时返回的默认值。</param>
  942. Public Function ReadIni(ByVal FileName As String, ByVal Key As String, Optional ByVal DefaultValue As String = "") As String
  943. Try
  944. '获取目前文件
  945. Dim NowIni As IniCache = GetIni(FileName)
  946. If IsNothing(NowIni) Then Return DefaultValue
  947. '使用缓存
  948. If NowIni.cache.ContainsKey(Key) Then Return If(NowIni.cache(Key), DefaultValue)
  949. '新读取文件
  950. If NowIni.content.Contains(vbCrLf & Key & ":") Then
  951. Dim Ret As String = Mid(NowIni.content, NowIni.content.IndexOf(vbCrLf & Key & ":") + 3)
  952. Ret = If(Ret.Contains(vbCrLf), Mid(Ret, 1, Ret.IndexOf(vbCrLf)), Ret).Replace(Key & ":", "")
  953. NowIni.cache.Add(Key, If(Ret = vbLf, "", Ret))
  954. Return If(Ret = vbLf, "", Ret)
  955. Else
  956. Return DefaultValue
  957. End If
  958. Catch ex As Exception
  959. '读取失败
  960. Return DefaultValue
  961. End Try
  962. End Function
  963. ''' <summary>
  964. ''' 写入ini文件,这会更新缓存。
  965. ''' </summary>
  966. ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
  967. ''' <param name="Key">键。</param>
  968. ''' <param name="Value">值。</param>
  969. ''' <remarks></remarks>
  970. Public Sub WriteIni(ByVal FileName As String, ByVal Key As String, ByVal Value As String)
  971. On Error Resume Next
  972. FileName = If(FileName.Contains(":\"), FileName, PATH & "PCL\" & FileName & ".ini")
  973. If IsNothing(Value) Then Value = ""
  974. Value = Value.Replace(vbCrLf, "")
  975. '创建文件夹
  976. If Not Directory.Exists(GetPathFromFullPath(FileName)) Then Directory.CreateDirectory(GetPathFromFullPath(FileName))
  977. '获取目前文件
  978. Dim NowFile As String = GetIni(FileName).content
  979. '如果值一样就不处理
  980. If NowFile.Contains(vbCrLf & Key & ":" & Value & vbCrLf) Then Exit Sub
  981. '处理文件
  982. Dim FindResult As String = ReadIni(FileName, Key)
  983. If FindResult = "" And Not NowFile.Contains(vbCrLf & Key & ":") Then
  984. '不存在这个键
  985. NowFile = NowFile & vbCrLf & Key & ":" & Value
  986. Else
  987. '存在这个键
  988. NowFile = NowFile.Replace(vbCrLf & Key & ":" & FindResult & vbCrLf, vbCrLf & Key & ":" & Value & vbCrLf)
  989. End If
  990. WriteFile(FileName, NowFile)
  991. '刷新目前缓存
  992. CacheIni(FileName).content = NowFile
  993. CacheIni(FileName).cache.Remove(Key)
  994. CacheIni(FileName).cache.Add(Key, Value)
  995. End Sub
  996. #End Region
  997. #Region "Review完成 | 网络"
  998. ''' <summary>
  999. ''' 获取网页源代码。
  1000. ''' </summary>
  1001. ''' <param name="URL">网页的URL。</param>
  1002. ''' <param name="Encode">网页的编码,通常为UTF-8。</param>
  1003. ''' <returns></returns>
  1004. ''' <remarks></remarks>
  1005. Public Function GetWebsiteCode(ByVal URL As String, ByVal Encode As Encoding) As String
  1006. If MODE_OFFLINE Then Return ""
  1007. '初始化
  1008. Dim req As HttpWebRequest = Nothing
  1009. Dim res As HttpWebResponse = Nothing
  1010. Dim strm As StreamReader = Nothing
  1011. GetWebsiteCode = ""
  1012. Try
  1013. req = WebRequest.Create(URL)
  1014. req.Timeout = 6000
  1015. res = req.GetResponse()
  1016. strm = New StreamReader(res.GetResponseStream(), Encode)
  1017. GetWebsiteCode = strm.ReadToEnd
  1018. Catch ex As Exception
  1019. If Not URL.Contains("https://sessionserver.mojang.com/session/minecraft/profile/") Then ExShow(ex, "获取网页源代码失败:" & URL)
  1020. Finally
  1021. '释放资源
  1022. If Not IsNothing(strm) Then strm.Dispose()
  1023. If Not IsNothing(res) Then res.Close()
  1024. If Not IsNothing(req) Then req.Abort()
  1025. End Try
  1026. End Function
  1027. ''' <summary>
  1028. ''' 从网络中直接下载文件。
  1029. ''' </summary>
  1030. ''' <param name="URL">网络URL。</param>
  1031. ''' <param name="localFile">下载的本地地址。</param>
  1032. ''' <returns>是否下载成功。</returns>
  1033. ''' <remarks></remarks>
  1034. Public Function DownloadFile(ByVal URL As String, ByVal LocalFile As String) As Boolean
  1035. If MODE_OFFLINE Then Return False
  1036. '初始化
  1037. Try
  1038. '建立目录
  1039. Directory.CreateDirectory(GetPathFromFullPath(LocalFile))
  1040. '尝试删除原文件
  1041. File.Delete(LocalFile)
  1042. Catch ex As Exception
  1043. ExShow(ex, "预处理文件失败:" & LocalFile)
  1044. Return False
  1045. End Try
  1046. '下载
  1047. Using Client As New WebClient
  1048. Try
  1049. Client.DownloadFile(URL, LocalFile)
  1050. log("[System] 直接下载文件成功:" & URL)
  1051. Return True
  1052. Catch ex As Exception
  1053. ExShow(ex, "直接下载文件失败:" & URL)
  1054. Return False
  1055. End Try
  1056. End Using
  1057. End Function
  1058. ''' <summary>
  1059. ''' 进行Ping测试。这不会异步进行,失败将直接抛出异常。
  1060. ''' </summary>
  1061. ''' <param name="IP">要进行Ping的IP。</param>
  1062. ''' <param name="MaxPingTime">最大响应时间,单位为毫秒。</param>
  1063. ''' <returns>Ping用时,单位为毫秒。</returns>
  1064. ''' <remarks></remarks>
  1065. Public Function Ping(ByVal IP As String, ByVal MaxPingTime As Integer) As Integer
  1066. If MODE_OFFLINE Then Throw New WebException("没有网络连接。")
  1067. Using pin = New System.Net.NetworkInformation.Ping
  1068. Return pin.Send(IP, MaxPingTime).RoundtripTime
  1069. End Using
  1070. End Function
  1071. #End Region
  1072. #Region "系统"
  1073. ''' <summary>
  1074. ''' 测试某段代码用时,单位为毫秒/次。
  1075. ''' </summary>
  1076. ''' <param name="run">需要测试的代码。</param>
  1077. ''' <returns></returns>
  1078. ''' <remarks></remarks>
  1079. Public Function TimeTest(ByVal run As ThreadStart) As Double
  1080. Dim StartTime As Long = My.Computer.Clock.TickCount
  1081. Dim RunCount As Integer = 0
  1082. Do While True
  1083. run.Invoke()
  1084. RunCount = RunCount + 1
  1085. If My.Computer.Clock.TickCount - StartTime > 1000 Or RunCount > 100000 Then Exit Do
  1086. Loop
  1087. Return (My.Computer.Clock.TickCount - StartTime) / RunCount
  1088. End Function
  1089. ''' <summary>
  1090. ''' 打开文件(等同于使用“运行”窗口)。
  1091. ''' </summary>
  1092. ''' <param name="FileName">文件名。可以为“notepad”等缩写。</param>
  1093. ''' <param name="Arguments">运行参数。</param>
  1094. ''' <param name="WaitForExit">是否等待该程序结束。默认为False。</param>
  1095. ''' <remarks></remarks>
  1096. Public Sub Shell(ByVal FileName As String, Optional ByVal Arguments As String = "", Optional ByVal WaitForExit As Boolean = False)
  1097. Try
  1098. Dim Program As New Process
  1099. Program.StartInfo.Arguments = Arguments
  1100. Program.StartInfo.FileName = FileName
  1101. Program.Start()
  1102. If WaitForExit Then Program.WaitForExit()
  1103. Catch ex As Exception
  1104. ExShow(ex, "执行命令失败:" & FileName, ErrorLevel.AllUsers)
  1105. End Try
  1106. End Sub
  1107. ''' <summary>
  1108. ''' 返回一个枚举对应的字符串。
  1109. ''' </summary>
  1110. ''' <param name="EnumData">一个已经实例化的枚举类型。</param>
  1111. ''' <returns></returns>
  1112. ''' <remarks></remarks>
  1113. Public Function GetStringFromEnum(ByVal EnumData As Object) As String
  1114. Return [Enum].GetName(EnumData.GetType, EnumData)
  1115. End Function
  1116. ''' <summary>
  1117. ''' 从指定的枚举中查找某字符串对应的枚举项。
  1118. ''' </summary>
  1119. ''' <param name="EnumData">源枚举。</param>
  1120. ''' <param name="Value">对应枚举一项的字符串。</param>
  1121. ''' <returns></returns>
  1122. ''' <remarks></remarks>
  1123. Public Function GetEnumFromString(ByVal EnumData As Object, ByVal Value As String)
  1124. Return [Enum].Parse(EnumData.GetType, Value)
  1125. End Function
  1126. ''' <summary>
  1127. ''' 获取格式类似于“11:08:52.037”的当前时间的字符串。
  1128. ''' </summary>
  1129. ''' <returns></returns>
  1130. ''' <remarks></remarks>
  1131. Public Function GetTime() As String
  1132. Return Date.Now.ToLongTimeString & "." & FillLength(Date.Now.Millisecond, "0", 3)
  1133. End Function
  1134. ''' <summary>
  1135. ''' 数组去重。
  1136. ''' </summary>
  1137. ''' <param name="array"></param>
  1138. ''' <returns></returns>
  1139. ''' <remarks></remarks>
  1140. Public Function ArrayNoDouble(ByVal array As Array) As ArrayList
  1141. Dim ResultArray As New ArrayList
  1142. For i = 0 To UBound(array)
  1143. For ii = i + 1 To UBound(array)
  1144. If array(i).Equals(array(ii)) Then GoTo NextElement
  1145. Next
  1146. ResultArray.Add(array(i))
  1147. NextElement:
  1148. Next i
  1149. Return ResultArray
  1150. End Function
  1151. ''' <summary>
  1152. ''' 将数组从大到小排序。
  1153. ''' </summary>
  1154. ''' <param name="Array">纯数字的ArrayList。</param>
  1155. ''' <remarks></remarks>
  1156. Public Sub ArrayBigToSmall(ByRef Array As ArrayList)
  1157. If Array.Count < 2 Then Exit Sub
  1158. For i = 1 To Array.Count - 1
  1159. If Array(i) > Array(i - 1) Then
  1160. Dim c = Array(i - 1)
  1161. Array(i - 1) = Array(i)
  1162. Array(i) = c
  1163. If i >= 2 Then i = i - 2
  1164. End If
  1165. Next i
  1166. End Sub
  1167. ''' <summary>
  1168. ''' 强制将一个支持IList接口的对象转换为任意格式的一维数组。
  1169. ''' </summary>
  1170. ''' <typeparam name="T">转换后的数组类型。</typeparam>
  1171. ''' <param name="Source"></param>
  1172. ''' <returns></returns>
  1173. ''' <remarks></remarks>
  1174. Public Function ArrayConventer(Of T, B As IList)(ByVal Source As B) As T()
  1175. Dim Re(Source.Count - 1) As T
  1176. For i = 0 To Source.Count - 1
  1177. Re(i) = Source(i)
  1178. Next
  1179. Return Re
  1180. End Function
  1181. ''' <summary>
  1182. ''' 检查是否拥有某一文件夹的读取权限。如果文件夹不存在,会返回 False。
  1183. ''' </summary>
  1184. ''' <param name="Path">检查目录。</param>
  1185. Public Function CheckDirectoryPermission(ByVal Path As String) As Boolean
  1186. Try
  1187. If Path = "" Then Return False
  1188. If Not Directory.Exists(Path) Then Return False
  1189. Dim folderCheck As New DirectoryInfo(Path)
  1190. folderCheck.EnumerateFiles()
  1191. Return True
  1192. Catch
  1193. Return False
  1194. End Try
  1195. End Function
  1196. ''' <summary>
  1197. ''' 获取程序启动参数。
  1198. ''' </summary>
  1199. ''' <param name="Name">参数名。</param>
  1200. ''' <param name="DefaultValue">默认值。</param>
  1201. ''' <returns></returns>
  1202. ''' <remarks></remarks>
  1203. Public Function GetProgramArgument(ByVal Name As String, Optional ByVal DefaultValue As Object = "")
  1204. Dim AllArguments() As String = Microsoft.VisualBasic.Command.Split(" ")
  1205. For i = 0 To AllArguments.Length - 1
  1206. If AllArguments(i) = "-" & Name Then
  1207. If AllArguments.Length = i + 1 Then Return True
  1208. If AllArguments(i + 1).StartsWith("-") Then Return True
  1209. Return AllArguments(i + 1)
  1210. End If
  1211. Next
  1212. Return DefaultValue
  1213. End Function
  1214. ''' <summary>
  1215. ''' 获取Json对象。
  1216. ''' </summary>
  1217. ''' <param name="Text"></param>
  1218. ''' <returns></returns>
  1219. ''' <remarks></remarks>
  1220. Public Function ReadJson(ByVal Text As String) As JObject
  1221. Try
  1222. Return CType(Newtonsoft.Json.JsonConvert.DeserializeObject(Text), JObject)
  1223. Catch ex As Exception
  1224. ExShow(ex, "Json读取失败:" & Left(Text, 30))
  1225. Throw New FileFormatException("错误的 Json:" & GetStringFromException(ex, True))
  1226. End Try
  1227. End Function
  1228. '执行命令行函数
  1229. 'Public Function RunCMD(ByVal Commands As String, ByVal Wait As Boolean) As String
  1230. ' Dim myProcess As New Process()
  1231. ' Dim myProcessStartInfo As New ProcessStartInfo("cmd.exe")
  1232. ' myProcessStartInfo.UseShellExecute = False
  1233. ' myProcessStartInfo.RedirectStandardOutput = True
  1234. ' myProcessStartInfo.CreateNoWindow = True
  1235. ' myProcessStartInfo.Arguments = "/c """ & Commands & """"
  1236. ' myProcess.StartInfo = myProcessStartInfo
  1237. ' myProcess.Start()
  1238. ' If Wait Then
  1239. ' myProcess.WaitForExit()
  1240. ' Dim myStreamReader As IO.StreamReader = myProcess.StandardOutput
  1241. ' Dim myString As String = myStreamReader.ReadToEnd()
  1242. ' myProcess.Close()
  1243. ' myProcess.Dispose()
  1244. ' Return myString
  1245. ' Else
  1246. ' Return ""
  1247. ' End If
  1248. 'End Function
  1249. '注册表IO
  1250. Public Function ReadReg(ByVal Key As String, Optional ByVal DefaultValue As String = "") As String
  1251. Try
  1252. Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
  1253. parentKey = My.Computer.Registry.CurrentUser
  1254. softKey = parentKey.OpenSubKey("Software\" & APPLICATION_SHORT_NAME, True)
  1255. If softKey Is Nothing Then
  1256. ReadReg = DefaultValue '不存在则返回默认值
  1257. Else
  1258. Dim readValue As New System.Text.StringBuilder
  1259. readValue.AppendLine(softKey.GetValue(Key))
  1260. Dim value = readValue.ToString.Replace(vbCrLf, "") '去除莫名的回车
  1261. Return If(value = "", DefaultValue, value) '错误则返回默认值
  1262. End If
  1263. Catch ex As Exception
  1264. ExShow(ex, "读取注册表出错:" & Key, ErrorLevel.Slient)
  1265. Return DefaultValue
  1266. End Try
  1267. End Function
  1268. Public Sub WriteReg(ByVal Key As String, ByVal Value As String, Optional ByVal ShowException As Boolean = False)
  1269. Try
  1270. Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
  1271. parentKey = My.Computer.Registry.CurrentUser
  1272. softKey = parentKey.OpenSubKey("Software\" & APPLICATION_SHORT_NAME, True)
  1273. If softKey Is Nothing Then softKey = parentKey.CreateSubKey("Software\" & APPLICATION_SHORT_NAME) '如果不存在就创建
  1274. softKey.SetValue(Key, Value)
  1275. Catch ex As Exception
  1276. ExShow(ex, "写入注册表出错:" & Key, If(ShowException, modMain.ErrorLevel.DebugOnly, modMain.ErrorLevel.Slient))
  1277. If ShowException Then Throw '如果显示错误就丢一个
  1278. End Try
  1279. End Sub
  1280. Private UUID As Integer = 0
  1281. ''' <summary>
  1282. ''' 获取一个全程序内不会重复的数字(伪UUID)。
  1283. ''' </summary>
  1284. ''' <returns>UUID,一个大于0的有序整数。</returns>
  1285. ''' <remarks></remarks>
  1286. Public Function GetUUID() As Integer
  1287. UUID = UUID + 1
  1288. Return UUID
  1289. End Function
  1290. #End Region
  1291. #Region "Review完成 | 窗体"
  1292. ''' <summary>
  1293. ''' 等待显示的弹窗。
  1294. ''' </summary>
  1295. ''' <remarks></remarks>
  1296. Public WaitingMyMsgbox As ArrayList = If(IsNothing(WaitingMyMsgbox), New ArrayList, WaitingMyMsgbox)
  1297. ''' <summary>
  1298. ''' 显示弹窗。
  1299. ''' </summary>
  1300. Public Function MyMsgbox(ByVal Converter As MyMsgboxConverter) As Integer
  1301. Try
  1302. '存入等待列表
  1303. If Thread.CurrentThread.IsBackground Or Not Thread.CurrentThread.GetApartmentState = ApartmentState.STA Or Not AniRunning Then
  1304. If IsNothing(WaitingMyMsgbox) Then WaitingMyMsgbox = New ArrayList '初始化
  1305. WaitingMyMsgbox.Add(Converter)
  1306. '返回值
  1307. If Converter.IsWaitExit Then
  1308. Do While Converter.ReturnCode = 0
  1309. Thread.Sleep(50)
  1310. Loop
  1311. Return Converter.ReturnCode
  1312. Else
  1313. Return 0
  1314. End If
  1315. End If
  1316. '在主线程,显示窗体
  1317. Dim MsgBox As New MetroMsgbox(Converter) With {.Owner = frmMain, .Width = MAINFORM_WIDTH - 20, .Height = MAINFORM_HEIGHT - 20, .Left = (My.Computer.Screen.WorkingArea.Width - MAINFORM_WIDTH) / 2 + 10, .Top = (My.Computer.Screen.WorkingArea.Height - MAINFORM_HEIGHT) / 2 + 10}
  1318. If Converter.IsWaitExit Then
  1319. MsgBox.ShowDialog()
  1320. Return Converter.ReturnCode
  1321. Else
  1322. MsgBox.Show()
  1323. Return 0
  1324. End If
  1325. Catch ex As Exception
  1326. ExShow(ex, "显示弹窗失败:" & Converter.Title, ErrorLevel.MsgboxAndFeedback)
  1327. Return 0
  1328. End Try
  1329. End Function
  1330. ''' <summary>
  1331. ''' 显示弹窗。
  1332. ''' </summary>
  1333. ''' <param name="Title">弹窗的标题。</param>
  1334. ''' <param name="Caption">弹窗的内容。</param>
  1335. ''' <param name="Button1">显示的第一个按钮,默认为“确定”。</param>
  1336. ''' <param name="Button2">显示的第二个按钮,默认为空。</param>
  1337. ''' <param name="Button3">显示的第三个按钮,默认为空。</param>
  1338. ''' <param name="IsWarn">是否为警告弹窗,若为 True,第一个按钮会显示为红色。</param>
  1339. ''' <param name="IsWaitExit">是否等待弹窗关闭。若为 True,将会返回从 1 开始的点击的按钮编号,否则返回 0。</param>
  1340. ''' <returns></returns>
  1341. ''' <remarks></remarks>
  1342. Public Function MyMsgbox(ByVal Caption As String, Optional ByVal Title As String = APPLICATION_FULL_NAME, Optional ByVal Button1 As String = "确定", Optional ByVal Button2 As String = "", Optional ByVal Button3 As String = "", Optional ByVal IsWarn As Boolean = False, Optional ByVal IsWaitExit As Boolean = True) As Integer
  1343. Dim NewMsgBoxConverter As New MyMsgboxConverter With {.Button1 = Button1, .Button2 = Button2, .Button3 = Button3, .Caption = Caption, .IsWarn = IsWarn, .Title = Title, .IsWaitExit = IsWaitExit}
  1344. Return MyMsgbox(NewMsgBoxConverter)
  1345. End Function
  1346. ''' <summary>
  1347. ''' 存储弹窗信息的转换器。
  1348. ''' </summary>
  1349. ''' <remarks></remarks>
  1350. Public Class MyMsgboxConverter
  1351. Public Title As String
  1352. Public Caption As String = ""
  1353. Public Button1 As String = "确定"
  1354. Public Button2 As String = ""
  1355. Public Button3 As String = ""
  1356. Public IsWarn As Boolean = False
  1357. Public IsWaitExit As Boolean = True
  1358. ''' <summary>
  1359. ''' 弹窗是否已经关闭。
  1360. ''' </summary>
  1361. ''' <remarks></remarks>
  1362. Public IsExited As Boolean = False
  1363. ''' <summary>
  1364. ''' 点击的按钮编号,从 1 开始。
  1365. ''' </summary>
  1366. ''' <remarks></remarks>
  1367. Public ReturnCode As Integer = 0
  1368. End Class
  1369. 'Public Function MyMsgbox(ByVal title As String, ByVal page As Grid, Optional ByVal caption As String = "", Optional ByVal btn1 As String = "确定", Optional ByVal btn2 As String = "", Optional ByVal btn3 As String = "", Optional ByVal wait As Boolean = False) As Object
  1370. ' Dim wind As New MetroMsgbox With {.Owner = frmMain, .Width = MAINFORM_WIDTH - 20, .Height = MAINFORM_HEIGHT - 20, .Left = (My.Computer.Screen.WorkingArea.Width - MAINFORM_WIDTH) / 2 + 10, .Top = (My.Computer.Screen.WorkingArea.Height - MAINFORM_HEIGHT) / 2 + 10}
  1371. ' wind.labTitle.Text = title
  1372. ' wind.panCaption.Child = page
  1373. ' wind.btn1.Text = btn1
  1374. ' wind.btn2.Text = btn2
  1375. ' wind.btn3.Text = btn3
  1376. ' wind.btn2.Visibility = If(btn2 = "", Visibility.Collapsed, Visibility.Visible)
  1377. ' wind.btn3.Visibility = If(btn3 = "", Visibility.Collapsed, Visibility.Visible)
  1378. ' msgboxCallback = 0
  1379. ' If wait Then
  1380. ' wind.Show()
  1381. ' Return wind
  1382. ' Else
  1383. ' wind.ShowDialog()
  1384. ' Return msgboxCallback
  1385. ' End If
  1386. 'End Function
  1387. ''' <summary>设置 WebBrowser 静默,即是否不产生弹窗。</summary>
  1388. ''' <param name="webBrowser">需要改变的 WebBrowser。</param>
  1389. ''' <param name="IsSilent">是否开启静默模式。</param>
  1390. Public Sub SetWebBrowserSilent(ByVal WebBrowser As WebBrowser, ByVal IsSilent As Boolean)
  1391. Try
  1392. Dim fi As FieldInfo = WebBrowser.GetType.GetField("_axIWebBrowser2", BindingFlags.Instance Or BindingFlags.NonPublic)
  1393. If Not IsNothing(fi) Then
  1394. Dim browser = fi.GetValue(WebBrowser)
  1395. If Not IsNothing(browser) Then
  1396. browser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, Nothing, browser, {IsSilent})
  1397. End If
  1398. End If
  1399. Catch ex As Exception
  1400. ExShow(ex, "设置浏览器失败", ErrorLevel.AllUsers)
  1401. End Try
  1402. End Sub
  1403. #End Region
  1404. #Region "随机"
  1405. '打乱数组
  1406. Public Function RandomArray(ByVal array As ArrayList) As ArrayList
  1407. RandomArray = New ArrayList
  1408. Do While array.Count > 0
  1409. Dim i As Integer = RandomInteger(0, array.Count - 1)
  1410. RandomArray.Add(array(i))
  1411. array.RemoveAt(i)
  1412. Loop
  1413. End Function
  1414. '获取随机整数
  1415. Public Function RandomInteger(ByVal min As Integer, ByVal max As Integer) As Integer
  1416. Return Math.Round((max - min) * Rnd.NextDouble) + min
  1417. End Function
  1418. #End Region
  1419. #Region "Review 完成 | 音乐"
  1420. ''' <summary>
  1421. ''' 播放音乐。
  1422. ''' </summary>
  1423. ''' <param name="FilePath">音乐文件完整路径。</param>
  1424. ''' <remarks></remarks>
  1425. Public Sub PlayBgm(ByVal FilePath As String, ByVal IsStop As Boolean, Optional ByVal IsShowHint As Boolean = False)
  1426. Try
  1427. If IsStop Then
  1428. '停止
  1429. log("[System] 停止播放音乐:" & FilePath)
  1430. mciSendString("close " & FilePath, 0, 0, 0)
  1431. PlaySound(Nothing, Nothing, Nothing)
  1432. Else
  1433. '播放
  1434. log("[System] 播放音乐:" & FilePath)
  1435. mciSendString("open " & FilePath, "", 0, 0)
  1436. Dim code = mciSendString("play " & FilePath & " repeat", "", 0, 0)
  1437. If code = 259 Then
  1438. PlaySound(FilePath, 0, 131072 Or 1 Or 8) '换用 PlaySound 播放不支持循环的 .wav
  1439. 'If IsShowHint Then ShowHint("该音乐不支持循环播放,音乐将在播放完一次后停止。")
  1440. 'code = mciSendString("play " & FilePath, "", 0, 0)
  1441. ElseIf code = 277 Then
  1442. If IsShowHint Then MyMsgbox("无效的音乐文件。" & vbCrLf & "PCL 不支持部分 MP3 的播放,请尝试更换文件。目前已知网易云下载的 MP3 会出现此问题,原因不明。", "播放音乐失败")
  1443. ElseIf Not code = 0 Then
  1444. Throw New Exception(code)
  1445. End If
  1446. End If
  1447. 'PlaySound(FilePath, 0, 131072 Or 1 Or 8)
  1448. Catch ex As Exception
  1449. ExShow(ex, "播放音乐失败", ErrorLevel.AllUsers)
  1450. End Try
  1451. End Sub
  1452. #End Region
  1453. End Module '基础函数
  1454. 'Module ComputerInfo
  1455. ' '声明
  1456. ' 'Private cpuCounter As New PerformanceCounter("Processor", "% Processor Time", "_Total")
  1457. ' 'Private downloadCounter As New PerformanceCounter("Network Interface", "Bytes Received/sec", New PerformanceCounterCategory("Network Interface").GetInstanceNames()(0))
  1458. ' 'Private uploadCounter As New PerformanceCounter("Network Interface", "Bytes Sent/sec", New PerformanceCounterCategory("Network Interface").GetInstanceNames()(0))
  1459. ' Private pcInfo As New Microsoft.VisualBasic.Devices.ComputerInfo
  1460. ' '启动代码
  1461. ' Public Sub InfoStartRun(ByVal time As Integer)
  1462. ' Dim timer As New DispatcherTimer()
  1463. ' timer.Interval = TimeSpan.FromMilliseconds(time)
  1464. ' AddHandler timer.Tick, AddressOf InfoTimer
  1465. ' timer.Start()
  1466. ' End Sub
  1467. ' '每次执行的代码
  1468. ' Private Sub InfoTimer()
  1469. ' '防止断网时获取错误
  1470. ' On Error Resume Next
  1471. ' infoDownloadSpeed = 0
  1472. ' infoUploadSpeed = 0
  1473. ' '获取值
  1474. ' 'infoCpuPercent = cpuCounter.NextValue
  1475. ' 'infoDownloadSpeed = downloadCounter.NextValue / 1024
  1476. ' 'infoUploadSpeed = uploadCounter.NextValue / 1024
  1477. ' End Sub
  1478. ' '获取信息
  1479. ' Public infoCpuPercent As Integer = 0 'CPU使用率
  1480. ' Public infoDownloadSpeed As Integer = 0 '下载速度(KB)
  1481. ' Public infoUploadSpeed As Integer = 0 '上传速度(KB)
  1482. ' Public Function infoNetworkSpeed() As Integer
  1483. ' Return infoDownloadSpeed + infoUploadSpeed
  1484. ' End Function '网络速度(KB)
  1485. ' Public Function infoRamPercent() As Integer
  1486. ' Return (pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory) / pcInfo.TotalPhysicalMemory * 100
  1487. ' End Function '内存使用率
  1488. ' Public Function infoRamUsed() As Integer
  1489. ' Return (pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory) / 1024 / 1024
  1490. ' End Function '内存使用量(MB)
  1491. ' Public Function infoRamTotal() As Integer
  1492. ' Return pcInfo.TotalPhysicalMemory / 1024 / 1024
  1493. ' End Function '内存总量(MB)
  1494. ' Public Function infoRamAvailable() As Integer
  1495. ' Return pcInfo.AvailablePhysicalMemory / 1024 / 1024
  1496. ' End Function '内存可用量(MB)
  1497. 'End Module '电脑信息获取
  1498. Public Module MyAnimationer
  1499. #Region "声明"
  1500. ''' <summary>
  1501. ''' 动画组列表。(组名→ArrayList)
  1502. ''' </summary>
  1503. ''' <remarks></remarks>
  1504. Private AniGroups As New Dictionary(Of String, ArrayList)
  1505. ''' <summary>
  1506. ''' 上一次记刻的时间。
  1507. ''' </summary>
  1508. ''' <remarks></remarks>
  1509. Public AniLastTick As Integer
  1510. ''' <summary>
  1511. ''' 动画执行是否开启。
  1512. ''' </summary>
  1513. ''' <remarks></remarks>
  1514. Public AniRunning As Boolean = False
  1515. #End Region
  1516. #Region "类与枚举"
  1517. ''' <summary>
  1518. ''' 单个动画对象。
  1519. ''' </summary>
  1520. ''' <remarks></remarks>
  1521. Public Structure Animation
  1522. ''' <summary>
  1523. ''' 动画种类。
  1524. ''' </summary>
  1525. ''' <remarks></remarks>
  1526. Public AniType As AniType
  1527. ''' <summary>
  1528. ''' 动画副种类。
  1529. ''' </summary>
  1530. ''' <remarks></remarks>
  1531. Public AniSubType As AniSubType
  1532. ''' <summary>
  1533. ''' 动画总长度。
  1534. ''' </summary>
  1535. ''' <remarks></remarks>
  1536. Public TotalLength As Integer
  1537. ''' <summary>
  1538. ''' 已经执行的动画长度。如果为负数则为延迟。
  1539. ''' </summary>
  1540. ''' <remarks></remarks>
  1541. Public FinishLength As Integer
  1542. ''' <summary>
  1543. ''' 已经完成的百分比。
  1544. ''' </summary>
  1545. ''' <remarks></remarks>
  1546. Public Percent As Double
  1547. ''' <summary>
  1548. ''' 是否为“以后”。
  1549. ''' </summary>
  1550. ''' <remarks></remarks>
  1551. Public After As Boolean
  1552. ''' <summary>
  1553. ''' 插值器类型。
  1554. ''' </summary>
  1555. ''' <remarks></remarks>
  1556. Public Ease As AniEase
  1557. ''' <summary>
  1558. ''' 动画对象。
  1559. ''' </summary>
  1560. ''' <remarks></remarks>
  1561. Public Obj As Object
  1562. ''' <summary>
  1563. ''' 动画值。
  1564. ''' </summary>
  1565. ''' <remarks></remarks>
  1566. Public Value As Object
  1567. ''' <summary>
  1568. ''' 上次执行时的动画值。
  1569. ''' </summary>
  1570. ''' <remarks></remarks>
  1571. Public Last As Object
  1572. Public Overrides Function ToString() As String
  1573. Return GetStringFromEnum(AniType) & " | " & FinishLength & "/" & TotalLength & "(" & Math.Round(Percent * 100) & "%) | " & Obj.name & "(" & Obj.GetType.Name & ")"
  1574. End Function
  1575. End Structure
  1576. ''' <summary>
  1577. ''' 动画基础种类。
  1578. ''' </summary>
  1579. ''' <remarks></remarks>
  1580. Public Enum AniType As Byte
  1581. ''' <summary>
  1582. ''' 单个Double的动画,包括位置、长宽、透明度等。这需要附属类型。
  1583. ''' </summary>
  1584. ''' <remarks></remarks>
  1585. DoubleAnimation = 0
  1586. ''' <summary>
  1587. ''' 颜色属性的动画。这需要附属类型。
  1588. ''' </summary>
  1589. ''' <remarks></remarks>
  1590. ColorAnimation = 1
  1591. ''' <summary>
  1592. ''' 缩放控件大小。比起4个DoubleAnimation来说效率更高。
  1593. ''' </summary>
  1594. ''' <remarks></remarks>
  1595. Scale = 2
  1596. ''' <summary>
  1597. ''' 文字一个个出现。
  1598. ''' </summary>
  1599. ''' <remarks></remarks>
  1600. TextAppear = 3
  1601. ''' <summary>
  1602. ''' 执行代码。
  1603. ''' </summary>
  1604. ''' <remarks></remarks>
  1605. Code = 4
  1606. ''' <summary>
  1607. ''' 执行按照规定格式书写的伪代码。比起Code来说这有很大的局限性,但效率更高。
  1608. ''' </summary>
  1609. ''' <remarks></remarks>
  1610. CodeEvent = 5
  1611. ''' <summary>
  1612. ''' 以 WPF 方式缩放控件。
  1613. ''' </summary>
  1614. ScaleTransform = 6
  1615. ''' <summary>
  1616. ''' 以 WPF 方式旋转控件。
  1617. ''' </summary>
  1618. RotateTransform = 7
  1619. End Enum
  1620. ''' <summary>
  1621. ''' 动画扩展种类。
  1622. ''' </summary>
  1623. ''' <remarks></remarks>
  1624. Public Enum AniSubType As Byte
  1625. X = 0
  1626. Y = 1
  1627. Width = 2
  1628. Height = 3
  1629. Opacity = 4
  1630. Value = 5
  1631. Radius = 10
  1632. BorderThickness = 11
  1633. Background = 6
  1634. BorderBrush = 7
  1635. Foreground = 8
  1636. Stroke = 9
  1637. End Enum
  1638. #End Region
  1639. #Region "种类"
  1640. 'DoubleAnimation
  1641. ''' <summary>
  1642. ''' 移动X轴的动画。
  1643. ''' </summary>
  1644. ''' <param name="Obj">动画的对象。</param>
  1645. ''' <param name="Value">进行移动的值。</param>
  1646. ''' <param name="Time">动画长度(毫秒)。</param>
  1647. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1648. ''' <param name="Ease">插值器类型。</param>
  1649. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1650. ''' <returns></returns>
  1651. ''' <remarks></remarks>
  1652. Public Function AaX(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1653. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.X,
  1654. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1655. End Function
  1656. ''' <summary>
  1657. ''' 移动Y轴的动画。
  1658. ''' </summary>
  1659. ''' <param name="Obj">动画的对象。</param>
  1660. ''' <param name="Value">进行移动的值。</param>
  1661. ''' <param name="Time">动画长度(毫秒)。</param>
  1662. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1663. ''' <param name="Ease">插值器类型。</param>
  1664. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1665. ''' <returns></returns>
  1666. ''' <remarks></remarks>
  1667. Public Function AaY(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1668. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Y,
  1669. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1670. End Function
  1671. ''' <summary>
  1672. ''' 改变宽度的动画。
  1673. ''' </summary>
  1674. ''' <param name="Obj">动画的对象。</param>
  1675. ''' <param name="Value">宽度改变的值。</param>
  1676. ''' <param name="Time">动画长度(毫秒)。</param>
  1677. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1678. ''' <param name="Ease">插值器类型。</param>
  1679. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1680. ''' <returns></returns>
  1681. ''' <remarks></remarks>
  1682. Public Function AaWidth(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1683. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Width,
  1684. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1685. End Function
  1686. ''' <summary>
  1687. ''' 改变高度的动画。
  1688. ''' </summary>
  1689. ''' <param name="Obj">动画的对象。</param>
  1690. ''' <param name="Value">高度改变的值。</param>
  1691. ''' <param name="Time">动画长度(毫秒)。</param>
  1692. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1693. ''' <param name="Ease">插值器类型。</param>
  1694. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1695. ''' <returns></returns>
  1696. ''' <remarks></remarks>
  1697. Public Function AaHeight(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1698. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Height,
  1699. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1700. End Function
  1701. ''' <summary>
  1702. ''' 改变透明度的动画。
  1703. ''' </summary>
  1704. ''' <param name="Obj">动画的对象。</param>
  1705. ''' <param name="Value">透明度改变的值。</param>
  1706. ''' <param name="Time">动画长度(毫秒)。</param>
  1707. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1708. ''' <param name="Ease">插值器类型。</param>
  1709. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1710. ''' <returns></returns>
  1711. ''' <remarks></remarks>
  1712. Public Function AaOpacity(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1713. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Opacity,
  1714. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1715. End Function
  1716. ''' <summary>
  1717. ''' 改变对象的Value属性的动画。
  1718. ''' </summary>
  1719. ''' <param name="Obj">动画的对象。</param>
  1720. ''' <param name="Value">Value属性改变的值。</param>
  1721. ''' <param name="Time">动画长度(毫秒)。</param>
  1722. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1723. ''' <param name="Ease">插值器类型。</param>
  1724. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1725. ''' <returns></returns>
  1726. ''' <remarks></remarks>
  1727. Public Function AaValue(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1728. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Value,
  1729. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1730. End Function
  1731. ''' <summary>
  1732. ''' 改变对象的Radius属性的动画。
  1733. ''' </summary>
  1734. ''' <param name="Obj">动画的对象。</param>
  1735. ''' <param name="Value">Radius属性改变的值。</param>
  1736. ''' <param name="Time">动画长度(毫秒)。</param>
  1737. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1738. ''' <param name="Ease">插值器类型。</param>
  1739. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1740. ''' <returns></returns>
  1741. ''' <remarks></remarks>
  1742. Public Function AaRadius(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1743. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Radius,
  1744. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1745. End Function
  1746. ''' <summary>
  1747. ''' 改变对象的BorderThickness属性的动画。
  1748. ''' </summary>
  1749. ''' <param name="Obj">动画的对象。</param>
  1750. ''' <param name="Value">BorderThickness属性改变的值。</param>
  1751. ''' <param name="Time">动画长度(毫秒)。</param>
  1752. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1753. ''' <param name="Ease">插值器类型。</param>
  1754. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1755. ''' <returns></returns>
  1756. ''' <remarks></remarks>
  1757. Public Function AaBorderThickness(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1758. Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.BorderThickness,
  1759. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1760. End Function
  1761. 'ColorAnimation
  1762. ''' <summary>
  1763. ''' 改变Background颜色属性的动画。
  1764. ''' </summary>
  1765. ''' <param name="Obj">动画的对象。</param>
  1766. ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
  1767. ''' <param name="Time">动画长度(毫秒)。</param>
  1768. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1769. ''' <param name="Ease">插值器类型。</param>
  1770. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1771. ''' <returns></returns>
  1772. ''' <remarks></remarks>
  1773. Public Function AaBackGround(ByVal Obj As Object, ByVal Value As MyColor, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1774. Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Background,
  1775. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
  1776. End Function
  1777. ''' <summary>
  1778. ''' 改变BorderBrush颜色属性的动画。
  1779. ''' </summary>
  1780. ''' <param name="Obj">动画的对象。</param>
  1781. ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
  1782. ''' <param name="Time">动画长度(毫秒)。</param>
  1783. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1784. ''' <param name="Ease">插值器类型。</param>
  1785. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1786. ''' <returns></returns>
  1787. ''' <remarks></remarks>
  1788. Public Function AaBorderBrush(ByVal Obj As Object, ByVal Value As MyColor, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1789. Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.BorderBrush,
  1790. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
  1791. End Function
  1792. ''' <summary>
  1793. ''' 改变Foreground颜色属性的动画。
  1794. ''' </summary>
  1795. ''' <param name="Obj">动画的对象。</param>
  1796. ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
  1797. ''' <param name="Time">动画长度(毫秒)。</param>
  1798. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1799. ''' <param name="Ease">插值器类型。</param>
  1800. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1801. ''' <returns></returns>
  1802. ''' <remarks></remarks>
  1803. Public Function AaForeGround(ByVal Obj As Object, ByVal Value As MyColor, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1804. Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Foreground,
  1805. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
  1806. End Function
  1807. ''' <summary>
  1808. ''' 改变Stroke颜色属性的动画。
  1809. ''' </summary>
  1810. ''' <param name="Obj">动画的对象。</param>
  1811. ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
  1812. ''' <param name="Time">动画长度(毫秒)。</param>
  1813. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1814. ''' <param name="Ease">插值器类型。</param>
  1815. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1816. ''' <returns></returns>
  1817. ''' <remarks></remarks>
  1818. Public Function AaStroke(ByVal Obj As Object, ByVal Value As MyColor, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1819. Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Stroke,
  1820. .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
  1821. End Function
  1822. 'Scale
  1823. ''' <summary>
  1824. ''' 缩放控件的动画。
  1825. ''' </summary>
  1826. ''' <param name="Obj">动画的对象。</param>
  1827. ''' <param name="Value">大小改变的百分比(如-0.6)或值。</param>
  1828. ''' <param name="Time">动画长度(毫秒)。</param>
  1829. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1830. ''' <param name="Ease">插值器类型。</param>
  1831. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1832. ''' <param name="Absolute">大小改变是否为绝对值。若为False则会按照控件当前大小计算相对缩放值。</param>
  1833. ''' <returns></returns>
  1834. ''' <remarks></remarks>
  1835. Public Function AaScale(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False, Optional ByVal Absolute As Boolean = False) As Animation
  1836. Dim ChangeRect As New AdvancedRect
  1837. If Absolute Then
  1838. ChangeRect = New AdvancedRect(-0.5 * Value, -0.5 * Value, Value, Value)
  1839. Else
  1840. ChangeRect = New AdvancedRect(-0.5 * Obj.ActualWidth * Value, -0.5 * Obj.ActualHeight * Value, Obj.ActualWidth * Value, Obj.ActualHeight * Value)
  1841. End If
  1842. Return New Animation With {.AniType = AniType.Scale, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = ChangeRect, .After = After, .FinishLength = -Delay}
  1843. End Function
  1844. 'TextAppear
  1845. ''' <summary>
  1846. ''' 让一段文字一个个字出现或消失的动画。
  1847. ''' </summary>
  1848. ''' <param name="Obj">动画的对象。必须是Label或TextBlock。</param>
  1849. ''' <param name="Hide">是否为一个个字隐藏。默认为False(一个个字出现)。这些字必须已经存在了。</param>
  1850. ''' <param name="TimePerText">是否采用根据文本长度决定时间的方式。</param>
  1851. ''' <param name="Time">动画长度(毫秒)。若TimePerText为True,这代表每个字所占据的时间。</param>
  1852. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1853. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1854. ''' <returns></returns>
  1855. ''' <remarks></remarks>
  1856. Public Function AaTextAppear(ByVal Obj As Object, Optional ByVal Hide As Boolean = False, Optional ByVal TimePerText As Boolean = True, Optional ByVal Time As Integer = 70, Optional ByVal Delay As Integer = 0, Optional ByVal After As Boolean = False) As Animation
  1857. 'Are we cool yet?
  1858. Return New Animation With {.AniType = AniType.TextAppear, .TotalLength = If(TimePerText, Time * Len(If(Obj.GetType.Name = "TextBlock", Obj.Text, Obj.Context.ToString)), Time), .Obj = Obj, .Value = {If(Obj.GetType.Name = "TextBlock", Obj.Text, Obj.Context.ToString), Hide}, .After = After, .FinishLength = -Delay}
  1859. End Function
  1860. 'Code
  1861. ''' <summary>
  1862. ''' 执行代码。
  1863. ''' </summary>
  1864. ''' <param name="Code">一个ThreadStart。这将会在执行时在主线程调用。</param>
  1865. ''' <param name="Delay">代码延迟执行的时间(毫秒)。</param>
  1866. ''' <param name="After">是否等到以前的动画完成后才执行。</param>
  1867. ''' <returns></returns>
  1868. ''' <remarks></remarks>
  1869. Public Function AaCode(ByVal Code As ThreadStart, Optional ByVal Delay As Integer = 0, Optional ByVal After As Boolean = False) As Animation
  1870. Return New Animation With {.AniType = AniType.Code,
  1871. .TotalLength = 1, .Value = Code, .After = After, .FinishLength = -Delay}
  1872. End Function
  1873. 'CodeEvent
  1874. ''' <summary>
  1875. ''' 执行按照规定格式书写的伪代码。这有很大的局限性,但不会建立线程,性能也更好。
  1876. ''' </summary>
  1877. ''' <param name="Code">伪代码元素数组。</param>
  1878. ''' <param name="Delay">代码延迟执行的时间(毫秒)。</param>
  1879. ''' <param name="After">是否等到以前的动画完成后才执行。</param>
  1880. ''' <returns></returns>
  1881. ''' <remarks></remarks>
  1882. Public Function AaCode(ByVal Code As Array, Optional ByVal Delay As Integer = 0, Optional ByVal After As Boolean = False) As Animation
  1883. Return New Animation With {.AniType = AniType.CodeEvent,
  1884. .TotalLength = 1, .Value = Code, .After = After, .FinishLength = -Delay}
  1885. End Function
  1886. 'ScaleTransform
  1887. ''' <summary>
  1888. ''' 按照 WPF 方式缩放控件的动画。
  1889. ''' </summary>
  1890. ''' <param name="Obj">动画的对象。它必须已经拥有了单一的 ScaleTransform 值。</param>
  1891. ''' <param name="Value">大小改变的百分比(如-0.6)。</param>
  1892. ''' <param name="Time">动画长度(毫秒)。</param>
  1893. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1894. ''' <param name="Ease">插值器类型。</param>
  1895. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1896. ''' <returns></returns>
  1897. ''' <remarks></remarks>
  1898. Public Function AaScaleTransform(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1899. Return New Animation With {.AniType = AniType.ScaleTransform, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1900. End Function
  1901. 'RotateTransform
  1902. ''' <summary>
  1903. ''' 按照 WPF 方式旋转控件的动画。
  1904. ''' </summary>
  1905. ''' <param name="Obj">动画的对象。它必须已经拥有了单一的 ScaleTransform 值。</param>
  1906. ''' <param name="Value">大小改变的百分比(如-0.6)。</param>
  1907. ''' <param name="Time">动画长度(毫秒)。</param>
  1908. ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
  1909. ''' <param name="Ease">插值器类型。</param>
  1910. ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
  1911. ''' <returns></returns>
  1912. ''' <remarks></remarks>
  1913. Public Function AaRotateTransform(ByVal Obj As Object, ByVal Value As Double, Optional ByVal Time As Integer = 400, Optional ByVal Delay As Integer = 0, Optional ByVal Ease As AniEase = Nothing, Optional ByVal After As Boolean = False) As Animation
  1914. Return New Animation With {.AniType = AniType.RotateTransform, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
  1915. End Function
  1916. '特殊
  1917. ''' <summary>
  1918. ''' 将一个StackPanel中的各个项目依次显示。
  1919. ''' </summary>
  1920. ''' <remarks></remarks>
  1921. Public Function AaStack(ByVal Stack As StackPanel) As ArrayList
  1922. AaStack = New ArrayList
  1923. Dim AniDelay As Integer = 0
  1924. For Each Item In Stack.Children
  1925. Item.Opacity = 0
  1926. AaStack.Add(AaOpacity(Item, 1, 100, AniDelay))
  1927. AniDelay = AniDelay + 25
  1928. Next
  1929. End Function
  1930. #End Region
  1931. #Region "插值器"
  1932. '基类
  1933. Public MustInherit Class AniEase
  1934. ''' <summary>
  1935. ''' 获取增加值。
  1936. ''' </summary>
  1937. ''' <param name="t1">较大的时间百分比。</param>
  1938. ''' <param name="t0">较小的时间百分比。</param>
  1939. ''' <returns></returns>
  1940. Public MustOverride Function GetDelta(t1 As Double, t0 As Double) As Double
  1941. End Class
  1942. ''' <summary>
  1943. ''' 线性,无缓动。
  1944. ''' </summary>
  1945. Public Class AniEaseNone
  1946. Inherits AniEase
  1947. Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
  1948. t1 = MathRange(t1, 0, 1)
  1949. t0 = MathRange(t0, 0, 1)
  1950. Return t1 - t0
  1951. End Function
  1952. End Class
  1953. ''' <summary>
  1954. ''' 平滑开始。
  1955. ''' </summary>
  1956. Public Class AniEaseStart
  1957. Inherits AniEase
  1958. Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
  1959. t1 = MathRange(t1, 0, 1)
  1960. t0 = MathRange(t0, 0, 1)
  1961. Return (t1 - t0) * (t1 + t0)
  1962. End Function
  1963. End Class
  1964. ''' <summary>
  1965. ''' 平滑结束。
  1966. ''' </summary>
  1967. Public Class AniEaseEnd
  1968. Inherits AniEase
  1969. Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
  1970. t1 = MathRange(t1, 0, 1)
  1971. t0 = MathRange(t0, 0, 1)
  1972. Return (t1 - t0) * (2 - t1 - t0)
  1973. End Function
  1974. End Class
  1975. ''' <summary>
  1976. ''' 跳跃开始。
  1977. ''' </summary>
  1978. Public Class AniEaseJumpStart
  1979. Inherits AniEase
  1980. ''' <summary>
  1981. '''
  1982. ''' </summary>
  1983. ''' <param name="JumpEndPercent">跳跃结束时占整个动画的百分比。</param>
  1984. Public Sub New(JumpEndPercent As Double)
  1985. o = JumpEndPercent
  1986. End Sub
  1987. Private o As Double
  1988. Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
  1989. t1 = MathRange(t1, 0, 1)
  1990. t0 = MathRange(t0, 0, 1)
  1991. Return (t1 - t0) * (t1 + t0 - o) / (1 - o)
  1992. End Function
  1993. End Class
  1994. ''' <summary>
  1995. ''' 跳跃结束。
  1996. ''' </summary>
  1997. Public Class AniEaseJumpEnd
  1998. Inherits AniEase
  1999. ''' <summary>
  2000. '''
  2001. ''' </summary>
  2002. ''' <param name="JumpStartPercent">跳跃开始时占整个动画的百分比。</param>
  2003. Public Sub New(JumpStartPercent As Double)
  2004. o = JumpStartPercent
  2005. End Sub
  2006. Private o As Double
  2007. Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
  2008. t1 = MathRange(t1, 0, 1)
  2009. t0 = MathRange(t0, 0, 1)
  2010. Return (t1 - t0) * (o + 1 - t1 - t0) / o
  2011. End Function
  2012. End Class
  2013. #End Region
  2014. '等待处理的动画组列表
  2015. Private AniWaitingList As New ArrayList
  2016. Private AniWaitingListName As New ArrayList
  2017. ''' <summary>
  2018. ''' 开始一个动画组。
  2019. ''' </summary>
  2020. ''' <param name="AniGroup">由Aa开头的函数初始化的Animation对象集合。</param>
  2021. ''' <param name="Name">动画组的名称。如果重复会直接停止同名动画组。</param>
  2022. ''' <param name="RefreshTime">是否重新开始这一帧的计时。如果该动画组连续执行请设置为False。</param>
  2023. ''' <remarks></remarks>
  2024. Public Sub AniStart(ByVal AniGroup As ArrayList, ByVal Name As String, Optional ByVal refreshTime As Boolean = True)
  2025. '把组动画(如 AniStack)分解
  2026. Dim AniGroupSet As New ArrayList
  2027. For i = 0 To AniGroup.Count - 1
  2028. If AniGroup(i).GetType.ToString.Contains("ArrayList") Then
  2029. AniGroupSet.AddRange(AniGroup(i))
  2030. Else
  2031. AniGroupSet.Add(AniGroup(i))
  2032. End If
  2033. Next i
  2034. '添加到正在执行的动画组
  2035. If refreshTime Then AniLastTick = Computer.Clock.TickCount '避免处理动画时已经造成了极大的延迟,导致动画突然结束
  2036. AniStop(Name)
  2037. AniGroups.Add(Name, AniGroupSet)
  2038. End Sub
  2039. ''' <summary>
  2040. ''' 开始一个动画组。
  2041. ''' </summary>
  2042. ''' <param name="AniGroup">由Aa开头的函数初始化的Animation对象集合。</param>
  2043. ''' <param name="Name">动画组的名称。如果重复会直接停止同名动画组。</param>
  2044. ''' <param name="RefreshTime">是否重新开始这一帧的计时。如果该动画组连续执行请设置为False。</param>
  2045. ''' <remarks></remarks>
  2046. Public Sub AniStart(ByVal aniGroup As Array, ByVal name As String, Optional ByVal refreshTime As Boolean = True)
  2047. '让Array和ArrayList都可以添加
  2048. AniStart(New ArrayList(aniGroup), name, refreshTime)
  2049. End Sub
  2050. ''' <summary>
  2051. ''' 停止一个动画组。
  2052. ''' </summary>
  2053. ''' <param name="name">需要停止的动画组的名称。</param>
  2054. ''' <remarks></remarks>
  2055. Public Sub AniStop(ByVal Name As String)
  2056. If AniGroups.ContainsKey(Name) Then AniGroups.Remove(Name)
  2057. End Sub
  2058. Private AniMissions As New ArrayList
  2059. Private AniFPSCounter As Integer = 0
  2060. Private AniFPSTimer As Long = 0
  2061. ''' <summary>
  2062. ''' 当前的动画 FPS。
  2063. ''' </summary>
  2064. Public AniFPS As Integer = 0
  2065. ''' <summary>
  2066. ''' 开始动画执行。
  2067. ''' </summary>
  2068. ''' <remarks></remarks>
  2069. Public Sub AniStartRun()
  2070. '初始化计时器
  2071. AniLastTick = My.Computer.Clock.TickCount
  2072. AniFPSTimer = My.Computer.Clock.TickCount
  2073. AniRunning = True '标记动画执行开始
  2074. Dim th = New Thread(Sub()
  2075. Do While True
  2076. '两帧之间的间隔时间
  2077. Dim DeltaTime As Integer = My.Computer.Clock.TickCount - AniLastTick
  2078. If DeltaTime < 2 Then GoTo Sleeper
  2079. AniLastTick = My.Computer.Clock.TickCount
  2080. '执行动画
  2081. frmMain.Dispatcher.Invoke(Sub() AniTimer(DeltaTime))
  2082. '记录 FPS
  2083. If AniLastTick - AniFPSTimer >= 1000 Then
  2084. AniFPS = AniFPSCounter
  2085. AniFPSCounter = 0
  2086. AniFPSTimer = AniLastTick
  2087. If MODE_DEVELOPER Then frmMain.Dispatcher.Invoke(Sub() frmMain.Title = "PCL / FPS : " & AniFPS)
  2088. End If
  2089. AniFPSCounter = AniFPSCounter + 1
  2090. Sleeper:
  2091. '控制 FPS
  2092. Thread.Sleep(1)
  2093. Loop
  2094. End Sub)
  2095. th.Start()
  2096. End Sub
  2097. Private AniCodeList As New ArrayList
  2098. ''' <summary>
  2099. ''' 动画定时器事件。
  2100. ''' </summary>
  2101. ''' <remarks></remarks>
  2102. Public Sub AniTimer(DeltaTime As Integer)
  2103. Rnd.NextDouble() '重置随机数发生器
  2104. For Each Code In AniCodeList
  2105. frmMain.Dispatcher.Invoke(Code)
  2106. Next
  2107. AniCodeList.Clear()
  2108. Try
  2109. Dim i As Integer = 0
  2110. '循环每个动画组
  2111. Do While i < AniGroups.Count
  2112. '初始化
  2113. Dim aniGroup = AniGroups.Values(i)
  2114. Dim CanRemoveAfter = True '是否应该去除“之后”标记
  2115. Dim ii = 0
  2116. '循环每个动画
  2117. Do While ii < aniGroup.Count
  2118. Dim Anim As Animation = aniGroup(ii)
  2119. '执行种类
  2120. If Anim.After = False Then '之前
  2121. CanRemoveAfter = False '取消“之后”标记
  2122. '增加执行时间
  2123. Anim.FinishLength = Anim.FinishLength + DeltaTime
  2124. '执行动画
  2125. If Anim.FinishLength > 0 Then Anim = AniRun(Anim) '执行动画
  2126. '如果当前动画已执行完毕
  2127. If Anim.FinishLength >= Anim.TotalLength Then
  2128. '删除
  2129. aniGroup.RemoveAt(ii)
  2130. GoTo NextAni
  2131. End If
  2132. aniGroup(ii) = Anim
  2133. Else '之后
  2134. If CanRemoveAfter Then
  2135. '之后改为之前
  2136. CanRemoveAfter = False
  2137. Anim.After = False
  2138. aniGroup(ii) = Anim
  2139. '重新循环该动画
  2140. GoTo NextAni
  2141. Else
  2142. '不能去除该“之后”标记,结束该动画组
  2143. Exit Do
  2144. End If
  2145. End If
  2146. ii = ii + 1
  2147. NextAni:
  2148. Loop
  2149. '如果当前动画组都执行完毕则删除
  2150. If aniGroup.Count = 0 Then
  2151. AniGroups.Remove(AniGroups.Keys(i))
  2152. i = i - 1
  2153. End If
  2154. '继续循环
  2155. i = i + 1
  2156. Loop
  2157. Catch ex As Exception
  2158. ExShow(ex, "动画刻执行失败", ErrorLevel.Slient)
  2159. End Try
  2160. End Sub
  2161. ''' <summary>
  2162. ''' 执行一个动画。
  2163. ''' </summary>
  2164. ''' <param name="Ani">执行的动画对象。</param>
  2165. ''' <remarks></remarks>
  2166. Private Function AniRun(ByVal Ani As Animation) As Animation
  2167. Try
  2168. Select Case Ani.AniType
  2169. Case AniType.DoubleAnimation
  2170. Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
  2171. Select Case Ani.AniSubType
  2172. Case AniSubType.X
  2173. SetLeft(Ani.Obj, GetLeft(Ani.Obj) + Delta)
  2174. Case AniSubType.Y
  2175. SetTop(Ani.Obj, GetTop(Ani.Obj) + Delta)
  2176. Case AniSubType.Opacity
  2177. Ani.Obj.Opacity = MathRange(Ani.Obj.Opacity + Delta, 0, 1)
  2178. Case AniSubType.Width
  2179. Ani.Obj.Width = MathRange(Ani.Obj.Width + Delta, 0)
  2180. Case AniSubType.Height
  2181. Ani.Obj.Height = MathRange(Ani.Obj.Height + Delta, 0)
  2182. Case AniSubType.Value
  2183. Ani.Obj.Value = Ani.Obj.Value + Delta
  2184. Case AniSubType.Radius
  2185. Ani.Obj.Radius = Ani.Obj.Radius + Delta
  2186. Case AniSubType.BorderThickness
  2187. Ani.Obj.BorderThickness = New Thickness(CType(Ani.Obj.BorderThickness, Thickness).Bottom + Delta)
  2188. End Select
  2189. Case AniType.ColorAnimation
  2190. '利用Last记录了余下的小数值
  2191. Dim Delta As MyColor = MathPercent(New MyColor, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent)) + Ani.Last
  2192. Select Case Ani.AniSubType
  2193. Case AniSubType.Background
  2194. Dim NewColor As MyColor = New MyColor(Ani.Obj.Background.Color) + Delta
  2195. Ani.Obj.Background = NewColor
  2196. Ani.Last = NewColor - New MyColor(Ani.Obj.Background.Color)
  2197. Case AniSubType.Foreground
  2198. Dim NewColor As MyColor = New MyColor(Ani.Obj.Foreground.Color) + Delta
  2199. Ani.Obj.Foreground = NewColor
  2200. Ani.Last = NewColor - New MyColor(Ani.Obj.Foreground.Color)
  2201. Case AniSubType.Stroke
  2202. Dim NewColor As MyColor = New MyColor(Ani.Obj.Stroke.Color) + Delta
  2203. Ani.Obj.Stroke = NewColor
  2204. Ani.Last = NewColor - New MyColor(Ani.Obj.Stroke.Color)
  2205. Case AniSubType.BorderBrush
  2206. Dim NewColor As MyColor = New MyColor(Ani.Obj.BorderBrush.Color) + Delta
  2207. Ani.Obj.BorderBrush = NewColor
  2208. Ani.Last = NewColor - New MyColor(Ani.Obj.BorderBrush.Color)
  2209. End Select
  2210. Case AniType.Scale
  2211. Dim Delta As Double = Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent)
  2212. Ani.Obj.Margin = New Thickness(Ani.Obj.Margin.Left + MathPercent(0, Ani.Value.Left, Delta), Ani.Obj.Margin.Top + MathPercent(0, Ani.Value.Top, Delta), Ani.Obj.Margin.Right, Ani.Obj.Margin.Bottom)
  2213. Ani.Obj.Width = Math.Max(Ani.Obj.Width + MathPercent(0, Ani.Value.Width, Delta), 0)
  2214. Ani.Obj.Height = Math.Max(Ani.Obj.Height + MathPercent(0, Ani.Value.Height, Delta), 0)
  2215. Case AniType.TextAppear
  2216. Dim NewText As String = Mid(Ani.Value(0), 1, If(Ani.Value(1), Len(Ani.Value(0)), 0) + Math.Round(Len(Ani.Value(0)) * If(Ani.Value(1), -1, 1) * Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, 0)))
  2217. If Ani.Obj.GetType.Name = "TextBlock" Then
  2218. Ani.Obj.Text = NewText
  2219. Else
  2220. Ani.Obj.Context = NewText
  2221. End If
  2222. Case AniType.Code
  2223. AniCodeList.Add(Ani.Value)
  2224. Case AniType.CodeEvent
  2225. Select Case Ani.Value(0)
  2226. Case "Close"
  2227. Ani.Value(1).Close()
  2228. Case "Clear"
  2229. Ani.Value(1).Clear()
  2230. Case "Remove"
  2231. Ani.Value(1).Remove(Ani.Value(2))
  2232. Case "Add"
  2233. Ani.Value(1).Add(Ani.Value(2))
  2234. Case "Set"
  2235. Ani.Value(1) = Ani.Value(2)
  2236. Case "Tag"
  2237. Ani.Value(1).Tag = Ani.Value(2)
  2238. Case "Enabled"
  2239. Ani.Value(1).IsEnabled = Ani.Value(2)
  2240. Case "State"
  2241. Ani.Value(1).State = Ani.Value(2)
  2242. Case "IsHitTestVisible"
  2243. Ani.Value(1).IsHitTestVisible = Ani.Value(2)
  2244. Case "ShowInTaskbar"
  2245. Ani.Value(1).ShowInTaskbar = Ani.Value(2)
  2246. Case "Nothing"
  2247. Ani.Value(1) = Nothing
  2248. Case "Visible"
  2249. Ani.Value(1).Visibility = If(Ani.Value(2), Visibility.Visible, Visibility.Collapsed)
  2250. Case "End"
  2251. EndForce()
  2252. Case Else
  2253. AaCodeCall(Ani.Value(0), Ani.Value)
  2254. End Select
  2255. Case AniType.ScaleTransform
  2256. Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
  2257. CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleX = CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleX + Delta
  2258. CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleY = CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleY + Delta
  2259. Case AniType.RotateTransform
  2260. Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
  2261. CType(Ani.Obj.RenderTransform, RotateTransform).Angle = CType(Ani.Obj.RenderTransform, RotateTransform).Angle + Delta
  2262. End Select
  2263. Ani.Percent = Ani.FinishLength / Ani.TotalLength '修改执行百分比
  2264. Catch ex As Exception
  2265. ExShow(ex, "执行动画失败:" & GetStringFromEnum(Ani.AniType), ErrorLevel.Slient)
  2266. End Try
  2267. Return Ani
  2268. End Function
  2269. End Module '动画
  2270. Public Module Web
  2271. ''' <summary>
  2272. ''' 正在下载的列表。
  2273. ''' </summary>
  2274. ''' <remarks></remarks>
  2275. Public WebGroups As New Dictionary(Of String, WebGroup)
  2276. Private WebDownloadingList As New ArrayList
  2277. Public WebDownloadCountMax As Integer = ReadIni("setup", "DownMaxinum", "20")
  2278. #Region "类与枚举"
  2279. ''' <summary>
  2280. ''' 下载文件的文件大小处理方式。
  2281. ''' </summary>
  2282. Public Enum WebRequireSize As Integer
  2283. ''' <summary>
  2284. ''' 在下载前已经知道了文件大小。
  2285. ''' </summary>
  2286. Known = 0
  2287. ''' <summary>
  2288. ''' 下载前不知道文件大小,需要从网络中获取。
  2289. ''' </summary>
  2290. Require = 1
  2291. ''' <summary>
  2292. ''' 下载前不知道文件大小,也不获取大小。
  2293. ''' </summary>
  2294. DontNeed = 2
  2295. ''' <summary>
  2296. ''' 不需要知道准确大小,只要求文件至少有一定的大小。
  2297. ''' </summary>
  2298. AtLeast = 3
  2299. End Enum
  2300. Public Class WebGroup
  2301. Public Name As String
  2302. ''' <summary>
  2303. ''' 文件列表(WebFile)。
  2304. ''' </summary>
  2305. ''' <remarks></remarks>
  2306. Public Files As ArrayList
  2307. ''' <summary>
  2308. ''' 是否尝试从服务器确认文件大小。
  2309. ''' </summary>
  2310. ''' <remarks></remarks>
  2311. Public GetServerFileSize As WebRequireSize
  2312. ''' <summary>
  2313. ''' 下载成功时执行的线程。
  2314. ''' </summary>
  2315. ''' <remarks></remarks>
  2316. Public OnSuccess As System.Threading.ParameterizedThreadStart
  2317. ''' <summary>
  2318. ''' 下载失败时执行的线程。
  2319. ''' </summary>
  2320. ''' <remarks></remarks>
  2321. Public OnFail As System.Threading.ParameterizedThreadStart
  2322. ''' <summary>
  2323. ''' 已下载的文件数目(下载成功或失败的)。(用于文件数较多情况下的快速进度计算)
  2324. ''' </summary>
  2325. Public FinishedCount As Integer = 0
  2326. ''' <summary>
  2327. ''' 下载完成的文件数目的百分比。取值为0到1。
  2328. ''' </summary>
  2329. ''' <remarks></remarks>
  2330. Public ReadOnly Property Percent As Double
  2331. Get
  2332. Select Case Files.Count
  2333. Case 0
  2334. Percent = 0
  2335. Case 1
  2336. Percent = Math.Round(CType(Files(0), WebFile).Percent, 4)
  2337. Case Is < 60
  2338. Dim TotalPercent As Double = 0
  2339. For i = 0 To Files.Count - 1
  2340. TotalPercent = TotalPercent + CType(Files(i), WebFile).Percent
  2341. Next
  2342. Percent = Math.Round(TotalPercent / Files.Count, 4)
  2343. Case Else
  2344. Percent = Math.Round(FinishedCount / Files.Count, 4)
  2345. End Select
  2346. End Get
  2347. End Property
  2348. ''' <summary>
  2349. ''' 该文件组的唯一标识符。
  2350. ''' </summary>
  2351. ''' <remarks></remarks>
  2352. Public UUID As Integer = GetUUID()
  2353. End Class
  2354. Public Class WebFile
  2355. ''' <summary>
  2356. ''' 文件所有可能的网络URL。
  2357. ''' </summary>
  2358. ''' <remarks></remarks>
  2359. Public AllWebAddress As ArrayList
  2360. ''' <summary>
  2361. ''' 文件当前的网络URL。
  2362. ''' </summary>
  2363. ''' <remarks></remarks>
  2364. Public ReadOnly Property WebAddress As String
  2365. Get
  2366. Return If(AllWebAddress(0), "")
  2367. End Get
  2368. End Property
  2369. ''' <summary>
  2370. ''' 文件在本地的完整地址。
  2371. ''' </summary>
  2372. ''' <remarks></remarks>
  2373. Public ReadOnly Property LocalAddress As String
  2374. Get
  2375. Return LocalFolder & LocalName
  2376. End Get
  2377. End Property
  2378. ''' <summary>
  2379. ''' 文件在本地的所在的文件夹,以“\”结尾。
  2380. ''' </summary>
  2381. ''' <remarks></remarks>
  2382. Public LocalFolder As String
  2383. ''' <summary>
  2384. ''' 是否需要刷新文件名。
  2385. ''' </summary>
  2386. ''' <remarks></remarks>
  2387. Public RefreshName As Boolean = False
  2388. Private _LocalName As String = ""
  2389. ''' <summary>
  2390. ''' 当前的文件名。如果需要刷新文件名,它有可能改变。
  2391. ''' </summary>
  2392. ''' <remarks></remarks>
  2393. Public Property LocalName As String
  2394. Get
  2395. If _LocalName = "" Or IsNothing(_LocalName) Then _LocalName = GetFileNameFromPath(WebAddress)
  2396. Return _LocalName
  2397. End Get
  2398. Set(ByVal value As String)
  2399. _LocalName = value
  2400. End Set
  2401. End Property
  2402. ''' <summary>
  2403. ''' 使用下一个下载地址。
  2404. ''' </summary>
  2405. ''' <remarks></remarks>
  2406. Public Function NextAddress() As Boolean
  2407. If AllWebAddress.Count > 1 Then
  2408. AllWebAddress.RemoveAt(0)
  2409. If RefreshName Then LocalName = GetFileNameFromPath(WebAddress)
  2410. Return True
  2411. Else
  2412. Return False
  2413. End If
  2414. End Function
  2415. Private _State As WebDownloadStats = WebDownloadStats.FirstLoad
  2416. ''' <summary>
  2417. ''' 状态标记。
  2418. ''' </summary>
  2419. ''' <remarks></remarks>
  2420. Public Property State As WebDownloadStats
  2421. Get
  2422. Return _State
  2423. End Get
  2424. Set(ByVal value As WebDownloadStats)
  2425. If value = _State Then Exit Property
  2426. '改变状态
  2427. _State = value
  2428. Select Case value
  2429. Case WebDownloadStats.FirstLoad
  2430. '等待下载
  2431. GetSize = 0
  2432. Speed = 0
  2433. Percent = 0
  2434. SyncLock WebWaitingLockObj
  2435. WebWaitingList.Add(Me)
  2436. End SyncLock
  2437. Case WebDownloadStats.Wait
  2438. '等待下载
  2439. frmDownloadRight.RefreshFile(Me)
  2440. GetSize = 0
  2441. Speed = 0
  2442. Percent = 0
  2443. SyncLock WebWaitingLockObj
  2444. WebWaitingList.Insert(0, Me)
  2445. End SyncLock
  2446. WebWaitingToRun()
  2447. Case WebDownloadStats.GetSize
  2448. '获取大小
  2449. frmDownloadRight.RefreshFile(Me)
  2450. WebStateGetSize(Me)
  2451. Case WebDownloadStats.Download
  2452. '下载
  2453. frmDownloadRight.RefreshFile(Me)
  2454. WebStateDownload(Me)
  2455. Case WebDownloadStats.Success
  2456. '下载成功
  2457. Speed = 0
  2458. Percent = 1
  2459. WebStateSuccess(Me)
  2460. WebGroups(GroupName).FinishedCount = WebGroups(GroupName).FinishedCount + 1
  2461. frmDownloadRight.RefreshFile(Me)
  2462. WebFinishCheck(Me.GroupName)
  2463. Case WebDownloadStats.Fail
  2464. '下载失败
  2465. GetSize = 0
  2466. Speed = 0
  2467. Percent = 0
  2468. If Not WebStateFail(Me) Then
  2469. WebGroups(GroupName).FinishedCount = WebGroups(GroupName).FinishedCount + 1
  2470. frmDownloadRight.RefreshFile(Me)
  2471. WebFinishCheck(Me.GroupName)
  2472. End If
  2473. Case WebDownloadStats.Retry
  2474. '重试
  2475. _State = value
  2476. frmDownloadRight.RefreshFile(Me)
  2477. Thread.Sleep(If(WebGroups(GroupName).Files.Count = 1, 200, 1000))
  2478. #Disable Warning BC42026
  2479. State = WebDownloadStats.Wait
  2480. End Select
  2481. End Set
  2482. End Property
  2483. ''' <summary>
  2484. ''' 该文件的唯一标识符。
  2485. ''' </summary>
  2486. ''' <remarks></remarks>
  2487. Public UUID As Integer = GetUUID()
  2488. Public GetServerFileSize As WebRequireSize
  2489. Public GroupName As String
  2490. Public RefreshThread As Thread
  2491. ''' <summary>
  2492. ''' 文件总大小,可能为 0。
  2493. ''' </summary>
  2494. ''' <remarks></remarks>
  2495. Public TotalSize As FileSize = 0
  2496. ''' <summary>
  2497. ''' 已经下载了的部分的大小。
  2498. ''' </summary>
  2499. ''' <remarks></remarks>
  2500. Public GetSize As FileSize = 0
  2501. ''' <summary>
  2502. ''' 下载速度,单位为秒。
  2503. ''' </summary>
  2504. ''' <remarks></remarks>
  2505. Public Speed As FileSize = 0
  2506. ''' <summary>
  2507. ''' 已经下载的百分比。取值为 0 到 1。
  2508. ''' </summary>
  2509. ''' <remarks></remarks>
  2510. Public Percent As Double = 0
  2511. ''' <summary>
  2512. ''' 计算下载速度的计刻。
  2513. ''' </summary>
  2514. ''' <remarks></remarks>
  2515. Public SpeedCount As Integer
  2516. End Class
  2517. Public Enum WebDownloadStats As Byte
  2518. ''' <summary>
  2519. ''' 第一次加入列表。等同于 Wait,但是不会刷新队列。
  2520. ''' </summary>
  2521. FirstLoad = 6
  2522. ''' <summary>
  2523. ''' 等待中。若队列有空闲,需要获取大小的转为 GetSize,不需要获取大小的转为 Download。
  2524. ''' </summary>
  2525. ''' <remarks></remarks>
  2526. Wait = 0
  2527. ''' <summary>
  2528. ''' 正在获取大小。获取大小成功的转为 Download,失败的转为 Fail。
  2529. ''' </summary>
  2530. ''' <remarks></remarks>
  2531. GetSize = 1
  2532. ''' <summary>
  2533. ''' 正在下载。下载成功的转为 Success,失败的转为 Fail。
  2534. ''' </summary>
  2535. ''' <remarks></remarks>
  2536. Download = 2
  2537. ''' <summary>
  2538. ''' 下载成功。
  2539. ''' </summary>
  2540. ''' <remarks></remarks>
  2541. Success = 3
  2542. ''' <summary>
  2543. ''' 下载失败。可以重试的转为 Retry。
  2544. ''' </summary>
  2545. ''' <remarks></remarks>
  2546. Fail = 4
  2547. ''' <summary>
  2548. ''' 等待重试。半秒后转为 Wait。
  2549. ''' </summary>
  2550. Retry = 5
  2551. End Enum
  2552. #End Region
  2553. '开始下载
  2554. ''' <summary>
  2555. ''' 需要下载的文件。
  2556. ''' </summary>
  2557. Public Class WebRequireFile
  2558. ''' <summary>
  2559. ''' 所有可能的下载地址。若前一个地址下载失败会自动尝试下一个地址。
  2560. ''' </summary>
  2561. Public WebURLs As ArrayList
  2562. ''' <summary>
  2563. ''' 本地文件夹地址。不包含文件名。
  2564. ''' </summary>
  2565. Public LocalFolder As String = ""
  2566. ''' <summary>
  2567. ''' 本地文件名,不包含文件夹路径。若为空,则会从下载地址自动生成文件名。
  2568. ''' </summary>
  2569. Public LocalName As String = ""
  2570. ''' <summary>
  2571. ''' 根据文件大小处理方式在这里提交准确大小或至少应有的大小。
  2572. ''' </summary>
  2573. Public KnownFileSize As Integer = 0
  2574. End Class
  2575. ''' <summary>
  2576. ''' 开始下载一个列表中的文件。
  2577. ''' </summary>
  2578. ''' <param name="SourceFiles">WebRequireFile 的一维数组。</param>
  2579. ''' <param name="Name">下载列表的名称。</param>
  2580. ''' <param name="OnSuccess">下载成功时执行的代码。</param>
  2581. ''' <param name="OnFail">下载失败时执行的代码。</param>
  2582. ''' <param name="RequireSize">文件大小处理方式。</param>
  2583. ''' <remarks></remarks>
  2584. Public Sub WebStart(ByVal SourceFiles() As WebRequireFile, ByVal Name As String, ByVal OnSuccess As ParameterizedThreadStart, ByVal OnFail As ParameterizedThreadStart, ByVal RequireSize As WebRequireSize)
  2585. Dim th As New Thread(Sub()
  2586. Try
  2587. '检查哪些文件需要下载,并将真正需要下载的文件整理为 CheckedFiles 数组
  2588. Dim CheckedFiles As New ArrayList(SourceFiles)
  2589. '检查文件是否存在文件名,如果不存在文件名则跳过过滤
  2590. If Not CheckedFiles(0).LocalName = "" Then
  2591. '过滤已经存在的文件
  2592. Select Case RequireSize
  2593. Case WebRequireSize.Known
  2594. '已知文件大小,检查文件:如果大小一致则不下载
  2595. For i = 0 To CheckedFiles.Count - 1
  2596. If CheckedFiles.Count - 1 < i Then Exit For
  2597. If GetFileSize(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) = CheckedFiles(i).KnownFileSize Then
  2598. CheckedFiles.RemoveAt(i)
  2599. i = i - 1
  2600. End If
  2601. Next
  2602. Case WebRequireSize.Require
  2603. '不知道文件大小,所以不进行过滤
  2604. Case WebRequireSize.DontNeed
  2605. '不需要知道文件大小,检查文件:如果文件存在则不下载
  2606. For i = 0 To CheckedFiles.Count - 1
  2607. If CheckedFiles.Count - 1 < i Then Exit For
  2608. If File.Exists(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) Then
  2609. CheckedFiles.RemoveAt(i)
  2610. i = i - 1
  2611. End If
  2612. Next
  2613. Case WebRequireSize.AtLeast
  2614. '文件有大小要求,检查文件:如果文件大小大于指定值则不下载
  2615. For i = 0 To CheckedFiles.Count - 1
  2616. If CheckedFiles.Count - 1 < i Then Exit For
  2617. If GetFileSize(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) >= Math.Max(1, CheckedFiles(i).KnownFileSize) Then
  2618. CheckedFiles.RemoveAt(i)
  2619. i = i - 1
  2620. End If
  2621. Next
  2622. End Select
  2623. '去重
  2624. CheckedFiles = ArrayNoDouble(CheckedFiles.ToArray)
  2625. '如果没有剩余文件直接成功
  2626. If CheckedFiles.Count = 0 Then
  2627. '直接成功
  2628. frmMain.Dispatcher.Invoke(OnSuccess, Name)
  2629. Exit Sub
  2630. End If
  2631. End If
  2632. '初始化文件组
  2633. Dim NewGroup As New WebGroup With {.OnSuccess = OnSuccess, .OnFail = OnFail, .Files = New ArrayList, .GetServerFileSize = RequireSize, .Name = Name}
  2634. '二次处理文件,将 WebRequireFile 转为 WebFile
  2635. For i = 0 To CheckedFiles.Count - 1
  2636. Dim NewFile As WebFile
  2637. If CheckedFiles(0).LocalName = "" Then
  2638. NewFile = New WebFile With {.AllWebAddress = CheckedFiles(i).WebURLs, .GetServerFileSize = RequireSize, .GroupName = Name,
  2639. .LocalFolder = CheckedFiles(i).LocalFolder, .TotalSize = New FileSize(CheckedFiles(i).KnownFileSize), .RefreshName = True}
  2640. Else
  2641. NewFile = New WebFile With {.AllWebAddress = CheckedFiles(i).WebURLs, .GetServerFileSize = RequireSize, .GroupName = Name,
  2642. .LocalFolder = CheckedFiles(i).LocalFolder, .TotalSize = New FileSize(CheckedFiles(i).KnownFileSize), .LocalName = CheckedFiles(i).LocalName, .RefreshName = False}
  2643. End If
  2644. NewGroup.Files.Add(NewFile)
  2645. Next
  2646. WebWaitingList.AddRange(NewGroup.Files)
  2647. '添加进总列表
  2648. If NewGroup.Files.Count = 0 Then Exit Sub
  2649. If WebGroups.ContainsKey(Name) Then
  2650. frmDownloadRight.RemoveGroup(WebGroups(Name))
  2651. WebGroups.Remove(Name)
  2652. End If
  2653. log("[System] 开始下载列表文件:" & Name)
  2654. WebTaskbarShow = ReadIni("setup", "DownProcess", "True") = "True"
  2655. WebGroups.Add(Name, NewGroup)
  2656. frmDownloadRight.AddGroup(NewGroup)
  2657. '要求执行刷新
  2658. WebWaitingToRun()
  2659. Catch ex As Exception
  2660. ExShow(ex, "处理下载列表失败:" & Name, ErrorLevel.MsgboxAndFeedback)
  2661. frmMain.Dispatcher.Invoke(OnFail, Name)
  2662. End Try
  2663. End Sub)
  2664. th.Start()
  2665. End Sub
  2666. '下载中
  2667. ''' <summary>
  2668. ''' 处于 Waiting 状态的文件。
  2669. ''' </summary>
  2670. Private WebWaitingList As New ArrayList
  2671. Public WebWaitingLockObj As Object = New Object
  2672. ''' <summary>
  2673. ''' 若队列有空闲,尝试让 Waiting 状态的文件开始下载。
  2674. ''' </summary>
  2675. Private Sub WebWaitingToRun()
  2676. SyncLock WebWaitingLockObj
  2677. For i = 0 To Math.Min(6, WebWaitingList.Count - 1)
  2678. Try
  2679. If WebDownloadingList.Count >= WebDownloadCountMax Or i > Math.Min(6, WebWaitingList.Count - 1) Then Exit Sub
  2680. If WebDownloadingList.Contains(WebWaitingList(i).UUID) Then GoTo NextFile
  2681. WebDownloadingList.Add(WebWaitingList(i).UUID)
  2682. WebWaitingList(i).State = If(WebWaitingList(i).GetServerFileSize = WebRequireSize.Require Or WebWaitingList(i).GetServerFileSize = WebRequireSize.AtLeast,
  2683. WebDownloadStats.GetSize, WebDownloadStats.Download)
  2684. WebWaitingList.RemoveAt(i) '移出等待队列
  2685. i = i - 1
  2686. Catch
  2687. i = i - 1
  2688. End Try
  2689. NextFile:
  2690. Next
  2691. End SyncLock
  2692. End Sub
  2693. ''' <summary>
  2694. ''' 获取文件大小,之后转入 Fail 或 Download 状态。
  2695. ''' </summary>
  2696. Private Sub WebStateGetSize(File As WebFile)
  2697. Dim th As New Thread(Sub()
  2698. Try
  2699. If MODE_OFFLINE Then File.State = WebDownloadStats.Fail : Exit Sub
  2700. Select Case File.GetServerFileSize
  2701. Case WebRequireSize.AtLeast
  2702. '要求至少有一定大小
  2703. Dim TrueSize = GetFileSize(File.WebAddress, File)
  2704. If TrueSize < 1 Then
  2705. Throw New Exception("获取文件大小失败!")
  2706. ElseIf TrueSize < File.TotalSize Then
  2707. Throw New Exception("文件过小!(" & New FileSize(TrueSize).ToString & "/" & File.TotalSize.ToString & ")")
  2708. End If
  2709. File.TotalSize = TrueSize
  2710. Case WebRequireSize.Require
  2711. '只是需要知道大小
  2712. File.TotalSize = GetFileSize(File.WebAddress, File)
  2713. If File.TotalSize < 1 Then Throw New Exception("获取文件大小失败!")
  2714. End Select
  2715. '获取大小成功,开始下载
  2716. File.State = WebDownloadStats.Download
  2717. Catch ex As Exception
  2718. ExShow(ex, "获取文件大小失败(" & File.LocalName & ")", ErrorLevel.Slient)
  2719. File.State = WebDownloadStats.Fail
  2720. End Try
  2721. End Sub)
  2722. th.Start()
  2723. End Sub
  2724. ''' <summary>
  2725. ''' 下载文件,之后转入 Fail 或 Success 状态。
  2726. ''' </summary>
  2727. Private Sub WebStateDownload(File As WebFile)
  2728. Dim th As New Thread(Sub()
  2729. Try
  2730. '准备
  2731. If Not Directory.Exists(File.LocalFolder) Then Directory.CreateDirectory(File.LocalFolder)
  2732. File.SpeedCount = My.Computer.Clock.TickCount
  2733. '下载
  2734. My.Computer.Network.DownloadFile(File.WebAddress, File.LocalAddress & DOWNLOADING_END, "", "", False, 10000, True)
  2735. '下载完毕检查
  2736. File.GetSize = GetFileSize(File.LocalAddress & DOWNLOADING_END)
  2737. If File.GetServerFileSize = WebRequireSize.DontNeed Or (File.GetSize = File.TotalSize And File.GetSize > 1) Then
  2738. '下载成功
  2739. IO.File.Delete(File.LocalAddress)
  2740. Rename(File.LocalAddress & DOWNLOADING_END, File.LocalAddress)
  2741. log("[Download] 下载文件成功:" & File.WebAddress)
  2742. File.State = WebDownloadStats.Success
  2743. Else
  2744. '下载失败
  2745. log("[Download] 下载文件失败(文件大小不匹配):" & File.LocalAddress & ",所需大小:" & File.TotalSize.ToString & ",实际大小:" & File.GetSize.ToString & "(" & File.GetSize.Value & ")", True)
  2746. IO.File.Delete(File.LocalAddress & DOWNLOADING_END)
  2747. File.State = WebDownloadStats.Fail
  2748. End If
  2749. Catch ex As Exception
  2750. ExShow(ex, "下载文件失败(" & File.LocalName & ")", ErrorLevel.Slient)
  2751. File.State = WebDownloadStats.Fail
  2752. End Try
  2753. End Sub)
  2754. th.Start()
  2755. '刷新显示线程
  2756. File.RefreshThread = New Thread(Sub()
  2757. Try
  2758. Do While File.State = WebDownloadStats.Download
  2759. Thread.Sleep(950)
  2760. If Not File.State = WebDownloadStats.Download Then Exit Sub
  2761. Dim NewSize = GetFileSize(File.LocalAddress & DOWNLOADING_END)
  2762. File.Speed = (NewSize - File.GetSize) / (My.Computer.Clock.TickCount - File.SpeedCount) * 1000
  2763. File.SpeedCount = My.Computer.Clock.TickCount
  2764. File.GetSize = NewSize
  2765. File.Percent = If(File.TotalSize = 0, 0, Math.Round(File.GetSize / File.TotalSize, 3))
  2766. If Not File.State = WebDownloadStats.Download Then Exit Sub
  2767. frmDownloadRight.RefreshFile(File)
  2768. Loop
  2769. Catch
  2770. End Try
  2771. End Sub)
  2772. File.RefreshThread.Start()
  2773. End Sub
  2774. ''' <summary>
  2775. ''' 下载失败,之后可能转入 Retry。若重试成功才返回 True。
  2776. ''' </summary>
  2777. ''' <param name="File"></param>
  2778. Private Function WebStateFail(File As WebFile)
  2779. '重试
  2780. If File.NextAddress() And Not MODE_OFFLINE Then
  2781. '重试成功
  2782. log("[Download] 重试地址:" & File.WebAddress)
  2783. File.State = WebDownloadStats.Retry
  2784. WebStateFail = True
  2785. Else
  2786. '重试失败
  2787. WebStateFail = False
  2788. End If
  2789. '队列处理
  2790. WebDownloadingList.Remove(File.UUID)
  2791. WebWaitingToRun()
  2792. End Function
  2793. ''' <summary>
  2794. ''' 下载成功。
  2795. ''' </summary>
  2796. Private Sub WebStateSuccess(File As WebFile)
  2797. '队列处理
  2798. WebDownloadingList.Remove(File.UUID)
  2799. WebWaitingToRun()
  2800. End Sub
  2801. '任务栏进度条
  2802. Public WebTaskbarShow As Boolean = True
  2803. Private WebTaskbarLastState As TaskbarItemProgressState = TaskbarItemProgressState.None
  2804. Private WebTaskbarLastValue As Double = 0
  2805. ''' <summary>
  2806. ''' 下载完成检查。
  2807. ''' </summary>
  2808. ''' <remarks></remarks>
  2809. Public Sub WebFinishCheck(ByVal Name As String)
  2810. Try
  2811. If Not WebGroups.Keys.Contains(Name) Then Exit Sub
  2812. Dim Group As WebGroup = WebGroups(Name)
  2813. If IsNothing(Group.Files) Then Exit Sub
  2814. If Not Group.Files.Count = Group.FinishedCount Then Exit Sub
  2815. '遍历文件:如果存在失败的文件,将 isFail 设置为 True
  2816. Dim isFail As Boolean = False
  2817. For i = Group.Files.Count - 1 To 0 Step -1
  2818. If Group.Files(i).State = WebDownloadStats.Fail Then isFail = True
  2819. Next i
  2820. '下载完成
  2821. log("[Download] 列表文件下载完成:" & Name)
  2822. '结束
  2823. WebGroups.Remove(Name)
  2824. frmDownloadRight.RemoveGroup(Group)
  2825. If isFail Then
  2826. frmMain.Dispatcher.Invoke(Group.OnFail, Name)
  2827. Else
  2828. frmMain.Dispatcher.Invoke(Group.OnSuccess, Name)
  2829. End If
  2830. Catch ex As Exception
  2831. ExShow(ex, "检查下载列表出错")
  2832. End Try
  2833. End Sub
  2834. ''' <summary>
  2835. ''' 停止下载列表文件。
  2836. ''' </summary>
  2837. ''' <param name="Name"></param>
  2838. ''' <remarks></remarks>
  2839. Public Sub WebDownloadStop(ByVal Name As String)
  2840. If WebGroups.ContainsKey(Name) Then
  2841. frmDownloadRight.RemoveGroup(WebGroups(Name))
  2842. WebGroups.Remove(Name)
  2843. End If
  2844. End Sub
  2845. Public Sub WebStartRun()
  2846. Dim th As New Thread(Sub()
  2847. Do While True
  2848. WebTimer()
  2849. Thread.Sleep(250)
  2850. Loop
  2851. End Sub)
  2852. th.Priority = ThreadPriority.BelowNormal
  2853. th.Start()
  2854. End Sub
  2855. Public Sub WebTimer()
  2856. If Not WebTaskbarShow Then Exit Sub
  2857. '应有值
  2858. Dim ShouldState As TaskbarItemProgressState
  2859. Dim ShouldValue As Double
  2860. '获取应有值
  2861. Try
  2862. If WebGroups.Count > 0 Then
  2863. Dim TotalPercent As Double = 0
  2864. For Each Group As WebGroup In WebGroups.Values
  2865. TotalPercent = TotalPercent + Group.Percent
  2866. Next
  2867. ShouldState = If(TotalPercent = 0, TaskbarItemProgressState.Indeterminate, TaskbarItemProgressState.Normal)
  2868. ShouldValue = TotalPercent / WebGroups.Count
  2869. Else
  2870. ShouldState = TaskbarItemProgressState.None
  2871. ShouldValue = 0
  2872. End If
  2873. Catch
  2874. End Try
  2875. '更新值
  2876. If Not WebTaskbarLastState = ShouldState Then
  2877. frmMain.Dispatcher.Invoke(Sub() frmMain.TaskbarItemInfo.ProgressState = ShouldState)
  2878. WebTaskbarLastState = ShouldState
  2879. End If
  2880. If Not WebTaskbarLastValue = ShouldValue Then
  2881. frmMain.Dispatcher.Invoke(Sub() frmMain.TaskbarItemInfo.ProgressValue = ShouldValue)
  2882. WebTaskbarLastValue = ShouldValue
  2883. End If
  2884. End Sub
  2885. End Module 'HTTP下载
  2886. Public Module BitDrawer
  2887. Public GifList As New ArrayList 'Gif列表
  2888. 'Timer
  2889. Public Sub GifStartRun()
  2890. Dim time As New DispatcherTimer()
  2891. time.Interval = TimeSpan.FromMilliseconds(1)
  2892. AddHandler time.Tick, AddressOf GifTimer
  2893. time.Start()
  2894. End Sub
  2895. Public Sub GifTimer()
  2896. For i = 0 To GifList.Count - 1
  2897. Dim gif As MyBitmap = GifList(i)
  2898. '切换Gif的帧
  2899. If My.Computer.Clock.TickCount - gif.RoundLastTime >= gif.RoundTime Then
  2900. gif.RoundLastTime = My.Computer.Clock.TickCount
  2901. If gif.CurrentFlame = gif.MaxFlame - 1 Then
  2902. If gif.PlayOnce Then
  2903. '如果只播放一次那么拜拜
  2904. GifList.Remove(gif)
  2905. Else
  2906. '如果不只播放一次那么继续
  2907. gif.SetGifFrame(0)
  2908. End If
  2909. Else
  2910. gif.SetGifFrame(gif.CurrentFlame + 1)
  2911. End If
  2912. End If
  2913. '刷新绑定控件的显示
  2914. If Not IsNothing(gif.Control) Then gif.Control.Source = New MyBitmap(gif.Pic)
  2915. Next
  2916. End Sub
  2917. '类
  2918. Public Class MyBitmap
  2919. ''' <summary>
  2920. ''' 存储的图片
  2921. ''' </summary>
  2922. ''' <remarks></remarks>
  2923. Public Pic As System.Drawing.Bitmap
  2924. ''' <summary>
  2925. ''' (Gif)绑定的控件
  2926. ''' </summary>
  2927. ''' <remarks></remarks>
  2928. Public Control As System.Windows.Controls.Image = Nothing
  2929. ''' <summary>
  2930. ''' (Gif)每一帧的时间
  2931. ''' </summary>
  2932. ''' <remarks></remarks>
  2933. Public RoundTime As Integer
  2934. ''' <summary>
  2935. ''' (Gif)上一次改变时的时间
  2936. ''' </summary>
  2937. ''' <remarks></remarks>
  2938. Public RoundLastTime As Integer
  2939. ''' <summary>
  2940. ''' (Gif)是否只播放一次
  2941. ''' </summary>
  2942. ''' <remarks></remarks>
  2943. Public PlayOnce As Boolean = False
  2944. ''' <summary>
  2945. ''' (Gif)当前帧,从0开始
  2946. ''' </summary>
  2947. ''' <remarks></remarks>
  2948. Public CurrentFlame As Integer = 0
  2949. ''' <summary>
  2950. ''' (Gif)最大帧数,从1开始
  2951. ''' </summary>
  2952. ''' <remarks></remarks>
  2953. Public MaxFlame As Integer
  2954. '类型转换
  2955. '支持的类:Image ImageSource Bitmap ImageBrush
  2956. Public Shared Widening Operator CType(ByVal Image As System.Drawing.Image) As MyBitmap
  2957. Return New MyBitmap(Image)
  2958. End Operator
  2959. Public Shared Widening Operator CType(ByVal Image As MyBitmap) As System.Drawing.Image
  2960. Return Image.Pic
  2961. End Operator
  2962. Public Shared Widening Operator CType(ByVal Image As ImageSource) As MyBitmap
  2963. Return New MyBitmap(Image)
  2964. End Operator
  2965. Public Shared Widening Operator CType(ByVal Image As MyBitmap) As ImageSource
  2966. Dim ptr As IntPtr = Image.Pic.GetHbitmap()
  2967. Dim re As ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
  2968. ptr,
  2969. IntPtr.Zero,
  2970. Int32Rect.Empty,
  2971. BitmapSizeOptions.FromEmptyOptions())
  2972. DeleteObject(ptr)
  2973. Return re
  2974. End Operator
  2975. Public Shared Widening Operator CType(ByVal Image As System.Drawing.Bitmap) As MyBitmap
  2976. Return New MyBitmap(Image)
  2977. End Operator
  2978. Public Shared Widening Operator CType(ByVal Image As MyBitmap) As System.Drawing.Bitmap
  2979. Return Image.Pic
  2980. End Operator
  2981. Public Shared Widening Operator CType(ByVal Image As ImageBrush) As MyBitmap
  2982. Return New MyBitmap(Image)
  2983. End Operator
  2984. Public Shared Widening Operator CType(ByVal Image As MyBitmap) As ImageBrush
  2985. Return New ImageBrush(New MyBitmap(Image.Pic))
  2986. End Operator
  2987. '构造函数
  2988. Public Sub New()
  2989. End Sub
  2990. Public Sub New(ByVal FilePath As String)
  2991. Try
  2992. If FilePath.StartsWith(PATH_IMAGE) Then
  2993. '使用缓存
  2994. If BitmapCache.ContainsKey(FilePath) Then
  2995. Pic = BitmapCache(FilePath).Pic
  2996. Else
  2997. Pic = New MyBitmap(CType((New ImageSourceConverter).ConvertFromString(FilePath), ImageSource))
  2998. BitmapCache.Add(FilePath, Pic)
  2999. End If
  3000. Else
  3001. Using inputStream As New FileStream(FilePath, FileMode.Open)
  3002. Pic = New System.Drawing.Bitmap(inputStream)
  3003. End Using
  3004. End If
  3005. Catch ex As Exception
  3006. Pic = My.Application.TryFindResource(FilePath)
  3007. If IsNothing(Pic) Then
  3008. Pic = New System.Drawing.Bitmap(1, 1)
  3009. ExShow(ex, "加载图片失败,该图片加载已被跳过:" & FilePath, ErrorLevel.DebugOnly)
  3010. End If
  3011. End Try
  3012. End Sub
  3013. Public Sub New(ByVal Image As ImageSource)
  3014. Using MS = New MemoryStream()
  3015. Dim Encoder = New PngBitmapEncoder()
  3016. Encoder.Frames.Add(BitmapFrame.Create(Image))
  3017. Encoder.Save(MS)
  3018. Pic = New System.Drawing.Bitmap(MS)
  3019. End Using
  3020. End Sub
  3021. Public Sub New(ByVal Image As System.Drawing.Image)
  3022. Pic = Image
  3023. End Sub
  3024. Public Sub New(ByVal Image As System.Drawing.Bitmap)
  3025. Pic = Image
  3026. End Sub
  3027. Public Sub New(ByVal Image As ImageBrush)
  3028. Using MS = New MemoryStream()
  3029. Dim Encoder = New BmpBitmapEncoder()
  3030. Encoder.Frames.Add(BitmapFrame.Create(Image.ImageSource))
  3031. Encoder.Save(MS)
  3032. Pic = New System.Drawing.Bitmap(MS)
  3033. End Using
  3034. End Sub
  3035. ''' <summary>
  3036. ''' 设置Gif的当前帧
  3037. ''' </summary>
  3038. ''' <param name="count">帧的编号,从0开始,超限制报错</param>
  3039. ''' <remarks></remarks>
  3040. Public Sub SetGifFrame(ByVal count As Integer)
  3041. Pic.SelectActiveFrame(New FrameDimension(Pic.FrameDimensionsList()(0)), count)
  3042. CurrentFlame = count
  3043. End Sub
  3044. ''' <summary>
  3045. ''' 把这个对象视作Gif初始化
  3046. ''' </summary>
  3047. ''' <param name="round">两帧之间的间隔(毫秒)。</param>
  3048. ''' <param name="once">是否只播放一次,True为是。</param>
  3049. ''' <param name="control">绑定的控件。</param>
  3050. ''' <remarks></remarks>
  3051. Public Sub GifLoad(ByVal round As Integer, ByVal once As Boolean, Optional ByVal control As System.Windows.Controls.Image = Nothing)
  3052. RoundTime = round
  3053. RoundLastTime = My.Computer.Clock.TickCount
  3054. PlayOnce = once
  3055. Me.Control = control
  3056. GifList.Add(Me)
  3057. MaxFlame = Pic.GetFrameCount(New FrameDimension(Pic.FrameDimensionsList()(0)))
  3058. End Sub
  3059. ''' <summary>
  3060. ''' 获取旋转的图片,这个方法不会导致原对象改变
  3061. ''' </summary>
  3062. ''' <param name="angle">旋转角度,单位为角度不是弧度啊</param>
  3063. ''' <returns>旋转后的Bitmap</returns>
  3064. ''' <remarks></remarks>
  3065. Public Function Rotation(ByVal angle As Double) As System.Drawing.Bitmap
  3066. With Me
  3067. Dim img As System.Drawing.Image = Me.Pic
  3068. Dim bitSize As Single = Math.Sqrt(img.Width ^ 2 + img.Height ^ 2)
  3069. bitSize = img.Width
  3070. Dim bmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(CInt(bitSize), CInt(bitSize))
  3071. Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp)
  3072. g.TranslateTransform(bitSize / 2, bitSize / 2)
  3073. g.RotateTransform(angle)
  3074. g.TranslateTransform(-bitSize / 2, -bitSize / 2)
  3075. g.DrawImage(img, New System.Drawing.Rectangle(0, 0, img.Width, img.Width))
  3076. End Using
  3077. Return bmp
  3078. End With
  3079. End Function
  3080. ''' <summary>
  3081. ''' 获取左右翻转的图片,这个方法不会导致原对象改变
  3082. ''' </summary>
  3083. ''' <returns></returns>
  3084. ''' <remarks></remarks>
  3085. Public Function LeftRightFilp() As System.Drawing.Bitmap
  3086. Dim bmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(Me.Pic)
  3087. bmp.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX)
  3088. Return bmp
  3089. End Function
  3090. End Class
  3091. '合并Bitmap
  3092. Public Function BitmapAdd(ByVal background As System.Drawing.Bitmap, ByVal position As System.Drawing.Point, ByVal img As System.Drawing.Bitmap) As System.Drawing.Bitmap
  3093. Dim graph As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(background)
  3094. graph.DrawImage(img, position)
  3095. Return background
  3096. End Function
  3097. '裁剪Bitmap
  3098. Public Function BitmapCut(ByVal img As BitmapSource, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer) As BitmapSource
  3099. Return New CroppedBitmap(img, New Int32Rect(x, y, width, height))
  3100. End Function
  3101. End Module '绘图
  3102. 'Public Module FTP
  3103. ' Public Function DownloadFTPFile(ByVal ftpclient As FTPDownloader, ByVal webPath As String, ByVal localPath As String)
  3104. ' File.Delete(localPath)
  3105. ' DownloadFTPFile = False
  3106. ' Try
  3107. ' If Not ftpclient.ftpIsLogin Then ftpclient.Login()
  3108. ' If webPath.Contains("/") Then ftpclient.ChangeDirectory(Mid(webPath, 1, webPath.LastIndexOf("/")))
  3109. ' ftpclient.DownloadFile(Mid(webPath, webPath.LastIndexOf("/") + 2), localPath)
  3110. ' Return True
  3111. ' Catch ex As Exception
  3112. ' End Try
  3113. ' End Function '直接下载单个文件
  3114. ' Public Class FTPDownloader
  3115. '#Region "变量声明"
  3116. ' Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String
  3117. ' Private m_sRemotePassword, m_sMess As String
  3118. ' Private m_iRemotePort, m_iBytes As Int32
  3119. ' Private m_objClientSocket As Socket
  3120. ' Private m_iRetValue As Int32
  3121. ' Public ftpIsLogin As Boolean
  3122. ' Private m_sMes, m_sReply As String
  3123. ' '设置用户来对FTP服务器读取和写入数据的数据包的大小
  3124. ' Public Const BLOCK_SIZE = 512
  3125. ' Private m_aBuffer(BLOCK_SIZE) As Byte
  3126. ' Private ASCII As Encoding = Encoding.ASCII
  3127. ' Public flag_bool As Boolean
  3128. ' '普通变量定义
  3129. ' Private m_sMessageString As String
  3130. '#End Region
  3131. '#Region "构造函数"
  3132. ' Public Sub New()
  3133. ' m_sRemoteHost = "localhost"
  3134. ' m_sRemotePath = "."
  3135. ' m_sRemoteUser = "anonymous"
  3136. ' m_sRemotePassword = ""
  3137. ' m_sMessageString = ""
  3138. ' m_iRemotePort = 21
  3139. ' ftpIsLogin = False
  3140. ' End Sub
  3141. ' Public Sub New(ByVal sRemoteHost As String, ByVal sRemotePath As String, ByVal sRemoteUser As String, ByVal sRemotePassword As String, ByVal iRemotePort As Int32)
  3142. ' m_sRemoteHost = sRemoteHost
  3143. ' m_sRemotePath = sRemotePath
  3144. ' m_sRemoteUser = sRemoteUser
  3145. ' m_sRemotePassword = sRemotePassword
  3146. ' m_sMessageString = ""
  3147. ' m_iRemotePort = iRemotePort
  3148. ' ftpIsLogin = False
  3149. ' End Sub
  3150. '#End Region
  3151. '#Region "属性"
  3152. ' '设置或获取FTP服务器的名称
  3153. ' Public Property RemoteHostFTPServer() As String
  3154. ' Get
  3155. ' Return m_sRemoteHost
  3156. ' End Get
  3157. ' Set(ByVal Value As String)
  3158. ' m_sRemoteHost = Value
  3159. ' End Set
  3160. ' End Property
  3161. ' '设置或获取FTP服务器的端口
  3162. ' Public Property RemotePort() As Int32
  3163. ' Get
  3164. ' Return m_iRemotePort
  3165. ' End Get
  3166. ' Set(ByVal Value As Int32)
  3167. ' m_iRemotePort = Value
  3168. ' End Set
  3169. ' End Property
  3170. ' '设置或获取FTP服务器的远程路径
  3171. ' Public Property RemotePath() As String
  3172. ' Get
  3173. ' Return m_sRemotePath
  3174. ' End Get
  3175. ' Set(ByVal Value As String)
  3176. ' m_sRemotePath = Value
  3177. ' End Set
  3178. ' End Property
  3179. ' '设置或获取FTP服务器的用户
  3180. ' Public Property RemoteUser() As String
  3181. ' Get
  3182. ' Return m_sRemoteUser
  3183. ' End Get
  3184. ' Set(ByVal Value As String)
  3185. ' m_sRemoteUser = Value
  3186. ' End Set
  3187. ' End Property
  3188. ' '设置FTP服务器的密码
  3189. ' Public Property RemotePassword() As String
  3190. ' Get
  3191. ' Return m_sRemotePassword
  3192. ' End Get
  3193. ' Set(ByVal Value As String)
  3194. ' m_sRemotePassword = Value
  3195. ' End Set
  3196. ' End Property
  3197. ' '设置信息
  3198. ' Public Property MessageString() As String
  3199. ' Get
  3200. ' Return m_sMessageString
  3201. ' End Get
  3202. ' Set(ByVal Value As String)
  3203. ' m_sMessageString = Value
  3204. ' End Set
  3205. ' End Property
  3206. '#End Region
  3207. ' '登录FTP服务器
  3208. ' Public Function Login() As Boolean
  3209. ' If ftpIsLogin Then Return True
  3210. ' m_objClientSocket = _
  3211. ' New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
  3212. ' Dim ep As New IPEndPoint(Dns.GetHostEntry(m_sRemoteHost).AddressList(0), m_iRemotePort)
  3213. ' Try
  3214. ' m_objClientSocket.Connect(ep)
  3215. ' Catch ex As Exception
  3216. ' MessageString = m_sReply
  3217. ' Throw New IOException("无法链接到FTP服务器。")
  3218. ' End Try
  3219. ' ReadReply()
  3220. ' If (m_iRetValue <> 220) Then
  3221. ' CloseConnection()
  3222. ' MessageString = m_sReply
  3223. ' Throw New IOException(m_sReply.Substring(4))
  3224. ' End If
  3225. ' '为了发送一个对服务器的用户登录ID,发送一个FTP命令
  3226. ' SendCommand("USER " & m_sRemoteUser)
  3227. ' If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then
  3228. ' Cleanup()
  3229. ' MessageString = m_sReply
  3230. ' Throw New IOException(m_sReply.Substring(4))
  3231. ' End If
  3232. ' If (m_iRetValue <> 230) Then
  3233. ' '为了发送一个对服务器的用户密码,发送一个FTP命令
  3234. ' SendCommand("PASS " & m_sRemotePassword)
  3235. ' If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then
  3236. ' Cleanup()
  3237. ' MessageString = m_sReply
  3238. ' Throw New IOException(m_sReply.Substring(4))
  3239. ' End If
  3240. ' End If
  3241. ' ftpIsLogin = True
  3242. ' '为了改变映射的远程服务器的文件夹的目录,调用用户定义的ChangeDirectory函数
  3243. ' ChangeDirectory(m_sRemotePath)
  3244. ' '返回最终结果
  3245. ' Return ftpIsLogin
  3246. ' End Function
  3247. ' '获取文件列表
  3248. ' Public Function GetFileList(ByVal sMask As String) As String()
  3249. ' Dim cSocket As Socket
  3250. ' Dim bytes As Int32
  3251. ' Dim seperator As Char = ControlChars.Lf
  3252. ' Dim mess() As String
  3253. ' m_sMes = ""
  3254. ' '检查是否登录
  3255. ' If (Not (ftpIsLogin)) Then Login()
  3256. ' cSocket = CreateDataSocket()
  3257. ' '发送FTP命令
  3258. ' SendCommand("NLST " & sMask)
  3259. ' If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
  3260. ' MessageString = m_sReply
  3261. ' Throw New IOException(m_sReply.Substring(4))
  3262. ' End If
  3263. ' m_sMes = ""
  3264. ' Do While (True)
  3265. ' Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
  3266. ' bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
  3267. ' m_sMes += ASCII.GetString(m_aBuffer, 0, bytes)
  3268. ' If (bytes < m_aBuffer.Length) Then
  3269. ' Exit Do
  3270. ' End If
  3271. ' Loop
  3272. ' mess = m_sMes.Split(seperator)
  3273. ' cSocket.Close()
  3274. ' ReadReply()
  3275. ' If (m_iRetValue <> 226) Then
  3276. ' MessageString = m_sReply
  3277. ' Throw New IOException(m_sReply.Substring(4))
  3278. ' End If
  3279. ' Return mess
  3280. ' End Function
  3281. ' '获取文件大小
  3282. ' Public Function GetFileSize(ByVal sFileName As String) As Integer
  3283. ' Dim size As Integer
  3284. ' '检查是否登录
  3285. ' If Not ftpIsLogin Then Login()
  3286. ' '发送FTP命令
  3287. ' SetBinaryMode(True)
  3288. ' SendCommand("SIZE " & sFileName)
  3289. ' size = 0
  3290. ' If (m_iRetValue = 213) Then
  3291. ' size = Int64.Parse(m_sReply.Substring(4))
  3292. ' Else
  3293. ' MessageString = m_sReply
  3294. ' Throw New IOException(m_sReply.Substring(4))
  3295. ' End If
  3296. ' Return size
  3297. ' End Function
  3298. ' '下载文件
  3299. ' Public Sub DownloadFile(ByVal fileName As String, Optional ByVal localFile As String = "", Optional ByVal isResume As Boolean = False)
  3300. ' Dim st As Stream
  3301. ' Dim cSocket As Socket
  3302. ' Dim offset, npos As Integer
  3303. ' If Not ftpIsLogin Then Login() '检查是否登录
  3304. ' SetBinaryMode(True) '设置下载模式
  3305. ' '检查下载目录
  3306. ' If localFile = "" Then localFile = fileName
  3307. ' If Not (File.Exists(localFile)) Then
  3308. ' st = File.Create(localFile)
  3309. ' st.Close()
  3310. ' End If
  3311. ' '下载
  3312. ' Using output As New FileStream(localFile, FileMode.Open)
  3313. ' cSocket = CreateDataSocket()
  3314. ' offset = 0
  3315. ' If isResume Then
  3316. ' offset = output.Length
  3317. ' If offset > 0 Then
  3318. ' '发送一个FTP命令重新启动
  3319. ' SendCommand("REST " & offset)
  3320. ' If (m_iRetValue <> 350) Then offset = 0
  3321. ' npos = output.Seek(offset, SeekOrigin.Begin)
  3322. ' End If
  3323. ' End If
  3324. ' '发送一个FTP命令重新找到一个文件
  3325. ' SendCommand("RETR " & fileName)
  3326. ' If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
  3327. ' MessageString = m_sReply
  3328. ' Throw New IOException(m_sReply.Substring(4))
  3329. ' End If
  3330. ' Do While (True)
  3331. ' Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
  3332. ' m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
  3333. ' output.Write(m_aBuffer, 0, m_iBytes)
  3334. ' If (m_iBytes <= 0) Then
  3335. ' Exit Do
  3336. ' End If
  3337. ' Loop
  3338. ' End Using
  3339. ' If (cSocket.Connected) Then
  3340. ' cSocket.Close()
  3341. ' End If
  3342. ' ReadReply()
  3343. ' If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
  3344. ' MessageString = m_sReply
  3345. ' Throw New IOException(m_sReply.Substring(4))
  3346. ' End If
  3347. ' End Sub
  3348. ' '设置下载模式
  3349. ' Public Sub SetBinaryMode(ByVal bMode As Boolean)
  3350. ' '发送FTP命令,设置为二进制模式(True)或ASCII模式(False)
  3351. ' SendCommand(If(bMode, "TYPE I", "TYPE A"))
  3352. ' If (m_iRetValue <> 200) Then
  3353. ' MessageString = m_sReply
  3354. ' Throw New IOException(m_sReply.Substring(4))
  3355. ' End If
  3356. ' End Sub
  3357. ' 'Dim str_file_path As String = "C:\test.txt" '要上传的文件名及路径
  3358. ' 'Dim str_filename As String = IO.Path.GetFileName(str_file_path) '要上传的文件名
  3359. ' 'Dim MyFileSize As Integer = FileLen(str_file_path) '要上传得文件大小
  3360. ' 'If (ftpClient.Login() = True) Then
  3361. ' ' '创建一个新文件夹
  3362. ' ' ftpClient.CreateDirectory("FTPFOLDERNEW")
  3363. ' ' '将新的文件夹设置为活动文件夹。
  3364. ' ' ftpClient.ChangeDirectory("FTPFOLDERNEW")
  3365. ' ' '设置FTP模式
  3366. ' ' ftpClient.SetBinaryMode(True)
  3367. ' ' '从你的硬盘上上载一个文件到FTP网页
  3368. ' ' ftpClient.UploadFile(str_file_path)
  3369. ' ' '获得刚刚上传的文件的大小
  3370. ' ' Dim lng_filesize As Integer
  3371. ' ' lng_filesize = ftpClient.GetFileSize(str_filename)
  3372. ' ' If lng_filesize = MyFileSize Then
  3373. ' ' MsgBox("成功上传文件" & str_filename & " 文件大小" & lng_filesize)
  3374. ' ' Else
  3375. ' ' MsgBox("上传失败")
  3376. ' ' End If
  3377. ' ' '对上载文件重命名
  3378. ' ' 'ftpClient.RenameFile("SampleFile.xml", "SampleFile_new.xml")
  3379. ' ' '删除一个文件
  3380. ' ' 'ftpClient.DeleteFile("SampleFile_new.xml")
  3381. ' ' ftpClient.CloseConnection()
  3382. ' 'End If
  3383. ' ''这是一个从你的本地硬盘上向你的FTP文件夹中上载文件的函数
  3384. ' 'Public Sub UploadFile(ByVal sFileName As String)
  3385. ' ' UploadFile(sFileName, False)
  3386. ' 'End Sub
  3387. ' ''这是一个从你的本地硬盘上向你的FTP网页上上载的函数和设置恢复标志
  3388. ' 'Public Sub UploadFile(ByVal sFileName As String,
  3389. ' ' ByVal bResume As Boolean)
  3390. ' ' Dim cSocket As Socket
  3391. ' ' Dim offset As Integer
  3392. ' ' Dim input As FileStream
  3393. ' ' Dim bFileNotFound As Boolean
  3394. ' ' If (Not (ftpIsLogin)) Then
  3395. ' ' Login()
  3396. ' ' End If
  3397. ' ' cSocket = CreateDataSocket()
  3398. ' ' offset = 0
  3399. ' ' If (bResume) Then
  3400. ' ' Try
  3401. ' ' SetBinaryMode(True)
  3402. ' ' offset = GetFileSize(sFileName)
  3403. ' ' Catch ex As Exception
  3404. ' ' offset = 0
  3405. ' ' End Try
  3406. ' ' End If
  3407. ' ' If (offset > 0) Then
  3408. ' ' SendCommand("REST " & offset)
  3409. ' ' If (m_iRetValue <> 350) Then
  3410. ' ' '远程服务器可能不支持恢复。
  3411. ' ' offset = 0
  3412. ' ' End If
  3413. ' ' End If
  3414. ' ' '发送一个FTP命令,存储一个文件。
  3415. ' ' SendCommand("STOR " & Path.GetFileName(sFileName))
  3416. ' ' If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then
  3417. ' ' MessageString = m_sReply
  3418. ' ' Throw New IOException(m_sReply.Substring(4))
  3419. ' ' End If
  3420. ' ' '在上载之前,检查文件是否存在。
  3421. ' ' bFileNotFound = False
  3422. ' ' If (File.Exists(sFileName)) Then
  3423. ' ' '打开输入流读取源文件
  3424. ' ' input = New FileStream(sFileName, FileMode.Open)
  3425. ' ' If (offset <> 0) Then
  3426. ' ' input.Seek(offset, SeekOrigin.Begin)
  3427. ' ' End If
  3428. ' ' '上载这个文件
  3429. ' ' m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
  3430. ' ' Do While (m_iBytes > 0)
  3431. ' ' cSocket.Send(m_aBuffer, m_iBytes, 0)
  3432. ' ' m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
  3433. ' ' Loop
  3434. ' ' input.Close()
  3435. ' ' Else
  3436. ' ' bFileNotFound = True
  3437. ' ' End If
  3438. ' ' If (cSocket.Connected) Then
  3439. ' ' cSocket.Close()
  3440. ' ' End If
  3441. ' ' '如果找不到文件,检查返回值
  3442. ' ' If (bFileNotFound) Then
  3443. ' ' MessageString = m_sReply
  3444. ' ' Throw New IOException("The file: " & sFileName & " was not found. " & _
  3445. ' ' "Cannot upload the file to the FTP site")
  3446. ' ' End If
  3447. ' ' ReadReply()
  3448. ' ' If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
  3449. ' ' MessageString = m_sReply
  3450. ' ' Throw New IOException(m_sReply.Substring(4))
  3451. ' ' End If
  3452. ' 'End Sub
  3453. ' ''从远程FTP服务器上删除一个文件。
  3454. ' 'Public Function DeleteFile(ByVal sFileName As String) As Boolean
  3455. ' ' Dim bResult As Boolean
  3456. ' ' bResult = True
  3457. ' ' If (Not (ftpIsLogin)) Then
  3458. ' ' Login()
  3459. ' ' End If
  3460. ' ' '发送一个FTP命令,删除一个文件。
  3461. ' ' SendCommand("DELE " & sFileName)
  3462. ' ' If (m_iRetValue <> 250) Then
  3463. ' ' bResult = False
  3464. ' ' MessageString = m_sReply
  3465. ' ' End If
  3466. ' ' '返回最终结果
  3467. ' ' Return bResult
  3468. ' 'End Function
  3469. ' ''在远程FTP服务器上重命名一个文件
  3470. ' 'Public Function RenameFile(ByVal sOldFileName As String,
  3471. ' 'ByVal sNewFileName As String) As Boolean
  3472. ' ' Dim bResult As Boolean
  3473. ' ' bResult = True
  3474. ' ' If (Not (ftpIsLogin)) Then
  3475. ' ' Login()
  3476. ' ' End If
  3477. ' ' '发送一个FTP命令,对一个文件重命名
  3478. ' ' SendCommand("RNFR " & sOldFileName)
  3479. ' ' If (m_iRetValue <> 350) Then
  3480. ' ' MessageString = m_sReply
  3481. ' ' Throw New IOException(m_sReply.Substring(4))
  3482. ' ' End If
  3483. ' ' '发送一个FTP命令,对一个文件更改为新名称
  3484. ' ' '如果新的文件名存在,会被覆盖。
  3485. ' ' SendCommand("RNTO " & sNewFileName)
  3486. ' ' If (m_iRetValue <> 250) Then
  3487. ' ' MessageString = m_sReply
  3488. ' ' Throw New IOException(m_sReply.Substring(4))
  3489. ' ' End If
  3490. ' ' '返回最终结果
  3491. ' ' Return bResult
  3492. ' 'End Function
  3493. ' ''这是一个在远程服务器上创建目录的函数
  3494. ' 'Public Function CreateDirectory(ByVal sDirName As String) As Boolean
  3495. ' ' Dim bResult As Boolean
  3496. ' ' bResult = True
  3497. ' ' If (Not (ftpIsLogin)) Then
  3498. ' ' Login()
  3499. ' ' End If
  3500. ' ' '发送一个FTP命令,在FTP服务器上制作一个目录
  3501. ' ' SendCommand("MKD " & sDirName)
  3502. ' ' If (m_iRetValue <> 257) Then
  3503. ' ' bResult = False
  3504. ' ' MessageString = m_sReply
  3505. ' ' End If
  3506. ' ' '返回最终结果
  3507. ' ' Return bResult
  3508. ' 'End Function
  3509. ' ''这是一个在远程FTP服务器上删除目录的函数
  3510. ' 'Public Function RemoveDirectory(ByVal sDirName As String) As Boolean
  3511. ' ' Dim bResult As Boolean
  3512. ' ' bResult = True
  3513. ' ' '检查是否已登录FTP服务器
  3514. ' ' If (Not (ftpIsLogin)) Then
  3515. ' ' Login()
  3516. ' ' End If
  3517. ' ' '发送一个FTP命令,删除在FTP服务器上的目录
  3518. ' ' SendCommand("RMD " & sDirName)
  3519. ' ' If (m_iRetValue <> 250) Then
  3520. ' ' bResult = False
  3521. ' ' MessageString = m_sReply
  3522. ' ' End If
  3523. ' ' '返回最终结果
  3524. ' ' Return bResult
  3525. ' 'End Function
  3526. ' '改变当前工作目录
  3527. ' Public Function ChangeDirectory(ByVal sDirName As String) As Boolean
  3528. ' Dim bResult As Boolean
  3529. ' bResult = True
  3530. ' '检查你是否在根目录
  3531. ' If (sDirName.Equals(".")) Then Return False
  3532. ' '检查是否已登录FTP服务器
  3533. ' If Not (ftpIsLogin) Then Login()
  3534. ' '发送FTP命令,改变在FTP服务器上的目录。
  3535. ' SendCommand("CWD " & sDirName)
  3536. ' If (m_iRetValue <> 250) Then
  3537. ' bResult = False
  3538. ' MessageString = m_sReply
  3539. ' End If
  3540. ' Me.m_sRemotePath = sDirName
  3541. ' '返回最终结果
  3542. ' Return bResult
  3543. ' End Function
  3544. ' '关闭FTP链接
  3545. ' Public Sub CloseConnection()
  3546. ' If Not (m_objClientSocket Is Nothing) Then
  3547. ' '发送一个FTP命令,结束FTP服务系统
  3548. ' SendCommand("QUIT")
  3549. ' End If
  3550. ' Cleanup()
  3551. ' End Sub
  3552. '#Region "内部函数"
  3553. ' '从FTP服务器得到回应。
  3554. ' Private Sub ReadReply()
  3555. ' m_sMes = ""
  3556. ' m_sReply = ReadLine()
  3557. ' m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3))
  3558. ' End Sub
  3559. ' '重置
  3560. ' Private Sub Cleanup()
  3561. ' If Not (m_objClientSocket Is Nothing) Then
  3562. ' m_objClientSocket.Close()
  3563. ' m_objClientSocket = Nothing
  3564. ' End If
  3565. ' ftpIsLogin = False
  3566. ' End Sub
  3567. ' '从FTP服务器读取一行
  3568. ' Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String
  3569. ' Dim seperator As Char = ControlChars.Lf
  3570. ' Dim mess() As String
  3571. ' If (bClearMes) Then
  3572. ' m_sMes = ""
  3573. ' End If
  3574. ' Do While (True)
  3575. ' Array.Clear(m_aBuffer, 0, BLOCK_SIZE)
  3576. ' Try
  3577. ' m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
  3578. ' Catch ex As Exception
  3579. ' Login()
  3580. ' m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
  3581. ' End Try
  3582. ' m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes)
  3583. ' If (m_iBytes < m_aBuffer.Length) Then
  3584. ' Exit Do
  3585. ' End If
  3586. ' Loop
  3587. ' mess = m_sMes.Split(seperator)
  3588. ' If (m_sMes.Length > 2) Then
  3589. ' m_sMes = mess(mess.Length - 2)
  3590. ' Else
  3591. ' m_sMes = mess(0)
  3592. ' End If
  3593. ' If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then
  3594. ' Return ReadLine(True)
  3595. ' End If
  3596. ' Return m_sMes
  3597. ' End Function
  3598. ' '向FTP服务器发送命令
  3599. ' Private Sub SendCommand(ByVal command As String)
  3600. ' command = command & ControlChars.CrLf
  3601. ' Dim cmdbytes As Byte() = ASCII.GetBytes(command)
  3602. ' m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0)
  3603. ' ReadReply()
  3604. ' End Sub
  3605. ' '创建一个数据包
  3606. ' Private Function CreateDataSocket() As Socket
  3607. ' Dim index1, index2, len As Int32
  3608. ' Dim partCount, i, port As Int32
  3609. ' Dim ipData, buf, ipAddress As String
  3610. ' Dim parts(6) As Int32
  3611. ' Dim ch As Char
  3612. ' Dim s As Socket
  3613. ' Dim ep As IPEndPoint
  3614. ' '发送一个FTP命令,用于被动数据链接
  3615. ' SendCommand("PASV")
  3616. ' If (m_iRetValue <> 227) Then
  3617. ' MessageString = m_sReply
  3618. ' Throw New IOException(m_sReply.Substring(4))
  3619. ' End If
  3620. ' index1 = m_sReply.IndexOf("(")
  3621. ' index2 = m_sReply.IndexOf(")")
  3622. ' ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1)
  3623. ' len = ipData.Length
  3624. ' partCount = 0
  3625. ' buf = ""
  3626. ' For i = 0 To ((len - 1) And partCount <= 6)
  3627. ' ch = Char.Parse(ipData.Substring(i, 1))
  3628. ' If (Char.IsDigit(ch)) Then
  3629. ' buf += ch
  3630. ' ElseIf (ch <> ",") Then
  3631. ' MessageString = m_sReply
  3632. ' Throw New IOException("Malformed PASV reply: " & m_sReply)
  3633. ' End If
  3634. ' If ((ch = ",") Or (i + 1 = len)) Then
  3635. ' Try
  3636. ' parts(partCount) = Int32.Parse(buf)
  3637. ' partCount += 1
  3638. ' buf = ""
  3639. ' Catch ex As Exception
  3640. ' MessageString = m_sReply
  3641. ' Throw New IOException("Malformed PASV reply: " & m_sReply)
  3642. ' End Try
  3643. ' End If
  3644. ' Next
  3645. ' ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3)
  3646. ' '在Visual Basic .Net 2002中进行调用。你想移动8位。在Visual Basic .NET 2002中,你必须将此数乘2的8次方。
  3647. ' '端口=parts(4)*(2^8)
  3648. ' '进行这个调用,并且用Visual Basic .NET 2003解释当前行。
  3649. ' port = parts(4) << 8
  3650. ' '确定数据端口数
  3651. ' port = port + parts(5)
  3652. ' s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
  3653. ' ep = New IPEndPoint(Dns.GetHostEntry(ipAddress).AddressList(0), port)
  3654. ' Try
  3655. ' s.Connect(ep)
  3656. ' Catch ex As Exception
  3657. ' MessageString = m_sReply
  3658. ' Throw New IOException("Cannot connect to remote server.")
  3659. ' '如果你不能链接到特定的FTP服务器,也就是说,将其布尔值设置为False。
  3660. ' flag_bool = False
  3661. ' End Try
  3662. ' '如果你能够链接到特定的FTP服务器,将布尔值设置为True。
  3663. ' flag_bool = True
  3664. ' Return s
  3665. ' End Function
  3666. '#End Region
  3667. ' End Class
  3668. 'End Module 'FTP协议下载