N~~oJuj$JpXv`d6H@C*9HPVV5F%j;5-+6UXYf(
z6bPIRJ}>i04y~gv04;sVWK3x})p9BYo9AC^o_}4|c{2%ZnU?uC<4Ms{W3W;Rywx)Q
zR_bqWoj9^?#~b&h9=q=Noz4H6-WyX}2JsH#9mRVJZw>ECmF;Ue9DF{D%)8|jgPLr)
z#>JKK6cYhz3|6LuJgjpHk1Tv#S$z}%2x-~iY{`%*3sOJCHvu`Ex$s;fC|!@yxEPYu
zHG*0eG7|0iM>Vapy%TqM*9h8d>^8dFcXW1a>+IUKYuk>Fo!#5^6uY{&wNLKo?A)Ul
zcXbvgadm_SI&kBJKf+m%F3sIEIKGgPwT0Vb4{oJ)!p_Xf1r}$pmOjT>a|_qe7C0JY
z<7{59pspxaiFS(IxZ_w}4vC6mPa#)CVqK0ll>VA&A+{#@229#>Owf&^X32FtXVT9_
z8%M2dI=LV-g`zOS#W
z*Sf&s$UKh8hTEn^$C@@R@=j=Qn-(S;J+@KvUEONa#%e{J1#UFv#+{Rf-BaAXTi;pQ
zxvOJO*AAn-d(Wl|8w-vyQJd&qXeUhL3)wvXv(5ik?dEQLy8HWo!e8!M4R0?ljC=Vv
zxP}K;my4c5g?z!j`_8B5zx1P#r&quFw)q#oxs}IkVDAKfS3VzINm_4M{(b!@xLcCmoX5{_*uiLiu_rhx
z%HKgRptIb0L{I|x=?hq_1;1%xFSxsBPgEgv*GNbObj*#{mbiUly>#AEcXr4+9Pb
zzt++Z;_rSK+>`{mf-*K^R*VPHUD_&<5acE82=;6jdQ9x!xUWEd!+SYDn`NzWaCJ~U
z@O8O!b4C_CkHx=?#UWsm4=K*yrY@psTFP)n6a4K!Zh|mQmr8#OptXw3XPU6|H1zH;Q1S3?2-U{@(xEqYTNbnBZd@yVy$gr&ipK%Xl4vo3Zqq{hhYqWir
z^mUNKl@Sd~u(sZFUKH2JJIw<
z+wVU8!+qDyRxE8MxSQ!|#m3sI8FtAjW83X%Jv=_Nt-Dp@%e%5};Y`%iI%jyT*X>`H
zUY6dchZjW}RM=imYt6OydWgvt-P=})w)<^3uhZ`q#%QM1GNhRAaVohZF_C>bu+rHog2<+P)jSzln{a!nE3b2Cj6xP|IhEA
G2mTv@+i6n(
literal 0
HcmV?d00001
diff --git a/Planifolia/bin/Debug/Planifolia.exe.config b/Planifolia/bin/Debug/Planifolia.exe.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/Planifolia/bin/Debug/Planifolia.exe.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Planifolia/bin/Debug/Planifolia.pdb b/Planifolia/bin/Debug/Planifolia.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..fdb7b05430398c92c580f9d77bbe4b85478cda7c
GIT binary patch
literal 32256
zcmeHP3vg6bnm#v#K#+$41dPD65XSIG=gA|i3Q3v}ga{7t9f#Z`H%X68cc!}ogc_yY
zaUDwM0kh1j%AHwvU6(3#XDP8nMTgpAEZJpuow0U`vYZ(h7)o|VM9ZpmrX1bxJCE+0
zOiv=oMSDAF|QZw
z+9(dK|Hqui4zF7KgEOapUa)J0ieK?}58YMJ@p{2a3xxP!?3$M*y*7X6fr2TuUwdTh
z#J~C8Q_}+42i`q<^pPb8H@;D7-~H_U?|-B6-_|ZU^o^IF_+jtP6VHvCSF}^J`Q#$A
zfLHzh*sBX3Kl0G~$uYm%cVFbWfBDrT4bz*ZKlgay!_P!t`T1Sz|K}oWwqG4>0k8VM
z`li3%_Qw4SUi|9oTju`XFArCq?0Dz6{ShpogHaM4;ITmKjO{eRK+
zm)8~ZYX9f&|Gn;+Pe-0t{qOJpKb`*aT8mfxKeOkJ9gqLX?yV`9xbM4-XHPF0A1-^l
z_^B86-1xJ%wnTQE_PXA_JZ~)ERsWCu-O1Ti$$Y!iguETOGTnyLo-o3B|)(oaRuht!J|nO(vRGhm#FG
ztR+I2heWY|eG
zf5Az_dg5(PqR$ZUsLn=7Jgvm@u@H|LB^#Y&G92x^pbbeF9bUI1*7~L9kki`J*&Mui
zRZ~5NjM%yaY7o`(0?uXc|oFYQdZ%yaY7?uIvDe|HUe*)QZ}o|~8bXL#@V
zaMDupvR}!|JU1_rJ`+GSL{Ka!pz`n2K!E9r$S0EW7?4@Pwqz_W#56IgfaO|{Xn2`F
zP81c~y0JHrbT*6GnQ*W!7Ku1*Nw}OuaJ7RCLAXs6_Q~Jejr~A0*%)hgB0@}d<%R5|
zP5ph+;`UZJ~@q6Hra`L6Mgb-4@cW$TNAKB+NO-%==0Zje%vT|DbC0a}-&dZw^A~Fl
z&dbkv@yY!y$P$ergghZ~VLaNCpI8DNJZ@`rv>wQ$$8~W0K
zKF>Qrex_u$(3{r9>~g%?XZCz^6&_=JJ
zeo2%ezu_@s23ctvnK48AQI0#0V{4Tv-__Ha(zbUrMN~<2IYQX
z3g|S@t3dO`Oq3fZCWyI`QqMM^@*9@)A(Tgq013!T(XP;&f=qEWC=h)vQgcAB0i6#z
z6Lcl$EYO=kXM-wTH$YzyxEiI2
zfI>#
z-JVL+>x;mezDr@O$#I9i6G)TegyWC;
zF&5K$5tTM6K<_CV&P(h6JsPj(mL<%bL*I(yGz#Ezki%dAl=JmkP>$m{pg=iZI4(IJ
zU_&_`Xd{k;Fet|XofpT!w?G$xJ_^cl@HA*S=nJ6i_hX=ypl^d#fqn$K7<3vc!2X#F
zx)ihuly11$=Rf&~lucw=(mArv--k^xrUaTS
z;ee(X&k`_>P+CBX+Ea6U?gIWR@KxY(;0M4fA)pwz&Im%956S|$AZGvHrHzvBG7iFd
zzZj+aK=1$0XFrRg65Q+NO5G3iIR?f-#Rh?BO<7a3&=fQ&QvSK$xaz&Z+bwt
z>k6exJ`v8F0VB&SwyUlulI)2)%v?U${_f9p%Y6uaj9YIJ_z3jH2F640T%#8!Om4mB
zv;Sb5sp~xmhW`?3ELfPI3fRA8IvjvM8H4b(psWk}0{&%|oXcjddJyTV-z?dOh)P+U
zy9D}P+6wbJg)t%5kO`nAh;#MiT3iguwHRT!79%WuGyJXe&1wyXBtQXHpR2?^V6hAr
zU^QjFX^-j~OPD@$w}*b3by4f0^3zH-eOg9_va^-8zgtF)mQf2z+th(78T7Fe1$`WC
z^+zfK1c2=bZv*ZE?gt(Pz6C_5i-89s~*3$Uw=|EFIi6e=R0
z7@K(qF)ld#M57&!g3#Zx++iSjP5$|u|G3X{%-PLQ&uQqN&Sy>H6vCPyeJK4vQ@RaS
zy6wzw01~d$bC~;D&f&?R^hJD+x*8Pw5coO1Lvc@23oMmB&&+L}Q4%=MtDwBW<2fva
z5Anf%H0zh~!NwO-Bz$k)LNLiDaQzB79X6IQ<_&lKGUM(|3Ip&R!N4TwU1IbG+vLIH
zaMmr=hU|WR2KtZfLtmmF)q8AzKVO7&RUa!|PnJPh2^JjNGm$}rKvgY+I9XCE^DtWM`4
z5#vwma<-;_(0q+Lf1i%ur}Izf_->v59i6^L)7?5B`vNJySM$x+^glJVH2)FJXK}y}
z0E6YTXuw?_@-+lV2P^N&M@=|7`U0vwAh^nB<#UxEq@`Jl_f51xmyIv{VVsjTnAc!5g>ixgTP(DM}d2R`+`gc
ze+B)h;^+Ch)$d^5lu>!Q3=ULg>oP5J&++Gn;-;L+*X61*b>lgb~HU^f+ez0rGDjr=HFC}gpkIG`>Q9|=pXY_Ckj-t)7
zya*dTibt2VGxp}VQ)M$Ro2HD)(`8zRH#*H4H#{kR>Ce&v0nAO#{cK?N2Hdxf1>aBQ
zJkG{>*`~4Smo*q4eNg(0z6V9dXQ({wGurz4vmE_WXm~l6a*RJ)mhnkU&z1fx^8(>6
zlWWSfXMFQlWEs8rN7(SIbX}hgt{D^MdWFuyXOFt|jSDxeiYDW|n>NJ4QTe8V!aiiR
z0O$DD{BjH35Btvi=5#S7IRh))RLu3SBXJSZk0ESe8UlDv0-QZ02_7GRtU{ESWqv%&{6K~Ym%SzW)X8tWm!$jdH&Di>r4Tn}|nCE%G68r-1nJBqr>
zrOQH#YcV(h1IwN)igks%Ab4Qe`pRI?99$+R5YlrtK|0z@}_{FOqaQy
zDC+9Us?a25uz}k&CGGELKu`bvxISb@J0rLslfLu2prWF(vZ}JRy~JL&xVogO+^#IC
zE^8|*sc!GE%gf3;%I)gKH;Se8wV|4d5Vn1y%xjw
zdZv3`?P1*9^|+1wug-cT-rQsNNZf$ewT1bOgPsN$!5TQ|739mwp~5D2M9@7!wf56C
z#u$cP14mMd!})vVO~2Bn#yT6n_7J5}TqIA3(nP$ivfY1@VS
zv4>Q9LA1a@cr85h3k&Zhn=zmLcMum&U)G;1c&u(1KOOM6CIeja=TeN#r`&o(9~qx^
z7u@ag(>2~jZMK+5431fN<2uMqIl(pexS?gO7WB!2Uj
zO6kFn>>Y3~9{~OsbDcZlDcAz2oiQSS!)VP;s4YggYXCflR_%w30C@QAItgq+d?gxi
z3Wy-@S@DjQG|W8E&jYUmQZ{!UY$#vk@O@1hjE3X>iUy;RXb>8S2BPt3eC~PpPQv{p
z_p@vd_iMO=$oq%9d&ql-yc;I#HWzdb@LFIIaHInVqz@z40$%<8*Z=YdluRD1yel6b*BtF+1mf6aKya1M%I7MtJ$hEQPnMWP0*-Rh-w$27
z((;%;Tv$1PfB?Qr4Heuad6vZUq9R}!@Ooequmua4d{*Dc=9%{P(~At8X9Z#`JvvhItZsxqtsx?Ht&@!@ED+>)0^NPk|w1d2)f{61)F%
zfiACHxa&l?`Dktnm>Yv5=*p6R{|9sSF9GlW+_CKW@6p#qAKdX`>f!%b_u{l;r^7$`
z!*>7vPv(E&4(Zwv)%vx5ATuVCx`Oh5Z_ODsj37R1oHoV@XY3X?*HJYh5SEF{GUwx|4jb
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
diff --git a/Planifolia/obj/Debug/DesignTimeResolveAssemblyReferences.cache b/Planifolia/obj/Debug/DesignTimeResolveAssemblyReferences.cache
new file mode 100644
index 0000000000000000000000000000000000000000..5b002f71b0d7c46b4343c72443cff49251a44214
GIT binary patch
literal 1195
zcmcK3u}%Xq3iN~zPLC{$P7n-x>fjW26-Am#bT?ahT*!xk8Vg>ohWzI6y-iQx4D1pA;n=ad?wil4X7Z~Qv>OFbLwCVD!VUf$&)
z%&Y|wY|&xdrwOkarr^aAJ8aYGyA0`vKX}H_(IC1e_L7#oHb{?
g!-_#5#3mwz|3gVr`plGy7}AP1gW|B0^G4EuU;dGe7ytkO
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Planifolia/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 0000000000000000000000000000000000000000..b2d3105205bf05d6c82eaf1dfa9960a7f44660e2
GIT binary patch
literal 7228
zcmeHMZBrXJ5Vm=_VDeH-Q<9J-aoV&^TK8&)5R%N~LxOR_lu!m!(ix5c`EG3#bdoFS
zFfPMy=`ZN?C$_uiH$n*Q2j5IS_!zInO4>)-TirdoPNh?+)IWI9H(i%TPy}zdua!|X
z>uz!rF;THmz?HkG!cfWO(o#OR3EFTapBEpy1^Ub979(LJ4bLS+Rx^>$twmMA{hy(=
zq4q&OuNLNN^R1_NG;$ssX!-M$A24mr6qkY7AYmERDtW^;g$6{QdcZ+UD9r
zuko`@-1rev?5>1u03eo60v~)#xwXs{A5ogqKQmIjt
zBk6S7!4JyR$e-htma!0Gc;fx_Ed`wW3M6RmyDR9d-Qw2PIYaP7Y%&qS8smERVQ*-~
zYA);fTxfiy1+Vtc*rWe_#1I4*2I!z(oZD&Q!I@DMlbJDUj*~z-kjh*@fnO6OG9)HR
zTtqSHTtb<0E~9vPwBBJ(&nifyn@oe(BfFlvy0p>bkokj0?tH#WKs#h}>G0UOf_9pV
z&%9p^vQMuHENXbaNGNH30A5M?Q3%o+?-jSNqpG*bBo~6Mut@rQpuIJLikcFfd8+!(
zD?v4?qcq4sH;^T*gHht3M~VBC$n_b{&wNHZnL;u9{$jh#pBC+8v45KSbG_Z~{NIM?GA972|E
z19`+D?!P+-w;=Juq{1R8_9|d4(l6s8n~xjLETXIq0_8=c;rekh;@m`=b+n1Vbxb^R
zaUPPpfB59_1Fv@ja-B$^W%VPb=im2Z$0H~Ahq;TDJ*FG6=e|U+odm$T1T_Y^g&@@g
zKzjUHLyU79acpupC1#mR0^^{cM#ji@lHFm9Oo5(5oV^5h2o0fH^uUOBbr;dLlS88o
zeT5K^97IVod{)%s-F%Huwd9~y!Md-lZ6B+9h_#;_)>|$E)iiEd>CnWR`vw77a)7^u
zB8K@kSsxP23YWhV))>7^hZJx~0S8*_7<2{|lad`QGKFS*$M8R3V&|Y;^~9dP$9iw5
z4~sy<3J=wLKU$1RBJKx$^9P*oZf#FYWWK|vUiZpUDnS)+=RS%`0+07Bis@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HYR*8GxXUf^%t3Noi54ZC+|=Nl{{sjzU0bQch;FcWPxwes*e}ZIZcpqG__J
onW3ezNveT`r81^vrFkWpxv4PQgHubGfR2KJ07n-P+5+SQ04Y>DD*ylh
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/Planifolia.Properties.Resources.resources b/Planifolia/obj/Debug/Planifolia.Properties.Resources.resources
new file mode 100644
index 0000000000000000000000000000000000000000..6c05a9776bd7cbae976fdcec7e3a254e93018279
GIT binary patch
literal 180
zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HYR*8GxXUf^%t3Noi54ZC+|=Nl{{sjzU0bQch;FcWPxwes*e}ZIZcpqG__J
onW3ezNveT`r81^vrFkWpxv4PQgHubGfR2KJ07n-P+5+SQ04Y>DD*ylh
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/Planifolia.csproj.AssemblyReference.cache b/Planifolia/obj/Debug/Planifolia.csproj.AssemblyReference.cache
new file mode 100644
index 0000000000000000000000000000000000000000..c463ee57aaee7786b53dfe08cab1e42d5df04689
GIT binary patch
literal 5927
zcmd5=&u`N(6pqEOsvDpImq{FY1PNI~8whqmqie;1RZ}wohoH$#oz7}vcecB(yX?%J
ze*=jde+DNw^QT~ENuf(56y+JMhboSvXTSHp?|XjUd)@cj2(5aahYs7@!M+qDNs?BV
z#ZRs5Fm%dLl*q5hO>mQd_d$wb{Vb9Pl5j;rTdGy1>@O=U
zLU%KRy=h`pJFI7HJu}wfn#ze}ikebz!a`cj>@q^Z3RMy6M-HJ*C$X3(lcYB{@%D<}%(`1ENwl}yhof&DU&7P2YHjPX$|Th59lbqLA}ze^Aa
z+EGAAaE?f*uB1qQhuuVvYWzm)vNOq*3$!yFkKN&TNv2BB+=SFuNYMaQGYFd9-U&^0
zR&2oHy5b7WScITz$Xb5Wk2XmgNK*cW6{W6MSDBks6qZ&Hd!
ze9)#D9%=V-gxChfKaT6&TtW1B#hf|p%WO|ulC;LajjM6G~n3O#yUJg{1!m
DD0>|8
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/Planifolia.csproj.CoreCompileInputs.cache b/Planifolia/obj/Debug/Planifolia.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..876886f
--- /dev/null
+++ b/Planifolia/obj/Debug/Planifolia.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+892380c4dcf55b90dcd2f55ac7afaebb31573f97
diff --git a/Planifolia/obj/Debug/Planifolia.csproj.FileListAbsolute.txt b/Planifolia/obj/Debug/Planifolia.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..71671e9
--- /dev/null
+++ b/Planifolia/obj/Debug/Planifolia.csproj.FileListAbsolute.txt
@@ -0,0 +1,10 @@
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\bin\Debug\Planifolia.exe.config
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\bin\Debug\Planifolia.exe
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\bin\Debug\Planifolia.pdb
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.csproj.AssemblyReference.cache
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.Planifolia.resources
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.Properties.Resources.resources
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.csproj.GenerateResource.cache
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.csproj.CoreCompileInputs.cache
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.exe
+C:\Users\beaup\OneDrive\Documents\GitHub\VanillaLauncher\Planifolia\obj\Debug\Planifolia.pdb
diff --git a/Planifolia/obj/Debug/Planifolia.csproj.GenerateResource.cache b/Planifolia/obj/Debug/Planifolia.csproj.GenerateResource.cache
new file mode 100644
index 0000000000000000000000000000000000000000..935d33378723447acd9ad1ca426053348fa98ad2
GIT binary patch
literal 1017
zcma)4!EVz)5VafIjgyqx2UH;tiVz2+L{_XSf=dK6RiUDl0;wtv2(Kw-FnYa7)%|6F<9Oo|veJMI?nBE_XOe>>uo9vWA
z^5lq_xk<)KL%(|r+6YyQ(qWP&gJjU}j!S7v4Wj}|tC{R~C*@3v>=mqz)EtV@Y_OdV
z^T&Cb^5KAOGoQ#F)pNW7^8$)pSVF;}$OISOf!xBtr;`;
zSImJEVpnL$tkSFQ)G`ZH+Cf0?g8?m=6rX^fDeyekc~F0g%ltHu8^YEI8#XA>ty{iN
z>lH?6o=;FYntGg$r21wHXPq?H|x0e&(C^TqhSBq
z`M+L2dD@~|wJI5O!LW(RB|)Tz0Qflvgt!c8Lqt#-M9{{xIgzXoxsrk<=#|r;gT*_j
zVhP%!N#3EaRH-vCRXZYzYKj}U2ybDE=wynBPN(pxm)0BPx=njnsw_%R(v}x~G+P&D
zT9FxhIi`Xw;O>>WWX2vUE^-0<_LUx-3S&)xHra5iYi}Y+NWy=AkAK{M{_~6Ll88!8
XOg++n^7YTR&(E+I6PzNZ9!2{ffa@Ah
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/Planifolia.exe b/Planifolia/obj/Debug/Planifolia.exe
new file mode 100644
index 0000000000000000000000000000000000000000..e44965ed2f74f95b16ca7631f4b380701bd4f848
GIT binary patch
literal 9728
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
G2mTv@+i6n(
literal 0
HcmV?d00001
diff --git a/Planifolia/obj/Debug/Planifolia.pdb b/Planifolia/obj/Debug/Planifolia.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..fdb7b05430398c92c580f9d77bbe4b85478cda7c
GIT binary patch
literal 32256
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
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4f64904
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# Vanilla
+ Vanilla, a launcher for an old brick-building game
+
+# License
+read license.md. if you modify Vanilla and intend on releasing it you must do so under the GPL v3 license.
diff --git a/VanillaLauncher.sln b/VanillaLauncher.sln
new file mode 100644
index 0000000..578ff3d
--- /dev/null
+++ b/VanillaLauncher.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.33920.266
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VanillaLauncher", "VanillaLauncher\VanillaLauncher.csproj", "{F60C2EED-2270-4387-90BF-A1DAE0AB3236}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aphylla", "AssetDownloader\Aphylla.csproj", "{50457F32-C740-4417-B6D1-5E746A3E645F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F60C2EED-2270-4387-90BF-A1DAE0AB3236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F60C2EED-2270-4387-90BF-A1DAE0AB3236}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F60C2EED-2270-4387-90BF-A1DAE0AB3236}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F60C2EED-2270-4387-90BF-A1DAE0AB3236}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50457F32-C740-4417-B6D1-5E746A3E645F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50457F32-C740-4417-B6D1-5E746A3E645F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50457F32-C740-4417-B6D1-5E746A3E645F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50457F32-C740-4417-B6D1-5E746A3E645F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4E8CF918-533A-42F2-9DB3-16B48D05AAE2}
+ EndGlobalSection
+EndGlobal
diff --git a/VanillaLauncher/.gitattributes b/VanillaLauncher/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/VanillaLauncher/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/VanillaLauncher/.gitignore b/VanillaLauncher/.gitignore
new file mode 100644
index 0000000..f94123a
--- /dev/null
+++ b/VanillaLauncher/.gitignore
@@ -0,0 +1,2 @@
+VanillaLauncher/bin
+VanillaLauncher/obj
diff --git a/VanillaLauncher/App.config b/VanillaLauncher/App.config
new file mode 100644
index 0000000..85d8705
--- /dev/null
+++ b/VanillaLauncher/App.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VanillaLauncher/Classes/App.config b/VanillaLauncher/Classes/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/VanillaLauncher/Classes/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VanillaLauncher/Classes/ColorLoader.cs b/VanillaLauncher/Classes/ColorLoader.cs
new file mode 100644
index 0000000..81f427f
--- /dev/null
+++ b/VanillaLauncher/Classes/ColorLoader.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace VanillaLauncher.Classes
+{
+ class ColorLoader
+ {
+ void loadFile()
+ {
+ var filepath = "files\\colors.txt";
+ }
+
+ }
+}
diff --git a/VanillaLauncher/Classes/RichPresence.cs b/VanillaLauncher/Classes/RichPresence.cs
new file mode 100644
index 0000000..bf69410
--- /dev/null
+++ b/VanillaLauncher/Classes/RichPresence.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DiscordRPC;
+
+namespace VanillaLauncher.Classes
+{
+
+ class RichPresence
+ {
+ public DiscordRpcClient client;
+
+ public string Details { get; private set; }
+ public string State { get; private set; }
+
+ void Start()
+ {
+
+ }
+ }
+}
diff --git a/VanillaLauncher/Classes/SOAP.cs b/VanillaLauncher/Classes/SOAP.cs
new file mode 100644
index 0000000..cccda58
--- /dev/null
+++ b/VanillaLauncher/Classes/SOAP.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+//using System.Net.Http;
+using System.Net;
+using System.Xml;
+using System.Data;
+using System.IO;
+namespace VanillaLauncher.Classes
+{
+ class SOAP
+ {
+ public static void Execute(string Client)
+ {
+ HttpWebRequest httpWebRequest = CreateWebRequest();
+ httpWebRequest.Timeout = 1000;
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.LoadXml(File.ReadAllText("clients\\" + Client + "\\RCC\\SOAP.xml"));
+ using (Stream outStream = httpWebRequest.GetRequestStream())
+ {
+ xmlDocument.Save(outStream);
+ }
+ // have to get response for some reason, but it errors or times out so we do this
+ try
+ {
+ using (WebResponse webResponse = httpWebRequest.GetResponse())
+ {
+ }
+ }
+ catch
+ {
+ return;
+ }
+
+ }
+
+ public static HttpWebRequest CreateWebRequest()
+ {
+ HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:64989");
+ httpWebRequest.Headers.Add("SOAP:Action");
+ httpWebRequest.ContentType = "application/xml;charset=\"utf-8\"";
+ httpWebRequest.Accept = "*/*";
+ httpWebRequest.Method = "POST";
+ return httpWebRequest;
+ }
+ }
+}
diff --git a/VanillaLauncher/DarkMode/DarkModeCS.cs b/VanillaLauncher/DarkMode/DarkModeCS.cs
new file mode 100644
index 0000000..6ccf5da
--- /dev/null
+++ b/VanillaLauncher/DarkMode/DarkModeCS.cs
@@ -0,0 +1,1145 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace BlueMystic
+{
+ /// This tries to automatically apply Windows Dark Mode (if enabled) to a Form.
+ /// Author: Blue Mystic - 2024
+ public class DarkModeCS
+ {
+ #region Win32 API Declarations
+
+
+ public struct DWMCOLORIZATIONcolors
+ {
+ public uint ColorizationColor,
+ ColorizationAfterglow,
+ ColorizationColorBalance,
+ ColorizationAfterglowBalance,
+ ColorizationBlurBalance,
+ ColorizationGlassReflectionIntensity,
+ ColorizationOpaqueBlend;
+ }
+
+ [Flags]
+ public enum DWMWINDOWATTRIBUTE : uint
+ {
+ ///
+ /// Use with DwmGetWindowAttribute. Discovers whether non-client rendering is enabled. The retrieved value is of type BOOL. TRUE if non-client rendering is enabled; otherwise, FALSE.
+ ///
+ DWMWA_NCRENDERING_ENABLED = 1,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Sets the non-client rendering policy. The pvAttribute parameter points to a value from the DWMNCRENDERINGPOLICY enumeration.
+ ///
+ DWMWA_NCRENDERING_POLICY,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Enables or forcibly disables DWM transitions. The pvAttribute parameter points to a value of type BOOL. TRUE to disable transitions, or FALSE to enable transitions.
+ ///
+ DWMWA_TRANSITIONS_FORCEDISABLED,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Enables content rendered in the non-client area to be visible on the frame drawn by DWM. The pvAttribute parameter points to a value of type BOOL. TRUE to enable content rendered in the non-client area to be visible on the frame; otherwise, FALSE.
+ ///
+ DWMWA_ALLOW_NCPAINT,
+
+ ///
+ /// Use with DwmGetWindowAttribute. Retrieves the bounds of the caption button area in the window-relative space. The retrieved value is of type RECT. If the window is minimized or otherwise not visible to the user, then the value of the RECT retrieved is undefined. You should check whether the retrieved RECT contains a boundary that you can work with, and if it doesn't then you can conclude that the window is minimized or otherwise not visible.
+ ///
+ DWMWA_CAPTION_BUTTON_BOUNDS,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Specifies whether non-client content is right-to-left (RTL) mirrored. The pvAttribute parameter points to a value of type BOOL. TRUE if the non-client content is right-to-left (RTL) mirrored; otherwise, FALSE.
+ ///
+ DWMWA_NONCLIENT_RTL_LAYOUT,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Forces the window to display an iconic thumbnail or peek representation (a static bitmap), even if a live or snapshot representation of the window is available. This value is normally set during a window's creation, and not changed throughout the window's lifetime. Some scenarios, however, might require the value to change over time. The pvAttribute parameter points to a value of type BOOL. TRUE to require a iconic thumbnail or peek representation; otherwise, FALSE.
+ ///
+ DWMWA_FORCE_ICONIC_REPRESENTATION,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Sets how Flip3D treats the window. The pvAttribute parameter points to a value from the DWMFLIP3DWINDOWPOLICY enumeration.
+ ///
+ DWMWA_FLIP3D_POLICY,
+
+ ///
+ /// Use with DwmGetWindowAttribute. Retrieves the extended frame bounds rectangle in screen space. The retrieved value is of type RECT.
+ ///
+ DWMWA_EXTENDED_FRAME_BOUNDS,
+
+ ///
+ /// Use with DwmSetWindowAttribute. The window will provide a bitmap for use by DWM as an iconic thumbnail or peek representation (a static bitmap) for the window. DWMWA_HAS_ICONIC_BITMAP can be specified with DWMWA_FORCE_ICONIC_REPRESENTATION. DWMWA_HAS_ICONIC_BITMAP normally is set during a window's creation and not changed throughout the window's lifetime. Some scenarios, however, might require the value to change over time. The pvAttribute parameter points to a value of type BOOL. TRUE to inform DWM that the window will provide an iconic thumbnail or peek representation; otherwise, FALSE. Windows Vista and earlier: This value is not supported.
+ ///
+ DWMWA_HAS_ICONIC_BITMAP,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Do not show peek preview for the window. The peek view shows a full-sized preview of the window when the mouse hovers over the window's thumbnail in the taskbar. If this attribute is set, hovering the mouse pointer over the window's thumbnail dismisses peek (in case another window in the group has a peek preview showing). The pvAttribute parameter points to a value of type BOOL. TRUE to prevent peek functionality, or FALSE to allow it. Windows Vista and earlier: This value is not supported.
+ ///
+ DWMWA_DISALLOW_PEEK,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Prevents a window from fading to a glass sheet when peek is invoked. The pvAttribute parameter points to a value of type BOOL. TRUE to prevent the window from fading during another window's peek, or FALSE for normal behavior. Windows Vista and earlier: This value is not supported.
+ ///
+ DWMWA_EXCLUDED_FROM_PEEK,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Cloaks the window such that it is not visible to the user. The window is still composed by DWM. Using with DirectComposition: Use the DWMWA_CLOAK flag to cloak the layered child window when animating a representation of the window's content via a DirectComposition visual that has been associated with the layered child window. For more details on this usage case, see How to animate the bitmap of a layered child window. Windows 7 and earlier: This value is not supported.
+ ///
+ DWMWA_CLOAK,
+
+ ///
+ /// Use with DwmGetWindowAttribute. If the window is cloaked, provides one of the following values explaining why. DWM_CLOAKED_APP (value 0x0000001). The window was cloaked by its owner application. DWM_CLOAKED_SHELL(value 0x0000002). The window was cloaked by the Shell. DWM_CLOAKED_INHERITED(value 0x0000004). The cloak value was inherited from its owner window. Windows 7 and earlier: This value is not supported.
+ ///
+ DWMWA_CLOAKED,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Freeze the window's thumbnail image with its current visuals. Do no further live updates on the thumbnail image to match the window's contents. Windows 7 and earlier: This value is not supported.
+ ///
+ DWMWA_FREEZE_REPRESENTATION,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Enables a non-UWP window to use host backdrop brushes. If this flag is set, then a Win32 app that calls Windows::UI::Composition APIs can build transparency effects using the host backdrop brush (see Compositor.CreateHostBackdropBrush). The pvAttribute parameter points to a value of type BOOL. TRUE to enable host backdrop brushes for the window, or FALSE to disable it. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_USE_HOSTBACKDROPBRUSH,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled. For compatibility reasons, all windows default to light mode regardless of the system setting. The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode. This value is supported starting with Windows 10 Build 17763.
+ ///
+ DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled. For compatibility reasons, all windows default to light mode regardless of the system setting. The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Specifies the rounded corner preference for a window. The pvAttribute parameter points to a value of type DWM_WINDOW_CORNER_PREFERENCE. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_WINDOW_CORNER_PREFERENCE = 33,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Specifies the color of the window border. The pvAttribute parameter points to a value of type COLORREF. The app is responsible for changing the border color according to state changes, such as a change in window activation. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_BORDER_COLOR,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Specifies the color of the caption. The pvAttribute parameter points to a value of type COLORREF. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_CAPTION_COLOR,
+
+ ///
+ /// Use with DwmSetWindowAttribute. Specifies the color of the caption text. The pvAttribute parameter points to a value of type COLORREF. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_TEXT_COLOR,
+
+ ///
+ /// Use with DwmGetWindowAttribute. Retrieves the width of the outer border that the DWM would draw around this window. The value can vary depending on the DPI of the window. The pvAttribute parameter points to a value of type UINT. This value is supported starting with Windows 11 Build 22000.
+ ///
+ DWMWA_VISIBLE_FRAME_BORDER_THICKNESS,
+
+ ///
+ /// The maximum recognized DWMWINDOWATTRIBUTE value, used for validation purposes.
+ ///
+ DWMWA_LAST,
+ }
+
+ [Flags]
+ public enum DWM_WINDOW_CORNER_PREFERENCE
+ {
+ DWMWCP_DEFAULT = 0,
+ DWMWCP_DONOTROUND = 1,
+ DWMWCP_ROUND = 2,
+ DWMWCP_ROUNDSMALL = 3
+ }
+
+
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public Rectangle ToRectangle()
+ {
+ return Rectangle.FromLTRB(Left, Top, Right, Bottom);
+ }
+ }
+
+ public const int EM_SETCUEBANNER = 5377;
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public extern static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
+
+
+ [DllImport("DwmApi")]
+ public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, int[] attrValue, int attrSize);
+
+ [DllImport("dwmapi.dll")]
+ public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute);
+
+ [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
+ private extern static int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
+
+ [DllImport("dwmapi.dll", EntryPoint = "#127")]
+ public static extern void DwmGetColorizationParameters(ref DWMCOLORIZATIONcolors colors);
+
+ [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
+ private static extern IntPtr CreateRoundRectRgn
+ (
+ int nLeftRect, // x-coordinate of upper-left corner
+ int nTopRect, // y-coordinate of upper-left corner
+ int nRightRect, // x-coordinate of lower-right corner
+ int nBottomRect, // y-coordinate of lower-right corner
+ int nWidthEllipse, // height of ellipse
+ int nHeightEllipse // width of ellipse
+ );
+
+ #endregion
+
+ #region Public Members
+
+ /// 'true' if Dark Mode Color is set in Windows's Settings.
+ public bool IsDarkMode { get; set; } = false;
+
+ /// Option to re-colorize all Icons in Toolbars and Menus.
+ public bool ColorizeIcons { get; set; } = true;
+
+ /// Option to make all Panels Borders Rounded
+ public bool RoundedPanels { get; set; } = false;
+
+ /// The PArent form for them all.
+ public Form OwnerForm { get; set; }
+
+ /// Windows Colors. Can be customized.
+ public OSThemeColors OScolors { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ /// This tries to automatically apply Windows Dark Mode (if enabled) to a Form.
+ /// The Form to become Dark
+ public DarkModeCS(Form _Form)
+ {
+ OwnerForm = _Form;
+ IsDarkMode = GetWindowsColorMode() <= 0 ? true : false;
+ OScolors = GetSystemColors(OwnerForm);
+
+ if (IsDarkMode && OScolors != null)
+ {
+ if (OwnerForm != null && OwnerForm.Controls != null)
+ {
+ foreach (Control _control in OwnerForm.Controls)
+ {
+ ThemeControl(_control);
+ }
+ OwnerForm.ControlAdded += (object sender, ControlEventArgs e) =>
+ {
+ ThemeControl(e.Control);
+ };
+ }
+ }
+ }
+
+ /// This tries to automatically apply Windows Dark Mode (if enabled) to a Form.
+ /// The Form to become Dark
+ /// [OPTIONAL] re-colorize all Icons in Toolbars and Menus.
+ /// [OPTIONAL] make all Panels Borders Rounded
+ public DarkModeCS(Form _Form, bool _ColorizeIcons = true, bool _RoundedPanels = false)
+ {
+ //Sets the Properties:
+ OwnerForm = _Form;
+ ColorizeIcons = _ColorizeIcons;
+ RoundedPanels = _RoundedPanels;
+ IsDarkMode = GetWindowsColorMode() <= 0 ? true : false;
+ OScolors = GetSystemColors(OwnerForm);
+
+ if (IsDarkMode && OScolors != null)
+ {
+ if (OwnerForm != null && OwnerForm.Controls != null)
+ {
+ foreach (Control _control in OwnerForm.Controls)
+ {
+ ThemeControl(_control);
+ }
+ OwnerForm.ControlAdded += (object sender, ControlEventArgs e) =>
+ {
+ ThemeControl(e.Control);
+ };
+ }
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// Recursively apply the Colors from 'OScolors' to the Control and all its childs.
+ /// Can be a Form or any Winforms Control.
+ public void ThemeControl(Control control)
+ {
+ BorderStyle BStyle = (IsDarkMode ? BorderStyle.FixedSingle : BorderStyle.Fixed3D);
+ FlatStyle FStyle = (IsDarkMode ? FlatStyle.Flat : FlatStyle.Standard);
+
+ //Change the Colors only if its the default ones, this allows the user to set own colors:
+ if (control.BackColor == SystemColors.Control || control.BackColor == SystemColors.Window)
+ {
+ control.GetType().GetProperty("BackColor")?.SetValue(control, OScolors.Control);
+ }
+ if (control.ForeColor == SystemColors.ControlText || control.ForeColor == SystemColors.WindowText)
+ {
+ control.GetType().GetProperty("ForeColor")?.SetValue(control, OScolors.TextActive);
+ }
+ control.GetType().GetProperty("BorderStyle")?.SetValue(control, BStyle);
+
+ control.HandleCreated += (object sender, EventArgs e) =>
+ {
+ ApplySystemDarkTheme(control);
+ };
+ control.ControlAdded += (object sender, ControlEventArgs e) =>
+ {
+ ThemeControl(e.Control);
+ };
+
+ if (control is TextBox tb)
+ {
+ //SetRoundBorders(tb, 4, OScolors.SurfaceDark, 1);
+ }
+ if (control is Panel panel)
+ {
+ // Process the panel within the container
+ panel.BackColor = OScolors.Surface;
+ panel.BorderStyle = BorderStyle.None;
+
+ if ( !(panel.Parent is TabControl) || !(panel.Parent is TableLayoutPanel))
+ {
+ if (RoundedPanels)
+ {
+ SetRoundBorders(panel, 6, OScolors.SurfaceDark, 1);
+ }
+ }
+ }
+ if (control is GroupBox group)
+ {
+ group.BackColor = group.Parent.BackColor;
+ group.ForeColor = OScolors.TextInactive;
+ }
+ if (control is TableLayoutPanel table)
+ {
+ // Process the panel within the container
+ table.BackColor = table.Parent.BackColor;
+ table.BorderStyle = BorderStyle.None;
+ }
+ if (control is TabControl tab)
+ {
+ tab.Appearance = TabAppearance.Normal;
+ tab.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed;
+ tab.DrawItem += (object sender, DrawItemEventArgs e) =>
+ {
+ //Draw the background of the main control
+ using (SolidBrush backColor = new SolidBrush(tab.Parent.BackColor))
+ {
+ e.Graphics.FillRectangle(backColor, tab.ClientRectangle);
+ }
+
+ using (Brush tabBack = new SolidBrush(OScolors.Surface))
+ {
+ for (int i = 0; i < tab.TabPages.Count; i++)
+ {
+ TabPage tabPage = tab.TabPages[i];
+ tabPage.BackColor = OScolors.Surface;
+ tabPage.BorderStyle = BorderStyle.FixedSingle;
+ tabPage.ControlAdded += (object _s, ControlEventArgs _e) =>
+ {
+ ThemeControl(_e.Control);
+ };
+
+ var tBounds = e.Bounds;
+ //tBounds.Inflate(100, 100);
+
+ bool IsSelected = (tab.SelectedIndex == i);
+ if (IsSelected)
+ {
+ e.Graphics.FillRectangle(tabBack, tBounds);
+ TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font, e.Bounds, OScolors.TextActive);
+ }
+ else
+ {
+ TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font, tab.GetTabRect(i), OScolors.TextInactive);
+ }
+ }
+ }
+ };
+
+ }
+ if (control is FlatTabControl fTab)
+ {
+ fTab.BackColor = OScolors.Background;
+ fTab.TabColor = OScolors.Surface;
+ fTab.SelectTabColor = OScolors.Control;
+ fTab.SelectedForeColor = OScolors.TextActive;
+ fTab.BorderColor = OScolors.Background;
+ fTab.ForeColor = OScolors.TextInactive;
+ fTab.LineColor = OScolors.Background;
+ }
+ if (control is PictureBox pic)
+ {
+ pic.BorderStyle = BorderStyle.None;
+ pic.BackColor = pic.Parent.BackColor;
+ }
+ if (control is Button button)
+ {
+ button.FlatStyle = FStyle;
+ button.FlatAppearance.CheckedBackColor = OScolors.Accent;
+ button.BackColor = OScolors.Control;
+ button.FlatAppearance.BorderColor = (OwnerForm.AcceptButton == button) ?
+ OScolors.Accent : OScolors.Control;
+ //SetRoundBorders(button, 4, OScolors.SurfaceDark, 1);
+ }
+ if (control is Label label)
+ {
+ label.BorderStyle = BorderStyle.None;
+ }
+ if (control is LinkLabel link)
+ {
+ link.LinkColor = OScolors.AccentLight;
+ link.VisitedLinkColor = OScolors.Primary;
+ }
+ if (control is CheckBox chk)
+ {
+ chk.BackColor = chk.Parent.BackColor;
+ }
+ if (control is RadioButton opt)
+ {
+ opt.BackColor = opt.Parent.BackColor;
+ }
+ if (control is ComboBox combo)
+ {
+ combo.FlatStyle = FStyle;
+ combo.BackColor = OScolors.Control;
+ control.GetType().GetProperty("ButtonColor")?.SetValue(control, OScolors.Surface);
+ combo.Invalidate();
+ }
+ if (control is MenuStrip menu)
+ {
+ menu.RenderMode = ToolStripRenderMode.Professional;
+ menu.Renderer = new MyRenderer(new CustomColorTable(OScolors), ColorizeIcons)
+ {
+ MyColors = OScolors
+ };
+ }
+ if (control is ToolStrip toolBar)
+ {
+ toolBar.GripStyle = ToolStripGripStyle.Hidden;
+ toolBar.RenderMode = ToolStripRenderMode.Professional;
+ toolBar.Renderer = new MyRenderer(new CustomColorTable(OScolors), ColorizeIcons) { MyColors = OScolors };
+ }
+ if (control is ContextMenuStrip cMenu)
+ {
+ cMenu.RenderMode = ToolStripRenderMode.Professional;
+ cMenu.Renderer = new MyRenderer(new CustomColorTable(OScolors), ColorizeIcons) { MyColors = OScolors };
+ }
+ if (control is DataGridView grid)
+ {
+ grid.EnableHeadersVisualStyles = false;
+ grid.BorderStyle = BorderStyle.FixedSingle;
+ grid.BackgroundColor = OScolors.Control;
+ grid.GridColor = OScolors.Control;
+
+ grid.DefaultCellStyle.BackColor = OScolors.Surface;
+ grid.DefaultCellStyle.ForeColor = OScolors.TextActive;
+
+
+ grid.ColumnHeadersDefaultCellStyle.BackColor = OScolors.Surface;
+ grid.ColumnHeadersDefaultCellStyle.ForeColor = OScolors.TextActive;
+ grid.ColumnHeadersDefaultCellStyle.SelectionBackColor = OScolors.Accent;
+ grid.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
+ grid.ColumnHeadersHeight = 140;
+
+ grid.RowHeadersDefaultCellStyle.BackColor = OScolors.Surface;
+ grid.RowHeadersDefaultCellStyle.ForeColor = OScolors.TextActive;
+ grid.RowHeadersDefaultCellStyle.SelectionBackColor = OScolors.Accent;
+ grid.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
+ }
+ if (control is PropertyGrid pGrid)
+ {
+ pGrid.BackColor = OScolors.Control;
+ pGrid.ViewBackColor = OScolors.Control;
+ pGrid.LineColor = OScolors.Surface;
+ pGrid.ViewForeColor = OScolors.TextActive;
+ pGrid.ViewBorderColor = OScolors.ControlDark;
+ pGrid.CategoryForeColor = OScolors.TextActive;
+ pGrid.CategorySplitterColor = OScolors.ControlLight;
+ }
+ if (control is TreeView tree)
+ {
+ tree.BorderStyle = BorderStyle.None;
+ tree.BackColor = OScolors.Surface;
+ }
+
+ if (control.ContextMenuStrip != null)
+ ThemeControl(control.ContextMenuStrip);
+
+ foreach (Control childControl in control.Controls)
+ {
+ // Recursively process its children
+ ThemeControl(childControl);
+ }
+ }
+
+ /// Returns Windows Color Mode for Applications.
+ /// 0=dark theme, 1=light theme
+ ///
+ public static int GetWindowsColorMode(bool GetSystemColorModeInstead = false)
+ {
+ try
+ {
+ return (int)Microsoft.Win32.Registry.GetValue(
+ @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize",
+ GetSystemColorModeInstead ? "SystemUsesLightTheme" : "AppsUseLightTheme",
+ -1);
+ }
+ catch
+ {
+ return 1;
+ }
+ }
+
+ /// Returns the Accent Color used by Windows.
+ /// a Color
+ public static Color GetWindowsAccentColor()
+ {
+ DWMCOLORIZATIONcolors colors = new DWMCOLORIZATIONcolors();
+ DwmGetColorizationParameters(ref colors);
+
+ //get the theme --> only if Windows 10 or newer
+ if (IsWindows10orGreater())
+ {
+ var opaque = true;
+ var color = (int)colors.ColorizationColor;
+
+ return Color.FromArgb((byte)(opaque ? 255 : (color >> 24) & 0xff),
+ (byte)((color >> 16) & 0xff),
+ (byte)((color >> 8) & 0xff),
+ (byte)(color) & 0xff);
+ }
+ else
+ {
+ return Color.CadetBlue;
+ }
+ }
+
+ /// Returns Windows's System Colors for UI components following Google Material Design concepts.
+ /// [OPTIONAL] Applies DarkMode (if set) to this Window Title and Background.
+ /// List of Colors: Background, OnBackground, Surface, OnSurface, Primary, OnPrimary, Secondary, OnSecondary
+ public static OSThemeColors GetSystemColors(Form Window = null)
+ {
+ OSThemeColors _ret = new OSThemeColors();
+
+ bool IsDarkMode = (GetWindowsColorMode() <= 0); //<- O: DarkMode, 1: LightMode
+ if (IsDarkMode)
+ {
+ _ret.Background = Color.FromArgb(32, 32, 32); //<- Negro Claro
+ _ret.BackgroundDark = Color.FromArgb(18, 18, 18);
+ _ret.BackgroundLight = ControlPaint.Light(_ret.Background);
+
+ _ret.Surface = Color.FromArgb(43, 43, 43); //<- Gris Oscuro
+ _ret.SurfaceLight = Color.FromArgb(50, 50, 50);
+ _ret.SurfaceDark = Color.FromArgb(29, 29, 29);
+
+ _ret.TextActive = Color.White;
+ _ret.TextInactive = Color.FromArgb(176, 176, 176); //<- Blanco Palido
+ _ret.TextInAccent = GetReadableColor(_ret.Accent);
+
+ _ret.Control = Color.FromArgb(55, 55, 55); //<- Gris Oscuro
+ _ret.ControlDark = ControlPaint.Dark(_ret.Control);
+ _ret.ControlLight = Color.FromArgb(67, 67, 67);
+
+ _ret.Primary = Color.FromArgb(3, 218, 198); //<- Verde Pastel
+ _ret.Secondary = Color.MediumSlateBlue; //<- Magenta Claro
+
+ //Apply Window's Dark Mode to the Form's Title bar
+ if (Window != null)
+ {
+ //SetWin32ApiTheme(Window);
+ ApplySystemDarkTheme(Window);
+
+ Window.BackColor = _ret.Background;
+ Window.ForeColor = _ret.TextInactive;
+ }
+ }
+
+ return _ret;
+ }
+
+ /// Apply Round Corners to the indicated Control or Form.
+ /// the one who will have rounded Corners. Set BorderStyle = None.
+ /// Radious for the Corners
+ /// Color for the Border
+ /// Size in pixels of the border line
+ ///
+ public static void SetRoundBorders(Control _Control, int Radius = 10, Color? borderColor = null, int borderSize = 2, bool underlinedStyle = false)
+ {
+ try
+ {
+ borderColor = borderColor ?? Color.MediumSlateBlue;
+
+ if (_Control != null)
+ {
+ _Control.GetType().GetProperty("BorderStyle")?.SetValue(_Control, BorderStyle.None);
+ _Control.Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, _Control.Width, _Control.Height, Radius, Radius));
+ _Control.Paint += (object sender, PaintEventArgs e) =>
+ {
+ //base.OnPaint(e);
+ Graphics graph = e.Graphics;
+
+ if (Radius > 1)//Rounded TextBox
+ {
+ //-Fields
+ var rectBorderSmooth = _Control.ClientRectangle;
+ var rectBorder = Rectangle.Inflate(rectBorderSmooth, -borderSize, -borderSize);
+ int smoothSize = borderSize > 0 ? borderSize : 1;
+
+ using (GraphicsPath pathBorderSmooth = GetFigurePath(rectBorderSmooth, Radius))
+ using (GraphicsPath pathBorder = GetFigurePath(rectBorder, Radius - borderSize))
+ using (Pen penBorderSmooth = new Pen(_Control.Parent.BackColor, smoothSize))
+ using (Pen penBorder = new Pen((Color)borderColor, borderSize))
+ {
+ //-Drawing
+ _Control.Region = new Region(pathBorderSmooth);//Set the rounded region of UserControl
+ if (Radius > 15) //Set the rounded region of TextBox component
+ {
+ using (GraphicsPath pathTxt = GetFigurePath(_Control.ClientRectangle, borderSize * 2))
+ {
+ _Control.Region = new Region(pathTxt);
+ }
+ }
+ graph.SmoothingMode = SmoothingMode.AntiAlias;
+ penBorder.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
+ //if (isFocused) penBorder.Color = borderFocusColor;
+
+ if (underlinedStyle) //Line Style
+ {
+ //Draw border smoothing
+ graph.DrawPath(penBorderSmooth, pathBorderSmooth);
+ //Draw border
+ graph.SmoothingMode = SmoothingMode.None;
+ graph.DrawLine(penBorder, 0, _Control.Height - 1, _Control.Width, _Control.Height - 1);
+ }
+ else //Normal Style
+ {
+ //Draw border smoothing
+ graph.DrawPath(penBorderSmooth, pathBorderSmooth);
+ //Draw border
+ graph.DrawPath(penBorder, pathBorder);
+ }
+ }
+ }
+ };
+ }
+ }
+ catch { throw; }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ /// Attemps to apply Window's Dark Style to the Control and all its childs.
+ ///
+ private static void ApplySystemDarkTheme(Control control = null)
+ {
+ /*
+ DWMWA_USE_IMMERSIVE_DARK_MODE: https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
+
+ Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled.
+ For compatibility reasons, all windows default to light mode regardless of the system setting.
+ The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode.
+
+ This value is supported starting with Windows 11 Build 22000.
+
+ SetWindowTheme: https://learn.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-setwindowtheme
+ Causes a window to use a different set of visual style information than its class normally uses.
+ */
+ int[] DarkModeOn = new[] { 0x01 }; //<- 1=True, 0=False
+
+ SetWindowTheme(control.Handle, "DarkMode_Explorer", null);
+
+ if (DwmSetWindowAttribute(control.Handle, (int)DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, DarkModeOn, 4) != 0)
+ DwmSetWindowAttribute(control.Handle, (int)DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, DarkModeOn, 4);
+
+ foreach (Control child in control.Controls)
+ {
+ if (child.Controls.Count != 0)
+ ApplySystemDarkTheme(child);
+ }
+ }
+
+ private static bool IsWindows10orGreater()
+ {
+ if (WindowsVersion() >= 10)
+ return true;
+ else
+ return false;
+ }
+
+ private static int WindowsVersion()
+ {
+ //for .Net4.8 and Minor
+ int result = 10;
+ var reg = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
+ string[] productName = reg.GetValue("ProductName").ToString().Split((char)32);
+ int.TryParse(productName[1], out result);
+ return result;
+
+ //fixed .Net6
+ //return System.Environment.OSVersion.Version.Major;
+ }
+
+ private static Color GetReadableColor(Color backgroundColor)
+ {
+ // Calculate the relative luminance of the background color.
+ // Normalize values to 0-1 range first.
+ double normalizedR = backgroundColor.R / 255.0;
+ double normalizedG = backgroundColor.G / 255.0;
+ double normalizedB = backgroundColor.B / 255.0;
+ double luminance = 0.299 * normalizedR + 0.587 * normalizedG + 0.114 * normalizedB;
+
+ // Choose a contrasting foreground color based on the luminance,
+ // with a slight bias towards lighter colors for better readability.
+ return luminance < 0.5 ? Color.FromArgb(182, 180, 215) : Color.FromArgb(34, 34, 34); // Dark gray for light backgrounds
+ }
+
+ // For Rounded Corners:
+ private static GraphicsPath GetFigurePath(Rectangle rect, int radius)
+ {
+ GraphicsPath path = new GraphicsPath();
+ float curveSize = radius * 2F;
+
+ path.StartFigure();
+ path.AddArc(rect.X, rect.Y, curveSize, curveSize, 180, 90);
+ path.AddArc(rect.Right - curveSize, rect.Y, curveSize, curveSize, 270, 90);
+ path.AddArc(rect.Right - curveSize, rect.Bottom - curveSize, curveSize, curveSize, 0, 90);
+ path.AddArc(rect.X, rect.Bottom - curveSize, curveSize, curveSize, 90, 90);
+ path.CloseFigure();
+ return path;
+ }
+
+ #endregion
+ }
+
+ /// Windows 10+ System Colors for Clear Color Mode.
+ public class OSThemeColors
+ {
+ public OSThemeColors() { }
+
+ /// For the very back of the Window
+ public System.Drawing.Color Background { get; set; } = SystemColors.Control;
+ /// For Borders around the Background
+ public System.Drawing.Color BackgroundDark { get; set; } = SystemColors.ControlDark;
+
+ /// For hightlights over the Background
+ public System.Drawing.Color BackgroundLight { get; set; } = SystemColors.ControlLight;
+
+ /// For Container above the Background
+ public System.Drawing.Color Surface { get; set; } = SystemColors.ControlLightLight;
+ /// For Borders around the Surface
+ public System.Drawing.Color SurfaceDark { get; set; } = SystemColors.ControlLight;
+ /// For Highligh over the Surface
+ public System.Drawing.Color SurfaceLight { get; set; } = Color.White;
+
+ /// For Main Texts
+ public System.Drawing.Color TextActive { get; set; } = SystemColors.ControlText;
+ /// For Inactive Texts
+ public System.Drawing.Color TextInactive { get; set; } = SystemColors.GrayText;
+ /// For Hightligh Texts
+ public System.Drawing.Color TextInAccent { get; set; } = SystemColors.HighlightText;
+
+ /// For the background of any Control
+ public System.Drawing.Color Control { get; set; } = SystemColors.ButtonFace;
+ /// For Bordes of any Control
+ public System.Drawing.Color ControlDark { get; set; } = SystemColors.ButtonShadow;
+ /// For Highlight elements in a Control
+ public System.Drawing.Color ControlLight { get; set; } = SystemColors.ButtonHighlight;
+
+ /// Windows 10+ Chosen Accent Color
+ public System.Drawing.Color Accent { get; set; } = DarkModeCS.GetWindowsAccentColor();
+ public System.Drawing.Color AccentDark { get { return ControlPaint.Dark(Accent); } }
+ public System.Drawing.Color AccentLight { get { return ControlPaint.Light(Accent); } }
+
+ /// the color displayed most frequently across your app's screens and components.
+ public System.Drawing.Color Primary { get; set; } = SystemColors.Highlight;
+ public System.Drawing.Color PrimaryDark { get { return ControlPaint.Dark(Primary); } }
+ public System.Drawing.Color PrimaryLight { get { return ControlPaint.Light(Primary); } }
+
+ /// to accent select parts of your UI.
+ public System.Drawing.Color Secondary { get; set; } = SystemColors.HotTrack;
+ public System.Drawing.Color SecondaryDark { get { return ControlPaint.Dark(Secondary); } }
+ public System.Drawing.Color SecondaryLight { get { return ControlPaint.Light(Secondary); } }
+ }
+
+ /* Custom Renderers for Menus and ToolBars */
+ public class MyRenderer : ToolStripProfessionalRenderer
+ {
+ public bool ColorizeIcons { get; set; } = true;
+ public OSThemeColors MyColors { get; set; } //<- Your Custom Colors Colection
+
+ public MyRenderer(ProfessionalColorTable table, bool pColorizeIcons = true) : base(table)
+ {
+ ColorizeIcons = pColorizeIcons;
+ }
+
+ private void DrawTitleBar(Graphics g, Rectangle rect)
+ {
+ // Assign the image for the grip.
+ //Image titlebarGrip = titleBarGripBmp;
+
+ // Fill the titlebar.
+ // This produces the gradient and the rounded-corner effect.
+ //g.DrawLine(new Pen(titlebarColor1), rect.X, rect.Y, rect.X + rect.Width, rect.Y);
+ //g.DrawLine(new Pen(titlebarColor2), rect.X, rect.Y + 1, rect.X + rect.Width, rect.Y + 1);
+ //g.DrawLine(new Pen(titlebarColor3), rect.X, rect.Y + 2, rect.X + rect.Width, rect.Y + 2);
+ //g.DrawLine(new Pen(titlebarColor4), rect.X, rect.Y + 3, rect.X + rect.Width, rect.Y + 3);
+ //g.DrawLine(new Pen(titlebarColor5), rect.X, rect.Y + 4, rect.X + rect.Width, rect.Y + 4);
+ //g.DrawLine(new Pen(titlebarColor6), rect.X, rect.Y + 5, rect.X + rect.Width, rect.Y + 5);
+ //g.DrawLine(new Pen(titlebarColor7), rect.X, rect.Y + 6, rect.X + rect.Width, rect.Y + 6);
+
+ // Center the titlebar grip.
+ //g.DrawImage(
+ // titlebarGrip,
+ // new Point(rect.X + ((rect.Width / 2) - (titlebarGrip.Width / 2)),
+ // rect.Y + 1));
+ }
+
+ // This method handles the RenderGrip event.
+ protected override void OnRenderGrip(ToolStripGripRenderEventArgs e)
+ {
+ DrawTitleBar(
+ e.Graphics,
+ new Rectangle(0, 0, e.ToolStrip.Width, 7));
+ }
+
+ // This method handles the RenderToolStripBorder event.
+ protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
+ {
+ DrawTitleBar(
+ e.Graphics,
+ new Rectangle(0, 0, e.ToolStrip.Width, 7));
+ }
+
+ // Background of the whole ToolBar Or MenuBar:
+ protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
+ {
+ e.ToolStrip.BackColor = MyColors.Background;
+ base.OnRenderToolStripBackground(e);
+ }
+
+ // For Normal Buttons on a ToolBar:
+ protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
+ {
+ Graphics g = e.Graphics;
+ Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
+
+ Color gradientBegin = MyColors.Background; // Color.FromArgb(203, 225, 252);
+ Color gradientEnd = MyColors.Background;
+
+ Pen BordersPencil = new Pen(MyColors.Background);
+
+ ToolStripButton button = e.Item as ToolStripButton;
+ if (button.Pressed || button.Checked)
+ {
+ gradientBegin = MyColors.Control;
+ gradientEnd = MyColors.Control;
+ }
+ else if (button.Selected)
+ {
+ gradientBegin = MyColors.Accent;
+ gradientEnd = MyColors.Accent;
+ }
+
+ using (Brush b = new LinearGradientBrush(
+ bounds,
+ gradientBegin,
+ gradientEnd,
+ LinearGradientMode.Vertical))
+ {
+ g.FillRectangle(b, bounds);
+ }
+
+ e.Graphics.DrawRectangle(
+ BordersPencil,
+ bounds);
+
+ g.DrawLine(
+ BordersPencil,
+ bounds.X,
+ bounds.Y,
+ bounds.Width - 1,
+ bounds.Y);
+
+ g.DrawLine(
+ BordersPencil,
+ bounds.X,
+ bounds.Y,
+ bounds.X,
+ bounds.Height - 1);
+
+ ToolStrip toolStrip = button.Owner;
+
+ if (!(button.Owner.GetItemAt(button.Bounds.X, button.Bounds.Bottom + 1) is ToolStripButton nextItem))
+ {
+ g.DrawLine(
+ BordersPencil,
+ bounds.X,
+ bounds.Height - 1,
+ bounds.X + bounds.Width - 1,
+ bounds.Height - 1);
+ }
+ }
+
+ // For DropDown Buttons on a ToolBar:
+ protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEventArgs e)
+ {
+ Graphics g = e.Graphics;
+ Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
+ Color gradientBegin = MyColors.Background; // Color.FromArgb(203, 225, 252);
+ Color gradientEnd = MyColors.Background;
+
+ Pen BordersPencil = new Pen(MyColors.Background);
+
+ //1. Determine the colors to use:
+ if (e.Item.Pressed)
+ {
+ gradientBegin = MyColors.Control;
+ gradientEnd = MyColors.Control;
+ }
+ else if (e.Item.Selected)
+ {
+ gradientBegin = MyColors.Accent;
+ gradientEnd = MyColors.Accent;
+ }
+
+ //2. Draw the Box around the Control
+ using (Brush b = new LinearGradientBrush(
+ bounds,
+ gradientBegin,
+ gradientEnd,
+ LinearGradientMode.Vertical))
+ {
+ e.Graphics.FillRectangle(b, bounds);
+ }
+
+
+ //3. Draws the Chevron:
+ #region Chevron
+
+ //int Padding = 2; //<- From the right side
+ //Size cSize = new Size(8, 4); //<- Size of the Chevron: 8x4 px
+ //Pen ChevronPen = new Pen(MyColors.TextInactive, 2); //<- Color and Border Width
+ //Point P1 = new Point(bounds.Width - (cSize.Width + Padding), (bounds.Height / 2) - (cSize.Height / 2));
+ //Point P2 = new Point(bounds.Width - Padding, (bounds.Height / 2) - (cSize.Height / 2));
+ //Point P3 = new Point(bounds.Width - (cSize.Width / 2 + Padding), (bounds.Height / 2) + (cSize.Height / 2));
+
+ //e.Graphics.DrawLine(ChevronPen, P1, P3);
+ //e.Graphics.DrawLine(ChevronPen, P2, P3);
+
+ #endregion
+ }
+
+ // For SplitButtons on a ToolBar:
+ protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventArgs e)
+ {
+ Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
+ Color gradientBegin = MyColors.Background; // Color.FromArgb(203, 225, 252);
+ Color gradientEnd = MyColors.Background;
+
+ //1. Determine the colors to use:
+ if (e.Item.Pressed)
+ {
+ gradientBegin = MyColors.Control;
+ gradientEnd = MyColors.Control;
+ }
+ else if (e.Item.Selected)
+ {
+ gradientBegin = MyColors.Accent;
+ gradientEnd = MyColors.Accent;
+ }
+
+ //2. Draw the Box around the Control
+ using (Brush b = new LinearGradientBrush(
+ bounds,
+ gradientBegin,
+ gradientEnd,
+ LinearGradientMode.Vertical))
+ {
+ e.Graphics.FillRectangle(b, bounds);
+ }
+
+ //3. Draws the Chevron:
+ #region Chevron
+
+ int Padding = 2; //<- From the right side
+ Size cSize = new Size(8, 4); //<- Size of the Chevron: 8x4 px
+ Pen ChevronPen = new Pen(MyColors.TextInactive, 2); //<- Color and Border Width
+ Point P1 = new Point(bounds.Width - (cSize.Width + Padding), (bounds.Height / 2) - (cSize.Height / 2));
+ Point P2 = new Point(bounds.Width - Padding, (bounds.Height / 2) - (cSize.Height / 2));
+ Point P3 = new Point(bounds.Width - (cSize.Width / 2 + Padding), (bounds.Height / 2) + (cSize.Height / 2));
+
+ e.Graphics.DrawLine(ChevronPen, P1, P3);
+ e.Graphics.DrawLine(ChevronPen, P2, P3);
+
+ #endregion
+ }
+
+ // For the Text Color of all Items:
+ protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
+ {
+ if (e.Item.Enabled)
+ {
+ e.TextColor = MyColors.TextActive;
+ }
+ else
+ {
+ e.TextColor = MyColors.TextInactive;
+ }
+ base.OnRenderItemText(e);
+ }
+
+ protected override void OnRenderItemBackground(ToolStripItemRenderEventArgs e)
+ {
+ base.OnRenderItemBackground(e);
+
+ // Only draw border for ComboBox items
+ if (e.Item is ComboBox)
+ {
+ Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
+ e.Graphics.DrawRectangle(new Pen(MyColors.ControlLight, 1), rect);
+ }
+ }
+
+ // For Menu Items BackColor:
+ protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
+ {
+ Graphics g = e.Graphics;
+ Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
+
+ Color gradientBegin = MyColors.Background; // Color.FromArgb(203, 225, 252);
+ Color gradientEnd = MyColors.Background; // Color.FromArgb(125, 165, 224);
+
+ bool DrawIt = false;
+ var _menu = e.Item as ToolStripItem;
+ if (_menu.Pressed)
+ {
+ gradientBegin = MyColors.Control; // Color.FromArgb(254, 128, 62);
+ gradientEnd = MyColors.Control; // Color.FromArgb(255, 223, 154);
+ DrawIt = true;
+ }
+ else if (_menu.Selected)
+ {
+ gradientBegin = MyColors.Accent;// Color.FromArgb(255, 255, 222);
+ gradientEnd = MyColors.Accent; // Color.FromArgb(255, 203, 136);
+ DrawIt = true;
+ }
+
+ if (DrawIt)
+ {
+ using (Brush b = new LinearGradientBrush(
+ bounds,
+ gradientBegin,
+ gradientEnd,
+ LinearGradientMode.Vertical))
+ {
+ g.FillRectangle(b, bounds);
+ }
+ }
+ }
+
+ // Re-Colors the Icon Images to a Clear color:
+ protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
+ {
+ if (ColorizeIcons && e.Image != null)
+ {
+ // Get the current icon
+ Image image = e.Image;
+ Color _ClearColor = e.Item.Enabled ? MyColors.TextInactive : MyColors.SurfaceDark;
+
+ // Create a new image with the desired color adjustments
+ using (Image adjustedImage = ChangeToColor(image, _ClearColor))
+ {
+ e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
+ e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
+ e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+ e.Graphics.DrawImage(adjustedImage, e.ImageRectangle);
+ }
+
+ }
+ }
+
+ /// Colorea una imagen usando una Matrix de Color.
+ /// Imagen a Colorear
+ /// Color a Utilizar
+ private Bitmap ChangeToColor(Bitmap bmp, Color c)
+ {
+ Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height);
+ using (Graphics g = Graphics.FromImage(bmp2))
+ {
+ g.InterpolationMode = InterpolationMode.HighQualityBilinear;
+ g.CompositingQuality = CompositingQuality.HighQuality;
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+
+ float tR = c.R / 255f;
+ float tG = c.G / 255f;
+ float tB = c.B / 255f;
+
+ System.Drawing.Imaging.ColorMatrix colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][]
+ {
+ new float[] { 0, 0, 0, 0, 0 },
+ new float[] { 0, 0, 0, 0, 0 },
+ new float[] { 0, 0, 0, 0, 0 },
+ new float[] { 0, 0, 0, 1, 0 }, //<- not changing alpha
+ new float[] { tR, tG, tB, 0, 1 }
+ });
+
+ System.Drawing.Imaging.ImageAttributes attributes = new System.Drawing.Imaging.ImageAttributes();
+ attributes.SetColorMatrix(colorMatrix);
+
+ g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),
+ 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes);
+ }
+ return bmp2;
+ }
+ private Image ChangeToColor(Image bmp, Color c) => (Image)ChangeToColor((Bitmap)bmp, c);
+
+ }
+ public class CustomColorTable : ProfessionalColorTable
+ {
+ public OSThemeColors Colors { get; set; }
+
+ public CustomColorTable(OSThemeColors _Colors)
+ {
+ Colors = _Colors;
+ base.UseSystemColors = false;
+ }
+
+ public override Color ImageMarginGradientBegin
+ {
+ get { return Colors.Control; }
+ }
+ public override Color ImageMarginGradientMiddle
+ {
+ get { return Colors.Control; }
+ }
+ public override Color ImageMarginGradientEnd
+ {
+ get { return Colors.Control; }
+ }
+ }
+}
diff --git a/VanillaLauncher/DarkMode/FlatComboBox.cs b/VanillaLauncher/DarkMode/FlatComboBox.cs
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/VanillaLauncher/DarkMode/FlatComboBox.cs
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/VanillaLauncher/DarkMode/FlatTabControl.cs b/VanillaLauncher/DarkMode/FlatTabControl.cs
new file mode 100644
index 0000000..a5f1424
--- /dev/null
+++ b/VanillaLauncher/DarkMode/FlatTabControl.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace BlueMystic
+{
+ public class FlatTabControl : TabControl
+ {
+ #region Public Properties
+
+ [Description("Color for a decorative line"), Category("Appearance")]
+ public Color LineColor { get; set; } = SystemColors.Highlight;
+
+ [Description("Color for all Borders"), Category("Appearance")]
+ public Color BorderColor { get; set; } = SystemColors.ControlDark;
+
+ [Description("Back color for selected Tab"), Category("Appearance")]
+ public Color SelectTabColor { get; set; } = SystemColors.ControlLight;
+
+ [Description("Fore Color for Selected Tab"), Category("Appearance")]
+ public Color SelectedForeColor { get; set; } = SystemColors.HighlightText;
+
+ [Description("Back Color for un-selected tabs"), Category("Appearance")]
+ public Color TabColor { get; set; } = SystemColors.ControlLight;
+
+ [Description("Background color for the whole control"), Category("Appearance"), Browsable(true)]
+ public override Color BackColor { get; set; } = SystemColors.Control;
+
+ [Description("Fore Color for all Texts"), Category("Appearance")]
+ public override Color ForeColor { get; set; } = SystemColors.ControlText;
+
+ #endregion
+
+ public FlatTabControl()
+ {
+ try
+ {
+ Appearance = TabAppearance.Buttons;
+ DrawMode = TabDrawMode.Normal;
+ ItemSize = new Size(0, 0);
+ SizeMode = TabSizeMode.Fixed;
+ }
+ catch { }
+ }
+
+ protected override void InitLayout()
+ {
+ SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ SetStyle(ControlStyles.DoubleBuffer, true);
+ SetStyle(ControlStyles.ResizeRedraw, true);
+ SetStyle(ControlStyles.SupportsTransparentBackColor, true);
+ SetStyle(ControlStyles.UserPaint, true);
+ base.InitLayout();
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+ DrawControl(e.Graphics);
+ }
+
+ internal void DrawControl(Graphics g)
+ {
+ try
+ {
+ if (!Visible)
+ {
+ return;
+ }
+
+ Rectangle clientRectangle = ClientRectangle;
+ clientRectangle.Inflate(2, 2);
+
+ // Whole Control Background:
+ using (Brush bBackColor = new SolidBrush(BackColor))
+ {
+ g.FillRectangle(bBackColor, ClientRectangle);
+ }
+
+ Region region = g.Clip;
+
+ for (int i = 0; i < TabCount; i++)
+ {
+ DrawTab(g, TabPages[i], i);
+ TabPages[i].BackColor = TabColor;
+ }
+
+ g.Clip = region;
+
+ using (Pen border = new Pen(BorderColor))
+ {
+ g.DrawRectangle(border, clientRectangle);
+
+ if (SelectedTab != null)
+ {
+ clientRectangle.Offset(1, 1);
+ clientRectangle.Width -= 2;
+ clientRectangle.Height -= 2;
+ g.DrawRectangle(border, clientRectangle);
+ clientRectangle.Width -= 1;
+ clientRectangle.Height -= 1;
+ g.DrawRectangle(border, clientRectangle);
+ }
+ }
+
+ // a decorative line on top of pages:
+ using (Brush bLineColor = new SolidBrush(LineColor))
+ {
+ Rectangle rectangle = ClientRectangle;
+ rectangle.Height = 1;
+ rectangle.Y = 25;
+ g.FillRectangle(bLineColor, rectangle);
+
+ rectangle = ClientRectangle;
+ rectangle.Height = 1;
+ rectangle.Y = 26;
+ g.FillRectangle(bLineColor, rectangle);
+ }
+
+ }
+ catch { }
+ }
+
+ internal void DrawTab(Graphics g, TabPage customTabPage, int nIndex)
+ {
+ Rectangle tabRect = GetTabRect(nIndex);
+ Rectangle tabTextRect = GetTabRect(nIndex);
+ bool isSelected = (SelectedIndex == nIndex);
+ Point[] points;
+
+ if (Alignment == TabAlignment.Top)
+ {
+ points = new[]
+ {
+ new Point(tabRect.Left, tabRect.Bottom),
+ new Point(tabRect.Left, tabRect.Top + 0),
+ new Point(tabRect.Left + 0, tabRect.Top),
+ new Point(tabRect.Right - 0, tabRect.Top),
+ new Point(tabRect.Right, tabRect.Top + 0),
+ new Point(tabRect.Right, tabRect.Bottom),
+ new Point(tabRect.Left, tabRect.Bottom)
+ };
+ }
+ else
+ {
+ points = new[]
+ {
+ new Point(tabRect.Left, tabRect.Top),
+ new Point(tabRect.Right, tabRect.Top),
+ new Point(tabRect.Right, tabRect.Bottom - 0),
+ new Point(tabRect.Right - 0, tabRect.Bottom),
+ new Point(tabRect.Left + 0, tabRect.Bottom),
+ new Point(tabRect.Left, tabRect.Bottom - 0),
+ new Point(tabRect.Left, tabRect.Top)
+ };
+ }
+
+ // Draws the Tab Header:
+ Color HeaderColor = isSelected ? SelectTabColor : BackColor;
+ using (Brush brush = new SolidBrush(HeaderColor))
+ {
+ g.FillPolygon(brush, points);
+ brush.Dispose();
+ g.DrawPolygon(new Pen(HeaderColor), points);
+ }
+
+ Rectangle rectangleF = tabTextRect;
+ rectangleF.Y += 2;
+
+ TextRenderer.DrawText(g, customTabPage.Text, Font, rectangleF,
+ isSelected ? SelectedForeColor : ForeColor);
+ }
+ }
+}
diff --git a/VanillaLauncher/DarkMode/Messenger.cs b/VanillaLauncher/DarkMode/Messenger.cs
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/VanillaLauncher/DarkMode/Messenger.cs
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/VanillaLauncher/FodyWeavers.xml b/VanillaLauncher/FodyWeavers.xml
new file mode 100644
index 0000000..18894c0
--- /dev/null
+++ b/VanillaLauncher/FodyWeavers.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VanillaLauncher/FodyWeavers.xsd b/VanillaLauncher/FodyWeavers.xsd
new file mode 100644
index 0000000..05e92c1
--- /dev/null
+++ b/VanillaLauncher/FodyWeavers.xsd
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+ A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks
+
+
+
+
+ A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.
+
+
+
+
+ A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks
+
+
+
+
+ A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.
+
+
+
+
+ A list of unmanaged 32 bit assembly names to include, delimited with line breaks.
+
+
+
+
+ A list of unmanaged 64 bit assembly names to include, delimited with line breaks.
+
+
+
+
+ The order of preloaded assemblies, delimited with line breaks.
+
+
+
+
+
+ This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.
+
+
+
+
+ Controls if .pdbs for reference assemblies are also embedded.
+
+
+
+
+ Controls if runtime assemblies are also embedded.
+
+
+
+
+ Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.
+
+
+
+
+ Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.
+
+
+
+
+ As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.
+
+
+
+
+ Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.
+
+
+
+
+ Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.
+
+
+
+
+ A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |
+
+
+
+
+ A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.
+
+
+
+
+ A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |
+
+
+
+
+ A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.
+
+
+
+
+ A list of unmanaged 32 bit assembly names to include, delimited with |.
+
+
+
+
+ A list of unmanaged 64 bit assembly names to include, delimited with |.
+
+
+
+
+ The order of preloaded assemblies, delimited with |.
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/VanillaLauncher/MobileProxy/Helpers/ConsoleHelper.cs b/VanillaLauncher/MobileProxy/Helpers/ConsoleHelper.cs
new file mode 100644
index 0000000..64b89c9
--- /dev/null
+++ b/VanillaLauncher/MobileProxy/Helpers/ConsoleHelper.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Titanium.Web.Proxy.Examples.Basic.Helpers
+{
+ ///
+ /// Adapted from
+ /// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode
+ ///
+ internal static class ConsoleHelper
+ {
+ private const uint EnableQuickEdit = 0x0040;
+
+ // STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
+ private const int StdInputHandle = -10;
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetStdHandle(int nStdHandle);
+
+ [DllImport("kernel32.dll")]
+ private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
+
+ [DllImport("kernel32.dll")]
+ private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
+
+ internal static bool DisableQuickEditMode()
+ {
+ var consoleHandle = GetStdHandle(StdInputHandle);
+
+ // get current console mode
+ if (!GetConsoleMode(consoleHandle, out var consoleMode))
+ // ERROR: Unable to get console mode.
+ return false;
+
+ // Clear the quick edit bit in the mode flags
+ consoleMode &= ~EnableQuickEdit;
+
+ // set the new mode
+ if (!SetConsoleMode(consoleHandle, consoleMode))
+ // ERROR: Unable to set console mode
+ return false;
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/VanillaLauncher/MobileProxy/Main.cs b/VanillaLauncher/MobileProxy/Main.cs
new file mode 100644
index 0000000..f8086ba
--- /dev/null
+++ b/VanillaLauncher/MobileProxy/Main.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Security;
+using System.Threading;
+using System.Threading.Tasks;
+using Titanium.Web.Proxy;
+using Titanium.Web.Proxy.EventArguments;
+using Titanium.Web.Proxy.Exceptions;
+using Titanium.Web.Proxy.Helpers;
+using Titanium.Web.Proxy.Http;
+using Titanium.Web.Proxy.Models;
+using Titanium.Web.Proxy.StreamExtended.Network;
+
+
+namespace VanillaLauncher.MobileProxy
+{
+ public class Main
+ {
+
+
+ public void startProxy()
+ {
+
+ var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);
+ var proxyServer = new ProxyServer();
+ proxyServer.CertificateManager.CertificateEngine = Titanium.Web.Proxy.Network.CertificateEngine.DefaultWindows;
+ proxyServer.CertificateManager.EnsureRootCertificate();
+ // locally trust root certificate used by this proxy
+ //proxyServer.CertificateManager.TrustRootCertificate(true);
+
+ // optionally set the Certificate Engine
+ // Under Mono only BouncyCastle will be supported
+ //proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
+ //proxyServer.BeforeRequest += OnRequest;
+ //proxyServer.BeforeResponse += OnResponse;
+
+ //proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
+ //proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
+
+ //proxyServer.EnableWinAuth = true;
+
+ explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);
+
+ // Fired when a CONNECT request is received
+ explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
+
+
+ // An explicit endpoint is where the client knows about the existence of a proxy
+ // So client sends request in a proxy friendly manner
+ proxyServer.AddEndPoint(explicitEndPoint);
+ proxyServer.Start();
+
+ }
+
+ private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
+ {
+ string hostname = e.HttpClient.Request.RequestUri.Host;
+
+ if (hostname.Contains("dropbox.com"))
+ {
+ // Exclude Https addresses you don't want to proxy
+ // Useful for clients that use certificate pinning
+ // for example dropbox.com
+ e.DecryptSsl = false;
+ }
+ }
+
+ public async Task OnRequest(object sender, SessionEventArgs e)
+ {
+ Console.WriteLine(e.HttpClient.Request.Url);
+
+ // read request headers
+ var requestHeaders = e.HttpClient.Request.Headers;
+
+ var method = e.HttpClient.Request.Method.ToUpper();
+ if ((method == "POST" || method == "PUT" || method == "PATCH"))
+ {
+ // Get/Set request body bytes
+ byte[] bodyBytes = await e.GetRequestBody();
+ e.SetRequestBody(bodyBytes);
+
+ // Get/Set request body as string
+ string bodyString = await e.GetRequestBodyAsString();
+ e.SetRequestBodyString(bodyString);
+
+ // store request
+ // so that you can find it from response handler
+ e.UserData = e.HttpClient.Request;
+ }
+
+ // To cancel a request with a custom HTML content
+ // Filter URL
+ if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("google.com"))
+ {
+ e.Ok("" +
+ "" +
+ "Website Blocked" +
+ "
" +
+ "Blocked by titanium web proxy.
" +
+ "" +
+ "");
+ }
+
+ // Redirect example
+ if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
+ {
+ e.Redirect("https://www.paypal.com");
+ }
+ }
+
+ // Modify response
+ public async Task OnResponse(object sender, SessionEventArgs e)
+ {
+ // read response headers
+ var responseHeaders = e.HttpClient.Response.Headers;
+
+ //if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
+ if (e.HttpClient.Request.Method == "GET" || e.HttpClient.Request.Method == "POST")
+ {
+ if (e.HttpClient.Response.StatusCode == 200)
+ {
+ if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
+ {
+ byte[] bodyBytes = await e.GetResponseBody();
+ e.SetResponseBody(bodyBytes);
+
+ string body = await e.GetResponseBodyAsString();
+ e.SetResponseBodyString(body);
+ }
+ }
+ }
+
+ if (e.UserData != null)
+ {
+ // access request from UserData property where we stored it in RequestHandler
+ var request = (Request)e.UserData;
+ }
+ }
+
+ // Allows overriding default certificate validation logic
+ public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
+ {
+ // set IsValid to true/false based on Certificate Errors
+ if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
+ e.IsValid = true;
+
+ return Task.CompletedTask;
+ }
+
+ // Allows overriding default client certificate selection logic during mutual authentication
+ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
+ {
+ // set e.clientCertificate to override
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/VanillaLauncher/MobileProxy/ProxyEventArgsBaseExtensions.cs b/VanillaLauncher/MobileProxy/ProxyEventArgsBaseExtensions.cs
new file mode 100644
index 0000000..8738442
--- /dev/null
+++ b/VanillaLauncher/MobileProxy/ProxyEventArgsBaseExtensions.cs
@@ -0,0 +1,14 @@
+using Titanium.Web.Proxy.EventArguments;
+
+namespace Titanium.Web.Proxy.Examples.Basic
+{
+ public static class ProxyEventArgsBaseExtensions
+ {
+ public static SampleClientState GetState(this ProxyEventArgsBase args)
+ {
+ if (args.ClientUserData == null) args.ClientUserData = new SampleClientState();
+
+ return (SampleClientState)args.ClientUserData;
+ }
+ }
+}
\ No newline at end of file
diff --git a/VanillaLauncher/MobileProxy/ProxyTestController.cs b/VanillaLauncher/MobileProxy/ProxyTestController.cs
new file mode 100644
index 0000000..01a6ee0
--- /dev/null
+++ b/VanillaLauncher/MobileProxy/ProxyTestController.cs
@@ -0,0 +1,437 @@
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Security;
+using System.Threading;
+using System.Threading.Tasks;
+using Titanium.Web.Proxy.EventArguments;
+using Titanium.Web.Proxy.Exceptions;
+using Titanium.Web.Proxy.Helpers;
+using Titanium.Web.Proxy.Http;
+using Titanium.Web.Proxy.Models;
+using Titanium.Web.Proxy.StreamExtended.Network;
+
+namespace Titanium.Web.Proxy.Examples.Basic
+{
+ public class ProxyTestController : IDisposable
+ {
+ private readonly ProxyServer proxyServer;
+
+ private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
+
+ private readonly ConcurrentQueue> consoleMessageQueue
+ = new ConcurrentQueue>();
+
+ private ExplicitProxyEndPoint explicitEndPoint;
+
+ public ProxyTestController()
+ {
+ Task.Run(() => ListenToConsole());
+
+ proxyServer = new ProxyServer();
+
+ //proxyServer.EnableHttp2 = true;
+
+ // generate root certificate without storing it in file system
+ //proxyServer.CertificateManager.CreateRootCertificate(false);
+
+ //proxyServer.CertificateManager.TrustRootCertificate();
+ //proxyServer.CertificateManager.TrustRootCertificateAsAdmin();
+
+ proxyServer.ExceptionFunc = async exception =>
+ {
+ if (exception is ProxyHttpException phex)
+ WriteToConsole(exception.Message + ": " + phex.InnerException?.Message, ConsoleColor.Red);
+ else
+ WriteToConsole(exception.Message, ConsoleColor.Red);
+ };
+
+ proxyServer.TcpTimeWaitSeconds = 10;
+ proxyServer.ConnectionTimeOutSeconds = 15;
+ proxyServer.ReuseSocket = false;
+ proxyServer.EnableConnectionPool = false;
+ proxyServer.ForwardToUpstreamGateway = true;
+ proxyServer.CertificateManager.SaveFakeCertificates = true;
+ //proxyServer.ProxyBasicAuthenticateFunc = async (args, userName, password) =>
+ //{
+ // return true;
+ //};
+
+ // this is just to show the functionality, provided implementations use junk value
+ //proxyServer.GetCustomUpStreamProxyFunc = onGetCustomUpStreamProxyFunc;
+ //proxyServer.CustomUpStreamProxyFailureFunc = onCustomUpStreamProxyFailureFunc;
+
+ // optionally set the Certificate Engine
+ // Under Mono or Non-Windows runtimes only BouncyCastle will be supported
+ //proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
+
+ // optionally set the Root Certificate
+ //proxyServer.CertificateManager.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable);
+ }
+
+ private CancellationToken CancellationToken => cancellationTokenSource.Token;
+
+ public void Dispose()
+ {
+ cancellationTokenSource.Dispose();
+ proxyServer.Dispose();
+ }
+
+ public void StartProxy()
+ {
+ proxyServer.BeforeRequest += OnRequest;
+ proxyServer.BeforeResponse += OnResponse;
+ proxyServer.AfterResponse += OnAfterResponse;
+
+ proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
+ proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
+
+ //proxyServer.EnableWinAuth = true;
+
+ explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);
+
+ // Fired when a CONNECT request is received
+ explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
+ explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse;
+
+ // An explicit endpoint is where the client knows about the existence of a proxy
+ // So client sends request in a proxy friendly manner
+ proxyServer.AddEndPoint(explicitEndPoint);
+ proxyServer.Start();
+
+ // Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
+ // A transparent endpoint usually requires a network router port forwarding HTTP(S) packets
+ // or by DNS to send data to this endPoint.
+ //var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
+ //{
+ // // Generic Certificate hostname to use
+ // // When SNI is disabled by client
+ // GenericCertificateName = "localhost"
+ //};
+
+ //proxyServer.AddEndPoint(transparentEndPoint);
+ //proxyServer.UpStreamHttpProxy = new ExternalProxy("localhost", 8888);
+ //proxyServer.UpStreamHttpsProxy = new ExternalProxy("localhost", 8888);
+
+ // SOCKS proxy
+ //proxyServer.UpStreamHttpProxy = new ExternalProxy("127.0.0.1", 1080)
+ // { ProxyType = ExternalProxyType.Socks5, UserName = "User1", Password = "Pass" };
+ //proxyServer.UpStreamHttpsProxy = new ExternalProxy("127.0.0.1", 1080)
+ // { ProxyType = ExternalProxyType.Socks5, UserName = "User1", Password = "Pass" };
+
+
+ //var socksEndPoint = new SocksProxyEndPoint(IPAddress.Any, 1080, true)
+ //{
+ // // Generic Certificate hostname to use
+ // // When SNI is disabled by client
+ // GenericCertificateName = "google.com"
+ //};
+
+ //proxyServer.AddEndPoint(socksEndPoint);
+
+ foreach (var endPoint in proxyServer.ProxyEndPoints)
+ Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ", endPoint.GetType().Name,
+ endPoint.IpAddress, endPoint.Port);
+
+ // Only explicit proxies can be set as system proxy!
+ //proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
+ //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
+ if (RunTime.IsWindows) proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
+ }
+
+ public void Stop()
+ {
+ explicitEndPoint.BeforeTunnelConnectRequest -= OnBeforeTunnelConnectRequest;
+ explicitEndPoint.BeforeTunnelConnectResponse -= OnBeforeTunnelConnectResponse;
+
+ proxyServer.BeforeRequest -= OnRequest;
+ proxyServer.BeforeResponse -= OnResponse;
+ proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
+ proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
+
+ proxyServer.Stop();
+
+ // remove the generated certificates
+ //proxyServer.CertificateManager.RemoveTrustedRootCertificates();
+ }
+
+ private async Task OnGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
+ {
+ arg.GetState().PipelineInfo.AppendLine(nameof(OnGetCustomUpStreamProxyFunc));
+
+ // this is just to show the functionality, provided values are junk
+ return new ExternalProxy
+ {
+ BypassLocalhost = false,
+ HostName = "127.0.0.9",
+ Port = 9090,
+ Password = "fake",
+ UserName = "fake",
+ UseDefaultCredentials = false
+ };
+ }
+
+ private async Task OnCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
+ {
+ arg.GetState().PipelineInfo.AppendLine(nameof(OnCustomUpStreamProxyFailureFunc));
+
+ // this is just to show the functionality, provided values are junk
+ return new ExternalProxy
+ {
+ BypassLocalhost = false,
+ HostName = "127.0.0.10",
+ Port = 9191,
+ Password = "fake2",
+ UserName = "fake2",
+ UseDefaultCredentials = false
+ };
+ }
+
+ private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
+ {
+ var hostname = e.HttpClient.Request.RequestUri.Host;
+ e.GetState().PipelineInfo.AppendLine(nameof(OnBeforeTunnelConnectRequest) + ":" + hostname);
+ WriteToConsole("Tunnel to: " + hostname);
+
+ var clientLocalIp = e.ClientLocalEndPoint.Address;
+ if (!clientLocalIp.Equals(IPAddress.Loopback) && !clientLocalIp.Equals(IPAddress.IPv6Loopback))
+ e.HttpClient.UpStreamEndPoint = new IPEndPoint(clientLocalIp, 0);
+
+ if (hostname.Contains("dropbox.com"))
+ // Exclude Https addresses you don't want to proxy
+ // Useful for clients that use certificate pinning
+ // for example dropbox.com
+ e.DecryptSsl = false;
+ }
+
+ private void WebSocket_DataSent(object sender, DataEventArgs e)
+ {
+ var args = (SessionEventArgs)sender;
+ WebSocketDataSentReceived(args, e, true);
+ }
+
+ private void WebSocket_DataReceived(object sender, DataEventArgs e)
+ {
+ var args = (SessionEventArgs)sender;
+ WebSocketDataSentReceived(args, e, false);
+ }
+
+ private void WebSocketDataSentReceived(SessionEventArgs args, DataEventArgs e, bool sent)
+ {
+ var color = sent ? ConsoleColor.Green : ConsoleColor.Blue;
+
+ foreach (var frame in args.WebSocketDecoder.Decode(e.Buffer, e.Offset, e.Count))
+ {
+ if (frame.OpCode == WebsocketOpCode.Binary)
+ {
+ var data = frame.Data.ToArray();
+ var str = string.Join(",", data.ToArray().Select(x => x.ToString("X2")));
+ WriteToConsole(str, color);
+ }
+
+ if (frame.OpCode == WebsocketOpCode.Text) WriteToConsole(frame.GetText(), color);
+ }
+ }
+
+ private Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
+ {
+ e.GetState().PipelineInfo
+ .AppendLine(nameof(OnBeforeTunnelConnectResponse) + ":" + e.HttpClient.Request.RequestUri);
+
+ return Task.CompletedTask;
+ }
+
+ // intercept & cancel redirect or update requests
+ private async Task OnRequest(object sender, SessionEventArgs e)
+ {
+ e.GetState().PipelineInfo.AppendLine(nameof(OnRequest) + ":" + e.HttpClient.Request.RequestUri);
+
+ var clientLocalIp = e.ClientLocalEndPoint.Address;
+ if (!clientLocalIp.Equals(IPAddress.Loopback) && !clientLocalIp.Equals(IPAddress.IPv6Loopback))
+ e.HttpClient.UpStreamEndPoint = new IPEndPoint(clientLocalIp, 0);
+
+ if (e.HttpClient.Request.Url.Contains("yahoo.com"))
+ e.CustomUpStreamProxy = new ExternalProxy("localhost", 8888);
+
+ WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
+ WriteToConsole(e.HttpClient.Request.Url);
+
+ // store it in the UserData property
+ // It can be a simple integer, Guid, or any type
+ //e.UserData = new CustomUserData()
+ //{
+ // RequestHeaders = e.HttpClient.Request.Headers,
+ // RequestBody = e.HttpClient.Request.HasBody ? e.HttpClient.Request.Body:null,
+ // RequestBodyString = e.HttpClient.Request.HasBody? e.HttpClient.Request.BodyString:null
+ //};
+
+ ////This sample shows how to get the multipart form data headers
+ //if (e.HttpClient.Request.Host == "mail.yahoo.com" && e.HttpClient.Request.IsMultipartFormData)
+ //{
+ // e.MultipartRequestPartSent += MultipartRequestPartSent;
+ //}
+
+ // To cancel a request with a custom HTML content
+ // Filter URL
+ //if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("yahoo.com"))
+ //{
+ // e.Ok("" +
+ // "" +
+ // "Website Blocked" +
+ // "
" +
+ // "Blocked by titanium web proxy.
" +
+ // "" +
+ // "");
+ //}
+
+ ////Redirect example
+ //if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
+ //{
+ // e.Redirect("https://www.paypal.com");
+ //}
+ }
+
+ // Modify response
+ private async Task MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
+ {
+ e.GetState().PipelineInfo.AppendLine(nameof(MultipartRequestPartSent));
+
+ var session = (SessionEventArgs)sender;
+ WriteToConsole("Multipart form data headers:");
+ foreach (var header in e.Headers) WriteToConsole(header.ToString());
+ }
+
+ private async Task OnResponse(object sender, SessionEventArgs e)
+ {
+ e.GetState().PipelineInfo.AppendLine(nameof(OnResponse));
+
+ if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket)
+ {
+ e.DataSent += WebSocket_DataSent;
+ e.DataReceived += WebSocket_DataReceived;
+ }
+
+ WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
+
+ var ext = Path.GetExtension(e.HttpClient.Request.RequestUri.AbsolutePath);
+
+ // access user data set in request to do something with it
+ //var userData = e.HttpClient.UserData as CustomUserData;
+
+ //if (ext == ".gif" || ext == ".png" || ext == ".jpg")
+ //{
+ // byte[] btBody = Encoding.UTF8.GetBytes("" +
+ // "" +
+ // "Image is blocked" +
+ // "
" +
+ // "Blocked by Titanium
" +
+ // "" +
+ // "");
+
+ // var response = new OkResponse(btBody);
+ // response.HttpVersion = e.HttpClient.Request.HttpVersion;
+
+ // e.Respond(response);
+ // e.TerminateServerConnection();
+ //}
+
+ //// print out process id of current session
+ ////WriteToConsole($"PID: {e.HttpClient.ProcessId.Value}");
+
+ ////if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
+ //if (e.HttpClient.Request.Method == "GET" || e.HttpClient.Request.Method == "POST")
+ //{
+ // if (e.HttpClient.Response.StatusCode == (int)HttpStatusCode.OK)
+ // {
+ // if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
+ // {
+ // var bodyBytes = await e.GetResponseBody();
+ // e.SetResponseBody(bodyBytes);
+
+ // string body = await e.GetResponseBodyAsString();
+ // e.SetResponseBodyString(body);
+ // }
+ // }
+ //}
+ }
+
+ private async Task OnAfterResponse(object sender, SessionEventArgs e)
+ {
+ WriteToConsole($"Pipelineinfo: {e.GetState().PipelineInfo}", ConsoleColor.Yellow);
+ }
+
+ ///
+ /// Allows overriding default certificate validation logic
+ ///
+ ///
+ ///
+ public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
+ {
+ e.GetState().PipelineInfo.AppendLine(nameof(OnCertificateValidation));
+
+ // set IsValid to true/false based on Certificate Errors
+ if (e.SslPolicyErrors == SslPolicyErrors.None) e.IsValid = true;
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Allows overriding default client certificate selection logic during mutual authentication
+ ///
+ ///
+ ///
+ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
+ {
+ e.GetState().PipelineInfo.AppendLine(nameof(OnCertificateSelection));
+
+ // set e.clientCertificate to override
+
+ return Task.CompletedTask;
+ }
+
+ private void WriteToConsole(string message, ConsoleColor? consoleColor = null)
+ {
+ consoleMessageQueue.Enqueue(new Tuple(consoleColor, message));
+ }
+
+ private async Task ListenToConsole()
+ {
+ while (!CancellationToken.IsCancellationRequested)
+ {
+ while (consoleMessageQueue.TryDequeue(out var item))
+ {
+ var consoleColor = item.Item1;
+ var message = item.Item2;
+
+ if (consoleColor.HasValue)
+ {
+ var existing = Console.ForegroundColor;
+ Console.ForegroundColor = consoleColor.Value;
+ Console.WriteLine(message);
+ Console.ForegroundColor = existing;
+ }
+ else
+ {
+ Console.WriteLine(message);
+ }
+ }
+
+ //reduce CPU usage
+ await Task.Delay(50);
+ }
+ }
+
+ /////
+ ///// User data object as defined by user.
+ ///// User data can be set to each SessionEventArgs.HttpClient.UserData property
+ /////
+ //public class CustomUserData
+ //{
+ // public HeaderCollection RequestHeaders { get; set; }
+ // public byte[] RequestBody { get; set; }
+ // public string RequestBodyString { get; set; }
+ //}
+ }
+}
\ No newline at end of file
diff --git a/VanillaLauncher/MobileProxy/SampleClientState.cs b/VanillaLauncher/MobileProxy/SampleClientState.cs
new file mode 100644
index 0000000..eb9a104
--- /dev/null
+++ b/VanillaLauncher/MobileProxy/SampleClientState.cs
@@ -0,0 +1,9 @@
+using System.Text;
+
+namespace Titanium.Web.Proxy.Examples.Basic
+{
+ public class SampleClientState
+ {
+ public StringBuilder PipelineInfo { get; } = new StringBuilder();
+ }
+}
\ No newline at end of file
diff --git a/VanillaLauncher/Program.cs b/VanillaLauncher/Program.cs
new file mode 100644
index 0000000..aee4974
--- /dev/null
+++ b/VanillaLauncher/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VanillaLauncher
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Vanilla());
+ }
+ }
+}
diff --git a/VanillaLauncher/Properties/AssemblyInfo.cs b/VanillaLauncher/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..11d9224
--- /dev/null
+++ b/VanillaLauncher/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VanillaLauncher")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("VanillaLauncher")]
+[assembly: AssemblyCopyright("Copyright © 2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f60c2eed-2270-4387-90bf-a1dae0ab3236")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/VanillaLauncher/Properties/Resources.Designer.cs b/VanillaLauncher/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..d5c4239
--- /dev/null
+++ b/VanillaLauncher/Properties/Resources.Designer.cs
@@ -0,0 +1,103 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VanillaLauncher.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VanillaLauncher.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap atti {
+ get {
+ object obj = ResourceManager.GetObject("atti", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap atti1 {
+ get {
+ object obj = ResourceManager.GetObject("atti1", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ipmbgqr1e8mc1 {
+ get {
+ object obj = ResourceManager.GetObject("ipmbgqr1e8mc1", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap vanillablu2x {
+ get {
+ object obj = ResourceManager.GetObject("vanillablu2x", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/VanillaLauncher/Properties/Resources.resx b/VanillaLauncher/Properties/Resources.resx
new file mode 100644
index 0000000..e5fff8d
--- /dev/null
+++ b/VanillaLauncher/Properties/Resources.resx
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\atti1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\atti.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\vanillablu2x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ipmbgqr1e8mc1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/VanillaLauncher/Properties/Settings.Designer.cs b/VanillaLauncher/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..3f2d520
--- /dev/null
+++ b/VanillaLauncher/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VanillaLauncher.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/VanillaLauncher/Properties/Settings.settings b/VanillaLauncher/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/VanillaLauncher/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/VanillaLauncher/Resources/atti.png b/VanillaLauncher/Resources/atti.png
new file mode 100644
index 0000000000000000000000000000000000000000..d12a903a5af506c06e2caf318eef2ed830460252
GIT binary patch
literal 160645
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 |