| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957 |
- Imports System.Drawing.Imaging
- Imports System.Reflection
- Imports System.Security.Cryptography
- Imports System.Windows.Threading
- Imports Ionic.Zip
- Public Module Modules
- #Region "Review完成 | 声明"
- ''' <summary>
- ''' 程序的启动路径,以“\”结尾。
- ''' </summary>
- ''' <remarks></remarks>
- Public PATH As String = GetPathFromFullPath(System.Windows.Forms.Application.ExecutablePath)
- ''' <summary>
- ''' 随机数。
- ''' </summary>
- ''' <remarks></remarks>
- Public Rnd As New Random
- ''' <summary>
- ''' 正在拖动的滚动条。
- ''' </summary>
- ''' <remarks></remarks>
- Public DragingScroll As VScroll = Nothing
- ''' <summary>
- ''' 位图缓存。
- ''' </summary>
- ''' <remarks></remarks>
- Public BitmapCache As New Dictionary(Of String, MyBitmap)
- #End Region
- #Region "Review完成 | API"
- ''' <summary>
- ''' 获取指定窗口的句柄。返回查找到的第一个窗口的句柄。
- ''' </summary>
- ''' <param name="lpClassName">窗口的类名,使用Spy++可以查看。</param>
- ''' <param name="lpWindowName">窗口的标题。</param>
- ''' <returns>查找到的第一个窗口的句柄。</returns>
- ''' <remarks></remarks>
- Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
- ''' <summary>
- ''' 彻底释放某个句柄对应项目的资源。
- ''' </summary>
- ''' <param name="hObject">需要释放资源的句柄。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject" (ByVal hObject As IntPtr) As Boolean
- ''' <summary>
- ''' 根据句柄设置对应窗口的标题。
- ''' </summary>
- ''' <param name="hwnd">窗口句柄。</param>
- ''' <param name="lpString">要设置的标题。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As String) As Integer
- ''' <summary>
- ''' 获取某个句柄对应的窗口的所属进程ID。
- ''' </summary>
- ''' <param name="hwnd">窗口句柄。</param>
- ''' <param name="lpdwProcessId">获取到的ID。需要变量承载。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Integer, ByVal lpdwProcessId As Integer) As Integer
- ''' <summary>
- ''' 设置某个句柄对应的窗口的属性。
- ''' </summary>
- ''' <param name="hwnd">窗口句柄。</param>
- ''' <param name="hWndInsertAfter">置顶标记。-1 为置顶,-2 为不置顶。</param>
- ''' <param name="x">窗口的 X 坐标。</param>
- ''' <param name="y">窗口的 Y 坐标。</param>
- ''' <param name="cx">窗口的宽度。</param>
- ''' <param name="cy">窗口的高度。</param>
- ''' <param name="wFlags">利用 Or 连接的参数。
- ''' SWP_HIDEWINDOW:隐藏窗口。
- ''' SWP_SHOWWINDOW:显示窗口。
- ''' SWP_NOMOVE:维持当前位置(忽略 X 和 Y 参数)。
- ''' SWP_NOSIZE:维持当前尺寸(忽略 cx 和 cy 参数)。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- ''' <summary>
- ''' 播放 BGM。
- ''' </summary>
- ''' <param name="lpszSoundName">音乐文件的完整路径。</param>
- ''' <param name="hModule">填写“0”。</param>
- ''' <param name="dwFlags">填写“131072 Or 1 Or 8”。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Declare Function PlaySound Lib "winmm.dll" (ByVal lpszSoundName As String, ByVal hModule As Integer, ByVal dwFlags As Integer) As Integer
- ''' <summary>
- ''' 播放 MP3 相关项。
- ''' </summary>
- ''' <param name="lpstrCommand"></param>
- ''' <param name="lpstrRetumString"></param>
- ''' <param name="uReturnLength"></param>
- ''' <param name="hwndCallback"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Public Const SWP_HIDEWINDOW As Integer = 8 * 16 '0x0080
- Public Const SWP_SHOWWINDOW As Integer = 4 * 16 '0x0040
- Public Const SWP_NOMOVE As Integer = 2 '0x0002
- Public Const SWP_NOSIZE As Integer = 1 '0x0001
- #End Region
- #Region "类"
- ''' <summary>
- ''' 支持浮点数与常见类型隐式转换的颜色。
- ''' </summary>
- ''' <remarks></remarks>
- Public Class MyColor
- '属性
- Public A As Double = 0
- Public R As Double = 0
- Public G As Double = 0
- Public B As Double = 0
- '类型转换
- Public Shared Widening Operator CType(ByVal col As Color) As MyColor
- Return New MyColor(col)
- End Operator
- Public Shared Widening Operator CType(ByVal conv As MyColor) As Color
- Return Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B))
- End Operator
- Public Shared Widening Operator CType(ByVal conv As MyColor) As System.Drawing.Color
- Return System.Drawing.Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B))
- End Operator
- Public Shared Widening Operator CType(ByVal bru As SolidColorBrush) As MyColor
- Return New MyColor(bru.Color)
- End Operator
- Public Shared Widening Operator CType(ByVal conv As MyColor) As SolidColorBrush
- Return New SolidColorBrush(Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B)))
- End Operator
- Public Shared Widening Operator CType(ByVal bru As Brush) As MyColor
- Return New MyColor(ColorConverter.ConvertFromString(bru.ToString))
- End Operator
- Public Shared Widening Operator CType(ByVal conv As MyColor) As Brush
- Return New SolidColorBrush(Color.FromArgb(MathByte(conv.A), MathByte(conv.R), MathByte(conv.G), MathByte(conv.B)))
- End Operator
- '颜色运算
- Shared Operator +(ByVal a As MyColor, ByVal b As MyColor) As MyColor
- Return New MyColor With {.A = a.A + b.A, .B = a.B + b.B, .G = a.G + b.G, .R = a.R + b.R}
- End Operator
- Shared Operator -(ByVal a As MyColor, ByVal b As MyColor) As MyColor
- Return New MyColor With {.A = a.A - b.A, .B = a.B - b.B, .G = a.G - b.G, .R = a.R - b.R}
- End Operator
- Shared Operator *(ByVal a As MyColor, ByVal b As Double) As MyColor
- Return New MyColor With {.A = a.A * b, .B = a.B * b, .G = a.G * b, .R = a.R * b}
- End Operator
- Shared Operator /(ByVal a As MyColor, ByVal b As Double) As MyColor
- Return New MyColor With {.A = a.A / b, .B = a.B / b, .G = a.G / b, .R = a.R / b}
- End Operator
- '构造函数
- Public Sub New()
- End Sub
- Public Sub New(ByVal col As Color)
- Me.A = col.A
- Me.R = col.R
- Me.G = col.G
- Me.B = col.B
- End Sub
- Public Sub New(ByVal newA As Double, ByVal col As Color)
- Me.A = newA
- Me.R = col.R
- Me.G = col.G
- Me.B = col.B
- End Sub
- Public Sub New(ByVal newR As Double, ByVal newG As Double, ByVal newB As Double)
- Me.A = 255
- Me.R = newR
- Me.G = newG
- Me.B = newB
- End Sub
- Public Sub New(ByVal newA As Double, ByVal newR As Double, ByVal newG As Double, ByVal newB As Double)
- Me.A = newA
- Me.R = newR
- Me.G = newG
- Me.B = newB
- End Sub
- '复写
- Public Shadows Function toString() As String
- Return "(" & A & "," & R & "," & G & "," & B & ")"
- End Function
- End Class
- Public Class AdvancedRect
- '属性
- Public Property Width As Double = 0
- Public Property Height As Double = 0
- Public Property Left As Double = 0
- Public Property Top As Double = 0
- '构造函数
- Public Sub New()
- End Sub
- Public Sub New(ByVal left As Double, ByVal top As Double, ByVal width As Double, ByVal height As Double)
- Me.Left = left
- Me.Top = top
- Me.Width = width
- Me.Height = height
- End Sub
- End Class '浮点矩形
- Public Class FileSize
- Public Value As Integer = 0
- '类型转换
- Public Shared Widening Operator CType(ByVal value As Long) As FileSize
- Return New FileSize(value)
- End Operator
- Public Shared Widening Operator CType(ByVal value As FileSize) As Long
- Return value.Value
- End Operator
- Public Shared Widening Operator CType(ByVal value As Integer) As FileSize
- Return New FileSize(value)
- End Operator
- Public Shared Widening Operator CType(ByVal value As FileSize) As Integer
- Return value.Value
- End Operator
- '运算
- Shared Operator +(ByVal a As FileSize, ByVal b As FileSize) As FileSize
- Return a.Value + b.Value
- End Operator
- Shared Operator -(ByVal a As FileSize, ByVal b As FileSize) As FileSize
- Return a.Value - b.Value
- End Operator
- Shared Operator *(ByVal a As FileSize, ByVal b As FileSize) As Integer
- Return a.Value * b.Value
- End Operator
- Shared Operator /(ByVal a As FileSize, ByVal b As FileSize) As Double
- Return MathRange(a.Value / b.Value, 0)
- End Operator
- Shared Operator =(ByVal a As FileSize, ByVal b As FileSize) As Boolean
- Return a.Value = b.Value
- End Operator
- Shared Operator <>(ByVal a As FileSize, ByVal b As FileSize) As Boolean
- Return Not a.Value = b.Value
- End Operator
- Shared Operator >(ByVal a As FileSize, ByVal b As FileSize) As Boolean
- Return a.Value > b.Value
- End Operator
- Shared Operator <(ByVal a As FileSize, ByVal b As FileSize) As Boolean
- Return a.Value < b.Value
- End Operator
- Shared Operator &(ByVal a As FileSize, ByVal b As String) As String
- Return a.ToString & b
- End Operator
- Shared Operator &(ByVal a As String, ByVal b As FileSize) As String
- Return a & b.ToString
- End Operator
- '构造函数
- Public Sub New()
- End Sub
- Public Sub New(ByVal value As Integer)
- Me.Value = value
- End Sub
- '复写
- Public Shadows Function ToString() As String
- Select Case Me.Value
- Case Is < 0
- Return "未知"
- Case Is < 1024
- Return Me.Value & "B"
- Case Is < 1024 ^ 2
- Return Math.Round(Me.Value / 1024, 1) & "K"
- Case Is < 1024 ^ 3
- Return Math.Round(Me.Value / 1024 ^ 2, 2) & "M"
- Case Else
- Return Math.Round(Me.Value / 1024 ^ 3, 2) & "G"
- End Select
- End Function
- End Class '文件大小
- Public Class Time
- Private Property Value As Integer = 0
- '类型转换
- Public Shared Widening Operator CType(ByVal value As Integer) As Time
- Return New Time(value)
- End Operator
- Public Shared Widening Operator CType(ByVal value As Time) As Integer
- Return value.Value
- End Operator
- Public Shared Widening Operator CType(ByVal value As Int64) As Time
- Return New Time(value)
- End Operator
- Public Shared Widening Operator CType(ByVal value As Time) As Int64
- Return value.Value
- End Operator
- '运算
- Shared Operator +(ByVal a As Time, ByVal b As Time) As Time
- Return a.Value + b.Value
- End Operator
- Shared Operator -(ByVal a As Time, ByVal b As Time) As Time
- Return a.Value - b.Value
- End Operator
- Shared Operator *(ByVal a As Time, ByVal b As Time) As Integer
- Return a.Value * b.Value
- End Operator
- Shared Operator /(ByVal a As Time, ByVal b As Time) As Double
- Return MathRange(a.Value / b.Value, 0)
- End Operator
- Shared Operator =(ByVal a As Time, ByVal b As Time) As Boolean
- Return a.Value = b.Value
- End Operator
- Shared Operator <>(ByVal a As Time, ByVal b As Time) As Boolean
- Return Not a.Value = b.Value
- End Operator
- Shared Operator >(ByVal a As Time, ByVal b As Time) As Boolean
- Return a.Value > b.Value
- End Operator
- Shared Operator <(ByVal a As Time, ByVal b As Time) As Boolean
- Return a.Value < b.Value
- End Operator
- Shared Operator &(ByVal a As Time, ByVal b As String) As String
- Return a.toString & b
- End Operator
- Shared Operator &(ByVal a As String, ByVal b As Time) As String
- Return a & b.toString
- End Operator
- '构造函数
- Public Sub New()
- End Sub
- Public Sub New(ByVal value As Integer)
- Me.Value = value
- End Sub
- '复写
- Public Shadows Function toString() As String
- Dim left As Integer = Me.Value
- Dim a As Integer
- a = Math.Floor(left / 3600)
- toString = FillLength(a.ToString, "0", 2)
- left = left - a * 3600
- a = Math.Floor(left / 60)
- toString = toString & ":" & FillLength(a.ToString, "0", 2) & ":" & FillLength((left - a * 60), "0", 2)
- End Function
- End Class '时间
- #End Region
- #Region "控件"
- ''' <summary>
- ''' 获取控件或窗体的左边距。无视Alignment。
- ''' </summary>
- ''' <param name="control"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetLeft(ByVal control) As Double
- GetLeft = 0
- If control.GetType.BaseType.Name.Equals("Window") Then
- Return control.Left
- Else
- Select Case control.HorizontalAlignment
- Case HorizontalAlignment.Left, HorizontalAlignment.Stretch, HorizontalAlignment.Center
- Return control.Margin.Left
- Case HorizontalAlignment.Right
- Return CType(control.Parent, Object).ActualWidth - control.ActualWidth - control.Margin.Right
- 'Case HorizontalAlignment.Stretch
- ' Dim MaxWidth As Double = CType(control.Parent, Object).ActualWidth - control.Margin.Left - control.Margin.Right
- ' Return If(control.ActualWidth >= MaxWidth, control.Margin.Left, control.Margin.Left + (MaxWidth - control.ActualWidth) / 2)
- 'Case HorizontalAlignment.Center
- ' Dim CenterPos As Double = control.Margin.Left + (CType(control.Parent, Object).ActualWidth - control.Margin.Left - control.Margin.Right) / 2
- ' Return CenterPos - control.ActualWidth / 2
- End Select
- End If
- End Function
- ''' <summary>
- ''' 获取控件或窗体的顶边距。无视Alignment。
- ''' </summary>
- ''' <param name="control"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetTop(ByVal control) As Double
- GetTop = 0
- If control.GetType.BaseType.Name.Equals("Window") Then
- Return control.Top
- Else
- Select Case control.VerticalAlignment
- Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
- Return control.Margin.Top
- Case VerticalAlignment.Bottom
- Return -control.Margin.Bottom
- 'Return CType(control.Parent, Object).ActualHeight - control.ActualHeight - control.Margin.Bottom
- 'Case VerticalAlignment.Stretch
- ' Dim MaxHeight As Double = CType(control.Parent, Object).ActualHeight - control.Margin.Top - control.Margin.Bottom
- ' Return If(control.ActualHeight >= MaxHeight, control.Margin.Top, control.Margin.Top + (MaxHeight - control.ActualHeight) / 2)
- 'Case VerticalAlignment.Center
- ' Dim CenterPos As Double = control.Margin.Top + (CType(control.Parent, Object).ActualHeight - control.Margin.Top - control.Margin.Bottom) / 2
- ' Return CenterPos - control.ActualHeight / 2
- End Select
- End If
- End Function
- ''' <summary>
- ''' 将一个IList中的内容添加到另外一个IList。
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub IListCopy(ByVal list As IList, ByVal arr As IList)
- For Each item In arr
- list.Add(item)
- Next
- End Sub
- Public Sub SetLeft(ByVal control As Object, ByVal newValue As Double)
- If Double.IsNaN(newValue) Or Double.IsInfinity(newValue) Then Exit Sub '安全性检查
- If control.GetType.BaseType.Name.Equals("Window") Then
- control.Left = newValue
- Else
- Select Case control.HorizontalAlignment
- Case HorizontalAlignment.Left, HorizontalAlignment.Stretch, HorizontalAlignment.Center
- control.Margin = New Thickness(newValue, control.Margin.Top, control.Margin.Right, control.Margin.Bottom)
- Case HorizontalAlignment.Right
- control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, CType(control.Parent, Object).ActualWidth - control.ActualWidth - newValue, control.Margin.Bottom)
- End Select
- End If
- End Sub '设置Left
- Public Sub SetTop(ByVal control As Object, ByVal newValue As Double)
- If Double.IsNaN(newValue) Or Double.IsInfinity(newValue) Then Exit Sub '安全性检查
- If control.GetType.BaseType.Name.Equals("Window") Then
- control.Top = newValue
- Else
- Select Case control.VerticalAlignment
- Case VerticalAlignment.Top, VerticalAlignment.Stretch, VerticalAlignment.Center
- control.Margin = New Thickness(control.Margin.Left, newValue, control.Margin.Right, control.Margin.Bottom)
- Case VerticalAlignment.Bottom
- control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, -newValue)
- 'control.Margin = New Thickness(control.Margin.Left, control.Margin.Top, control.Margin.Right, CType(control.Parent, Object).ActualHeight - control.ActualHeight - newValue)
- End Select
- End If
- End Sub '设置Top
- ''' <summary>
- ''' 拖动滚动条。
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub ControlStartRun()
- Dim timer As New DispatcherTimer()
- timer.Interval = TimeSpan.FromMilliseconds(20)
- AddHandler timer.Tick, Sub()
- If IsNothing(DragingScroll) Then Exit Sub
- If Mouse.LeftButton = MouseButtonState.Pressed Then
- DragingScroll.Draging(Mouse.GetPosition(DragingScroll.btnDrag).Y)
- Else
- '鼠标放下
- If Not DragingScroll.IsMouseOver Then DragingScroll.DragMouseLeave()
- DragingScroll = Nothing
- End If
- End Sub
- timer.Start()
- End Sub
- #End Region
- #Region "数学"
- ''' <summary>
- ''' 获取两数间的百分比。小数点精确到6位。
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function MathPercent(ByVal ValueA As Double, ByVal ValueB As Double, ByVal Percent As Object) As Double
- Return Math.Round(ValueA * (1 - Percent) + ValueB * Percent, 6) '解决Double计算错误
- End Function
- ''' <summary>
- ''' 获取两颜色间的百分比,根据RGB计算。小数点精确到6位。
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function MathPercent(ByVal ValueA As MyColor, ByVal ValueB As MyColor, ByVal Percent As Object) As MyColor
- Return MathRound(ValueA * (1 - Percent) + ValueB * Percent, 6) '解决Double计算错误
- End Function
- ''' <summary>
- ''' 检查一个数字是否正确(如检查无限、NaN等)。
- ''' </summary>
- ''' <param name="Num">需要检查的数字。</param>
- ''' <returns>是否正确。</returns>
- ''' <remarks></remarks>
- Public Function MathCheck(ByVal Num As Double) As Boolean
- Return Not (Double.IsInfinity(Num) Or Double.IsNaN(Num))
- End Function
- '贝塞尔曲线计算
- 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
- Dim a, b
- a = t
- Do
- b = 3 * a * ((1 / 3 + x1 - x2) * a * a + (x2 - 2 * x1) * a + x1)
- a = a + (t - b) * 0.5
- Loop Until Math.Abs(b - t) < 0.01 '精度1%
- Return 3 * a * ((1 / 3 + y1 - y2) * a * a + (y2 - 2 * y1) * a + y1)
- End Function
- 'Byte合理化
- Public Function MathByte(ByVal d As Double) As Byte
- If d < 0 Then d = 0
- If d > 255 Then d = 255
- Return Math.Round(d)
- End Function
- '提供扩展类支持的Round
- Public Function MathRound(ByVal col As MyColor, Optional ByVal w As Integer = 0) As MyColor
- 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)}
- End Function
- '把数值限定范围
- Public Function MathRange(ByVal value As Double, ByVal min As Double, Optional ByVal max As Double = Double.MaxValue) As Double
- Return Math.Max(min, Math.Min(max, value))
- End Function
- 'Byte类溢出处理
- Public Function ByteOverflow(ByVal int As Integer) As Byte
- Dim Original = int
- Dim ReturnValue As Byte
- Try
- If int < 0 Then
- Do Until int >= 0
- int = int + 256
- Loop
- ReturnValue = int
- Else
- ReturnValue = int Mod 256
- End If
- Return ReturnValue
- Catch ex As Exception
- ExShow(ex, "Byte 溢出处理出错:" & int)
- Return 0
- End Try
- End Function
- #End Region
- #Region "文本"
- '填充长度
- Public Function FillLength(ByVal str As String, ByVal code As String, ByVal length As Byte)
- If (Len(str) > length) Then Return Mid(str, 1, length)
- Return Mid(str.Replace(" ", "-").PadRight(length), str.Length + 1).Replace(" ", code) & str
- End Function
- '选择其一
- Public Function OneOf(ByVal objects As Array)
- Return objects.GetValue(RandomInteger(0, objects.Length - 1))
- End Function
- Public Function OneOf(ByVal objects As ArrayList)
- Return objects(RandomInteger(0, objects.Count - 1))
- End Function
- '正则搜索
- Public Function RegexSearch(ByVal str As String, ByVal regex As String) As ArrayList
- Try
- RegexSearch = New ArrayList
- Dim RegexSearchRes = (New RegularExpressions.Regex(regex)).Matches(str)
- If IsNothing(RegexSearchRes) Then Return RegexSearch
- For Each item As RegularExpressions.Match In RegexSearchRes
- RegexSearch.Add(item.Value)
- Next
- Catch
- Return New ArrayList
- End Try
- End Function
- '加密解密
- Public Function SerAdd(ByVal str As String) As String
- Dim text As Byte() = Encoding.Unicode.GetBytes(str)
- '-----------------------------------------------1
- Array.Reverse(text)
- '-----------------------------------------------2
- Dim out(text.Length - 1) As Byte
- For i As Integer = 0 To text.Length - 4 Step 4
- out(i) = text(i + 2)
- out(i + 1) = text(i + 1)
- out(i + 2) = text(i + 3)
- out(i + 3) = text(i)
- Next i
- If text.Length Mod 4 = 2 Then
- out(text.Length - 2) = text(text.Length - 1)
- out(text.Length - 1) = text(text.Length - 2)
- End If
- text = out
- '-----------------------------------------------3
- ReDim out(text.Length - 1)
- For i As Integer = 0 To text.Length - 3 Step 3
- out(i) = ByteOverflow(text(i + 2) + 12)
- out(i + 1) = ByteOverflow(text(i) - 85)
- out(i + 2) = ByteOverflow(text(i + 1) + 36)
- Next i
- Select Case text.Length Mod 3
- Case 1
- out(text.Length - 1) = ByteOverflow(text(text.Length - 1) - 52)
- Case 2
- out(text.Length - 1) = ByteOverflow(text(text.Length - 1) + 16)
- out(text.Length - 2) = ByteOverflow(text(text.Length - 2) + 48)
- End Select
- text = out
- '-----------------------------------------------4
- For i As Integer = 0 To text.Length - 1
- text(i) = ByteOverflow(text(i) + i)
- Next i
- '-----------------------------------------------E
- SerAdd = ""
- For Each bt As Byte In text
- SerAdd = SerAdd & BitConverter.ToString({bt})
- Next
- End Function
- Public Function SerRemove(ByVal str As String) As String
- Dim line1 As String, line2 As String
- line1 = "这就是解密函数……自己写的……很口胡很辣鸡……做一个加密只是为了防那些脑残熊孩子,既然都能搞到这函数了,那加密也没用,所以就别吐槽这辣鸡加密了吧233"
- line2 = "by 龙腾猫跃"
- Dim text(Len(str) / 2 - 1) As Byte
- For i As Integer = 0 To Len(str) - 2 Step 2
- text(i / 2) = Byte.Parse(Mid(str, i + 1, 2), Globalization.NumberStyles.AllowHexSpecifier)
- Next
- '-----------------------------------------------4
- For i As Integer = 0 To text.Length - 1
- text(i) = ByteOverflow(text(i) - i)
- Next i
- '-----------------------------------------------3
- Dim out(text.Length - 1) As Byte
- For i As Integer = 0 To text.Length - 3 Step 3
- out(i) = ByteOverflow(text(i + 1) + 85)
- out(i + 1) = ByteOverflow(text(i + 2) - 36)
- out(i + 2) = ByteOverflow(text(i) - 12)
- Next i
- Select Case text.Length Mod 3
- Case 1
- out(text.Length - 1) = ByteOverflow(text(text.Length - 1) + 52)
- Case 2
- out(text.Length - 1) = ByteOverflow(text(text.Length - 1) - 16)
- out(text.Length - 2) = ByteOverflow(text(text.Length - 2) - 48)
- End Select
- text = out
- '-----------------------------------------------2
- ReDim out(text.Length - 1)
- For i As Integer = 0 To text.Length - 4 Step 4
- out(i) = text(i + 3)
- out(i + 1) = text(i + 1)
- out(i + 2) = text(i)
- out(i + 3) = text(i + 2)
- Next i
- If text.Length Mod 4 = 2 Then
- out(text.Length - 2) = text(text.Length - 1)
- out(text.Length - 1) = text(text.Length - 2)
- End If
- text = out
- '-----------------------------------------------1
- Array.Reverse(text)
- '-----------------------------------------------E
- SerRemove = Encoding.Unicode.GetString(text)
- End Function
- ''' <summary>
- ''' 从用户输入的字符串中提取数字
- ''' </summary>
- ''' <param name="str">用户输入的字符串</param>
- ''' <returns>字符串中的数字,没有任何数字返回0</returns>
- ''' <remarks></remarks>
- Public Function GetDoubleFromString(ByVal str As String) As Double
- Dim regResult As ArrayList = RegexSearch(str, "(-?[0-9]\d*)?\.?[0-9]\d*")
- If regResult.Count = 0 Then
- Return 0
- Else
- Return Val(regResult(0))
- End If
- End Function
- '把Exception转为字符串
- Public Function GetStringFromException(ByVal ex As Exception, Optional ByVal isLong As Boolean = False) As String
- '构造基本信息与InnerException信息
- GetStringFromException = ex.Message.Replace(vbCrLf, "")
- If Not IsNothing(ex.InnerException) Then
- GetStringFromException = GetStringFromException & vbCrLf & "InnerException: " & ex.InnerException.Message.Replace(vbCrLf, "")
- If Not IsNothing(ex.InnerException.InnerException) Then
- GetStringFromException = GetStringFromException & vbCrLf & "InnerException: " & ex.InnerException.InnerException.Message.Replace(vbCrLf, "")
- End If
- End If
- '添加堆栈信息
- If isLong Then
- GetStringFromException = GetStringFromException & vbCrLf
- For Each Stack As String In ex.StackTrace.Split(vbCrLf)
- If Stack.Contains("pcl.") Then GetStringFromException = GetStringFromException & vbCrLf & Stack
- Next
- End If
- '清除双回车
- GetStringFromException = GetStringFromException.Replace(vbCrLf & vbCrLf, vbCrLf).Replace(vbCrLf & vbCrLf, vbCrLf)
- End Function
- #End Region
- #Region "Review完成 | 图片"
- ''' <summary>
- ''' 裁剪一个 BitmapSource。
- ''' </summary>
- ''' <param name="img">源图片。</param>
- 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
- Try
- Return New CroppedBitmap(img, New Int32Rect(x, y, width, height))
- Catch ex As Exception
- ExShow(ex, "裁剪图片失败", ErrorLevel.AllUsers)
- Return Nothing
- End Try
- End Function
- #End Region
- #Region "文件"
- ''' <summary>
- ''' 从应用资源释放文件。
- ''' </summary>
- ''' <param name="FileName">需要释放的文件在应用资源中的名称。</param>
- ''' <param name="OutputPath">释放的路径,包含文件名。</param>
- ''' <remarks></remarks>
- Public Sub OutputFileInResource(ByVal FileName As String, ByVal OutputPath As String, ByVal PassOnExists As Boolean)
- Try
- Dim Res = My.Resources.ResourceManager.GetObject(FileName)
- If IsNothing(Res) Then Throw New FileNotFoundException("没有找到名为" & FileName & "的资源")
- If PassOnExists And File.Exists(OutputPath) Then
- If GetFileSize(OutputPath) = Res.Length Then Exit Sub
- End If
- Directory.CreateDirectory(Mid(OutputPath, 1, OutputPath.LastIndexOf("\")))
- Using OutputStream As New FileStream(OutputPath, FileMode.OpenOrCreate, FileAccess.Write)
- OutputStream.Write(Res, 0, Res.Length)
- OutputStream.Flush()
- End Using
- log("[System] 释放文件:" & FileName)
- Catch ex As Exception
- ExShow(ex, "释放文件失败", ErrorLevel.DebugOnly)
- Throw ex
- End Try
- End Sub
- ''' <summary>
- ''' 解压文件。
- ''' </summary>
- ''' <param name="SourceFile">需要解压的文件的完整路径。</param>
- ''' <param name="UnzipDir">解压的目标文件夹。</param>
- ''' <param name="RunThread">解压结束后(无论成功还是失败)执行的方法。</param>
- ''' <remarks></remarks>
- Public Sub UnzipFile(ByVal SourceFile As String, ByVal UnzipDir As String, Optional ByVal RunThread As ParameterizedThreadStart = Nothing)
- Dim th As New Thread(Sub()
- Try
- Directory.CreateDirectory(UnzipDir)
- Using zip As New ZipFile(SourceFile)
- zip.ExtractAll(UnzipDir)
- End Using
- Catch ex As Exception
- ExShow(ex, "解压文件失败:" & SourceFile)
- End Try
- If Not IsNothing(RunThread) Then RunThread.Method.Invoke(Nothing, {Nothing})
- End Sub)
- th.Start()
- End Sub '解压ZIP文件
- ''' <summary>
- ''' 弹出选取文件对话框并且要求选取文件。
- ''' </summary>
- ''' <param name="FileFilter">要求的格式。如:“常用图片文件(*.png;*.jpeg)|*.png;*.jpg;*.jpeg”。</param>
- ''' <param name="Title">弹窗的标题。</param>
- ''' <returns>选择的唯一文件的完整路径,如果没有选择可能为空字符串。</returns>
- ''' <remarks></remarks>
- Public Function SelectFile(ByVal FileFilter As String, ByVal Title As String) As String
- Using fileDialog As New Forms.OpenFileDialog
- fileDialog.AddExtension = True
- fileDialog.AutoUpgradeEnabled = True
- fileDialog.CheckFileExists = True
- fileDialog.Filter = FileFilter
- fileDialog.Multiselect = False
- fileDialog.Title = Title
- fileDialog.ShowDialog()
- Return fileDialog.FileName
- End Using
- End Function
- ''' <summary>
- ''' 弹出选取文件夹对话框并且要求选取文件夹。
- ''' </summary>
- ''' <param name="Title">弹窗的标题。</param>
- ''' <returns>选择的唯一文件夹的完整路径,如果没有选择可能为空字符串。</returns>
- ''' <remarks></remarks>
- Public Function SelectFolder(ByVal Title As String) As String
- Using folderDialog As New Forms.FolderBrowserDialog
- folderDialog.Description = Title
- folderDialog.ShowNewFolderButton = True
- folderDialog.ShowDialog()
- Return folderDialog.SelectedPath
- End Using
- End Function
- ''' <summary>
- ''' 从文件路径或者URL获取不包含文件名的路径。不包含路径将会抛出异常。
- ''' </summary>
- ''' <param name="FilePath">文件路径,以标识符结尾。如果不包含文件名则必须以标识符结尾。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetPathFromFullPath(ByVal FilePath As String) As String
- If Not (FilePath.Contains("\") Or FilePath.Contains("/")) Then Throw New FileFormatException("不包含路径:" & FilePath)
- If FilePath.EndsWith("\") Or FilePath.EndsWith("/") Then Return FilePath
- GetPathFromFullPath = Left(FilePath, FilePath.LastIndexOfAny({"\", "/"}) + 1)
- If GetPathFromFullPath = "" Then Throw New FileFormatException("不包含路径:" & FilePath)
- End Function
- ''' <summary>
- ''' 从文件路径或者URL获取不包含路径的文件名。不包含文件名将会抛出异常。
- ''' </summary>
- ''' <param name="FilePath">文件路径。可以不完整。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetFileNameFromPath(ByVal FilePath As String) As String
- If FilePath.EndsWith("\") Or FilePath.EndsWith("/") Then Throw New FileFormatException("不包含文件名:" & FilePath)
- If Not (FilePath.Contains("\") Or FilePath.Contains("/")) Then Return FilePath
- GetFileNameFromPath = Mid(FilePath, FilePath.LastIndexOfAny({"\", "/"}) + 2)
- If GetFileNameFromPath.Contains("\\") And GetFileNameFromPath.Contains("?") Then
- '包含网络参数
- GetFileNameFromPath = Left(GetFileNameFromPath, FilePath.LastIndexOf("?"))
- End If
- If GetFileNameFromPath = "" Then Throw New FileFormatException("不包含文件名:" & FilePath)
- End Function
- ''' <summary>
- ''' 获取文件的版本信息。
- ''' </summary>
- ''' <param name="Path">文件目录。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetFileVersion(ByVal Path As String) As String
- Try
- Return Diagnostics.FileVersionInfo.GetVersionInfo(Path).FileVersion
- Catch ex As Exception
- ExShow(ex, "获取文件版本失败:" & Path, ErrorLevel.Slient)
- Return ""
- End Try
- End Function
- ''' <summary>
- ''' 获取一个文件夹下的所有文件的完整路径。
- ''' </summary>
- ''' <param name="SourcePath">源文件夹,不以“\”结尾。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetFilesFromPath(ByVal SourcePath As String) As ArrayList
- GetFilesFromPath = New ArrayList
- GetFilesFromPath(SourcePath, GetFilesFromPath)
- End Function
- Private Function GetFilesFromPath(ByVal SourcePath As String, ByRef CurrentList As ArrayList) As ArrayList
- Try
- If Not Directory.Exists(SourcePath) Then Return New ArrayList
- '列举文件
- For Each File As FileInfo In (New DirectoryInfo(SourcePath)).GetFiles
- CurrentList.Add(File.FullName)
- Next
- '列举目录
- For Each Folder As DirectoryInfo In (New DirectoryInfo(SourcePath)).GetDirectories
- GetFilesFromPath(Folder.FullName, CurrentList)
- Next
- Catch ex As Exception
- ExShow(ex, "列举文件失败:" & SourcePath, ErrorLevel.Slient)
- End Try
- '返回
- Return CurrentList
- End Function
- '获取文件大小(HTTP URL或文件路径)
- Public Function GetFileSize(ByVal Path As String, Optional ByRef FileMission As WebFile = Nothing) As Integer
- Try
- If Path.StartsWith("http") Then
- If MODE_OFFLINE Then Return 0
- '获取网络文件大小
- Dim Res As Net.WebRequest = Net.WebRequest.Create(Path)
- Dim Response As WebResponse = Res.GetResponse
- Dim Size As Integer = Response.ContentLength()
- If Not IsNothing(FileMission) Then
- '用Ref返回实际地址
- If Not FileMission.AllWebAddress(0) = Response.ResponseUri.ToString Then
- If FileMission.RefreshName Then FileMission.LocalName = GetFileNameFromPath(Response.ResponseUri.ToString)
- FileMission.AllWebAddress(0) = Response.ResponseUri.ToString
- End If
- End If
- '释放资源
- Response.Close()
- Res.Abort()
- Return Size
- Else
- If File.Exists(Path) Then
- Return New FileInfo(Path).Length
- Else
- Return 0
- End If
- End If
- Catch ex As Exception
- ExShow(ex, "获取文件大小失败:" & Path, ErrorLevel.Slient)
- Return 0
- End Try
- End Function
- '获取MD5
- Public Function GetFileMD5(ByVal filepath As String) As String
- Try
- '网上抄的啊,自己改了改而已XD
- Dim result As String = ""
- Using fstream As New FileStream(filepath, FileMode.Open, FileAccess.Read)
- Dim dataToHash(fstream.Length - 1) As Byte
- fstream.Read(dataToHash, 0, fstream.Length)
- Dim hashvalue As Byte() = CType(CryptoConfig.CreateFromName("MD5"), HashAlgorithm).ComputeHash(dataToHash)
- Dim i As Double
- For i = 0 To hashvalue.Length - 1
- result += FillLength(Hex(hashvalue(i)).ToLower, "0", 2)
- Next
- End Using
- Return result
- Catch ex As Exception
- ExShow(ex, "获取文件MD5失败:" & filepath, ErrorLevel.Slient)
- Return ""
- End Try
- End Function
- '读取文件
- Public Function ReadFileToEnd(ByVal filePath As String, Optional ByVal encode As Encoding = Nothing, Optional ByVal isFullPath As Boolean = True) As String
- Try
- Dim actualPath As String = If(isFullPath, "", PATH) & filePath
- If File.Exists(actualPath) Then
- encode = If(IsNothing(encode), New UTF8Encoding(False), encode)
- Using reader As New StreamReader(actualPath, encode)
- ReadFileToEnd = reader.ReadToEnd
- End Using
- Else
- Return ""
- End If
- Catch ex As Exception
- ExShow(ex, "读取文件出错:" & filePath)
- Return ""
- End Try
- End Function
- '写入文件
- 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)
- Try
- Dim actualpath As String = If(isFullPath, "", PATH) & filePath
- If Not File.Exists(actualpath) Then
- Directory.CreateDirectory(GetPathFromFullPath(actualpath))
- File.Create(actualpath).Dispose()
- End If
- encode = If(IsNothing(encode), New UTF8Encoding(False), encode)
- Using writer As New StreamWriter(actualpath, add, encode)
- writer.Write(text)
- writer.Flush()
- End Using
- Catch ex As Exception
- ExShow(ex, "写入文件时出错:" & filePath)
- End Try
- End Sub
- Private Class IniCache
- Public content As String = ""
- Public cache As New Dictionary(Of String, String)
- End Class
- Private CacheIni As New Dictionary(Of String, IniCache)
- ''' <summary>
- ''' 获取Ini文件内容,这可能会使用到缓存。
- ''' </summary>
- ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Private Function GetIni(ByVal FileName As String) As IniCache
- If Not FileName.Contains(":\") Then FileName = PATH & "PCL\" & FileName & ".ini"
- If CacheIni.ContainsKey(FileName) Then
- '返回缓存中的信息
- Dim Cache As New IniCache
- CacheIni.TryGetValue(FileName, Cache)
- Return Cache '防止ByRef导致缓存变更
- Else
- If File.Exists(FileName) Then
- '返回文件信息并且记入缓存
- Dim Cache As String = (vbCrLf & ReadFileToEnd(FileName) & vbCrLf).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf).Replace(vbCrLf & vbCrLf, vbCrLf)
- Dim Ini As New IniCache With {.content = Cache}
- CacheIni.Add(FileName, Ini)
- Return Ini
- Else
- '返回空信息
- Dim Ini As New IniCache With {.content = ""}
- CacheIni.Add(FileName, Ini)
- Return Ini
- End If
- End If
- End Function
- ''' <summary>
- ''' 读取Ini文件,这可能会使用到缓存。
- ''' </summary>
- ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
- ''' <param name="Key">键。</param>
- ''' <param name="DefaultValue">没有找到键时返回的默认值。</param>
- Public Function ReadIni(ByVal FileName As String, ByVal Key As String, Optional ByVal DefaultValue As String = "") As String
- Try
- '获取目前文件
- Dim NowIni As IniCache = GetIni(FileName)
- If IsNothing(NowIni) Then Return DefaultValue
- '使用缓存
- If NowIni.cache.ContainsKey(Key) Then Return If(NowIni.cache(Key), DefaultValue)
- '新读取文件
- If NowIni.content.Contains(vbCrLf & Key & ":") Then
- Dim Ret As String = Mid(NowIni.content, NowIni.content.IndexOf(vbCrLf & Key & ":") + 3)
- Ret = If(Ret.Contains(vbCrLf), Mid(Ret, 1, Ret.IndexOf(vbCrLf)), Ret).Replace(Key & ":", "")
- NowIni.cache.Add(Key, If(Ret = vbLf, "", Ret))
- Return If(Ret = vbLf, "", Ret)
- Else
- Return DefaultValue
- End If
- Catch ex As Exception
- '读取失败
- Return DefaultValue
- End Try
- End Function
- ''' <summary>
- ''' 写入ini文件,这会更新缓存。
- ''' </summary>
- ''' <param name="FileName">文件路径或简写。简写将会使用“PCL\文件名.ini”作为路径。</param>
- ''' <param name="Key">键。</param>
- ''' <param name="Value">值。</param>
- ''' <remarks></remarks>
- Public Sub WriteIni(ByVal FileName As String, ByVal Key As String, ByVal Value As String)
- On Error Resume Next
- FileName = If(FileName.Contains(":\"), FileName, PATH & "PCL\" & FileName & ".ini")
- If IsNothing(Value) Then Value = ""
- Value = Value.Replace(vbCrLf, "")
- '创建文件夹
- If Not Directory.Exists(GetPathFromFullPath(FileName)) Then Directory.CreateDirectory(GetPathFromFullPath(FileName))
- '获取目前文件
- Dim NowFile As String = GetIni(FileName).content
- '如果值一样就不处理
- If NowFile.Contains(vbCrLf & Key & ":" & Value & vbCrLf) Then Exit Sub
- '处理文件
- Dim FindResult As String = ReadIni(FileName, Key)
- If FindResult = "" And Not NowFile.Contains(vbCrLf & Key & ":") Then
- '不存在这个键
- NowFile = NowFile & vbCrLf & Key & ":" & Value
- Else
- '存在这个键
- NowFile = NowFile.Replace(vbCrLf & Key & ":" & FindResult & vbCrLf, vbCrLf & Key & ":" & Value & vbCrLf)
- End If
- WriteFile(FileName, NowFile)
- '刷新目前缓存
- CacheIni(FileName).content = NowFile
- CacheIni(FileName).cache.Remove(Key)
- CacheIni(FileName).cache.Add(Key, Value)
- End Sub
- #End Region
- #Region "Review完成 | 网络"
- ''' <summary>
- ''' 获取网页源代码。
- ''' </summary>
- ''' <param name="URL">网页的URL。</param>
- ''' <param name="Encode">网页的编码,通常为UTF-8。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetWebsiteCode(ByVal URL As String, ByVal Encode As Encoding) As String
- If MODE_OFFLINE Then Return ""
- '初始化
- Dim req As HttpWebRequest = Nothing
- Dim res As HttpWebResponse = Nothing
- Dim strm As StreamReader = Nothing
- GetWebsiteCode = ""
- Try
- req = WebRequest.Create(URL)
- req.Timeout = 6000
- res = req.GetResponse()
- strm = New StreamReader(res.GetResponseStream(), Encode)
- GetWebsiteCode = strm.ReadToEnd
- Catch ex As Exception
- If Not URL.Contains("https://sessionserver.mojang.com/session/minecraft/profile/") Then ExShow(ex, "获取网页源代码失败:" & URL)
- Finally
- '释放资源
- If Not IsNothing(strm) Then strm.Dispose()
- If Not IsNothing(res) Then res.Close()
- If Not IsNothing(req) Then req.Abort()
- End Try
- End Function
- ''' <summary>
- ''' 从网络中直接下载文件。
- ''' </summary>
- ''' <param name="URL">网络URL。</param>
- ''' <param name="localFile">下载的本地地址。</param>
- ''' <returns>是否下载成功。</returns>
- ''' <remarks></remarks>
- Public Function DownloadFile(ByVal URL As String, ByVal LocalFile As String) As Boolean
- If MODE_OFFLINE Then Return False
- '初始化
- Try
- '建立目录
- Directory.CreateDirectory(GetPathFromFullPath(LocalFile))
- '尝试删除原文件
- File.Delete(LocalFile)
- Catch ex As Exception
- ExShow(ex, "预处理文件失败:" & LocalFile)
- Return False
- End Try
- '下载
- Using Client As New WebClient
- Try
- Client.DownloadFile(URL, LocalFile)
- log("[System] 直接下载文件成功:" & URL)
- Return True
- Catch ex As Exception
- ExShow(ex, "直接下载文件失败:" & URL)
- Return False
- End Try
- End Using
- End Function
- ''' <summary>
- ''' 进行Ping测试。这不会异步进行,失败将直接抛出异常。
- ''' </summary>
- ''' <param name="IP">要进行Ping的IP。</param>
- ''' <param name="MaxPingTime">最大响应时间,单位为毫秒。</param>
- ''' <returns>Ping用时,单位为毫秒。</returns>
- ''' <remarks></remarks>
- Public Function Ping(ByVal IP As String, ByVal MaxPingTime As Integer) As Integer
- If MODE_OFFLINE Then Throw New WebException("没有网络连接。")
- Using pin = New System.Net.NetworkInformation.Ping
- Return pin.Send(IP, MaxPingTime).RoundtripTime
- End Using
- End Function
- #End Region
- #Region "系统"
- ''' <summary>
- ''' 测试某段代码用时,单位为毫秒/次。
- ''' </summary>
- ''' <param name="run">需要测试的代码。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function TimeTest(ByVal run As ThreadStart) As Double
- Dim StartTime As Long = My.Computer.Clock.TickCount
- Dim RunCount As Integer = 0
- Do While True
- run.Invoke()
- RunCount = RunCount + 1
- If My.Computer.Clock.TickCount - StartTime > 1000 Or RunCount > 100000 Then Exit Do
- Loop
- Return (My.Computer.Clock.TickCount - StartTime) / RunCount
- End Function
- ''' <summary>
- ''' 打开文件(等同于使用“运行”窗口)。
- ''' </summary>
- ''' <param name="FileName">文件名。可以为“notepad”等缩写。</param>
- ''' <param name="Arguments">运行参数。</param>
- ''' <param name="WaitForExit">是否等待该程序结束。默认为False。</param>
- ''' <remarks></remarks>
- Public Sub Shell(ByVal FileName As String, Optional ByVal Arguments As String = "", Optional ByVal WaitForExit As Boolean = False)
- Try
- Dim Program As New Process
- Program.StartInfo.Arguments = Arguments
- Program.StartInfo.FileName = FileName
- Program.Start()
- If WaitForExit Then Program.WaitForExit()
- Catch ex As Exception
- ExShow(ex, "执行命令失败:" & FileName, ErrorLevel.AllUsers)
- End Try
- End Sub
- ''' <summary>
- ''' 返回一个枚举对应的字符串。
- ''' </summary>
- ''' <param name="EnumData">一个已经实例化的枚举类型。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetStringFromEnum(ByVal EnumData As Object) As String
- Return [Enum].GetName(EnumData.GetType, EnumData)
- End Function
- ''' <summary>
- ''' 从指定的枚举中查找某字符串对应的枚举项。
- ''' </summary>
- ''' <param name="EnumData">源枚举。</param>
- ''' <param name="Value">对应枚举一项的字符串。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetEnumFromString(ByVal EnumData As Object, ByVal Value As String)
- Return [Enum].Parse(EnumData.GetType, Value)
- End Function
- ''' <summary>
- ''' 获取格式类似于“11:08:52.037”的当前时间的字符串。
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetTime() As String
- Return Date.Now.ToLongTimeString & "." & FillLength(Date.Now.Millisecond, "0", 3)
- End Function
- ''' <summary>
- ''' 数组去重。
- ''' </summary>
- ''' <param name="array"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function ArrayNoDouble(ByVal array As Array) As ArrayList
- Dim ResultArray As New ArrayList
- For i = 0 To UBound(array)
- For ii = i + 1 To UBound(array)
- If array(i).Equals(array(ii)) Then GoTo NextElement
- Next
- ResultArray.Add(array(i))
- NextElement:
- Next i
- Return ResultArray
- End Function
- ''' <summary>
- ''' 将数组从大到小排序。
- ''' </summary>
- ''' <param name="Array">纯数字的ArrayList。</param>
- ''' <remarks></remarks>
- Public Sub ArrayBigToSmall(ByRef Array As ArrayList)
- If Array.Count < 2 Then Exit Sub
- For i = 1 To Array.Count - 1
- If Array(i) > Array(i - 1) Then
- Dim c = Array(i - 1)
- Array(i - 1) = Array(i)
- Array(i) = c
- If i >= 2 Then i = i - 2
- End If
- Next i
- End Sub
- ''' <summary>
- ''' 强制将一个支持IList接口的对象转换为任意格式的一维数组。
- ''' </summary>
- ''' <typeparam name="T">转换后的数组类型。</typeparam>
- ''' <param name="Source"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function ArrayConventer(Of T, B As IList)(ByVal Source As B) As T()
- Dim Re(Source.Count - 1) As T
- For i = 0 To Source.Count - 1
- Re(i) = Source(i)
- Next
- Return Re
- End Function
- ''' <summary>
- ''' 检查是否拥有某一文件夹的读取权限。如果文件夹不存在,会返回 False。
- ''' </summary>
- ''' <param name="Path">检查目录。</param>
- Public Function CheckDirectoryPermission(ByVal Path As String) As Boolean
- Try
- If Path = "" Then Return False
- If Not Directory.Exists(Path) Then Return False
- Dim folderCheck As New DirectoryInfo(Path)
- folderCheck.EnumerateFiles()
- Return True
- Catch
- Return False
- End Try
- End Function
- ''' <summary>
- ''' 获取程序启动参数。
- ''' </summary>
- ''' <param name="Name">参数名。</param>
- ''' <param name="DefaultValue">默认值。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function GetProgramArgument(ByVal Name As String, Optional ByVal DefaultValue As Object = "")
- Dim AllArguments() As String = Microsoft.VisualBasic.Command.Split(" ")
- For i = 0 To AllArguments.Length - 1
- If AllArguments(i) = "-" & Name Then
- If AllArguments.Length = i + 1 Then Return True
- If AllArguments(i + 1).StartsWith("-") Then Return True
- Return AllArguments(i + 1)
- End If
- Next
- Return DefaultValue
- End Function
- ''' <summary>
- ''' 获取Json对象。
- ''' </summary>
- ''' <param name="Text"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function ReadJson(ByVal Text As String) As JObject
- Try
- Return CType(Newtonsoft.Json.JsonConvert.DeserializeObject(Text), JObject)
- Catch ex As Exception
- ExShow(ex, "Json读取失败:" & Left(Text, 30))
- Throw New FileFormatException("错误的 Json:" & GetStringFromException(ex, True))
- End Try
- End Function
- '执行命令行函数
- 'Public Function RunCMD(ByVal Commands As String, ByVal Wait As Boolean) As String
- ' Dim myProcess As New Process()
- ' Dim myProcessStartInfo As New ProcessStartInfo("cmd.exe")
- ' myProcessStartInfo.UseShellExecute = False
- ' myProcessStartInfo.RedirectStandardOutput = True
- ' myProcessStartInfo.CreateNoWindow = True
- ' myProcessStartInfo.Arguments = "/c """ & Commands & """"
- ' myProcess.StartInfo = myProcessStartInfo
- ' myProcess.Start()
- ' If Wait Then
- ' myProcess.WaitForExit()
- ' Dim myStreamReader As IO.StreamReader = myProcess.StandardOutput
- ' Dim myString As String = myStreamReader.ReadToEnd()
- ' myProcess.Close()
- ' myProcess.Dispose()
- ' Return myString
- ' Else
- ' Return ""
- ' End If
- 'End Function
- '注册表IO
- Public Function ReadReg(ByVal Key As String, Optional ByVal DefaultValue As String = "") As String
- Try
- Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
- parentKey = My.Computer.Registry.CurrentUser
- softKey = parentKey.OpenSubKey("Software\" & APPLICATION_SHORT_NAME, True)
- If softKey Is Nothing Then
- ReadReg = DefaultValue '不存在则返回默认值
- Else
- Dim readValue As New System.Text.StringBuilder
- readValue.AppendLine(softKey.GetValue(Key))
- Dim value = readValue.ToString.Replace(vbCrLf, "") '去除莫名的回车
- Return If(value = "", DefaultValue, value) '错误则返回默认值
- End If
- Catch ex As Exception
- ExShow(ex, "读取注册表出错:" & Key, ErrorLevel.Slient)
- Return DefaultValue
- End Try
- End Function
- Public Sub WriteReg(ByVal Key As String, ByVal Value As String, Optional ByVal ShowException As Boolean = False)
- Try
- Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
- parentKey = My.Computer.Registry.CurrentUser
- softKey = parentKey.OpenSubKey("Software\" & APPLICATION_SHORT_NAME, True)
- If softKey Is Nothing Then softKey = parentKey.CreateSubKey("Software\" & APPLICATION_SHORT_NAME) '如果不存在就创建
- softKey.SetValue(Key, Value)
- Catch ex As Exception
- ExShow(ex, "写入注册表出错:" & Key, If(ShowException, modMain.ErrorLevel.DebugOnly, modMain.ErrorLevel.Slient))
- If ShowException Then Throw '如果显示错误就丢一个
- End Try
- End Sub
- Private UUID As Integer = 0
- ''' <summary>
- ''' 获取一个全程序内不会重复的数字(伪UUID)。
- ''' </summary>
- ''' <returns>UUID,一个大于0的有序整数。</returns>
- ''' <remarks></remarks>
- Public Function GetUUID() As Integer
- UUID = UUID + 1
- Return UUID
- End Function
- #End Region
- #Region "Review完成 | 窗体"
- ''' <summary>
- ''' 等待显示的弹窗。
- ''' </summary>
- ''' <remarks></remarks>
- Public WaitingMyMsgbox As ArrayList = If(IsNothing(WaitingMyMsgbox), New ArrayList, WaitingMyMsgbox)
- ''' <summary>
- ''' 显示弹窗。
- ''' </summary>
- Public Function MyMsgbox(ByVal Converter As MyMsgboxConverter) As Integer
- Try
- '存入等待列表
- If Thread.CurrentThread.IsBackground Or Not Thread.CurrentThread.GetApartmentState = ApartmentState.STA Or Not AniRunning Then
- If IsNothing(WaitingMyMsgbox) Then WaitingMyMsgbox = New ArrayList '初始化
- WaitingMyMsgbox.Add(Converter)
- '返回值
- If Converter.IsWaitExit Then
- Do While Converter.ReturnCode = 0
- Thread.Sleep(50)
- Loop
- Return Converter.ReturnCode
- Else
- Return 0
- End If
- End If
- '在主线程,显示窗体
- 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}
- If Converter.IsWaitExit Then
- MsgBox.ShowDialog()
- Return Converter.ReturnCode
- Else
- MsgBox.Show()
- Return 0
- End If
- Catch ex As Exception
- ExShow(ex, "显示弹窗失败:" & Converter.Title, ErrorLevel.MsgboxAndFeedback)
- Return 0
- End Try
- End Function
- ''' <summary>
- ''' 显示弹窗。
- ''' </summary>
- ''' <param name="Title">弹窗的标题。</param>
- ''' <param name="Caption">弹窗的内容。</param>
- ''' <param name="Button1">显示的第一个按钮,默认为“确定”。</param>
- ''' <param name="Button2">显示的第二个按钮,默认为空。</param>
- ''' <param name="Button3">显示的第三个按钮,默认为空。</param>
- ''' <param name="IsWarn">是否为警告弹窗,若为 True,第一个按钮会显示为红色。</param>
- ''' <param name="IsWaitExit">是否等待弹窗关闭。若为 True,将会返回从 1 开始的点击的按钮编号,否则返回 0。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Dim NewMsgBoxConverter As New MyMsgboxConverter With {.Button1 = Button1, .Button2 = Button2, .Button3 = Button3, .Caption = Caption, .IsWarn = IsWarn, .Title = Title, .IsWaitExit = IsWaitExit}
- Return MyMsgbox(NewMsgBoxConverter)
- End Function
- ''' <summary>
- ''' 存储弹窗信息的转换器。
- ''' </summary>
- ''' <remarks></remarks>
- Public Class MyMsgboxConverter
- Public Title As String
- Public Caption As String = ""
- Public Button1 As String = "确定"
- Public Button2 As String = ""
- Public Button3 As String = ""
- Public IsWarn As Boolean = False
- Public IsWaitExit As Boolean = True
- ''' <summary>
- ''' 弹窗是否已经关闭。
- ''' </summary>
- ''' <remarks></remarks>
- Public IsExited As Boolean = False
- ''' <summary>
- ''' 点击的按钮编号,从 1 开始。
- ''' </summary>
- ''' <remarks></remarks>
- Public ReturnCode As Integer = 0
- End Class
- '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
- ' 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}
- ' wind.labTitle.Text = title
- ' wind.panCaption.Child = page
- ' wind.btn1.Text = btn1
- ' wind.btn2.Text = btn2
- ' wind.btn3.Text = btn3
- ' wind.btn2.Visibility = If(btn2 = "", Visibility.Collapsed, Visibility.Visible)
- ' wind.btn3.Visibility = If(btn3 = "", Visibility.Collapsed, Visibility.Visible)
- ' msgboxCallback = 0
- ' If wait Then
- ' wind.Show()
- ' Return wind
- ' Else
- ' wind.ShowDialog()
- ' Return msgboxCallback
- ' End If
- 'End Function
- ''' <summary>设置 WebBrowser 静默,即是否不产生弹窗。</summary>
- ''' <param name="webBrowser">需要改变的 WebBrowser。</param>
- ''' <param name="IsSilent">是否开启静默模式。</param>
- Public Sub SetWebBrowserSilent(ByVal WebBrowser As WebBrowser, ByVal IsSilent As Boolean)
- Try
- Dim fi As FieldInfo = WebBrowser.GetType.GetField("_axIWebBrowser2", BindingFlags.Instance Or BindingFlags.NonPublic)
- If Not IsNothing(fi) Then
- Dim browser = fi.GetValue(WebBrowser)
- If Not IsNothing(browser) Then
- browser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, Nothing, browser, {IsSilent})
- End If
- End If
- Catch ex As Exception
- ExShow(ex, "设置浏览器失败", ErrorLevel.AllUsers)
- End Try
- End Sub
- #End Region
- #Region "随机"
- '打乱数组
- Public Function RandomArray(ByVal array As ArrayList) As ArrayList
- RandomArray = New ArrayList
- Do While array.Count > 0
- Dim i As Integer = RandomInteger(0, array.Count - 1)
- RandomArray.Add(array(i))
- array.RemoveAt(i)
- Loop
- End Function
- '获取随机整数
- Public Function RandomInteger(ByVal min As Integer, ByVal max As Integer) As Integer
- Return Math.Round((max - min) * Rnd.NextDouble) + min
- End Function
- #End Region
- #Region "Review 完成 | 音乐"
- ''' <summary>
- ''' 播放音乐。
- ''' </summary>
- ''' <param name="FilePath">音乐文件完整路径。</param>
- ''' <remarks></remarks>
- Public Sub PlayBgm(ByVal FilePath As String, ByVal IsStop As Boolean, Optional ByVal IsShowHint As Boolean = False)
- Try
- If IsStop Then
- '停止
- log("[System] 停止播放音乐:" & FilePath)
- mciSendString("close " & FilePath, 0, 0, 0)
- PlaySound(Nothing, Nothing, Nothing)
- Else
- '播放
- log("[System] 播放音乐:" & FilePath)
- mciSendString("open " & FilePath, "", 0, 0)
- Dim code = mciSendString("play " & FilePath & " repeat", "", 0, 0)
- If code = 259 Then
- PlaySound(FilePath, 0, 131072 Or 1 Or 8) '换用 PlaySound 播放不支持循环的 .wav
- 'If IsShowHint Then ShowHint("该音乐不支持循环播放,音乐将在播放完一次后停止。")
- 'code = mciSendString("play " & FilePath, "", 0, 0)
- ElseIf code = 277 Then
- If IsShowHint Then MyMsgbox("无效的音乐文件。" & vbCrLf & "PCL 不支持部分 MP3 的播放,请尝试更换文件。目前已知网易云下载的 MP3 会出现此问题,原因不明。", "播放音乐失败")
- ElseIf Not code = 0 Then
- Throw New Exception(code)
- End If
- End If
- 'PlaySound(FilePath, 0, 131072 Or 1 Or 8)
- Catch ex As Exception
- ExShow(ex, "播放音乐失败", ErrorLevel.AllUsers)
- End Try
- End Sub
- #End Region
- End Module '基础函数
- 'Module ComputerInfo
- ' '声明
- ' 'Private cpuCounter As New PerformanceCounter("Processor", "% Processor Time", "_Total")
- ' 'Private downloadCounter As New PerformanceCounter("Network Interface", "Bytes Received/sec", New PerformanceCounterCategory("Network Interface").GetInstanceNames()(0))
- ' 'Private uploadCounter As New PerformanceCounter("Network Interface", "Bytes Sent/sec", New PerformanceCounterCategory("Network Interface").GetInstanceNames()(0))
- ' Private pcInfo As New Microsoft.VisualBasic.Devices.ComputerInfo
- ' '启动代码
- ' Public Sub InfoStartRun(ByVal time As Integer)
- ' Dim timer As New DispatcherTimer()
- ' timer.Interval = TimeSpan.FromMilliseconds(time)
- ' AddHandler timer.Tick, AddressOf InfoTimer
- ' timer.Start()
- ' End Sub
- ' '每次执行的代码
- ' Private Sub InfoTimer()
- ' '防止断网时获取错误
- ' On Error Resume Next
- ' infoDownloadSpeed = 0
- ' infoUploadSpeed = 0
- ' '获取值
- ' 'infoCpuPercent = cpuCounter.NextValue
- ' 'infoDownloadSpeed = downloadCounter.NextValue / 1024
- ' 'infoUploadSpeed = uploadCounter.NextValue / 1024
- ' End Sub
- ' '获取信息
- ' Public infoCpuPercent As Integer = 0 'CPU使用率
- ' Public infoDownloadSpeed As Integer = 0 '下载速度(KB)
- ' Public infoUploadSpeed As Integer = 0 '上传速度(KB)
- ' Public Function infoNetworkSpeed() As Integer
- ' Return infoDownloadSpeed + infoUploadSpeed
- ' End Function '网络速度(KB)
- ' Public Function infoRamPercent() As Integer
- ' Return (pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory) / pcInfo.TotalPhysicalMemory * 100
- ' End Function '内存使用率
- ' Public Function infoRamUsed() As Integer
- ' Return (pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory) / 1024 / 1024
- ' End Function '内存使用量(MB)
- ' Public Function infoRamTotal() As Integer
- ' Return pcInfo.TotalPhysicalMemory / 1024 / 1024
- ' End Function '内存总量(MB)
- ' Public Function infoRamAvailable() As Integer
- ' Return pcInfo.AvailablePhysicalMemory / 1024 / 1024
- ' End Function '内存可用量(MB)
- 'End Module '电脑信息获取
- Public Module MyAnimationer
- #Region "声明"
- ''' <summary>
- ''' 动画组列表。(组名→ArrayList)
- ''' </summary>
- ''' <remarks></remarks>
- Private AniGroups As New Dictionary(Of String, ArrayList)
- ''' <summary>
- ''' 上一次记刻的时间。
- ''' </summary>
- ''' <remarks></remarks>
- Public AniLastTick As Integer
- ''' <summary>
- ''' 动画执行是否开启。
- ''' </summary>
- ''' <remarks></remarks>
- Public AniRunning As Boolean = False
- #End Region
- #Region "类与枚举"
- ''' <summary>
- ''' 单个动画对象。
- ''' </summary>
- ''' <remarks></remarks>
- Public Structure Animation
- ''' <summary>
- ''' 动画种类。
- ''' </summary>
- ''' <remarks></remarks>
- Public AniType As AniType
- ''' <summary>
- ''' 动画副种类。
- ''' </summary>
- ''' <remarks></remarks>
- Public AniSubType As AniSubType
- ''' <summary>
- ''' 动画总长度。
- ''' </summary>
- ''' <remarks></remarks>
- Public TotalLength As Integer
- ''' <summary>
- ''' 已经执行的动画长度。如果为负数则为延迟。
- ''' </summary>
- ''' <remarks></remarks>
- Public FinishLength As Integer
- ''' <summary>
- ''' 已经完成的百分比。
- ''' </summary>
- ''' <remarks></remarks>
- Public Percent As Double
- ''' <summary>
- ''' 是否为“以后”。
- ''' </summary>
- ''' <remarks></remarks>
- Public After As Boolean
- ''' <summary>
- ''' 插值器类型。
- ''' </summary>
- ''' <remarks></remarks>
- Public Ease As AniEase
- ''' <summary>
- ''' 动画对象。
- ''' </summary>
- ''' <remarks></remarks>
- Public Obj As Object
- ''' <summary>
- ''' 动画值。
- ''' </summary>
- ''' <remarks></remarks>
- Public Value As Object
- ''' <summary>
- ''' 上次执行时的动画值。
- ''' </summary>
- ''' <remarks></remarks>
- Public Last As Object
- Public Overrides Function ToString() As String
- Return GetStringFromEnum(AniType) & " | " & FinishLength & "/" & TotalLength & "(" & Math.Round(Percent * 100) & "%) | " & Obj.name & "(" & Obj.GetType.Name & ")"
- End Function
- End Structure
- ''' <summary>
- ''' 动画基础种类。
- ''' </summary>
- ''' <remarks></remarks>
- Public Enum AniType As Byte
- ''' <summary>
- ''' 单个Double的动画,包括位置、长宽、透明度等。这需要附属类型。
- ''' </summary>
- ''' <remarks></remarks>
- DoubleAnimation = 0
- ''' <summary>
- ''' 颜色属性的动画。这需要附属类型。
- ''' </summary>
- ''' <remarks></remarks>
- ColorAnimation = 1
- ''' <summary>
- ''' 缩放控件大小。比起4个DoubleAnimation来说效率更高。
- ''' </summary>
- ''' <remarks></remarks>
- Scale = 2
- ''' <summary>
- ''' 文字一个个出现。
- ''' </summary>
- ''' <remarks></remarks>
- TextAppear = 3
- ''' <summary>
- ''' 执行代码。
- ''' </summary>
- ''' <remarks></remarks>
- Code = 4
- ''' <summary>
- ''' 执行按照规定格式书写的伪代码。比起Code来说这有很大的局限性,但效率更高。
- ''' </summary>
- ''' <remarks></remarks>
- CodeEvent = 5
- ''' <summary>
- ''' 以 WPF 方式缩放控件。
- ''' </summary>
- ScaleTransform = 6
- ''' <summary>
- ''' 以 WPF 方式旋转控件。
- ''' </summary>
- RotateTransform = 7
- End Enum
- ''' <summary>
- ''' 动画扩展种类。
- ''' </summary>
- ''' <remarks></remarks>
- Public Enum AniSubType As Byte
- X = 0
- Y = 1
- Width = 2
- Height = 3
- Opacity = 4
- Value = 5
- Radius = 10
- BorderThickness = 11
- Background = 6
- BorderBrush = 7
- Foreground = 8
- Stroke = 9
- End Enum
- #End Region
- #Region "种类"
- 'DoubleAnimation
- ''' <summary>
- ''' 移动X轴的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">进行移动的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.X,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 移动Y轴的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">进行移动的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Y,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变宽度的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">宽度改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Width,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变高度的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">高度改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Height,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变透明度的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">透明度改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Opacity,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变对象的Value属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">Value属性改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Value,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变对象的Radius属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">Radius属性改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.Radius,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- ''' <summary>
- ''' 改变对象的BorderThickness属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">BorderThickness属性改变的值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.DoubleAnimation, .AniSubType = AniSubType.BorderThickness,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- 'ColorAnimation
- ''' <summary>
- ''' 改变Background颜色属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Background,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
- End Function
- ''' <summary>
- ''' 改变BorderBrush颜色属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.BorderBrush,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
- End Function
- ''' <summary>
- ''' 改变Foreground颜色属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Foreground,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
- End Function
- ''' <summary>
- ''' 改变Stroke颜色属性的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">颜色改变的值。以RGB加减法进行计算。不用担心超额。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.ColorAnimation, .AniSubType = AniSubType.Stroke,
- .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay, .Last = New MyColor}
- End Function
- 'Scale
- ''' <summary>
- ''' 缩放控件的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。</param>
- ''' <param name="Value">大小改变的百分比(如-0.6)或值。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <param name="Absolute">大小改变是否为绝对值。若为False则会按照控件当前大小计算相对缩放值。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Dim ChangeRect As New AdvancedRect
- If Absolute Then
- ChangeRect = New AdvancedRect(-0.5 * Value, -0.5 * Value, Value, Value)
- Else
- ChangeRect = New AdvancedRect(-0.5 * Obj.ActualWidth * Value, -0.5 * Obj.ActualHeight * Value, Obj.ActualWidth * Value, Obj.ActualHeight * Value)
- End If
- Return New Animation With {.AniType = AniType.Scale, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = ChangeRect, .After = After, .FinishLength = -Delay}
- End Function
- 'TextAppear
- ''' <summary>
- ''' 让一段文字一个个字出现或消失的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。必须是Label或TextBlock。</param>
- ''' <param name="Hide">是否为一个个字隐藏。默认为False(一个个字出现)。这些字必须已经存在了。</param>
- ''' <param name="TimePerText">是否采用根据文本长度决定时间的方式。</param>
- ''' <param name="Time">动画长度(毫秒)。若TimePerText为True,这代表每个字所占据的时间。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- 'Are we cool yet?
- 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}
- End Function
- 'Code
- ''' <summary>
- ''' 执行代码。
- ''' </summary>
- ''' <param name="Code">一个ThreadStart。这将会在执行时在主线程调用。</param>
- ''' <param name="Delay">代码延迟执行的时间(毫秒)。</param>
- ''' <param name="After">是否等到以前的动画完成后才执行。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function AaCode(ByVal Code As ThreadStart, Optional ByVal Delay As Integer = 0, Optional ByVal After As Boolean = False) As Animation
- Return New Animation With {.AniType = AniType.Code,
- .TotalLength = 1, .Value = Code, .After = After, .FinishLength = -Delay}
- End Function
- 'CodeEvent
- ''' <summary>
- ''' 执行按照规定格式书写的伪代码。这有很大的局限性,但不会建立线程,性能也更好。
- ''' </summary>
- ''' <param name="Code">伪代码元素数组。</param>
- ''' <param name="Delay">代码延迟执行的时间(毫秒)。</param>
- ''' <param name="After">是否等到以前的动画完成后才执行。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function AaCode(ByVal Code As Array, Optional ByVal Delay As Integer = 0, Optional ByVal After As Boolean = False) As Animation
- Return New Animation With {.AniType = AniType.CodeEvent,
- .TotalLength = 1, .Value = Code, .After = After, .FinishLength = -Delay}
- End Function
- 'ScaleTransform
- ''' <summary>
- ''' 按照 WPF 方式缩放控件的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。它必须已经拥有了单一的 ScaleTransform 值。</param>
- ''' <param name="Value">大小改变的百分比(如-0.6)。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.ScaleTransform, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- 'RotateTransform
- ''' <summary>
- ''' 按照 WPF 方式旋转控件的动画。
- ''' </summary>
- ''' <param name="Obj">动画的对象。它必须已经拥有了单一的 ScaleTransform 值。</param>
- ''' <param name="Value">大小改变的百分比(如-0.6)。</param>
- ''' <param name="Time">动画长度(毫秒)。</param>
- ''' <param name="Delay">动画延迟执行的时间(毫秒)。</param>
- ''' <param name="Ease">插值器类型。</param>
- ''' <param name="After">是否等到以前的动画完成后才继续本动画。</param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- 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
- Return New Animation With {.AniType = AniType.RotateTransform, .TotalLength = Time, .Ease = If(Ease, New AniEaseNone), .Obj = Obj, .Value = Value, .After = After, .FinishLength = -Delay}
- End Function
- '特殊
- ''' <summary>
- ''' 将一个StackPanel中的各个项目依次显示。
- ''' </summary>
- ''' <remarks></remarks>
- Public Function AaStack(ByVal Stack As StackPanel) As ArrayList
- AaStack = New ArrayList
- Dim AniDelay As Integer = 0
- For Each Item In Stack.Children
- Item.Opacity = 0
- AaStack.Add(AaOpacity(Item, 1, 100, AniDelay))
- AniDelay = AniDelay + 25
- Next
- End Function
- #End Region
- #Region "插值器"
- '基类
- Public MustInherit Class AniEase
- ''' <summary>
- ''' 获取增加值。
- ''' </summary>
- ''' <param name="t1">较大的时间百分比。</param>
- ''' <param name="t0">较小的时间百分比。</param>
- ''' <returns></returns>
- Public MustOverride Function GetDelta(t1 As Double, t0 As Double) As Double
- End Class
- ''' <summary>
- ''' 线性,无缓动。
- ''' </summary>
- Public Class AniEaseNone
- Inherits AniEase
- Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
- t1 = MathRange(t1, 0, 1)
- t0 = MathRange(t0, 0, 1)
- Return t1 - t0
- End Function
- End Class
- ''' <summary>
- ''' 平滑开始。
- ''' </summary>
- Public Class AniEaseStart
- Inherits AniEase
- Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
- t1 = MathRange(t1, 0, 1)
- t0 = MathRange(t0, 0, 1)
- Return (t1 - t0) * (t1 + t0)
- End Function
- End Class
- ''' <summary>
- ''' 平滑结束。
- ''' </summary>
- Public Class AniEaseEnd
- Inherits AniEase
- Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
- t1 = MathRange(t1, 0, 1)
- t0 = MathRange(t0, 0, 1)
- Return (t1 - t0) * (2 - t1 - t0)
- End Function
- End Class
- ''' <summary>
- ''' 跳跃开始。
- ''' </summary>
- Public Class AniEaseJumpStart
- Inherits AniEase
- ''' <summary>
- '''
- ''' </summary>
- ''' <param name="JumpEndPercent">跳跃结束时占整个动画的百分比。</param>
- Public Sub New(JumpEndPercent As Double)
- o = JumpEndPercent
- End Sub
- Private o As Double
- Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
- t1 = MathRange(t1, 0, 1)
- t0 = MathRange(t0, 0, 1)
- Return (t1 - t0) * (t1 + t0 - o) / (1 - o)
- End Function
- End Class
- ''' <summary>
- ''' 跳跃结束。
- ''' </summary>
- Public Class AniEaseJumpEnd
- Inherits AniEase
- ''' <summary>
- '''
- ''' </summary>
- ''' <param name="JumpStartPercent">跳跃开始时占整个动画的百分比。</param>
- Public Sub New(JumpStartPercent As Double)
- o = JumpStartPercent
- End Sub
- Private o As Double
- Public Overrides Function GetDelta(t1 As Double, t0 As Double) As Double
- t1 = MathRange(t1, 0, 1)
- t0 = MathRange(t0, 0, 1)
- Return (t1 - t0) * (o + 1 - t1 - t0) / o
- End Function
- End Class
- #End Region
- '等待处理的动画组列表
- Private AniWaitingList As New ArrayList
- Private AniWaitingListName As New ArrayList
- ''' <summary>
- ''' 开始一个动画组。
- ''' </summary>
- ''' <param name="AniGroup">由Aa开头的函数初始化的Animation对象集合。</param>
- ''' <param name="Name">动画组的名称。如果重复会直接停止同名动画组。</param>
- ''' <param name="RefreshTime">是否重新开始这一帧的计时。如果该动画组连续执行请设置为False。</param>
- ''' <remarks></remarks>
- Public Sub AniStart(ByVal AniGroup As ArrayList, ByVal Name As String, Optional ByVal refreshTime As Boolean = True)
- '把组动画(如 AniStack)分解
- Dim AniGroupSet As New ArrayList
- For i = 0 To AniGroup.Count - 1
- If AniGroup(i).GetType.ToString.Contains("ArrayList") Then
- AniGroupSet.AddRange(AniGroup(i))
- Else
- AniGroupSet.Add(AniGroup(i))
- End If
- Next i
- '添加到正在执行的动画组
- If refreshTime Then AniLastTick = Computer.Clock.TickCount '避免处理动画时已经造成了极大的延迟,导致动画突然结束
- AniStop(Name)
- AniGroups.Add(Name, AniGroupSet)
- End Sub
- ''' <summary>
- ''' 开始一个动画组。
- ''' </summary>
- ''' <param name="AniGroup">由Aa开头的函数初始化的Animation对象集合。</param>
- ''' <param name="Name">动画组的名称。如果重复会直接停止同名动画组。</param>
- ''' <param name="RefreshTime">是否重新开始这一帧的计时。如果该动画组连续执行请设置为False。</param>
- ''' <remarks></remarks>
- Public Sub AniStart(ByVal aniGroup As Array, ByVal name As String, Optional ByVal refreshTime As Boolean = True)
- '让Array和ArrayList都可以添加
- AniStart(New ArrayList(aniGroup), name, refreshTime)
- End Sub
- ''' <summary>
- ''' 停止一个动画组。
- ''' </summary>
- ''' <param name="name">需要停止的动画组的名称。</param>
- ''' <remarks></remarks>
- Public Sub AniStop(ByVal Name As String)
- If AniGroups.ContainsKey(Name) Then AniGroups.Remove(Name)
- End Sub
- Private AniMissions As New ArrayList
- Private AniFPSCounter As Integer = 0
- Private AniFPSTimer As Long = 0
- ''' <summary>
- ''' 当前的动画 FPS。
- ''' </summary>
- Public AniFPS As Integer = 0
- ''' <summary>
- ''' 开始动画执行。
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub AniStartRun()
- '初始化计时器
- AniLastTick = My.Computer.Clock.TickCount
- AniFPSTimer = My.Computer.Clock.TickCount
- AniRunning = True '标记动画执行开始
- Dim th = New Thread(Sub()
- Do While True
- '两帧之间的间隔时间
- Dim DeltaTime As Integer = My.Computer.Clock.TickCount - AniLastTick
- If DeltaTime < 2 Then GoTo Sleeper
- AniLastTick = My.Computer.Clock.TickCount
- '执行动画
- frmMain.Dispatcher.Invoke(Sub() AniTimer(DeltaTime))
- '记录 FPS
- If AniLastTick - AniFPSTimer >= 1000 Then
- AniFPS = AniFPSCounter
- AniFPSCounter = 0
- AniFPSTimer = AniLastTick
- If MODE_DEVELOPER Then frmMain.Dispatcher.Invoke(Sub() frmMain.Title = "PCL / FPS : " & AniFPS)
- End If
- AniFPSCounter = AniFPSCounter + 1
- Sleeper:
- '控制 FPS
- Thread.Sleep(1)
- Loop
- End Sub)
- th.Start()
- End Sub
- Private AniCodeList As New ArrayList
- ''' <summary>
- ''' 动画定时器事件。
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub AniTimer(DeltaTime As Integer)
- Rnd.NextDouble() '重置随机数发生器
- For Each Code In AniCodeList
- frmMain.Dispatcher.Invoke(Code)
- Next
- AniCodeList.Clear()
- Try
- Dim i As Integer = 0
- '循环每个动画组
- Do While i < AniGroups.Count
- '初始化
- Dim aniGroup = AniGroups.Values(i)
- Dim CanRemoveAfter = True '是否应该去除“之后”标记
- Dim ii = 0
- '循环每个动画
- Do While ii < aniGroup.Count
- Dim Anim As Animation = aniGroup(ii)
- '执行种类
- If Anim.After = False Then '之前
- CanRemoveAfter = False '取消“之后”标记
- '增加执行时间
- Anim.FinishLength = Anim.FinishLength + DeltaTime
- '执行动画
- If Anim.FinishLength > 0 Then Anim = AniRun(Anim) '执行动画
- '如果当前动画已执行完毕
- If Anim.FinishLength >= Anim.TotalLength Then
- '删除
- aniGroup.RemoveAt(ii)
- GoTo NextAni
- End If
- aniGroup(ii) = Anim
- Else '之后
- If CanRemoveAfter Then
- '之后改为之前
- CanRemoveAfter = False
- Anim.After = False
- aniGroup(ii) = Anim
- '重新循环该动画
- GoTo NextAni
- Else
- '不能去除该“之后”标记,结束该动画组
- Exit Do
- End If
- End If
- ii = ii + 1
- NextAni:
- Loop
- '如果当前动画组都执行完毕则删除
- If aniGroup.Count = 0 Then
- AniGroups.Remove(AniGroups.Keys(i))
- i = i - 1
- End If
- '继续循环
- i = i + 1
- Loop
- Catch ex As Exception
- ExShow(ex, "动画刻执行失败", ErrorLevel.Slient)
- End Try
- End Sub
- ''' <summary>
- ''' 执行一个动画。
- ''' </summary>
- ''' <param name="Ani">执行的动画对象。</param>
- ''' <remarks></remarks>
- Private Function AniRun(ByVal Ani As Animation) As Animation
- Try
- Select Case Ani.AniType
- Case AniType.DoubleAnimation
- Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
- Select Case Ani.AniSubType
- Case AniSubType.X
- SetLeft(Ani.Obj, GetLeft(Ani.Obj) + Delta)
- Case AniSubType.Y
- SetTop(Ani.Obj, GetTop(Ani.Obj) + Delta)
- Case AniSubType.Opacity
- Ani.Obj.Opacity = MathRange(Ani.Obj.Opacity + Delta, 0, 1)
- Case AniSubType.Width
- Ani.Obj.Width = MathRange(Ani.Obj.Width + Delta, 0)
- Case AniSubType.Height
- Ani.Obj.Height = MathRange(Ani.Obj.Height + Delta, 0)
- Case AniSubType.Value
- Ani.Obj.Value = Ani.Obj.Value + Delta
- Case AniSubType.Radius
- Ani.Obj.Radius = Ani.Obj.Radius + Delta
- Case AniSubType.BorderThickness
- Ani.Obj.BorderThickness = New Thickness(CType(Ani.Obj.BorderThickness, Thickness).Bottom + Delta)
- End Select
- Case AniType.ColorAnimation
- '利用Last记录了余下的小数值
- Dim Delta As MyColor = MathPercent(New MyColor, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent)) + Ani.Last
- Select Case Ani.AniSubType
- Case AniSubType.Background
- Dim NewColor As MyColor = New MyColor(Ani.Obj.Background.Color) + Delta
- Ani.Obj.Background = NewColor
- Ani.Last = NewColor - New MyColor(Ani.Obj.Background.Color)
- Case AniSubType.Foreground
- Dim NewColor As MyColor = New MyColor(Ani.Obj.Foreground.Color) + Delta
- Ani.Obj.Foreground = NewColor
- Ani.Last = NewColor - New MyColor(Ani.Obj.Foreground.Color)
- Case AniSubType.Stroke
- Dim NewColor As MyColor = New MyColor(Ani.Obj.Stroke.Color) + Delta
- Ani.Obj.Stroke = NewColor
- Ani.Last = NewColor - New MyColor(Ani.Obj.Stroke.Color)
- Case AniSubType.BorderBrush
- Dim NewColor As MyColor = New MyColor(Ani.Obj.BorderBrush.Color) + Delta
- Ani.Obj.BorderBrush = NewColor
- Ani.Last = NewColor - New MyColor(Ani.Obj.BorderBrush.Color)
- End Select
- Case AniType.Scale
- Dim Delta As Double = Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent)
- 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)
- Ani.Obj.Width = Math.Max(Ani.Obj.Width + MathPercent(0, Ani.Value.Width, Delta), 0)
- Ani.Obj.Height = Math.Max(Ani.Obj.Height + MathPercent(0, Ani.Value.Height, Delta), 0)
- Case AniType.TextAppear
- 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)))
- If Ani.Obj.GetType.Name = "TextBlock" Then
- Ani.Obj.Text = NewText
- Else
- Ani.Obj.Context = NewText
- End If
- Case AniType.Code
- AniCodeList.Add(Ani.Value)
- Case AniType.CodeEvent
- Select Case Ani.Value(0)
- Case "Close"
- Ani.Value(1).Close()
- Case "Clear"
- Ani.Value(1).Clear()
- Case "Remove"
- Ani.Value(1).Remove(Ani.Value(2))
- Case "Add"
- Ani.Value(1).Add(Ani.Value(2))
- Case "Set"
- Ani.Value(1) = Ani.Value(2)
- Case "Tag"
- Ani.Value(1).Tag = Ani.Value(2)
- Case "Enabled"
- Ani.Value(1).IsEnabled = Ani.Value(2)
- Case "State"
- Ani.Value(1).State = Ani.Value(2)
- Case "IsHitTestVisible"
- Ani.Value(1).IsHitTestVisible = Ani.Value(2)
- Case "ShowInTaskbar"
- Ani.Value(1).ShowInTaskbar = Ani.Value(2)
- Case "Nothing"
- Ani.Value(1) = Nothing
- Case "Visible"
- Ani.Value(1).Visibility = If(Ani.Value(2), Visibility.Visible, Visibility.Collapsed)
- Case "End"
- EndForce()
- Case Else
- AaCodeCall(Ani.Value(0), Ani.Value)
- End Select
- Case AniType.ScaleTransform
- Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
- CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleX = CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleX + Delta
- CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleY = CType(Ani.Obj.RenderTransform, ScaleTransform).ScaleY + Delta
- Case AniType.RotateTransform
- Dim Delta As Double = MathPercent(0, Ani.Value, Ani.Ease.GetDelta(Ani.FinishLength / Ani.TotalLength, Ani.Percent))
- CType(Ani.Obj.RenderTransform, RotateTransform).Angle = CType(Ani.Obj.RenderTransform, RotateTransform).Angle + Delta
- End Select
- Ani.Percent = Ani.FinishLength / Ani.TotalLength '修改执行百分比
- Catch ex As Exception
- ExShow(ex, "执行动画失败:" & GetStringFromEnum(Ani.AniType), ErrorLevel.Slient)
- End Try
- Return Ani
- End Function
- End Module '动画
- Public Module Web
- ''' <summary>
- ''' 正在下载的列表。
- ''' </summary>
- ''' <remarks></remarks>
- Public WebGroups As New Dictionary(Of String, WebGroup)
- Private WebDownloadingList As New ArrayList
- Public WebDownloadCountMax As Integer = ReadIni("setup", "DownMaxinum", "20")
- #Region "类与枚举"
- ''' <summary>
- ''' 下载文件的文件大小处理方式。
- ''' </summary>
- Public Enum WebRequireSize As Integer
- ''' <summary>
- ''' 在下载前已经知道了文件大小。
- ''' </summary>
- Known = 0
- ''' <summary>
- ''' 下载前不知道文件大小,需要从网络中获取。
- ''' </summary>
- Require = 1
- ''' <summary>
- ''' 下载前不知道文件大小,也不获取大小。
- ''' </summary>
- DontNeed = 2
- ''' <summary>
- ''' 不需要知道准确大小,只要求文件至少有一定的大小。
- ''' </summary>
- AtLeast = 3
- End Enum
- Public Class WebGroup
- Public Name As String
- ''' <summary>
- ''' 文件列表(WebFile)。
- ''' </summary>
- ''' <remarks></remarks>
- Public Files As ArrayList
- ''' <summary>
- ''' 是否尝试从服务器确认文件大小。
- ''' </summary>
- ''' <remarks></remarks>
- Public GetServerFileSize As WebRequireSize
- ''' <summary>
- ''' 下载成功时执行的线程。
- ''' </summary>
- ''' <remarks></remarks>
- Public OnSuccess As System.Threading.ParameterizedThreadStart
- ''' <summary>
- ''' 下载失败时执行的线程。
- ''' </summary>
- ''' <remarks></remarks>
- Public OnFail As System.Threading.ParameterizedThreadStart
- ''' <summary>
- ''' 已下载的文件数目(下载成功或失败的)。(用于文件数较多情况下的快速进度计算)
- ''' </summary>
- Public FinishedCount As Integer = 0
- ''' <summary>
- ''' 下载完成的文件数目的百分比。取值为0到1。
- ''' </summary>
- ''' <remarks></remarks>
- Public ReadOnly Property Percent As Double
- Get
- Select Case Files.Count
- Case 0
- Percent = 0
- Case 1
- Percent = Math.Round(CType(Files(0), WebFile).Percent, 4)
- Case Is < 60
- Dim TotalPercent As Double = 0
- For i = 0 To Files.Count - 1
- TotalPercent = TotalPercent + CType(Files(i), WebFile).Percent
- Next
- Percent = Math.Round(TotalPercent / Files.Count, 4)
- Case Else
- Percent = Math.Round(FinishedCount / Files.Count, 4)
- End Select
- End Get
- End Property
- ''' <summary>
- ''' 该文件组的唯一标识符。
- ''' </summary>
- ''' <remarks></remarks>
- Public UUID As Integer = GetUUID()
- End Class
- Public Class WebFile
- ''' <summary>
- ''' 文件所有可能的网络URL。
- ''' </summary>
- ''' <remarks></remarks>
- Public AllWebAddress As ArrayList
- ''' <summary>
- ''' 文件当前的网络URL。
- ''' </summary>
- ''' <remarks></remarks>
- Public ReadOnly Property WebAddress As String
- Get
- Return If(AllWebAddress(0), "")
- End Get
- End Property
- ''' <summary>
- ''' 文件在本地的完整地址。
- ''' </summary>
- ''' <remarks></remarks>
- Public ReadOnly Property LocalAddress As String
- Get
- Return LocalFolder & LocalName
- End Get
- End Property
- ''' <summary>
- ''' 文件在本地的所在的文件夹,以“\”结尾。
- ''' </summary>
- ''' <remarks></remarks>
- Public LocalFolder As String
- ''' <summary>
- ''' 是否需要刷新文件名。
- ''' </summary>
- ''' <remarks></remarks>
- Public RefreshName As Boolean = False
- Private _LocalName As String = ""
- ''' <summary>
- ''' 当前的文件名。如果需要刷新文件名,它有可能改变。
- ''' </summary>
- ''' <remarks></remarks>
- Public Property LocalName As String
- Get
- If _LocalName = "" Or IsNothing(_LocalName) Then _LocalName = GetFileNameFromPath(WebAddress)
- Return _LocalName
- End Get
- Set(ByVal value As String)
- _LocalName = value
- End Set
- End Property
- ''' <summary>
- ''' 使用下一个下载地址。
- ''' </summary>
- ''' <remarks></remarks>
- Public Function NextAddress() As Boolean
- If AllWebAddress.Count > 1 Then
- AllWebAddress.RemoveAt(0)
- If RefreshName Then LocalName = GetFileNameFromPath(WebAddress)
- Return True
- Else
- Return False
- End If
- End Function
- Private _State As WebDownloadStats = WebDownloadStats.FirstLoad
- ''' <summary>
- ''' 状态标记。
- ''' </summary>
- ''' <remarks></remarks>
- Public Property State As WebDownloadStats
- Get
- Return _State
- End Get
- Set(ByVal value As WebDownloadStats)
- If value = _State Then Exit Property
- '改变状态
- _State = value
- Select Case value
- Case WebDownloadStats.FirstLoad
- '等待下载
- GetSize = 0
- Speed = 0
- Percent = 0
- SyncLock WebWaitingLockObj
- WebWaitingList.Add(Me)
- End SyncLock
- Case WebDownloadStats.Wait
- '等待下载
- frmDownloadRight.RefreshFile(Me)
- GetSize = 0
- Speed = 0
- Percent = 0
- SyncLock WebWaitingLockObj
- WebWaitingList.Insert(0, Me)
- End SyncLock
- WebWaitingToRun()
- Case WebDownloadStats.GetSize
- '获取大小
- frmDownloadRight.RefreshFile(Me)
- WebStateGetSize(Me)
- Case WebDownloadStats.Download
- '下载
- frmDownloadRight.RefreshFile(Me)
- WebStateDownload(Me)
- Case WebDownloadStats.Success
- '下载成功
- Speed = 0
- Percent = 1
- WebStateSuccess(Me)
- WebGroups(GroupName).FinishedCount = WebGroups(GroupName).FinishedCount + 1
- frmDownloadRight.RefreshFile(Me)
- WebFinishCheck(Me.GroupName)
- Case WebDownloadStats.Fail
- '下载失败
- GetSize = 0
- Speed = 0
- Percent = 0
- If Not WebStateFail(Me) Then
- WebGroups(GroupName).FinishedCount = WebGroups(GroupName).FinishedCount + 1
- frmDownloadRight.RefreshFile(Me)
- WebFinishCheck(Me.GroupName)
- End If
- Case WebDownloadStats.Retry
- '重试
- _State = value
- frmDownloadRight.RefreshFile(Me)
- Thread.Sleep(If(WebGroups(GroupName).Files.Count = 1, 200, 1000))
- #Disable Warning BC42026
- State = WebDownloadStats.Wait
- End Select
- End Set
- End Property
- ''' <summary>
- ''' 该文件的唯一标识符。
- ''' </summary>
- ''' <remarks></remarks>
- Public UUID As Integer = GetUUID()
- Public GetServerFileSize As WebRequireSize
- Public GroupName As String
- Public RefreshThread As Thread
- ''' <summary>
- ''' 文件总大小,可能为 0。
- ''' </summary>
- ''' <remarks></remarks>
- Public TotalSize As FileSize = 0
- ''' <summary>
- ''' 已经下载了的部分的大小。
- ''' </summary>
- ''' <remarks></remarks>
- Public GetSize As FileSize = 0
- ''' <summary>
- ''' 下载速度,单位为秒。
- ''' </summary>
- ''' <remarks></remarks>
- Public Speed As FileSize = 0
- ''' <summary>
- ''' 已经下载的百分比。取值为 0 到 1。
- ''' </summary>
- ''' <remarks></remarks>
- Public Percent As Double = 0
- ''' <summary>
- ''' 计算下载速度的计刻。
- ''' </summary>
- ''' <remarks></remarks>
- Public SpeedCount As Integer
- End Class
- Public Enum WebDownloadStats As Byte
- ''' <summary>
- ''' 第一次加入列表。等同于 Wait,但是不会刷新队列。
- ''' </summary>
- FirstLoad = 6
- ''' <summary>
- ''' 等待中。若队列有空闲,需要获取大小的转为 GetSize,不需要获取大小的转为 Download。
- ''' </summary>
- ''' <remarks></remarks>
- Wait = 0
- ''' <summary>
- ''' 正在获取大小。获取大小成功的转为 Download,失败的转为 Fail。
- ''' </summary>
- ''' <remarks></remarks>
- GetSize = 1
- ''' <summary>
- ''' 正在下载。下载成功的转为 Success,失败的转为 Fail。
- ''' </summary>
- ''' <remarks></remarks>
- Download = 2
- ''' <summary>
- ''' 下载成功。
- ''' </summary>
- ''' <remarks></remarks>
- Success = 3
- ''' <summary>
- ''' 下载失败。可以重试的转为 Retry。
- ''' </summary>
- ''' <remarks></remarks>
- Fail = 4
- ''' <summary>
- ''' 等待重试。半秒后转为 Wait。
- ''' </summary>
- Retry = 5
- End Enum
- #End Region
- '开始下载
- ''' <summary>
- ''' 需要下载的文件。
- ''' </summary>
- Public Class WebRequireFile
- ''' <summary>
- ''' 所有可能的下载地址。若前一个地址下载失败会自动尝试下一个地址。
- ''' </summary>
- Public WebURLs As ArrayList
- ''' <summary>
- ''' 本地文件夹地址。不包含文件名。
- ''' </summary>
- Public LocalFolder As String = ""
- ''' <summary>
- ''' 本地文件名,不包含文件夹路径。若为空,则会从下载地址自动生成文件名。
- ''' </summary>
- Public LocalName As String = ""
- ''' <summary>
- ''' 根据文件大小处理方式在这里提交准确大小或至少应有的大小。
- ''' </summary>
- Public KnownFileSize As Integer = 0
- End Class
- ''' <summary>
- ''' 开始下载一个列表中的文件。
- ''' </summary>
- ''' <param name="SourceFiles">WebRequireFile 的一维数组。</param>
- ''' <param name="Name">下载列表的名称。</param>
- ''' <param name="OnSuccess">下载成功时执行的代码。</param>
- ''' <param name="OnFail">下载失败时执行的代码。</param>
- ''' <param name="RequireSize">文件大小处理方式。</param>
- ''' <remarks></remarks>
- Public Sub WebStart(ByVal SourceFiles() As WebRequireFile, ByVal Name As String, ByVal OnSuccess As ParameterizedThreadStart, ByVal OnFail As ParameterizedThreadStart, ByVal RequireSize As WebRequireSize)
- Dim th As New Thread(Sub()
- Try
- '检查哪些文件需要下载,并将真正需要下载的文件整理为 CheckedFiles 数组
- Dim CheckedFiles As New ArrayList(SourceFiles)
- '检查文件是否存在文件名,如果不存在文件名则跳过过滤
- If Not CheckedFiles(0).LocalName = "" Then
- '过滤已经存在的文件
- Select Case RequireSize
- Case WebRequireSize.Known
- '已知文件大小,检查文件:如果大小一致则不下载
- For i = 0 To CheckedFiles.Count - 1
- If CheckedFiles.Count - 1 < i Then Exit For
- If GetFileSize(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) = CheckedFiles(i).KnownFileSize Then
- CheckedFiles.RemoveAt(i)
- i = i - 1
- End If
- Next
- Case WebRequireSize.Require
- '不知道文件大小,所以不进行过滤
- Case WebRequireSize.DontNeed
- '不需要知道文件大小,检查文件:如果文件存在则不下载
- For i = 0 To CheckedFiles.Count - 1
- If CheckedFiles.Count - 1 < i Then Exit For
- If File.Exists(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) Then
- CheckedFiles.RemoveAt(i)
- i = i - 1
- End If
- Next
- Case WebRequireSize.AtLeast
- '文件有大小要求,检查文件:如果文件大小大于指定值则不下载
- For i = 0 To CheckedFiles.Count - 1
- If CheckedFiles.Count - 1 < i Then Exit For
- If GetFileSize(CheckedFiles(i).LocalFolder & CheckedFiles(i).LocalName) >= Math.Max(1, CheckedFiles(i).KnownFileSize) Then
- CheckedFiles.RemoveAt(i)
- i = i - 1
- End If
- Next
- End Select
- '去重
- CheckedFiles = ArrayNoDouble(CheckedFiles.ToArray)
- '如果没有剩余文件直接成功
- If CheckedFiles.Count = 0 Then
- '直接成功
- frmMain.Dispatcher.Invoke(OnSuccess, Name)
- Exit Sub
- End If
- End If
- '初始化文件组
- Dim NewGroup As New WebGroup With {.OnSuccess = OnSuccess, .OnFail = OnFail, .Files = New ArrayList, .GetServerFileSize = RequireSize, .Name = Name}
- '二次处理文件,将 WebRequireFile 转为 WebFile
- For i = 0 To CheckedFiles.Count - 1
- Dim NewFile As WebFile
- If CheckedFiles(0).LocalName = "" Then
- NewFile = New WebFile With {.AllWebAddress = CheckedFiles(i).WebURLs, .GetServerFileSize = RequireSize, .GroupName = Name,
- .LocalFolder = CheckedFiles(i).LocalFolder, .TotalSize = New FileSize(CheckedFiles(i).KnownFileSize), .RefreshName = True}
- Else
- NewFile = New WebFile With {.AllWebAddress = CheckedFiles(i).WebURLs, .GetServerFileSize = RequireSize, .GroupName = Name,
- .LocalFolder = CheckedFiles(i).LocalFolder, .TotalSize = New FileSize(CheckedFiles(i).KnownFileSize), .LocalName = CheckedFiles(i).LocalName, .RefreshName = False}
- End If
- NewGroup.Files.Add(NewFile)
- Next
- WebWaitingList.AddRange(NewGroup.Files)
- '添加进总列表
- If NewGroup.Files.Count = 0 Then Exit Sub
- If WebGroups.ContainsKey(Name) Then
- frmDownloadRight.RemoveGroup(WebGroups(Name))
- WebGroups.Remove(Name)
- End If
- log("[System] 开始下载列表文件:" & Name)
- WebTaskbarShow = ReadIni("setup", "DownProcess", "True") = "True"
- WebGroups.Add(Name, NewGroup)
- frmDownloadRight.AddGroup(NewGroup)
- '要求执行刷新
- WebWaitingToRun()
- Catch ex As Exception
- ExShow(ex, "处理下载列表失败:" & Name, ErrorLevel.MsgboxAndFeedback)
- frmMain.Dispatcher.Invoke(OnFail, Name)
- End Try
- End Sub)
- th.Start()
- End Sub
- '下载中
- ''' <summary>
- ''' 处于 Waiting 状态的文件。
- ''' </summary>
- Private WebWaitingList As New ArrayList
- Public WebWaitingLockObj As Object = New Object
- ''' <summary>
- ''' 若队列有空闲,尝试让 Waiting 状态的文件开始下载。
- ''' </summary>
- Private Sub WebWaitingToRun()
- SyncLock WebWaitingLockObj
- For i = 0 To Math.Min(6, WebWaitingList.Count - 1)
- Try
- If WebDownloadingList.Count >= WebDownloadCountMax Or i > Math.Min(6, WebWaitingList.Count - 1) Then Exit Sub
- If WebDownloadingList.Contains(WebWaitingList(i).UUID) Then GoTo NextFile
- WebDownloadingList.Add(WebWaitingList(i).UUID)
- WebWaitingList(i).State = If(WebWaitingList(i).GetServerFileSize = WebRequireSize.Require Or WebWaitingList(i).GetServerFileSize = WebRequireSize.AtLeast,
- WebDownloadStats.GetSize, WebDownloadStats.Download)
- WebWaitingList.RemoveAt(i) '移出等待队列
- i = i - 1
- Catch
- i = i - 1
- End Try
- NextFile:
- Next
- End SyncLock
- End Sub
- ''' <summary>
- ''' 获取文件大小,之后转入 Fail 或 Download 状态。
- ''' </summary>
- Private Sub WebStateGetSize(File As WebFile)
- Dim th As New Thread(Sub()
- Try
- If MODE_OFFLINE Then File.State = WebDownloadStats.Fail : Exit Sub
- Select Case File.GetServerFileSize
- Case WebRequireSize.AtLeast
- '要求至少有一定大小
- Dim TrueSize = GetFileSize(File.WebAddress, File)
- If TrueSize < 1 Then
- Throw New Exception("获取文件大小失败!")
- ElseIf TrueSize < File.TotalSize Then
- Throw New Exception("文件过小!(" & New FileSize(TrueSize).ToString & "/" & File.TotalSize.ToString & ")")
- End If
- File.TotalSize = TrueSize
- Case WebRequireSize.Require
- '只是需要知道大小
- File.TotalSize = GetFileSize(File.WebAddress, File)
- If File.TotalSize < 1 Then Throw New Exception("获取文件大小失败!")
- End Select
- '获取大小成功,开始下载
- File.State = WebDownloadStats.Download
- Catch ex As Exception
- ExShow(ex, "获取文件大小失败(" & File.LocalName & ")", ErrorLevel.Slient)
- File.State = WebDownloadStats.Fail
- End Try
- End Sub)
- th.Start()
- End Sub
- ''' <summary>
- ''' 下载文件,之后转入 Fail 或 Success 状态。
- ''' </summary>
- Private Sub WebStateDownload(File As WebFile)
- Dim th As New Thread(Sub()
- Try
- '准备
- If Not Directory.Exists(File.LocalFolder) Then Directory.CreateDirectory(File.LocalFolder)
- File.SpeedCount = My.Computer.Clock.TickCount
- '下载
- My.Computer.Network.DownloadFile(File.WebAddress, File.LocalAddress & DOWNLOADING_END, "", "", False, 10000, True)
- '下载完毕检查
- File.GetSize = GetFileSize(File.LocalAddress & DOWNLOADING_END)
- If File.GetServerFileSize = WebRequireSize.DontNeed Or (File.GetSize = File.TotalSize And File.GetSize > 1) Then
- '下载成功
- IO.File.Delete(File.LocalAddress)
- Rename(File.LocalAddress & DOWNLOADING_END, File.LocalAddress)
- log("[Download] 下载文件成功:" & File.WebAddress)
- File.State = WebDownloadStats.Success
- Else
- '下载失败
- log("[Download] 下载文件失败(文件大小不匹配):" & File.LocalAddress & ",所需大小:" & File.TotalSize.ToString & ",实际大小:" & File.GetSize.ToString & "(" & File.GetSize.Value & ")", True)
- IO.File.Delete(File.LocalAddress & DOWNLOADING_END)
- File.State = WebDownloadStats.Fail
- End If
- Catch ex As Exception
- ExShow(ex, "下载文件失败(" & File.LocalName & ")", ErrorLevel.Slient)
- File.State = WebDownloadStats.Fail
- End Try
- End Sub)
- th.Start()
- '刷新显示线程
- File.RefreshThread = New Thread(Sub()
- Try
- Do While File.State = WebDownloadStats.Download
- Thread.Sleep(950)
- If Not File.State = WebDownloadStats.Download Then Exit Sub
- Dim NewSize = GetFileSize(File.LocalAddress & DOWNLOADING_END)
- File.Speed = (NewSize - File.GetSize) / (My.Computer.Clock.TickCount - File.SpeedCount) * 1000
- File.SpeedCount = My.Computer.Clock.TickCount
- File.GetSize = NewSize
- File.Percent = If(File.TotalSize = 0, 0, Math.Round(File.GetSize / File.TotalSize, 3))
- If Not File.State = WebDownloadStats.Download Then Exit Sub
- frmDownloadRight.RefreshFile(File)
- Loop
- Catch
- End Try
- End Sub)
- File.RefreshThread.Start()
- End Sub
- ''' <summary>
- ''' 下载失败,之后可能转入 Retry。若重试成功才返回 True。
- ''' </summary>
- ''' <param name="File"></param>
- Private Function WebStateFail(File As WebFile)
- '重试
- If File.NextAddress() And Not MODE_OFFLINE Then
- '重试成功
- log("[Download] 重试地址:" & File.WebAddress)
- File.State = WebDownloadStats.Retry
- WebStateFail = True
- Else
- '重试失败
- WebStateFail = False
- End If
- '队列处理
- WebDownloadingList.Remove(File.UUID)
- WebWaitingToRun()
- End Function
- ''' <summary>
- ''' 下载成功。
- ''' </summary>
- Private Sub WebStateSuccess(File As WebFile)
- '队列处理
- WebDownloadingList.Remove(File.UUID)
- WebWaitingToRun()
- End Sub
- '任务栏进度条
- Public WebTaskbarShow As Boolean = True
- Private WebTaskbarLastState As TaskbarItemProgressState = TaskbarItemProgressState.None
- Private WebTaskbarLastValue As Double = 0
- ''' <summary>
- ''' 下载完成检查。
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub WebFinishCheck(ByVal Name As String)
- Try
- If Not WebGroups.Keys.Contains(Name) Then Exit Sub
- Dim Group As WebGroup = WebGroups(Name)
- If IsNothing(Group.Files) Then Exit Sub
- If Not Group.Files.Count = Group.FinishedCount Then Exit Sub
- '遍历文件:如果存在失败的文件,将 isFail 设置为 True
- Dim isFail As Boolean = False
- For i = Group.Files.Count - 1 To 0 Step -1
- If Group.Files(i).State = WebDownloadStats.Fail Then isFail = True
- Next i
- '下载完成
- log("[Download] 列表文件下载完成:" & Name)
- '结束
- WebGroups.Remove(Name)
- frmDownloadRight.RemoveGroup(Group)
- If isFail Then
- frmMain.Dispatcher.Invoke(Group.OnFail, Name)
- Else
- frmMain.Dispatcher.Invoke(Group.OnSuccess, Name)
- End If
- Catch ex As Exception
- ExShow(ex, "检查下载列表出错")
- End Try
- End Sub
- ''' <summary>
- ''' 停止下载列表文件。
- ''' </summary>
- ''' <param name="Name"></param>
- ''' <remarks></remarks>
- Public Sub WebDownloadStop(ByVal Name As String)
- If WebGroups.ContainsKey(Name) Then
- frmDownloadRight.RemoveGroup(WebGroups(Name))
- WebGroups.Remove(Name)
- End If
- End Sub
- Public Sub WebStartRun()
- Dim th As New Thread(Sub()
- Do While True
- WebTimer()
- Thread.Sleep(250)
- Loop
- End Sub)
- th.Priority = ThreadPriority.BelowNormal
- th.Start()
- End Sub
- Public Sub WebTimer()
- If Not WebTaskbarShow Then Exit Sub
- '应有值
- Dim ShouldState As TaskbarItemProgressState
- Dim ShouldValue As Double
- '获取应有值
- Try
- If WebGroups.Count > 0 Then
- Dim TotalPercent As Double = 0
- For Each Group As WebGroup In WebGroups.Values
- TotalPercent = TotalPercent + Group.Percent
- Next
- ShouldState = If(TotalPercent = 0, TaskbarItemProgressState.Indeterminate, TaskbarItemProgressState.Normal)
- ShouldValue = TotalPercent / WebGroups.Count
- Else
- ShouldState = TaskbarItemProgressState.None
- ShouldValue = 0
- End If
- Catch
- End Try
- '更新值
- If Not WebTaskbarLastState = ShouldState Then
- frmMain.Dispatcher.Invoke(Sub() frmMain.TaskbarItemInfo.ProgressState = ShouldState)
- WebTaskbarLastState = ShouldState
- End If
- If Not WebTaskbarLastValue = ShouldValue Then
- frmMain.Dispatcher.Invoke(Sub() frmMain.TaskbarItemInfo.ProgressValue = ShouldValue)
- WebTaskbarLastValue = ShouldValue
- End If
- End Sub
- End Module 'HTTP下载
- Public Module BitDrawer
- Public GifList As New ArrayList 'Gif列表
- 'Timer
- Public Sub GifStartRun()
- Dim time As New DispatcherTimer()
- time.Interval = TimeSpan.FromMilliseconds(1)
- AddHandler time.Tick, AddressOf GifTimer
- time.Start()
- End Sub
- Public Sub GifTimer()
- For i = 0 To GifList.Count - 1
- Dim gif As MyBitmap = GifList(i)
- '切换Gif的帧
- If My.Computer.Clock.TickCount - gif.RoundLastTime >= gif.RoundTime Then
- gif.RoundLastTime = My.Computer.Clock.TickCount
- If gif.CurrentFlame = gif.MaxFlame - 1 Then
- If gif.PlayOnce Then
- '如果只播放一次那么拜拜
- GifList.Remove(gif)
- Else
- '如果不只播放一次那么继续
- gif.SetGifFrame(0)
- End If
- Else
- gif.SetGifFrame(gif.CurrentFlame + 1)
- End If
- End If
- '刷新绑定控件的显示
- If Not IsNothing(gif.Control) Then gif.Control.Source = New MyBitmap(gif.Pic)
- Next
- End Sub
- '类
- Public Class MyBitmap
- ''' <summary>
- ''' 存储的图片
- ''' </summary>
- ''' <remarks></remarks>
- Public Pic As System.Drawing.Bitmap
- ''' <summary>
- ''' (Gif)绑定的控件
- ''' </summary>
- ''' <remarks></remarks>
- Public Control As System.Windows.Controls.Image = Nothing
- ''' <summary>
- ''' (Gif)每一帧的时间
- ''' </summary>
- ''' <remarks></remarks>
- Public RoundTime As Integer
- ''' <summary>
- ''' (Gif)上一次改变时的时间
- ''' </summary>
- ''' <remarks></remarks>
- Public RoundLastTime As Integer
- ''' <summary>
- ''' (Gif)是否只播放一次
- ''' </summary>
- ''' <remarks></remarks>
- Public PlayOnce As Boolean = False
- ''' <summary>
- ''' (Gif)当前帧,从0开始
- ''' </summary>
- ''' <remarks></remarks>
- Public CurrentFlame As Integer = 0
- ''' <summary>
- ''' (Gif)最大帧数,从1开始
- ''' </summary>
- ''' <remarks></remarks>
- Public MaxFlame As Integer
- '类型转换
- '支持的类:Image ImageSource Bitmap ImageBrush
- Public Shared Widening Operator CType(ByVal Image As System.Drawing.Image) As MyBitmap
- Return New MyBitmap(Image)
- End Operator
- Public Shared Widening Operator CType(ByVal Image As MyBitmap) As System.Drawing.Image
- Return Image.Pic
- End Operator
- Public Shared Widening Operator CType(ByVal Image As ImageSource) As MyBitmap
- Return New MyBitmap(Image)
- End Operator
- Public Shared Widening Operator CType(ByVal Image As MyBitmap) As ImageSource
- Dim ptr As IntPtr = Image.Pic.GetHbitmap()
- Dim re As ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
- ptr,
- IntPtr.Zero,
- Int32Rect.Empty,
- BitmapSizeOptions.FromEmptyOptions())
- DeleteObject(ptr)
- Return re
- End Operator
- Public Shared Widening Operator CType(ByVal Image As System.Drawing.Bitmap) As MyBitmap
- Return New MyBitmap(Image)
- End Operator
- Public Shared Widening Operator CType(ByVal Image As MyBitmap) As System.Drawing.Bitmap
- Return Image.Pic
- End Operator
- Public Shared Widening Operator CType(ByVal Image As ImageBrush) As MyBitmap
- Return New MyBitmap(Image)
- End Operator
- Public Shared Widening Operator CType(ByVal Image As MyBitmap) As ImageBrush
- Return New ImageBrush(New MyBitmap(Image.Pic))
- End Operator
- '构造函数
- Public Sub New()
- End Sub
- Public Sub New(ByVal FilePath As String)
- Try
- If FilePath.StartsWith(PATH_IMAGE) Then
- '使用缓存
- If BitmapCache.ContainsKey(FilePath) Then
- Pic = BitmapCache(FilePath).Pic
- Else
- Pic = New MyBitmap(CType((New ImageSourceConverter).ConvertFromString(FilePath), ImageSource))
- BitmapCache.Add(FilePath, Pic)
- End If
- Else
- Using inputStream As New FileStream(FilePath, FileMode.Open)
- Pic = New System.Drawing.Bitmap(inputStream)
- End Using
- End If
- Catch ex As Exception
- Pic = My.Application.TryFindResource(FilePath)
- If IsNothing(Pic) Then
- Pic = New System.Drawing.Bitmap(1, 1)
- ExShow(ex, "加载图片失败,该图片加载已被跳过:" & FilePath, ErrorLevel.DebugOnly)
- End If
- End Try
- End Sub
- Public Sub New(ByVal Image As ImageSource)
- Using MS = New MemoryStream()
- Dim Encoder = New PngBitmapEncoder()
- Encoder.Frames.Add(BitmapFrame.Create(Image))
- Encoder.Save(MS)
- Pic = New System.Drawing.Bitmap(MS)
- End Using
- End Sub
- Public Sub New(ByVal Image As System.Drawing.Image)
- Pic = Image
- End Sub
- Public Sub New(ByVal Image As System.Drawing.Bitmap)
- Pic = Image
- End Sub
- Public Sub New(ByVal Image As ImageBrush)
- Using MS = New MemoryStream()
- Dim Encoder = New BmpBitmapEncoder()
- Encoder.Frames.Add(BitmapFrame.Create(Image.ImageSource))
- Encoder.Save(MS)
- Pic = New System.Drawing.Bitmap(MS)
- End Using
- End Sub
- ''' <summary>
- ''' 设置Gif的当前帧
- ''' </summary>
- ''' <param name="count">帧的编号,从0开始,超限制报错</param>
- ''' <remarks></remarks>
- Public Sub SetGifFrame(ByVal count As Integer)
- Pic.SelectActiveFrame(New FrameDimension(Pic.FrameDimensionsList()(0)), count)
- CurrentFlame = count
- End Sub
- ''' <summary>
- ''' 把这个对象视作Gif初始化
- ''' </summary>
- ''' <param name="round">两帧之间的间隔(毫秒)。</param>
- ''' <param name="once">是否只播放一次,True为是。</param>
- ''' <param name="control">绑定的控件。</param>
- ''' <remarks></remarks>
- Public Sub GifLoad(ByVal round As Integer, ByVal once As Boolean, Optional ByVal control As System.Windows.Controls.Image = Nothing)
- RoundTime = round
- RoundLastTime = My.Computer.Clock.TickCount
- PlayOnce = once
- Me.Control = control
- GifList.Add(Me)
- MaxFlame = Pic.GetFrameCount(New FrameDimension(Pic.FrameDimensionsList()(0)))
- End Sub
- ''' <summary>
- ''' 获取旋转的图片,这个方法不会导致原对象改变
- ''' </summary>
- ''' <param name="angle">旋转角度,单位为角度不是弧度啊</param>
- ''' <returns>旋转后的Bitmap</returns>
- ''' <remarks></remarks>
- Public Function Rotation(ByVal angle As Double) As System.Drawing.Bitmap
- With Me
- Dim img As System.Drawing.Image = Me.Pic
- Dim bitSize As Single = Math.Sqrt(img.Width ^ 2 + img.Height ^ 2)
- bitSize = img.Width
- Dim bmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(CInt(bitSize), CInt(bitSize))
- Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp)
- g.TranslateTransform(bitSize / 2, bitSize / 2)
- g.RotateTransform(angle)
- g.TranslateTransform(-bitSize / 2, -bitSize / 2)
- g.DrawImage(img, New System.Drawing.Rectangle(0, 0, img.Width, img.Width))
- End Using
- Return bmp
- End With
- End Function
- ''' <summary>
- ''' 获取左右翻转的图片,这个方法不会导致原对象改变
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function LeftRightFilp() As System.Drawing.Bitmap
- Dim bmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(Me.Pic)
- bmp.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX)
- Return bmp
- End Function
- End Class
- '合并Bitmap
- 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
- Dim graph As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(background)
- graph.DrawImage(img, position)
- Return background
- End Function
- '裁剪Bitmap
- 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
- Return New CroppedBitmap(img, New Int32Rect(x, y, width, height))
- End Function
- End Module '绘图
- 'Public Module FTP
- ' Public Function DownloadFTPFile(ByVal ftpclient As FTPDownloader, ByVal webPath As String, ByVal localPath As String)
- ' File.Delete(localPath)
- ' DownloadFTPFile = False
- ' Try
- ' If Not ftpclient.ftpIsLogin Then ftpclient.Login()
- ' If webPath.Contains("/") Then ftpclient.ChangeDirectory(Mid(webPath, 1, webPath.LastIndexOf("/")))
- ' ftpclient.DownloadFile(Mid(webPath, webPath.LastIndexOf("/") + 2), localPath)
- ' Return True
- ' Catch ex As Exception
- ' End Try
- ' End Function '直接下载单个文件
- ' Public Class FTPDownloader
- '#Region "变量声明"
- ' Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String
- ' Private m_sRemotePassword, m_sMess As String
- ' Private m_iRemotePort, m_iBytes As Int32
- ' Private m_objClientSocket As Socket
- ' Private m_iRetValue As Int32
- ' Public ftpIsLogin As Boolean
- ' Private m_sMes, m_sReply As String
- ' '设置用户来对FTP服务器读取和写入数据的数据包的大小
- ' Public Const BLOCK_SIZE = 512
- ' Private m_aBuffer(BLOCK_SIZE) As Byte
- ' Private ASCII As Encoding = Encoding.ASCII
- ' Public flag_bool As Boolean
- ' '普通变量定义
- ' Private m_sMessageString As String
- '#End Region
- '#Region "构造函数"
- ' Public Sub New()
- ' m_sRemoteHost = "localhost"
- ' m_sRemotePath = "."
- ' m_sRemoteUser = "anonymous"
- ' m_sRemotePassword = ""
- ' m_sMessageString = ""
- ' m_iRemotePort = 21
- ' ftpIsLogin = False
- ' End Sub
- ' Public Sub New(ByVal sRemoteHost As String, ByVal sRemotePath As String, ByVal sRemoteUser As String, ByVal sRemotePassword As String, ByVal iRemotePort As Int32)
- ' m_sRemoteHost = sRemoteHost
- ' m_sRemotePath = sRemotePath
- ' m_sRemoteUser = sRemoteUser
- ' m_sRemotePassword = sRemotePassword
- ' m_sMessageString = ""
- ' m_iRemotePort = iRemotePort
- ' ftpIsLogin = False
- ' End Sub
- '#End Region
- '#Region "属性"
- ' '设置或获取FTP服务器的名称
- ' Public Property RemoteHostFTPServer() As String
- ' Get
- ' Return m_sRemoteHost
- ' End Get
- ' Set(ByVal Value As String)
- ' m_sRemoteHost = Value
- ' End Set
- ' End Property
- ' '设置或获取FTP服务器的端口
- ' Public Property RemotePort() As Int32
- ' Get
- ' Return m_iRemotePort
- ' End Get
- ' Set(ByVal Value As Int32)
- ' m_iRemotePort = Value
- ' End Set
- ' End Property
- ' '设置或获取FTP服务器的远程路径
- ' Public Property RemotePath() As String
- ' Get
- ' Return m_sRemotePath
- ' End Get
- ' Set(ByVal Value As String)
- ' m_sRemotePath = Value
- ' End Set
- ' End Property
- ' '设置或获取FTP服务器的用户
- ' Public Property RemoteUser() As String
- ' Get
- ' Return m_sRemoteUser
- ' End Get
- ' Set(ByVal Value As String)
- ' m_sRemoteUser = Value
- ' End Set
- ' End Property
- ' '设置FTP服务器的密码
- ' Public Property RemotePassword() As String
- ' Get
- ' Return m_sRemotePassword
- ' End Get
- ' Set(ByVal Value As String)
- ' m_sRemotePassword = Value
- ' End Set
- ' End Property
- ' '设置信息
- ' Public Property MessageString() As String
- ' Get
- ' Return m_sMessageString
- ' End Get
- ' Set(ByVal Value As String)
- ' m_sMessageString = Value
- ' End Set
- ' End Property
- '#End Region
- ' '登录FTP服务器
- ' Public Function Login() As Boolean
- ' If ftpIsLogin Then Return True
- ' m_objClientSocket = _
- ' New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
- ' Dim ep As New IPEndPoint(Dns.GetHostEntry(m_sRemoteHost).AddressList(0), m_iRemotePort)
- ' Try
- ' m_objClientSocket.Connect(ep)
- ' Catch ex As Exception
- ' MessageString = m_sReply
- ' Throw New IOException("无法链接到FTP服务器。")
- ' End Try
- ' ReadReply()
- ' If (m_iRetValue <> 220) Then
- ' CloseConnection()
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' '为了发送一个对服务器的用户登录ID,发送一个FTP命令
- ' SendCommand("USER " & m_sRemoteUser)
- ' If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then
- ' Cleanup()
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' If (m_iRetValue <> 230) Then
- ' '为了发送一个对服务器的用户密码,发送一个FTP命令
- ' SendCommand("PASS " & m_sRemotePassword)
- ' If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then
- ' Cleanup()
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' End If
- ' ftpIsLogin = True
- ' '为了改变映射的远程服务器的文件夹的目录,调用用户定义的ChangeDirectory函数
- ' ChangeDirectory(m_sRemotePath)
- ' '返回最终结果
- ' Return ftpIsLogin
- ' End Function
- ' '获取文件列表
- ' Public Function GetFileList(ByVal sMask As String) As String()
- ' Dim cSocket As Socket
- ' Dim bytes As Int32
- ' Dim seperator As Char = ControlChars.Lf
- ' Dim mess() As String
- ' m_sMes = ""
- ' '检查是否登录
- ' If (Not (ftpIsLogin)) Then Login()
- ' cSocket = CreateDataSocket()
- ' '发送FTP命令
- ' SendCommand("NLST " & sMask)
- ' If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' m_sMes = ""
- ' Do While (True)
- ' Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
- ' bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
- ' m_sMes += ASCII.GetString(m_aBuffer, 0, bytes)
- ' If (bytes < m_aBuffer.Length) Then
- ' Exit Do
- ' End If
- ' Loop
- ' mess = m_sMes.Split(seperator)
- ' cSocket.Close()
- ' ReadReply()
- ' If (m_iRetValue <> 226) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' Return mess
- ' End Function
- ' '获取文件大小
- ' Public Function GetFileSize(ByVal sFileName As String) As Integer
- ' Dim size As Integer
- ' '检查是否登录
- ' If Not ftpIsLogin Then Login()
- ' '发送FTP命令
- ' SetBinaryMode(True)
- ' SendCommand("SIZE " & sFileName)
- ' size = 0
- ' If (m_iRetValue = 213) Then
- ' size = Int64.Parse(m_sReply.Substring(4))
- ' Else
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' Return size
- ' End Function
- ' '下载文件
- ' Public Sub DownloadFile(ByVal fileName As String, Optional ByVal localFile As String = "", Optional ByVal isResume As Boolean = False)
- ' Dim st As Stream
- ' Dim cSocket As Socket
- ' Dim offset, npos As Integer
- ' If Not ftpIsLogin Then Login() '检查是否登录
- ' SetBinaryMode(True) '设置下载模式
- ' '检查下载目录
- ' If localFile = "" Then localFile = fileName
- ' If Not (File.Exists(localFile)) Then
- ' st = File.Create(localFile)
- ' st.Close()
- ' End If
- ' '下载
- ' Using output As New FileStream(localFile, FileMode.Open)
- ' cSocket = CreateDataSocket()
- ' offset = 0
- ' If isResume Then
- ' offset = output.Length
- ' If offset > 0 Then
- ' '发送一个FTP命令重新启动
- ' SendCommand("REST " & offset)
- ' If (m_iRetValue <> 350) Then offset = 0
- ' npos = output.Seek(offset, SeekOrigin.Begin)
- ' End If
- ' End If
- ' '发送一个FTP命令重新找到一个文件
- ' SendCommand("RETR " & fileName)
- ' If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' Do While (True)
- ' Array.Clear(m_aBuffer, 0, m_aBuffer.Length)
- ' m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
- ' output.Write(m_aBuffer, 0, m_iBytes)
- ' If (m_iBytes <= 0) Then
- ' Exit Do
- ' End If
- ' Loop
- ' End Using
- ' If (cSocket.Connected) Then
- ' cSocket.Close()
- ' End If
- ' ReadReply()
- ' If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' End Sub
- ' '设置下载模式
- ' Public Sub SetBinaryMode(ByVal bMode As Boolean)
- ' '发送FTP命令,设置为二进制模式(True)或ASCII模式(False)
- ' SendCommand(If(bMode, "TYPE I", "TYPE A"))
- ' If (m_iRetValue <> 200) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' End Sub
- ' 'Dim str_file_path As String = "C:\test.txt" '要上传的文件名及路径
- ' 'Dim str_filename As String = IO.Path.GetFileName(str_file_path) '要上传的文件名
- ' 'Dim MyFileSize As Integer = FileLen(str_file_path) '要上传得文件大小
- ' 'If (ftpClient.Login() = True) Then
- ' ' '创建一个新文件夹
- ' ' ftpClient.CreateDirectory("FTPFOLDERNEW")
- ' ' '将新的文件夹设置为活动文件夹。
- ' ' ftpClient.ChangeDirectory("FTPFOLDERNEW")
- ' ' '设置FTP模式
- ' ' ftpClient.SetBinaryMode(True)
- ' ' '从你的硬盘上上载一个文件到FTP网页
- ' ' ftpClient.UploadFile(str_file_path)
- ' ' '获得刚刚上传的文件的大小
- ' ' Dim lng_filesize As Integer
- ' ' lng_filesize = ftpClient.GetFileSize(str_filename)
- ' ' If lng_filesize = MyFileSize Then
- ' ' MsgBox("成功上传文件" & str_filename & " 文件大小" & lng_filesize)
- ' ' Else
- ' ' MsgBox("上传失败")
- ' ' End If
- ' ' '对上载文件重命名
- ' ' 'ftpClient.RenameFile("SampleFile.xml", "SampleFile_new.xml")
- ' ' '删除一个文件
- ' ' 'ftpClient.DeleteFile("SampleFile_new.xml")
- ' ' ftpClient.CloseConnection()
- ' 'End If
- ' ''这是一个从你的本地硬盘上向你的FTP文件夹中上载文件的函数
- ' 'Public Sub UploadFile(ByVal sFileName As String)
- ' ' UploadFile(sFileName, False)
- ' 'End Sub
- ' ''这是一个从你的本地硬盘上向你的FTP网页上上载的函数和设置恢复标志
- ' 'Public Sub UploadFile(ByVal sFileName As String,
- ' ' ByVal bResume As Boolean)
- ' ' Dim cSocket As Socket
- ' ' Dim offset As Integer
- ' ' Dim input As FileStream
- ' ' Dim bFileNotFound As Boolean
- ' ' If (Not (ftpIsLogin)) Then
- ' ' Login()
- ' ' End If
- ' ' cSocket = CreateDataSocket()
- ' ' offset = 0
- ' ' If (bResume) Then
- ' ' Try
- ' ' SetBinaryMode(True)
- ' ' offset = GetFileSize(sFileName)
- ' ' Catch ex As Exception
- ' ' offset = 0
- ' ' End Try
- ' ' End If
- ' ' If (offset > 0) Then
- ' ' SendCommand("REST " & offset)
- ' ' If (m_iRetValue <> 350) Then
- ' ' '远程服务器可能不支持恢复。
- ' ' offset = 0
- ' ' End If
- ' ' End If
- ' ' '发送一个FTP命令,存储一个文件。
- ' ' SendCommand("STOR " & Path.GetFileName(sFileName))
- ' ' If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then
- ' ' MessageString = m_sReply
- ' ' Throw New IOException(m_sReply.Substring(4))
- ' ' End If
- ' ' '在上载之前,检查文件是否存在。
- ' ' bFileNotFound = False
- ' ' If (File.Exists(sFileName)) Then
- ' ' '打开输入流读取源文件
- ' ' input = New FileStream(sFileName, FileMode.Open)
- ' ' If (offset <> 0) Then
- ' ' input.Seek(offset, SeekOrigin.Begin)
- ' ' End If
- ' ' '上载这个文件
- ' ' m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
- ' ' Do While (m_iBytes > 0)
- ' ' cSocket.Send(m_aBuffer, m_iBytes, 0)
- ' ' m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)
- ' ' Loop
- ' ' input.Close()
- ' ' Else
- ' ' bFileNotFound = True
- ' ' End If
- ' ' If (cSocket.Connected) Then
- ' ' cSocket.Close()
- ' ' End If
- ' ' '如果找不到文件,检查返回值
- ' ' If (bFileNotFound) Then
- ' ' MessageString = m_sReply
- ' ' Throw New IOException("The file: " & sFileName & " was not found. " & _
- ' ' "Cannot upload the file to the FTP site")
- ' ' End If
- ' ' ReadReply()
- ' ' If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then
- ' ' MessageString = m_sReply
- ' ' Throw New IOException(m_sReply.Substring(4))
- ' ' End If
- ' 'End Sub
- ' ''从远程FTP服务器上删除一个文件。
- ' 'Public Function DeleteFile(ByVal sFileName As String) As Boolean
- ' ' Dim bResult As Boolean
- ' ' bResult = True
- ' ' If (Not (ftpIsLogin)) Then
- ' ' Login()
- ' ' End If
- ' ' '发送一个FTP命令,删除一个文件。
- ' ' SendCommand("DELE " & sFileName)
- ' ' If (m_iRetValue <> 250) Then
- ' ' bResult = False
- ' ' MessageString = m_sReply
- ' ' End If
- ' ' '返回最终结果
- ' ' Return bResult
- ' 'End Function
- ' ''在远程FTP服务器上重命名一个文件
- ' 'Public Function RenameFile(ByVal sOldFileName As String,
- ' 'ByVal sNewFileName As String) As Boolean
- ' ' Dim bResult As Boolean
- ' ' bResult = True
- ' ' If (Not (ftpIsLogin)) Then
- ' ' Login()
- ' ' End If
- ' ' '发送一个FTP命令,对一个文件重命名
- ' ' SendCommand("RNFR " & sOldFileName)
- ' ' If (m_iRetValue <> 350) Then
- ' ' MessageString = m_sReply
- ' ' Throw New IOException(m_sReply.Substring(4))
- ' ' End If
- ' ' '发送一个FTP命令,对一个文件更改为新名称
- ' ' '如果新的文件名存在,会被覆盖。
- ' ' SendCommand("RNTO " & sNewFileName)
- ' ' If (m_iRetValue <> 250) Then
- ' ' MessageString = m_sReply
- ' ' Throw New IOException(m_sReply.Substring(4))
- ' ' End If
- ' ' '返回最终结果
- ' ' Return bResult
- ' 'End Function
- ' ''这是一个在远程服务器上创建目录的函数
- ' 'Public Function CreateDirectory(ByVal sDirName As String) As Boolean
- ' ' Dim bResult As Boolean
- ' ' bResult = True
- ' ' If (Not (ftpIsLogin)) Then
- ' ' Login()
- ' ' End If
- ' ' '发送一个FTP命令,在FTP服务器上制作一个目录
- ' ' SendCommand("MKD " & sDirName)
- ' ' If (m_iRetValue <> 257) Then
- ' ' bResult = False
- ' ' MessageString = m_sReply
- ' ' End If
- ' ' '返回最终结果
- ' ' Return bResult
- ' 'End Function
- ' ''这是一个在远程FTP服务器上删除目录的函数
- ' 'Public Function RemoveDirectory(ByVal sDirName As String) As Boolean
- ' ' Dim bResult As Boolean
- ' ' bResult = True
- ' ' '检查是否已登录FTP服务器
- ' ' If (Not (ftpIsLogin)) Then
- ' ' Login()
- ' ' End If
- ' ' '发送一个FTP命令,删除在FTP服务器上的目录
- ' ' SendCommand("RMD " & sDirName)
- ' ' If (m_iRetValue <> 250) Then
- ' ' bResult = False
- ' ' MessageString = m_sReply
- ' ' End If
- ' ' '返回最终结果
- ' ' Return bResult
- ' 'End Function
- ' '改变当前工作目录
- ' Public Function ChangeDirectory(ByVal sDirName As String) As Boolean
- ' Dim bResult As Boolean
- ' bResult = True
- ' '检查你是否在根目录
- ' If (sDirName.Equals(".")) Then Return False
- ' '检查是否已登录FTP服务器
- ' If Not (ftpIsLogin) Then Login()
- ' '发送FTP命令,改变在FTP服务器上的目录。
- ' SendCommand("CWD " & sDirName)
- ' If (m_iRetValue <> 250) Then
- ' bResult = False
- ' MessageString = m_sReply
- ' End If
- ' Me.m_sRemotePath = sDirName
- ' '返回最终结果
- ' Return bResult
- ' End Function
- ' '关闭FTP链接
- ' Public Sub CloseConnection()
- ' If Not (m_objClientSocket Is Nothing) Then
- ' '发送一个FTP命令,结束FTP服务系统
- ' SendCommand("QUIT")
- ' End If
- ' Cleanup()
- ' End Sub
- '#Region "内部函数"
- ' '从FTP服务器得到回应。
- ' Private Sub ReadReply()
- ' m_sMes = ""
- ' m_sReply = ReadLine()
- ' m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3))
- ' End Sub
- ' '重置
- ' Private Sub Cleanup()
- ' If Not (m_objClientSocket Is Nothing) Then
- ' m_objClientSocket.Close()
- ' m_objClientSocket = Nothing
- ' End If
- ' ftpIsLogin = False
- ' End Sub
- ' '从FTP服务器读取一行
- ' Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String
- ' Dim seperator As Char = ControlChars.Lf
- ' Dim mess() As String
- ' If (bClearMes) Then
- ' m_sMes = ""
- ' End If
- ' Do While (True)
- ' Array.Clear(m_aBuffer, 0, BLOCK_SIZE)
- ' Try
- ' m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
- ' Catch ex As Exception
- ' Login()
- ' m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)
- ' End Try
- ' m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes)
- ' If (m_iBytes < m_aBuffer.Length) Then
- ' Exit Do
- ' End If
- ' Loop
- ' mess = m_sMes.Split(seperator)
- ' If (m_sMes.Length > 2) Then
- ' m_sMes = mess(mess.Length - 2)
- ' Else
- ' m_sMes = mess(0)
- ' End If
- ' If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then
- ' Return ReadLine(True)
- ' End If
- ' Return m_sMes
- ' End Function
- ' '向FTP服务器发送命令
- ' Private Sub SendCommand(ByVal command As String)
- ' command = command & ControlChars.CrLf
- ' Dim cmdbytes As Byte() = ASCII.GetBytes(command)
- ' m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0)
- ' ReadReply()
- ' End Sub
- ' '创建一个数据包
- ' Private Function CreateDataSocket() As Socket
- ' Dim index1, index2, len As Int32
- ' Dim partCount, i, port As Int32
- ' Dim ipData, buf, ipAddress As String
- ' Dim parts(6) As Int32
- ' Dim ch As Char
- ' Dim s As Socket
- ' Dim ep As IPEndPoint
- ' '发送一个FTP命令,用于被动数据链接
- ' SendCommand("PASV")
- ' If (m_iRetValue <> 227) Then
- ' MessageString = m_sReply
- ' Throw New IOException(m_sReply.Substring(4))
- ' End If
- ' index1 = m_sReply.IndexOf("(")
- ' index2 = m_sReply.IndexOf(")")
- ' ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1)
- ' len = ipData.Length
- ' partCount = 0
- ' buf = ""
- ' For i = 0 To ((len - 1) And partCount <= 6)
- ' ch = Char.Parse(ipData.Substring(i, 1))
- ' If (Char.IsDigit(ch)) Then
- ' buf += ch
- ' ElseIf (ch <> ",") Then
- ' MessageString = m_sReply
- ' Throw New IOException("Malformed PASV reply: " & m_sReply)
- ' End If
- ' If ((ch = ",") Or (i + 1 = len)) Then
- ' Try
- ' parts(partCount) = Int32.Parse(buf)
- ' partCount += 1
- ' buf = ""
- ' Catch ex As Exception
- ' MessageString = m_sReply
- ' Throw New IOException("Malformed PASV reply: " & m_sReply)
- ' End Try
- ' End If
- ' Next
- ' ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3)
- ' '在Visual Basic .Net 2002中进行调用。你想移动8位。在Visual Basic .NET 2002中,你必须将此数乘2的8次方。
- ' '端口=parts(4)*(2^8)
- ' '进行这个调用,并且用Visual Basic .NET 2003解释当前行。
- ' port = parts(4) << 8
- ' '确定数据端口数
- ' port = port + parts(5)
- ' s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
- ' ep = New IPEndPoint(Dns.GetHostEntry(ipAddress).AddressList(0), port)
- ' Try
- ' s.Connect(ep)
- ' Catch ex As Exception
- ' MessageString = m_sReply
- ' Throw New IOException("Cannot connect to remote server.")
- ' '如果你不能链接到特定的FTP服务器,也就是说,将其布尔值设置为False。
- ' flag_bool = False
- ' End Try
- ' '如果你能够链接到特定的FTP服务器,将布尔值设置为True。
- ' flag_bool = True
- ' Return s
- ' End Function
- '#End Region
- ' End Class
- 'End Module 'FTP协议下载
|