From 40ecfbefa301d0f8eaa35fa07c55f00399ef4b56 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 31 Aug 2025 10:47:33 +0800 Subject: [PATCH 01/10] =?UTF-8?q?improve:=E6=88=AA=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Windows/ScreenshotSelectorWindow.xaml | 14 ++- .../Windows/ScreenshotSelectorWindow.xaml.cs | 92 ++++++++++++++++++- 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml index d82fcbd6..c811439e 100644 --- a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml +++ b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml @@ -18,12 +18,14 @@ + Opacity="0.3" + IsHitTestVisible="False" /> @@ -43,8 +45,14 @@ + Fill="#01FFFFFF" + Visibility="Collapsed" + IsHitTestVisible="True" + Panel.ZIndex="1001" + MouseLeftButtonDown="SelectionRectangle_MouseLeftButtonDown" + MouseLeftButtonUp="SelectionRectangle_MouseLeftButtonUp" + MouseMove="SelectionRectangle_MouseMove" + Cursor="SizeAll" /> screenBounds.Right) newRect.X = screenBounds.Right - newRect.Width; + if (newRect.Bottom > screenBounds.Bottom) newRect.Y = screenBounds.Bottom - newRect.Height; + + _currentSelection = newRect; + UpdateSelectionDisplay(); + + _lastMousePosition = currentPosition; + e.Handled = true; + + // 添加调试信息 + System.Diagnostics.Debug.WriteLine($"SelectionRectangle moving: delta=({delta.X}, {delta.Y}), newRect=({newRect.X}, {newRect.Y}, {newRect.Width}, {newRect.Height})"); + } + catch (Exception ex) + { + // 如果出现异常,停止移动 + System.Diagnostics.Debug.WriteLine($"SelectionRectangle move error: {ex.Message}"); + _isMoving = false; + _activeControlPoint = ControlPointType.None; + SelectionRectangle.ReleaseMouseCapture(); + } + } + + private void SelectionRectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + if (_isMoving && _activeControlPoint == ControlPointType.Move) + { + _isMoving = false; + _activeControlPoint = ControlPointType.None; + SelectionRectangle.ReleaseMouseCapture(); + e.Handled = true; + } + } + private void ResetSelectionState() { // 重置所有选择相关的状态 @@ -724,6 +808,12 @@ namespace Ink_Canvas ReleaseMouseCapture(); } + // 释放选择矩形的鼠标捕获 + if (SelectionRectangle.IsMouseCaptured) + { + SelectionRectangle.ReleaseMouseCapture(); + } + // 重置选择区域 _currentSelection = new Rect(); SelectedArea = null; From a2b711da05042c0044bc767b10578e32b16be59c Mon Sep 17 00:00:00 2001 From: PrefacedCorg <1876568293@qq.com> Date: Sun, 31 Aug 2025 11:41:17 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E6=94=B9=E4=BA=86=E4=B8=AA=E5=9B=BE?= =?UTF-8?q?=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Resources/icc.ico | Bin 194680 -> 65915 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Ink Canvas/Resources/icc.ico b/Ink Canvas/Resources/icc.ico index 90853402f9b3aa9abb7e211393a92cdbdb32f5a2..e5d9b0d3acfbb2fd32a67a8daa45b064c7ab9050 100644 GIT binary patch literal 65915 zcmV*9KybeR0096200000000000A&FI02TlM0EtjeM-2)Z3IG5A4M|8uQUCw}00001 z00;&E003NasAd2F5CBO;K~#7F?0pBIWmS3gTIb%^+Z2YOH&Hr*iekkYtTEl;>ZxglYn#$0^1>lJmE?U>PD z2w_IKoc*QB724m@Tu0!4?E&Bge99@ORF699yx}v>xOn4pFS&ZV3zjY4dD&Gf_qyuZ zl~28V#f{IuX60@FeC>_5z44kGZ+qu8H{AN~D{i>$Kd!&&w*S2D#@i3L?&jMMy#A&; zKCxouZJ%0x<87b5_J-R(Yg}{vt%v0J-16&h`TRB4-SP$b_=0@>&+?VGe&y;LZu;t# z#>!j1a^(#xWBr;NZu#o+>u)~%YL!uD{>odveB}+dd`0{($4>PV1uc%)szUj-Q6LH;5U%p(h-evM@Tz>scU%v9%o4$0#wKxCw z}A)i{OqO6uRmnj^6NjB`}r^FeD*T=xm^0ouDbR}62z^4c5UAlb_ zX}|FiwKFoh|AMj6H!U0=d()z^@wY4-9eeWv`C2eMvY#;n^HqaR){K6>Ej@ZhJ$ zMut8!J~H$_VwHk%^p^9MUGIi!a_*C-{r5yZMe!Z?@$l zPTqCybiIIVKj*bjJd$6yvV_!8{LZqVz^&ujt$|MOXQLmFB1=9ee zsZa+)J(iM-PKCPQvI!5Gl3G3?*%TOS^8`Gmk6rXjxu z)#r*Fs$^l0hK<@4&D_p@GyjNfP(A|ci2kJ0EHhpZPw|OeL#WrNehEwxhAI(;DitiQ zRJeoI(DOzH2X(j%eQD|9MJH{(bn*Gy@3hBh%Wt^#%gdJE@KQfr>S=QjfO?3(s!K!r z*Awrt$1Wc@_u?yexZ;`{_kZ-`_WsrOTRr0JrHdwhzHoHp-$#b}pVF6b6D{sOhCp{r zlc><*6-{P)*Ydc$GkxN=dcEoU5)>P(>+LOY#gS4LiA&)VdMQR40ifNiv95icJ=! zM3Nx`p|S$UMN)c-I>?cd0*eg<@eTDNvRtOpF`^o!mg`v0kR!MZQHJ~qkaq-a3~KRf z<;S{t6ff4rr!*p%fI^V95!)4AlyI9+1L74)Vad9vDXx~9`SKK%RO-Mq$1p3FQD3sW z3@RH?Y;n_;d7@MCjVKfCR--RD4Tf|YK1y`dQy;P}sK;v7`ci?}u~e3*i`4jpP!~J& zR}(Jk?@RU^9_WAbg0aybZL-m#v$lN14o6*f^$qVh`@+i~>6??Hea#VS|5C20|o?6w3mHQ7;= zp`s%N$(fTGQ3pL*Myz+q3Ykl($I*40hPn!)FiZ8C zVrXazR#sZckRa$z?71;AVQWtHn_z>2AY}zuG}vE#-olB|?{2p7qCfu2Yu@;Yb1quGi`R4J_0OM|BS^}XzXaL?b?KEW zAGiGuyB@an=9`~9F*fr4{%U30K0Q-cD~ayN)bdcIUa2bPojg&-ybU+3fkUXLDN-Rj zz&5P^!W)TfynsfD{BjHhw2m8Ln3t>Mg_n6w_A1;^hfIwZt#*|I?d)hFCP~Qz5Puby z!c=O6s_!oBt5mia92oq-k|hgH+jQFzSJs# zmXQI47Y_qPg$UivAqtry{7OVhS592Ondr<&EvQZ=AQ_)yQT|0l5)kOI%`QX>XV#RH-44XBYiB@KGgo~Mu5VO=ulUanq^S4s*l49hx#h7 z9bY(c{3CbT^N0&Bz4CE~AAVlnT>L-WI?2P`z#RPZq_Zzw`nbKHcHq`qZF0)Q_~?Fp zRW6vzoXx@a!>^)1*XIz3foZQm_K{ZRO>KDnsrryo^i%TSrd*{nLxdNvH<)EvndKHk z@>rHKvkbE+g&>%Ypz;E-13?T!MSCi<)ql5IR$a&*~a`xF5Z=reOpR-$k)&t;Mr<^i)<+V5czg-`()yWGNjD1L7@fXvlzOW$&g{1CU zy~ml%Ybjw#rqcg_pDTrcmf4q1z0?+SBKQRY>(4UIZFF0X&15H#(yie=TPEB@Y_U)E(OsosiKobLm{w|B##=K82j?Zn{WI5GtRwySIw_>K%wxbDgWdR z`Xk6czxs7AeZ*E9A2T}K|I#WkKz-E@NTC4`)bWrg`|~Bwl{cr$Zc%u_q(Pg(D^?{* zu$y96p6qhIOhGm+-Tzz^3qpS+Cp!;{s4z?B7@MtiD$8vrGv~C(STLdY-E5xniOL0e zp~lZ8mGL_}_f=)dnerqV{XTAeSc@c_wQ6@bh4PdE}Wx zQRz>V{YiJ)dFNfV(T=-6_LEB%E&4`(e`Onw&!4ED|0kQFRv+7XuBF(cDOv^gpmsH8RxodAh-H~SZL^Ad@l|Q$U*7ZwFVL;nty|&C7-N?A6GPvFX z`IJ-b1=$w9q>$=+LIL{|D|_0|(|~D%q)fA?AwPwgH)l|qY7#~1whgi8lYDoNck?c` zQ6~QyuBf6;=C0kaNeN?r@_OMz{j#)54vq{BykpCa$A0vOb1vIOJR7LkFsYlDhy4K1 zWb&fRmhbtPAAoKVc(HdX0kDk1^Ls zd--X%*Dz(Ql0l;#3p-gk@!rnNFEEXIi#uB&sVW6m%>LSy5u%$U&7<1@TI( zV9H7^Az3WjGlERO2-B2;dzH0FP&Y-$@8(8X zn^f?Im>!w}*0Y_vNo7_cDJ`ccG0{Y1S#F5!x*&h7GVDCQVDv{9U2)yBwPte#>1^PX zY+!#4cMdj7ilP7j5CBO;K~(ypE3esS{{`pk6QSlf zTY@sC7G|u7$v_vSX9Wvj@Wh6m*1!S)V zMQ*Wamk&EQzZSHHyBeq)=3i)R*JT36nl zEn3mag2>fuiFRBCn(I`8Xq}ffG@_j|^RC#2t>#ro6CQM`3+nXi{lI`pn>wgIgX2t-c(6d<}GJ0n2Pq1na z4Q&&>E6LJ$kx|wtTiT)%vJ%sIW=B%5HHkJ*lZOp- zk(~D$DmU#2-9;nv<ZW>>^J+EO)kuW$BWI-|DYaHjU$_$6EEFkw`wINozQo58;7qhwa;W zuA4st$kzBhrG|EDn-$yYUMyM?r8Y=vEIQO03`qgTgkG238QtVDE(u)9P0JEBPa*}S zlvhY=MJ`Mlu7y-_o5(%5y)xt>N;@<8E1W=d-cDK1hfVHQL)b+@%GPND@+4o%ix@D+ z%RbadLpyqLCQjz7d;1crHAEm@g`Ud-7Ua%Enu~@-!FO2(X1^3zd=g-~@xldT-#q`a ztDii((cCpQ=mBung;#8|@sf?c+t-(D@1Pk6fQp77GpO=cov7#y6*0v{B`TY65wO%S z-3sd(1(zg9!&|87p^&?j)J0EZ{(9MFX3Po{rK_e3D{t?Nb{?RRtkOVeP_{D6DWjp# zosdIYbrWW7E7wBrD(~RCUBZ8w`V=YnW@D(~?&eR1MrX#v4%ZtK* zQJiX7MJAD{vXrD=s&yf~i!!!1s-6Tk8yg?{_Swsp@0@WTdTzfD-HSY&cEJTpw%mM^ zBlN*3Sf@ceD&w(_RpcF-mBSJXIna*Nn4|_lscuz#uix%&{bZSMTdJ+tD^m)%;7BRG#<&sV?PW?@^DW!ayBCUuhMUFSU7*Ov670cNt1 zYZ%?!7IsCMhtN$mpKdy1H`zA|xfKyqOy9x3ZfGJtz-lo2wq0*}jOv*cd@( zh`g9tkb`0v+8hM4ibbMgYIM@F$mz@^Vzh0FNH!}a%HxuTw6W=!+nHZdYb6Q9pH-1v z){V%jUGqj4ItVk2+^j@uksgmL~6WLmCN}5#b9XRJV%p6pKT&98~ z$PB7>BwIK(sQ|>xS3_P9F55A)3%BQawU+7FX30gAmFm{h38)mcqk5bl9gGb1{^5~< zkDYb?)jLGJ^~`#$l{vZl^&kE)wq)ZapRH7rrDX%sy$~laWB6X6VznpB3PhRoV)?%= z%g1Dn{fZMkN8Mg0mB+Q+g@-p)rWDP3=|o{+Y^4I`#jeCGE=scsc%z!8CDis(Lj}+L z4F?6Jq!xO+v^>IDrd&THL|1*jJTN=~mCkZBrmqJ5C ziYGJ}>a;s<$fpV|7xNklb0Dm5^icI+8HKnQK$it?w$k>-YbN(N@n}Krn5kEQp!bY-$_Fav`B0x*p8G?gykw?GM(z~ zx*k!|^XMApx9FHL z50q_5c~mN|DKGB1y0bZKY#(U5)R4n(hqWjhiA`$t6;x4XYzYdYXK6o>uLfv};t&t- z)f%fevo-+yclU$dw_2smNGyvwQ9&`r0aO`PiZWKREb57jWg*uL#k%+%snD@Nw34X^ z(Mpjlvi5qx?&ISjsy7@79*9|i^6iWWxh8IH_MKcXv!N|)7UvZhv?hLJ4fK;CZbyNbk zk{i!h1k~lTuDgLzyxS)-kC3e=!0-8%8>YopVr<8Ywt(E^e2cP$C@t}Tdg``Rx;??0 zq8ozykW@*1uayV6%yJQS8hwHGS|DQ;c_KR$B9&HEk+TSrQPty^>Kjn3tVc$&;j1tw z%e)}DB!tQY>OP7qRYgM(t7));NZHClgh!mRK?y`6IgrT^FVX5N#iL8f0}$JZBUUt! z4V)y%DC-&GSl`WqxlFur5<6D??WQ6dvfxB^%o6P*a}7l#N5SqIkQkMOTWq#y;{Aso zez?BFMYB0)(dV4CbHyF5xaQHr!^5wN)h$T!jf0_;qK2~u3LkQVVEg*CRGLSP6lLvP zkiGI!vQ@L1dlbWbK@4w*RB;%lC45*?*5_v2u4^z5)V4CXUe~y!>Vv|HF(m$3S{19n z+eU*Cw5d~_#u3_~J|ya>B4tJ6pgvhI8n`zZ7$vrZtfMDnW2|D96eOq6k-9KjS+Xqk zrNdsbj2AdGIP}lEKYpLbXZ0+fOFr)d!2e0F@reZ==&L3RJSd?NMAjVH+J(q%(}}!! zW_D3Vs+0*QHbo#N>1xcisCSZoK7oTy^b@xM10GoOAvqIPI+SaK;}mz&RHz!-dPP z#+BEs#0@v!F5T6#Nm27+*RoCBpzmfXvuH#($-i3+>RE&qe-Mxb0Oo(9s`!=}QBHF+ zFxLyRvmcU~KzZbeFR~+9MiL|&GV_cEqfFS3QScPM`&MTaH4Y#o{iw4a)1ude0o=8& zf}7V6*WNXSt8ZI_%Wi%Em)!IqE*37mX$>yFbserEfVi<#+eH}dWwSTdZk4vnioUkEQ=8@&x=|JzZTd>R5hTzP#DdY0!4DmO z{QN!$CQVm!qqcs;E>D>l9eg2mCn*B!uxtx5%1e_Q>vPQ9!8G4=0X}jvU_Je{Hyhd+ z<@y}j@InveO;NV*Mtf}Bs9||gnpS(MCUiQj;NI0!xZ>KI@T=oa!y#Y%I^OZV|HLcb z_;$SFb#KP2-uO1W?#=JUTi*44y#2i&!uvjS5Z?PA2jHFW`>=TbjyJsZJ$SWsU;kF= zz8&xS_mAS>FC2zn9(xKdz4AKTdHEo4pPi1+|Lin;>PNrF$G?3NKJgvld%wdMettH7 z{QE0$+EsVriaVxo&r~1QB}14_2K1y*)%It$t7D%o3OPhJJ55pnj(hG~jT>*i6&GB5 zDSmUzaroR9zKFNJ`~7(Ro8N)={Kv=eog;sPtMw!?ttSgvBAX*oic`7jK`>Qi8uUHK zWC@aLO}FM2lT`mQxNeZGb&rohHu!xI|A1Ctb1<-#h6d{P&Tk;&b0W5#KoKkNCr7H{+)J>sW&! z9R`E(NkiumbZ!e8i!4yUrFuc3kylSe{MhW=8()(QZef^uo+aIrZ^&2Bz`P%*Pir0vK&3<^5bYA)TH{n&bRs9vO zd4u$2^M<#|-3I^he`V6YWR)JMO+ucllHCj`x2AuTcC4ee$z7 z@#Ir*+wGeux2gaD5CBO;K~#5OYI+)Vtt=mkbuSD}w#>Q)&dAkqV?DuRX=JuR{gzB^ z*J^d#w(4%2b>1cT@)6&~{_l7{-uRAx$G3m{D_no;-I!Ehw()|p%b+<)_00fj&DB|9 zeJfFIxtuSez5A(t2R&KAhozio$dGE&`wo2fR2Ao}xEqK6>MR`ewcp0_)Jt!{%GDKZ z;vuXgWHsjrBLiXyr<=768%_>LEJdmhjXsK7vDSi zVtnQYr|M8R4JYe>xaENwYN*EXO+%tmKq60suVzcGwW5%bo*T)6IAw?xli0D89*kH~ zR;E>T8W|qld$%Q9JPX4^O)RsfWd@l{UW44*?4bufkM$$#1I~8?DHXWJDv>q{~#d(dMNDld* zBjTa&YJBS3C*W{Bwx7HFF5J0p z0BbOUY4jsi|NNAddLwER+K-`DK*i6@BVgwMtP70`d|DiE?Ufek>Z=e)Z zgEuRo&cx`Mb;5&?+ei|pO&yDa8YfYUODiMt<0Q!{Xh9=Ka9#G49vzQL2x%HHr9)(m z9-(zM03_D;vfIM8OqV@+QlW(x)HW2YC;E!z*W;s~{5)R2-`nuhpZy$n-E$vmI?Pfn z#2`mO-&P90b1&VhF@uG~p(KvusF-40kT9v@!8KF(!&w*L-#_w6y!`_Q;)GMr!h@4_ zY0(-D>lmkFjgkg?!w?EG4TLeR*N(N?Y}f0N{3pM=1fTuZZ}CfQx*P8U)?!$X-&G{K zqgQkfreaA12SJTD6(2mmS`z`5W`KECl02x45DgG8T)>wI#R2mS>&UOi%Qk6BOouA& z(5uB+*WZUP9(5kRq1TX0ZeEQC6?08bE70Y!QjteystL8wtn{SZS~sDsg&0>^Cm^X* z|Ng1ZdEvI*tlD{VJ^&Uk7=4NE{!8Qdsoi!*Gu5q5Di=tCWShF`aj-SKMTcCrX-TS7 zbXKKxJSiQ>WI_B?K-3dY(~yQ5rt3AVom>a#4j7=esbLUEf-C{eE67I!Vv{93(PG7v zDo>@GrU4NFIs$+jZ@&wl{nFR)hPVA2jz954_&vUkV#&&=Es=zRLE|dwu}nby2^zBq zDTT-9-uK~yaJHTZ z>LIg<7E+JOfQB}&6h-voiiEwAV=T!U<7(S{187yL^!m?cYQkw@{FXP!AU zIy@wYvFXU$&>6w31NmS>b(F4RaNN-*yS3KJZ^}G*mQk7MR4q;U5Lmkw&;V+##X*F1 z3ZQh^TZ9%ziQPeF6DnU)R?_Q79l!qVDf*!I4*clIU*N$t>)`f$NZ8o@a#_GO1>LK3 zd_Xo{Q9owpmZ2DsK?R_N8lp|6Q>G<^FVZsE(|w3#96@`U0lDv{M!p2ikEml!=*J(gxf`GR?s53lsh8o7)d5qXPva(C>o`my z$VqUY)Hjih6ueBuM=aeRiSoXQ5+mj@BMBvhtfpM!8bahj+bKi@xYNN}{*K@>BC0F1 zIMu-ftib>-x%obP?N_JamuFn5L#wLT6Ft2Kcx_OdK9Q}CfM^#pwHM2B)(oo5?M_?Q z68T90Bm@Qq248yAQRfYtJrk@ylRV0X#+U9o(BHQwNev7m?;&UM<%L5s_sND!^&_VV z|H&&4xzH4NrXtjKSf}p=*^_`+(K}<_o=LZz)uXN!yjCO)x&wK`eCXr7at1$gEJ;;=TQ@2k^Q7{t6EL$~SQL1M9?Q?3al3 zPDEX{#H45;kL-Vpm? z1&yK%nn^a^fS`Odxf!L67x|Jgv0TcQ&^04R&dX~( z3o`Q;q>*~@&CyQkJ(GReZMGOa_EayZadrtE1Hja}DNIdG#if?2O)rH^-`1GnlBV=i zdAskyNgVRuhvO?>Ib1*K>HC6ODSX6IUV?Zkx+antzbLaBpgQ$R5un(GMlxS$)I}8S z0QS`lXk3LqmtK$!fr-3NLG41mRF#T$zm#h!aq(r>-~%7|1kSza3LTbSMnsb6F&$kl z8#mY$c~eDx>hk@d9`ApB##Q*?ap&Ofwc0j5oGq3dLT2iIs3LxQirvqY047S-Ma#vk z#S+gP>56X(nmY?K+Ef$F$y_C_mB@2OXRUJ*9KVzuZR)=PR!Oy{Dwxzygcsd#H@^Fu zGjQEKbxi9?0J%Nj?TWcwc3eiA73@p$x}M%DmA>tkVt7Z)a3wRyqG)_#d>>GsUSq9G zRt&yHjSji8ekc}jwh7nIM>i{ti574WpzbgzLpFU7FK7`5OzJ7X2SK?@nDt_OYPe_h zT72v?|BYY#@>lwmAqDcWAd6No>qQcYep*GxH4h)MC+DtTG!+V>y)0b0)WD>vH3hYC z+p7EUssH*SPCw@o_$Rwe*6yISPHl%&uN5`kMPXLU6P zBdcj>9ZX&+@nN=+i?TutrHn4;X68^4iUvem%Y{+6H?36z?QIl1p{~ z{riG+l+jO6BG{>*Qg+U8h?Z$qQv49uw+Ua%h zUnU~Wn`ufc3-J;7fd|*>L*Jn|;p9_d-2sudkCd|(c#|7tCbe-j&QNS+cBBhWu~KC6 zZ@&7_ItNiM2{pB4L_XAnWbozqT>{kDo11Y=A-^b@r1{{Hgu|3NvYAS8*S!zozxBj( z%k8TgaTGDRlp-KI31y-dv?~IL2lQC{(~~a13FlsmwaEwq6)$woluX&`s3Y9wQc{8B{;4$~Z_nU`9f zdcCRQw#hnvdEA+}>%KL*c~DOkLAolfyn#S^-k6Mzj6P9gRD{yuy{EvM)#~E0zW%;l z68GMWxk8P{2`}_rH;Q_f(gPORA{dDcnaOFxoxB&-ZZS#bUk0Y8rnMQR+pxr!O2cHMNWh$!kV^=1J77qbh$!^1=IW-&dTy>?1H zCa)VKR=Q3{0$EI|=`Vjg*O> z;v)RPt1h|Lsx~{YcB+O$zx;Kac+$y;JS||`rm7g8NP}cHc6n)?7KpD98!YDcgRG3B z4>?dG;w61jw7?_*6K!~JdLh8m9<^FBk{}s*B#{UtL6k1lHED4Jm|N($OcH5oEFk!P zRmgYV;ZYm5Id%X55CBO;K~#ACYhHnhto-C;Kwd*o903{^jkL-jp7~Sy_lUhipAB(#|9%#6zy` z!frIxnLN+6RCKqt)Ie0XsR3OXS46=OnF=v}9daVkr*8ra`-o>gaW{-qrZK&464SLB zQau@!*No${eg{gv+hyf?w3kmZY=YsieOXqflX9h<9vd6nIjL}WH(W|_2(X=4;qc<$qO!scU%{A>DUg(&P zOl8!muI+>w1C!otsS+2LBO^#=>Was0krYp?IMWniWCfYis`^Bp)Cpa$)fKvx6`6ea zv_AKuWjO4JZ@~X(DFs1N7Fr&XM`EVTx;eA#Sjx z26X}e^#}PSnmMVWuJ+w#g(*gd2l3YZUyIFk2*5vmiB}lmKRc) zyS1VkOYO#}P>&%A$ zlWgVN*6T0xRLbSARGXD_3xh+|J$or;t#y&ce@#T}?m)VTXJok(Nu>gpy%b3eywR@U zh>dpshN`RCUapE}8>I%jR!=dhUkB=b{+FT0&Nxr(No1JPiH9TrOw8hY0t>9n&>7{t|t~(+@ zU0q09%!6t^1g2_w5)d6&#l5u(et68;xP5h^cV8kD|Ju>Y(&?QVt)ofx)}D)`(WE=5 z*+au~xdqWt&W04TTrA{81ChaKUrAEzzSR=!z4Mmn!#Zhd3^Z(BH*r|SSvR!~@##sl z$2k@q89O+gj3NNIZT40Bw^ut|_j*?*bZx!QKK%oI)osWw4T>j+Ehm^vI#OXtooYtA z0$FGPMIa?syZY>P8*4)*Nfklw!?cBY9)_HzY3i|FfbUx7=kT!kdqApZwp0N{$e(|* z@?R8+cNHW!;@dyO4L9DXHWFxmAl047<6$@U;j$Y@wJx;E#FI~!fcDEaNd-_zN?$bn zJF=n8Wj+*VERjdxRi(#El+vrKj}R(J*!<|D&+q!b5lafg_HxVN;gM=3*%<0%yR5w)Iv5!z z%iD#2%6hj5y73&7Ml3E}(`BTd3e>g9*Xet}S?6DjU;XB2Z4`jC4IZ|OB&dZ+9cc7{ z78ha#l>`{51`H2WuwZNuix*B{$wmvYaAFi=BLnE~OQb`P(Ddm&Q~lD%AXl2rD z!(x>Sl1YqWEvjK1l0+lGiW*6ggt{tqZO~M1gP>~6C03%)D+R@4d6ji+Is`m_?_Drj zsmWJeCPC&5D!J~+@nHZ)Wl>t?3zc4Gr0{o`XvQW-)i2x@eU zc8ebE%9Lo)CmW_dL5&6@Cw!;M$@M6j{xjpeu2Zn^+hgc6_4YgkDl#DGWrVx#U!&i= zzlL@GiBP(QPmw*7`)ECv4JA)>18Srp=p-nXo-&BNqkFR~@^Z2TGpFj8@y!-9@J=P$!nwF_T^~~Y z0-zHKVx!w76Bw3-#vx&6=0Gyjf|U#%RAM4tLGdV=4uPNo?ng} zu5G*ynCCTQbl8*`vTN6k;}|f~Kia>ztXj}XL9~}+BZCWcRu8rC9a+vG6>Uy;Ev##F z6+R41#X}Ng(It&WT*zvRn#4R7kz&j(*^}Y5m}*LoKJIt8dc}3{!nTKONto&llBiTF zAe${yF_wY+A_-FPqRP?VKY+*Vu^T@8{&(WbU-%3T_|SXtvX{I7kK1!MY_<7PESea_ z_;5c)2P;@KI*84dF2YWa+!oJ!_EYihx4s^Se)eNHgQ#FDld7 zh!F4m8Y9)4$kvstmtT zly^m{g=8UgQ*ItSHkkb;JT~bS+{@>pDp8x%WQ&;upVw z`=fCYclKmGqg_)6t30YrMFc}DiBwFES0!21<8~E~ee^E)!~q|~ClCApp8DjyuwZ-$ z32T7wBve#-w}iG9L>ob6sxR`;^NQR6>QjHEibpOv8zzE8Tp@BgArLY}(WQU^SQXG=Xp~J+pTGv~&pl=ZsJ*o|) zYp~q{;2)m43tsj7Ct~j%mg-SocXILlcwa$^L=76je`mu`J+0RwzoM}m(2L5DUI(^b zRKauh+!Fu#+`X{xZd+orp&F|Ca*ssqDs zI5~qAZbDsowX+~2FUupj0Wu9_?zeC@SO3|>ZnpT0xB;ca>iu6R)qlXrl9fiuL}VQ zsyg@3fggM8}q!fHj>m&3DbD;E?el;;R$%^qn2U} zlkgltoupzQr~@r%f2F42nEDmZ?prL9-8LBFI`Q3iVlJ0j2IN~Ae0dJntX&Hq0;bKI zGvr4J_E$^mo1)9r^8iSYEOLWnTj1^WE>7JE+q$$kmLcY@Mv#ODFjiW!R=pNcj|!=+ zEp&==Uy?QAQ5pg2Kp$Iw6{SnaZDuhT3)zYf@R(?&2AO8vz~^(fBxUa1ujubBBd!5%xJB}@2}&lrxToU z!BzSNpg%Sr2M^LvvOb;lfMpH0B5Yz((sF%y6Tq)Dl zDi^w5c2uUbS+#~hsv1P($&nYxS#vE~+L)^mJV-`&14cPO5(?A_zFcjT5}9s+yQD|s zKb~_QZo26v1awnsu>i>iESXz>65ZvA9Ui$o4*2ls-4Lve$~ z2YNSOi>(*+;bqTxJa$+*h-!U}w|q1p8TDc%#C(1krLJ!nffda=)?&A<7UG|u z^;m2^oM0fGgv0b*zXrXwp^mKvr|^O&?t%sV)9^S4&0nfRh?04(3<+jT8mUZ9Xy{Z6 zL1$5lHEY(!zj$V${TQaZfs}DBke-H(qj|NZ(2TUy8FNst*bUD3#p)tk8=wYS@5EBwd5|C>JIEk;E# zSCMFuOW$&>OB?_I5CBO;K~#$;0;ojULe|i4=Vk=Al3VCqW%E2 zKuW*ty5siv&kw!_+ibQN)rwRVb0r}jwcVC@+nZj8A-^Wbm&bzY8`DIOycOt{2W9Yg z2P4({Gt|F|{7#{Qvo5|?o4?;2^(2uEk)%ZXWsaI`u+;=Y8Y1l9NRY};5YnjUF|Ozx zdy}y$Uh>Snu*DekYt2-YL0SliR}jre$%`H5^h^awkb;${I4Hu0faZj9+@I>unE+n) z%*SBMh5jZZ-&RS0Mg1vW_>|qTbd2gVK>Z1kN@OVoWS8SNQgIDUFCsE=bZB{GYAg|b zRN(&jn?UiZXLakfqs%u=(g(-9eg&Z3I|pg&ZqQ)%l=aY$8(DVU#2TjtJ4DJuowbnF zBeN}&TpfcZCdfgMG-yE^RH0`589w;FcVmmCi_up}u*s5zc;{Q+fQ1u!YK(sDDTVDace3`1g|7g&Wuapa z>d)=>O<}p70H}pawTuXKy*vgj0?m(-eCAwN)G#Abq^eT`vv4rQi?#VT9j~IIeiR0o zUT&)*2w{z3V^caXVtmMMLmwgN&t% z+#b5*PkA}Xt9q4bnl8&Ct-%Qf66wiaN^Y#=fd2@-kMDbDgVu?sH{$Ar5H+76oPnz{e5`-YhH=%x7kA7 zu0br7QhA6e8`l{+s7*vttz;W`>n%6KzrE|Nc+}RL;GJ*VAKPrPX^bTfv9w~!2fVa-4u$9n|~xbDpphwqDqeq&|t_ zA_1bZ=+wtz>|FM8QVmmBs-Fm7tULa;;}tyn(c56BEhhB+VI2~E2ci7*vTf&g zYlqDH;UUb)!p{2bPXdLkTWNh^q?@eQ4p;Mf0V3O)?&d=4bsnAV;X!QoRE5%9++~4f zxlGy;b?0pQvyddTIx--;w4@?Yl(ACEYSVR`bKdznO6MBfP3X*1|`%iYwfS>J$2 zHcbn%C?#>*#@fm39~6~DYG12a8_06q_2JhknJAic)MYz*9RSc1Ks6NBB`Z<`UaH5w ziWg_6C`TidYj_lp>uJC#17z!36&0<^PDP-m&RN zfA!hH1=Z6MG^J+4Hd%D&xXdpAP~A*g039(A>X%Cb(h_8(P(-KbuMi8yhPBE3xF5uW z78GJ>eduGL;rNUwMDq%I|6e^>!_9Zx6E|j4Qc%%L>`M?UtBFwZQuFkPMAl#~RiPxF z`lCQ61_JikYZrZO_d9=3JJ=u>sde25U@k5dkH)g9Zy)0W3H+;oJjhV%F9@RMnn<>& z#&s%A&`3qvgC#h;pf=&T41{HCCnw{7x56}nEi@}CO;bKpi+Kw2po0#|Sdo)uNmjJx z(OC+lde0y!Q)UXHRY6{hyn=Q~5+ozPB@>Sn-)IqZR;)r29!&MQQ$ZXW&QumD*g~5= zXmdr{^;~FQ>W#+)G4lXfrgk*OrdknzR0DnW@@uhr&6=nZ$3*^H6(M&T^xR*Pr^LcA{m>2!N1J%BKzhZ?X)oo1a5E?MdOnhz=x7vPE;* zN}1}X+cTh;)QS#`x*ADUrDzC2a4E>Z@83|Y8DycpqPR5nD{s9!|KEv)oST<~d;+eC zgkjo%F1slo0t!c5CnB~fMqj0lJs-6>HklZZfEs(~u&PVW2r<_yk(|}e^J%myHlkO@ zM7tAG5EWw+857B_@sZv6Hi~UUM|Pc!b5>0dv<_24bLl-gwQeeFPyTF6Wh7&pq{qpY zV&VX2Ey!1F3$JH|JtPgj1|SCBuGfp-uBWOowW&T6Cl+Gq!6+R+}wX#9Hir^k1mE|6aRnr;lvYS|cf+*M+2F$%Xzou2R|w#Nm3~*w$NJK_U#2=6tYNn z*(6bJz7Z>$KhaS?uV;l~R3~)aWz`Lo2f4K?HR%H0k7Uk7=S3-`8q}+=Ss@A_3197T zCA#C2jB=7zfhtV^h+NAIAl7w;kq9daK|3pJMwMAo)RjJ|=t{al(MFE5P!hC| z1Zj8+u|+adCDUYXOK8vK>S{+5mdb)qPCn$~8nVECWKY4o zphasG`a%8@JvHt8h|TrkZyKKcME$e6+ivJ-UB$Qx#s)0y*O-e-$7HnYlH!)oE}u`` z1U!!jVb&a2x8cL0v+B4k?JvR9P(y!X9%C?jba@KfBCVr_lBT34&QPK*c z4JH+6zR`KfMzX-FPP2-Zuj-vjy*X0X4I9YY^#DRwR!RuN5kw|d-FY|eU;UukL31E; zTWNG8TW3tlQzB4R1ENC{^08>qBJB9cM?jBdNFo1iP<6%>ByERVDv)`Uk`igIh}cqH zL;-tHb%w-H(ffZBg=%x|B|}wx15zfqe{veD*VZ&%MVq#8I~rxL4?z@CDAxu~rDmx^ zED$Zkl&VSjvNka`RKezp$7BhRL@~la;e)VcgUD14^5f>lsNHj)nBE;KBMPr&o z)axnMPOa0pNkQWT2jbGoU66F)&CZfT(w=8mov%h5V8z~H=jOWcI}~ST*iENKyW^k( z;4ai^Ud#c0)GusI8%2G-B}r`mh;1=EG&En+KfAu?CQZ|39Qm*XCJ5@+-S@3VO$!jB z+1LtbTv5Ht1QeUSp(sKwltZqFB%Q{l+Wdok3A&i$FXK{VMbLlhfYfwsG7fM+UF+8W zb|CVcMZSqnB%Q3BQ_0INh1(;YXF}@MN;d0WC;3#!x@MEL+LGP1^ z%BCeDWz6>?Wd}j4%xjlgtR&$-_C?Z#;PzF-MBH-AZ3?l;BMFjG+Mbc(8|{LYx^

@s%T8jQvqncR^9V}ev%Ry z2*OvEyGN!Bb2GSRiTbQZR{JoR5Q%<{q)O;AuMgAMV(B9EtMod_+O(|{lt}xMM9O4F zi#=m1e2@gm8Feir8TClI+5pL%-(by36m8F{ID-P2wcDaX*J1|Wyw- z1B=^`wAEvE=be8l_j7nzMwtzN^VUI(C2gRTP(C`}5o zE6IxPc}0dgR9l3hrIuH6C6XYSGgXMD4*`{`#YD12r}Z=>Bvhg%J4KrNMZ5y^pb6g? zV%gc3s8!DVs7_KWMXk~lU~6r@_tN=a&V8>G8>^=gq?#)`o)mb9P%8z4P|87SWb z(e;uaIYeKzg3XpLkybz|)wHBc5+oys?9q0Vc4m&T07?0-qn^|vQu=Aboh#cV8slmM zX`sHdXE9}(SsY~x>iY|0e=}}~e^;S~pv@ojF8aXQbrRT4bEmOTr6pMcC|7*V64|AX zd?x(y&oEt}k^qY*Mghf`s!ft0S%_mv5{cIux?d!t4cS^2+GH!AY^@i1MJcIzs9b}k z^A9SJDmN4+j6%0p8MG$K=%q)h9WQ(-r24{Vh>R)Pr)pgZg6AP zDYmHIktH3RSs0u}u2G&%M&vCxBhw03f;#X})0n4uu%Q)=A$D#Xx0AJhck zQxkvw%j4CKhbyW8jhxb4{ae+r88m)6P`PfZ=5RY)bY0;~mMmeK`X6$)>c`VY8>lE- zrK+hh<QscwJL#X!k#kuKa?U>ybNs#QN)|F3E!>@+AN;eFX zWQ>csJA#p#nx2lOdaAN5hTNukC|GVt)k)tFT(pCsj={cad~!mZ`;tw&@(gv4XMq{i z9+HS8NcQwG@Al=2B>boB)CWSlFY`#2)go=ZdRhzt>#ggUMXmM8f)1lT9Vpdmf|-VkBxcO376(CoclB$uInq;>oX)HeLYrwyWQkkW#c|;zU2DrJA^{0FZ?9QtO&XLXD%iNP<+Hx;r*} zO6b4$RR-)|?}lt3kydLe^cmS9=H-kP8&dXGOb{@*_3Jln%88k z9~JaL$sMt~RuArm(aJ4qWF{lCvfvkG!FCzwei@c_>RU2Ut*ATs3boq2VK1#li5j2Q zZ?tudAK7fzl+miaVQUO-p^SF_mX&#(@i(PJ<}c@{FQj-03r1cR1woO~qX|Q+hmkA6 z3@Jz_t*5A`L0Vp}RN0!mUW``mpQzRu&Y!5^IW|L&TW?*DXjiHBVbC0Pm*u;Y?9zM7 z3chIHK@B@1yXaf6o*)U54eOxx$_s&Hn;cNT8v5;o)TNLOSYKbi#1xd|7dZlEJ`|_{ zkC0h=vgdW{rZJ_TW>PI^yNqqND|V@qZ1%;Dy6F6=SpId!DB7b5W&Kq>shRFT=(?1O zZUl`*he^(mTTJV9Y)Xef&U#1%$>uo96G`Rkm&m!Z`{Hb`?c8Y&;H2jf}hvm(ATD$(G4<=iB2T8Ch8#$sSpz;lZ+>p`k&@If}j_ zzlh%B0$uiEi0qoyt((N^2Ugp)adfzqK_@bj|VgMuzf zFVbACt;jScr>3!XT}_8bR&P_9bCrB(_T`4i4d<)u*RD1#OB57%a7}23A4j_g~3Wyh*xkSwc8DtHR6kGz4K=TTE zUGmNUz6aI-1k@1L=OS&qK9-#}pxXpF3-khyijhUQkw*W2yba=%KSK%+W?WIX( zUbDQH*35jZwWfmnDaEA;xZBh^6>?5g%ne9l$wrHjsEmAN)-*)Ml)!(=oXGB(6|Vf~ z?ElJ8(5TtkSl>n6v#~h|g0$KpmXaqwL#k=c038r%4sU!Pe%`)8-xjF8$PE6k2_^c# z8j8;5e9NN0IMzj*=0X}F0>u?VL1m?UP1h6Ldgr}}es!p4g1_Z+9RW%)MdLrxpjtC| zCp2q0wQAL>pqp9t+Mo%@*;(Ow`y^$OMjj_yI&D*#$z^Z3R#sN;nJaATqN|q{t5kQ1 z7Dis7mzLt7>W15lrRuQn9<>RQA;OJZMFTy>Sc zqdF2p%sg4g$g91J+|0TK$eh{RYF0_%t5@0XAV7B)HA_9EiNb>M5$H~XmT`_o9xby& zUW>)-Sw43ut5|v4-KZye!cbd_n6@m_!T!8sp_EXl6EjUQQw1Mc@l%aT_@YI{2m0+kkYmz%z*e*l6fju)< zN;JUZLw%SS9YW;EvWT-NZEu_0L>kab1!5`lI5sGcv6UrFl7Rcxq`2m$RnWA_jRl@Z z+1i;nf9jO2yNA|lFCV1)2MtA5Vjfq!Pt`rNJv}7dB*k9^_Qa8GLCok*6C#HsWAJ2F zsv>S{B6C^6_No!$d!Bd-T+TXYm!zZ?DLTax^~51FzDPC42-8NU6B@j%uDgjA7eF8a zx^h~t6k|gJ*m&b5YRC&M=a(LsD4U2xLs)7XapQ{@b%|J)ZY+b`sm*%5j#ExM1N9(z z&dXxLoUWjs%?f=|J_LQ^(Z&k`a#U0nND$)Krbu-F7#cmycE#}Iz9`%E^&JpYED#cn z*+3PD|F1y_+WiL^lNw8vg+G_6>zc=WXRB6DYFsw{uL0FGu9vO28FltaLEa=nqD*oz zS`tZ+Y~elBipRSQGV@>Ntxp@a?`B74{w*tXToy3D7YZGh{yP-VaP`vlO6@9R%Kol` zS(weRr5Go+vvsmXONv0jDN1h@%;O>nGDBB0$I@LOZV@9zLwm~cv%v) z)J9Y&$|zOVs9RI@QX(l610d8h#d7Wim*D1G??4(kVs=TMz%J|!!*U=S##6&fpEmxM zo9N?dTKt=UhA8$j8^0!RCW_I*8idIdRa|%Ly}0GRY1E(tO(O>#I@uEeS}u>9Q7}pQ zC@TL4OR{(WyB+{zWBz*p9`^MdEiLfEGEPLPPPPU^5+pNquMp|FfXa;7nn!;*tDuXY z=SVhv0OGQcHTuwqLlz;@qU|5>C0^zy=>e0Wai5@M!Vc~^If*Xe50M;t*&N(3N;~}(xj6GTzhTr|1DrQ z{cfAp!Fdw9>bEf)ddviQkyU!+B;k#3K$qK7(LG7GMWDywSnp^kfI0#~6b9_J%T5^5 zt3a%-cV>?sW|vJsE&cxVGjaJ<%K_cdpt@5mBSD~1qW2X7itdz^{K%heC_RjKQ3z5F z@=v-QRbmoNZ>w05G%Hb}P`cbkkV%BcEv;dj%@$*LP(I|xsuHVE49Z)RBu+x)hnQzs zPP_2Ds*74;0kyP(W!K(@>+W~}^#yeV4S){Hn*VFxXuG^J+gPq%?rhGG|2RSJPysQt{v?_2plBhv;a(F+Qk}_Q zy#gc)vZJ&wQgW>%4Fsr1RjArfRG5CRrk*Fwb{{I*G@CA2fXz4C42dR}{$STIXcE?K z)=CuRNp=wEkAXr!MG6%p^g#eTI5~~OzVSocw|YwaMEnFqqH(K45PGQ&6%D2I6+7}v zp+VopB1}smmz0a_FZcxAjiK#A*%vl0)c~@Mo7qq;Pfpiy*f)QKORl&MRDYvy@gY=n z2S(c!bW;h5+R5RQXnY{S);a_T4QffBIUOj_0u81J^Hj7X^U5fM_7?j9YE%=f;~>snb{#HTc`s`I znKGdysnjXVp4>*EWx5?CK{iq7&bRcF?*RuKkPT?bSgWm6%gKB0*{(w|7tO!W!kd@T zEG?6SH#FvP(Yms8F(35xRj~J7k3rDE0L&8D432GSG~*yB{X{Wcy?h0}`-7igx^4~K zIfEoh5;v21(W1$E$dsGY+}O1r*eC16H-7L79CylD_}u>-j!Un;5q16k9*`}OZujtR zG4v;Ta(dKO+5fsLj+?a9Pd6v3neslmFfgb7QSbj%tXwsTQ!iYBwfcE5WX7^CTA=1j z(W-CAFEUr^QP0_PDBOldE7SmCDy`z|D{sYbFS!lBJnL#)dCLPJ6U3WLJb35eat0N$ zHSQTy*ISfyv-IBtEchWGNcwAc!Q6ml^q;q3w?&t|IasNf)qpoXS!guaJqePU3@r$4 z-q=oAQ*%jD6N#w9L^N8jpm*9Q=m6-eYM8W`yXlZ^cCJ(UXyq5RtW@J_D(EAYRx6G< z{&)E0Z+?rK)>UGA*^*h@sm3O1Yo!wjND7$sa(~NcH%P>wkm}B^2N8Vt$G^m}C!UTe z9YlBEzXqTG;t^P}@@51*xnxfQF$!7Ckks!)8)N5fHpWQ5^$qFgg{Yp13Fp)=J6IR` zarR|5;k@N{U@Fn~fTW7zpt8Jx`(My5Nw-0h^Mu&;`8EoL znaa896+Wz=gH$^Of1V{-vMoALl=77=auKCO5|7+|YizsCHsS_Qe?+t-kBgBp84r{^ z%UH_A1>`FN?H5r`f$#tDNE~zAiF(Y{#!mzM$fi||Xd81;Is{ay=pN%Z7F z{OlJ;;n&9;AKSE6s`gjic^Cd$PXf2Ex*Krpn9D`ImejEE*Z_9eW)lEGe^lhTshJQ$ zNm{0Jw!=vD+L352uL*-V?ySpk!8NNem1@j%IA&^1L-!@)t#97+<-R~;pQ3_EJ@%is z{C1ph{?)i&am4x84dU*p3VwF##klDK^*iy;mF0FrxiTXi{mrP+6#AxUG&$X=1RA6+ zq8Sc=L|v6d9=GpS5ydQdHgd5C+E8`Y6!m25P8uBsk^zMF1fUXBhyoccb+QKdcXZ6_ zB1j^DvI+v^N3=*iv8tcc^2vbmC3#=9iWfZh?*PRhE3{vf8BN?ko!!nnG zlO-7}6-WA$Qz^dw?H}UD`ek5B8&GQv)F>o+=q2h>a-!l+B3v^(hDKezD zdbp6ML>>v(E%*PPX3J9m01yC4L_t*j=xg8nE`I)-V^K>Jkdzm|PaV^#J_g^k3ZMVd zH*k->Q6w6ns)DM3@c(oaqS0|_ZuC2SRo_@1zxyN5pZMp%I#T@!+8}PX!=%i}hr_I( zF>zUdv{2AIkS>WewFJNY!^JrB%Gj$0YiF6EUn$;6-$LLUyJrKlBbvW|X~bxm&H zXcv;5(USzphN|t12BQ}dlBQ8fCn?dhlGJMe+3KfJYvcEFmg=$B2T8l!L*33R*U7A< zqO(O=)|r{k>=7r`nySyzXreZaC+_`tY_xEJHlFR;AwTV`IoI<5)DA$btJU#?AO94e zJM>Gq?T&kpCR#v}1#KYsosubFIzr@3Nt*zTzCxQeRSR0I6gMQeX5}3?@H1b;aVPt+ zpCFle(_+pkh>0t&T7fTq#;27OKtl)R%aWjPfpzS#)y7!5a41GVB+^e5 zL%>W|cb}~m*=CX-r8@huIvv2VXI+J(&$t|SP4%OmXj9rm&Vt%awP~T&G2bh0c(tZ+ zsf!NsbMu3`!=HWyet-EbSgVh-+VgQuNDEmL0X6B}bl*Ds>aL`Xkw!L2kQpLF8HLz$mj$$N3UYnQ=(8|Xg&K5M+q9b9ghzla4?o#c`a(Rudp!z+iT_b)$d!sRuXZWA`)qQ9V)97nl+lV#^!VS0waF;Xx%v)# z>!>qv!S(lHG7L#p1vOSxQMM+XcQ!~;dTbH6#=4%F0+9NUsa5fZD_7xL$DNIfZe64A z4ueQFS3zTpY*qjnc}~&*#WR9y@14SL&%6}(*ZTDoPz9`j?iWdrY!TX*(ZW>4JVRtm zrj1xBWh6776w^@AEp=Pb{?ArN6ZNH=&BM!6%kGdLLtVzjs0BHfMl0Gx)}M>6C$7+Q zJ3c&Ix4mInp@5oTzjwai`TJtQMB9HOKuQ{C>4;eGq*m<2_F7P0R4Edyy6avX{`K$Z zAow_rKJFCUea~v0x!Qd3Uv+k!HhXA7cX?=Y!#^eJuH=n>^zpyPdq4DXeCJ2M!UJn2 zwJ<}}Pn7$hQ=v8jd=Pm2;}|KXDf#;Sndjq&NB%-jDFH$8GBdSF0~s$tqC=yqkAaWf zc?)c^a1d3lL#jqXP+uF`-H9%4TNLdhAkqF$f%y2XvYuj!gSh#D1V2CJ5`6Qw7vlVt zt8q_l0BiM2L8^FD?M(M6^&uB#ZY4;6IvKz{(}Oto+WYYB<1WC_=Ut0cYqO1Pb9?Z* zF&%pql$)uTf)2oGRB`#LH8@VM3iqY@P-(@Mp8RPm3A+c7bPMBw2lN#~0u8P5W+Dla zO-4b9=e`%!^(hHT@8IqK_5mF7g|Fb$GtS1XtM0+t>42IRS*mtZwND)k)Q@izFQgT$ zo32H@)BboN4*B9Y@Xik$gd@K56Wn~;U2&5uYXp<3QNs*JR7n!}3BdIvt;u_;Lm}X} zlm38TAAP)NFB`!Jj1C9n2sRD^#}k= z1$17FtSmQ~25ROK1SkeUE~5Lo#(xclv3%7Oe)_wMal|iA$5CfrjZ1G{i&c6(SfeL{ zTB4_e$^dG*v)8oAr*%NoRn{wmSc4(y4dU|Krf|%;*W#N;pM_tac{#4VKVVWiA*mq5 zexwdVbP&>bkUECQR2I^JT0LN0=)(m!-ijPJ!O(-d~goL1t2-t`G zdq)GP=qX^YUADsZn@^w`^eQ7>mIyaPRT>D0Jak;vFjERHas-Iqa3b1qN@jjt2h&;( z;np=(oO#9V`2I;3;fp^%6Nevl9=`j#%kZnSuf_2f-h|^XxDh8@uoAyIYX!b9{@0E< zA7A<98Tj7G7vt=!ZpCeDLVSX7-!%ZyyRw+vA{|4l6!iMv?zik$P8wuL1F;i~{bYLvR}wfruBG6RMF-TGd8Mg6@VgNVLEf zj1S=ruX!c<^r{j2Y@3Ko-TotARVD;UQLV{wgN~>v)0UBUWTpz#^~}nYHW@OcvP*TB ze{fwLD|IJ7=b|fc!l`HDXGfi+_xcm?i=$7*Z+~|t&bjDH+;IE7@!!wawJ~)wigzhD zKoTUO48^4y67dYuwL+4W#nS;my#l28u70vSTd=$Hn+6gLR6^%CI2xh$YyiMfh8Y;FoN;)AB(;BPk$}raGH~M>PgSh_QIxfBO zew=p2Dx7%9EjU3q@v_@-`qg*g{F~Nb#eFI6(rd#S4B|mO4XopUVop$U3%6@To(NJ| zBM=QiqngceiV9XILpbHq8*tf;_hCxDQ^n?|gu;v@NNRdC-yuYr%y@;)Y$ciL$Mw}s znH6?pJIZc+=%!F7+iVn^qU@^QtznX&9H~bwHY8i>uC#DeDHfyc4f`M^u<}C$K{#R7 zOL|fyiA0Mz(WC8Cp7=OC{b^4TH$`@3IvMR;6R3jHP|=b+Mw;RdNmDmSpE)2s)8gr= zAm}v#D#et*(`K0#4YcS4FwsI4kK&1jVZO|1JJDn&hfCGl6G^b0S*i!ggGS>1H8mXe z&F|y#E3c7M?J19`%{a(gs83-hJpnvr&qt!4lL}TI@+Snw^(0H#WnM(6T22j4gD6Ye z=v*iB6(rPXtM6Gmb=B28t4Q@4S7!yOP}ex6UZa*Oo`4iVPcBdi*=kVL3pthyLgv-V z5Fag9kea*Z(z+Q^)bx7xfPbwx_bObwY7#Xa0xgCcqN28ofZ{rHtb*g8$-P%nPq}>} zfBcJ1r5Q^(cByKXv@loW9D6Z-X(1QCJ;}PA z)u`K#E0n$U?C;+D9>A9l|0Zs@=@yMoJpyqYtXUwyVOPRB?EB_(>MAx#C>U^R%OLG>W)(i0xV z_7sWEObv803yuP{ybOy-b4=xMW04gz4G=&QMC(PegV&;=IGHnw($$Pst_fBi$DV4_ zh>clEAfr^2Q=woQYM0n}qlI|;TldFcU!rm=IN@A27i}IjYgeaqYQ5qqZ zQ7j6U36^F&nTW8K3RSWN9BF4d1UzqA;__vGX3hYOSuZKcD9Vmbk<6%@ZoeB}`s&wl z*S)LNhWH&xcF}LZaJ7bi-1qTVFrWhzXuqseKr-2*p$%O+MAU{4 zfjicu`0ZKCvcI#yJ~b&j$>5ueNGZ=R$%fkewh#8v#X3a)YO0GY>B4KUqG6-fo3LIS z%-$+pCAMo3s54oZAr7Cbi3ihYQEaPNUZ71BV%?sKi4#XDvb$uC$*_pb>`WK%SVDJ? z$3J!tyz*aOic0(*kjnWCP7C9f()wlpqN8*9ii4oKN(wDzrHVCNZI+^<4|BUfvZ8Md zsd&XkEO@RPMZL2Oaeka%yYf~X{*CYHR|m)4WjQG%sEvNT{cg9>AYSy0$6&BpmrGe| zd@WW55RI0rt>+EJ7NxAxVGCG2K+__0O;S+GM6$PTRteG88JTG~51Ftdw=82esbb19 zn}V-nPK_2K$^CUN|kmtvhxgrI{4ZVb(9K2*cI#<<*D&vS&Fkp%tzD!M&&nX#sd z9k@o)h33(nP%mPwl(})E#OfgJqa7us%&R6{MAjNW5^*8U<{PC;HlhT6*u74TUUYlBT*@35eAKqmHYKs?uk2Z zj^{n`kr?8G@S`i3t7odJ77U0+^UCD~!{HRPCZItUgw^fID0q$1Oeqv|8Tq+G50Cj) zG0Pes;GquZoYjL?z#JJ08}DKZ$;uEU9p``4{o=Un{nJ~ zM)k7Ugm~?%Ux6p>{dgqtJ;GXs zlw6dcp2a?u`)wYgPw6}60-*ksjHN@#B3E>jH2NHCjf{z=G}ocHBtcSC_Y`Aj6D86& z8th!jULqtni|Wz;r?=|>01yC4L_t(Qe?MOMg6CrEtu_ZWCJmbwLNOshqMbDqrtsXo z9)+juzD@QdV29R?bK+wK@tM!lHnrjYR@6itnfQ&bWWVpKpM>)7p)TVv^x#o~A^+IfiZv$!NYNBIN%^>^xc?94{ljg*6y5OA0*4d^`LEUAPx>T z3Sb|ImzI(iaVk)K>hG(>&Hsv*zXbXginx$^ z_>JZQO87O8ZUp=V|55@iUIvRNcn_gjCwOBV{LCG5p_!;MZ_soTV9F+@F;R%vXASn13(c9H4DY?BuMl8^*RQC(8x_mEj#a+2^L zC`W!dzMNEe?JX9P&a!L=E$Kv)zF=ek?|Ii-@Pfa4Ci*J+nMWTAp*9O^7DTz!qL2Kj z7b#GG6pWJYmJMCU#zw6mJWf({Ld@((%pyKpMP2dzNNNuleVfV6c+v(Y_|BKkTWPF$GD3yglVp8d*g-)vAhSVv{sQ8<=R*YqB$gMqRoYM}$)p zh!abI-u&{_r`MkG@E{()^+LRG@14}|b%34}kY67AUdUA%1*s!ObL^kOjfP+bLh3!G zy$^si^p?pTsgA0QDX7NC2!ZAuOtavLW4X9Q*Bdh@XL#aTGIX~ zI5OCe{onW+yzzCf#z_7j6AhZ^*ngIX)6p7HqL|9Gs_G96v(fvqxbP6QJO`0bmeYlt zB)lL=0tNt4APMt*IG}Xd&U?(qQ0@x-+WZs4eR%aNUWQk`^o1Cxgt+;ck1S`!J7Q(@U*|^D1b`$)-@tfFZY)kuMaL1sFn>XJs) zg3kNq{`l_h4?$5bJ;&jG*xG!{#cm|~j!+MRl#)tiO|6YCg`ij`^g8g&J-5LtU+_dcV&i@cChO!Ujf)^Y5vUDF z4~PV2y3{NT>sY&>UGKn*Ld4dJ9J)M?HZe$fPXwi?7|R4mst5vg!1bYqrGqJ6wD-<< z>TX+L7?WBiwHTkD8Y!RM5=oHkCejvi>l&JTZo4YAGc%KRZmcWfSaxO!>YdEFaf)}~ zIAG=X;klX5tkq*+W;SYUGx-D6k$*Qfpy&wl!o(cfQ{ zn%dN&fFaf9oQN-JOp;Lm&684*V%1sGst`qv^j%sb^0hb`v>B?q=my)FPZE_RL88*_ zCm_fQD(dF2Uh<#zggx=m5560_@3^fN@wE8bphU}6_-bL!S_$y5jU+YfxY;=V^#yz5 z*?Vq{g#%Nl>h+?|sy0*wP;7P;e>yZV11OmhR6dlH*=M=^P?5Uq3MN3JI3-MUzzuN< zyKX#)S3YBR?7GD$`t=$h(TwTOAym{4Q?pt~B-hKi4-Or5owo8fSC3?-nW*skFQzg2 zE_o&ik|jB=iYpXETbV01Y;&;544K z#};_yb03FYw;aZ3vIf<39pD=Yb0;c84yeqzjlzA46*Xcp6CzQ+sgg7Ya8a&97n#XK zg7HsI+14_;-U*V@MjV?VtixvglX%{q+u|ip-xHgU1%2dP7a#jOExU8(GJf4H=g&>% zZ!)`u2fF|@c+ddNZuM|zu+!-Vj)kPUCxB3&gZs;*4+$$;v_ZdhBRuKxyW`Uz{|H|5 z%74;tzYC-%ec2&iMBE8ltg+gXX(^j8U6LRPWoTTIiGzYSpM{giS0zbMNiw*O;*xA+ zWCSnVcOQK6zz^bSPkbEwpZiXjfRzL(8KLM3i}flUyI&P-oO(xV+y(}!7#je#TU5cz zb@zP9KD%PeMF|G{_zWEu>a+E!%uvyi6dKHL#O8`Lvau1Dh8RW4{Y4}3Bvqap6-;r8 zR7i??JiS!uXAKK0Yw_5v7T^`n*$Yp4)M89o6Vww8;=ih_BWP@c=va!DA;c6!QFgW!JTyUL1{2~# zuzzUYg6N839uI4=`z9lJ<+C1#7d>ewY&w$0Uo@zv7JVnxctI;5px0&pMjq%nRGT~gA8hl394#%=N(fYIc1r+Rm}yM7DToi}nOk!b8I zB_!}9w1Ab2=hA@c0{u~@(g%PbiHCBLM3N*SVFCklzPu2Vuw?Oq@H%a*FC6koymkNA zVCU_(z~JBj=*1Q%N~1=_NcB&Bkd>CYX*Ob)M%HT7Yw|Ou^5{opDS5-!wK0MhuFGf( z`35Q#V9QN5!b@KGY#jWt596)-y&BtYzA+L>3BW+wONgnh9{QrU<=fODkBp@Lja&W_|o+U!cL!> zGRx#R(E^nb92fy4@*N>R9#U#>69QC5mGC877jWHlexh6Mg;CLSroLmrb+x3hV;)U9 zV~OmpnRN?vRhWh8R-sLWFdY_642Ks#cOM+`$&ct`;fL|E7e5!z1}f@%3ilK4 zhY*B@>!N?L)PPwanj}cdeZ~voS>)5-kOUO3D#Bwiqz@8{$4BwR$L@xAzUB2Xj@P~7 zCD?rF0#sN-*1kPFOmLV5%1tOnbs};G2L{pC-w$}>Y155W)?wEzNAa3{AB{Kvzo+8w zAHNND-gE$?)oJvlYte@(B>I++gqrTUb@d^Dq}&O}E?31AFGPlOl5l@@R3L*zk|-8G zB|uLK)pQDjdcPm%Bp$V72>wCp~UAY_W7fJP^ELD+#nQfrOAQ)Aqu9-}*ZI*QY;<55Mnic=nU`#Ke&9yPCTM zzO)!Y6J3$&(bg!p+f{J}X4$sACCjMx6+Q+A`cbV`v^i4s#i${vt;MFpbv${erFiXg z_rN><;cMunkx~Z7w z!=s`n1J?(12##P98zpP7-N-cd+G-3h-fKJT|H3EW)z8`;d#kOb1M4uDu7UMaRP>lH zZ^2Wd(!tAjOll{V^UUVBPG|S3aC#|a^W95ozB=MS3XqvMk|1e~3_Us-H3~hIOp?q_ zw0&mAj6AV0te?z2@u7F&^PfHdpZnBD@tIG21fTijfx^dd$frLRK6miP!y%tKNO!CQ z!XY33X!^NNd^G&mrw<69`_zHqzdq^uN5UbW5I+8&;oyTljDrvSP&oL&{|E>D$9uw- zn=J`m1QjZVtl?g{rm<6$2ESo7`R(;WqJA;Tg1UtW5NJS4B)=o1S~S6e0KI5yt%pZ! zvuXIp7d;mr`QUrAe#lG!01yC4L_t*W#sB&gK7a55_`rMKidX;3OYod$JP|(V92d{nA%kYu+za58u z<{*6TlmCggzUd8k>fVpVrVB^)^He}3B+yHZKtXgWh=;bzy)UCpJg2IciP2Q9XgHb( z@mm9MyP8XD|Je_s`eXet0w2UJ>%zYYwBHCQ?v0J%U$zp&SKi|~@C?1cUP{z-U) z@QUX=4$s|ddp!OT8)4Ti#)3QO!Pesy z?6712du=^|XYaNpUbfGp@tPMr39oz6lkn1~><~Boro*W={aRFgXgD~<2w$;N6gLrc zn+Td)$rWznUEFH(h1SxHCL}?!p<{ic!I*_eW{@|%&Y-m6L~f2qR1E467#kk&&t{>o zq9vhIxym$9LkWFcQz<&2qUfzp4Sqb?wXIaQ%rg*lqNjfR*O>#u)1$Ep8PpK6D<80+ zS^<%riF%0c6QTQ+LTLynstlBcl9d}(;0U@~RS?4H&|uhR%gy6v{pXjwP(R1L z5g+@{_u&hl`53-*=)pMri=Pt?!D0XNSsd}j&x%$l`mjTFaOeO%=s(_tx4-d~_{SGK z2Yxczc=1AQqzb%5J!TqKweD0zXBud&;bFMcW6fD~9E#S8GIARknSh$SL47Al^m^#= zZ3s=s6`?=!*RR)vp-K&#jRx$p`7oZg%Tm1fDLd+`{GND&?%Z$v$EV^QFMm4TuGfcm zz4U2#_sjOdyI#7F>QBR)|KTZkCdT{^lCiR)1hv%pn-1Zn-`%+ESF_@tar1KZdtFL9_+7R zcyNFf68i8Gz!dZ$&_G=#bw+*?;4*|70r8M(ZP!TU6bDF=Ax@oWXnSQrQA$Q+&XB1e z@)nrTjYWHFt6>*eJ#OB7Aw-{y73-)P1Id(o`$SmK5GvI=qEh=pp`PEI9lLt!W$%r4mvVoGr3F} zF&LTE$R*9}_01h==SdqS6!^Re`8tYpn;SiEumG4hmFwG1gC4w3Eip>wdc;Vy&lS6RXx|y!tpI|7k(9GYsNzzv zUzyldUWg1*w@hTBk1(?qz`{z#vd=#mxQVO+72Ic?|^<;#`B}ZZg21GRY z(7FgAk*-9ls0v-wNh(H&C4wD_7U9(%<)#CgH?$Cb$9}>fEsfXvh%arq@Py=}s$#R0x8HBOurmLxThHbwJ|` z1(+eq3JtSF2f?qK(aa5JAew(5x(UR~>IR~$xlJ@TY9*7PbWyazb%+tFHj-nc{6u+! zn-S}qI}ZDu)t(v$MchlT*|T;HOEh@x?3Oy^-Hf6%Jp&xH#j%{tw-s|F{s=TMfc|Qg zy0p-VL<0(4I<1+8I@8qe{$k|GdO7J4h-9jT5Y(=ggsd461*I&?rBh-7UYUmYlIupI zjf2MJ)nGIjZcuGRJ(VT?+(^al2HYBDp(f!H;v2CoWf?DDZc>WvN#DsbshCtW!R|8J zxpl>zVOdx!gLE_EA?Ehe3`ovGfP)m(k=)Pbrj}TW?ty*8xMdr}?(6GA)D=CKl-bWk zvs0(twp=$o`#dXRsw17Q*Na2ybk{hnmvPA`Dba0YQ$)@XcrH`-+U!f!T&Kj*{LW}m zR*iHbANn4Efj%7q;*g3-n^J@CvA44j(zG}Tf-h-EQ%feK-W;YiWJ;nkBb%u*Q*s;f z8+VJ^r0NB1rgmETl4xGc7lQTNnsrp4F)3CDW8``S6}l=aAX<*)OupQg$V0r`6R0WQ zUmQxX%zh%z`cW;<8g*-kC+m=AepOR1>02#=y-C-+4F)PQHHFx;>5Pj0NiiaoWr`~! z3Y}=A0kH#Emq;|&Lqmgl63}yDn>}W@NZZe#&_mQd9_4zZXYd=tkFn>@O&fXjp%!l6 zn6IDaE^oI?Q=rtLS%++<&demk+%C6Y(S-XW&_G{bj7&ShY^_)=dQn<59_MU9%Wbi+ z%{Ro-3R130Tvt&$)+0Y3Ku6m|n#!}qQnsDcdnK|GUC5Y;?#wdOZ8kYq zMLA_>TR@babCUS|n=xGaHHS&6SE1AlBD)HE>TnV#4hH2%ae&g#_ykC$Oj~2apwLq2 zaMXKvD%7DTDb-W+1%=~g8o+v7l#Nk1QKO2Cf_s@rn!&LKQ1vV&In6kdiI^ILqGz$D zISEG40nmpev5o|DNO6+ppf{5W*^ISC&wQhWnN<|NhQW(Suz3%?O#4rh&pK+PBULae z$(&ZTJr#rM(kRPaH_E(u({5TwbO`uKpkGe{sfROYShetVT&bo7A;;ptuv`lrS|LC|u9kb?T54M`o;4{u1)K({D8{RpLVfJg%MiHX{nWHlJj*R>STb|Llk zPSFt>RLyYkibae_@dZI{gH~!9OVxwCM>?p9G(EUwkXqSJOtuFAb#e-aT>9Od1SF+H7nO} zzp_&C`&i5Yl}5-*s-bA7b`pW&Gxj!7*a;A66-tbthBQHcf1kb=RX`FmUFv@nlQZi@ zr5Q4kv$oZ4uAx8~?eh85$?olw-TA$Idqg{AOO`BQ2eX~w#guA`30{EY>?Z9l*0=6M zz#oD7t9l*K29%%JxCS?t&J6K`!V+5xS(S3i7DCX3XqRbcsSniGH*d3``#9t|5X?6T zsGde>Yv_PTwb^U>TwhC=25JxkLmIW+61BMvwPzP{9Y|GT3ZX#)R2V6B1p~TVQeIuE zs`voagPaGKdc2ADjJ9ev^G7r<>asp%BW@6)8_t5`MR3ce}X5ERKd z^=-awY3=qfNi1Slp*wCA!ZKa(igG4dp);S7WE==G!N|x6s+B4WdlC7P$T+G;LQIoJ ztTS8m-U4(tQ&RUm&}Ay+=>Y$uQ%)y+!XVb^x8$j05R>dn*0PT(Sxfq5(RZ9&8rWpj?I^Mo>7S0hJE{!G3IC zl%})Bp#WN-iW-*CNkIgcg5tI)0(tJze0PmaDk;iW6^lPj+0uU6d5-`#W<&bf0nFMqJco6@R$ z4bX?gbkI(9<3iS`mTk~(hawQ^AT^1K*`a9(gg{*ZjmxBvrlj@7k9Yqdd+Hofy_BS4 z--(`B$hsaz>S@AyojQ;z2-M*eDv~8?sA9;0#*7uYa9IVU17@_Ekd0)NuAhl|0OA)2 zIqkB5{2|hXA8NVz#3cb3s+;F}3Bf!lR@p%`NojjNRf^U~LBoq!BA|RF(x2j;laqJk+e|y2F!Zpo521t5yZ1sRT1vO4^lQKjT9DMi%;@-->%R9kD4e%9Hi z6|6-aRHW3#SE#y0Qt=_XsBqQ2z@X;^psrO>V_;oNT)Y%yq6Y_?#=Ze0wVCZO!Sy%Z z%41GCoxeWu3>M^Jo@C*@!Q{>iDOPV6Gxx)dmMApX*gCm z=EUFQ=;Kd?%VT77l<1>RI1Rr!{`dIxZ%@V1C!8+b({b#{X9|D7Z%;l$x~JnP$&Wti zboo*nE@PXgOZSY}j@vr+l(TT`sb{OrvxGBow0s;T`=d2ZN1tlm894eB>7RBEj{Uv# z#5?x)=i)fwm{ZTeF~2)o@;~CYr-^s^c{uL$bMf2XpM&FEKka;+cJ8HEJDsBaB8h6X z8pp>nk}g`Hf%e$7@a9t?+3;W3rP};@`qS(MXjTe#)FX)mO_)|S>IG=34cV9D@{9suz5hnRh97*Br5%000mGNklowZBkGlU+&t7ekm-tE9#$ zhE0bXbQmP4g(~mYUH;lB;P`89#o@m{51&8&EF5vhfZ8-n#N!(CNa0dtQK+=cR z)d4(M?Z?_mAJ)mkw5Dz<5bM$;*4MFuX(pJ~-E3{Oiutg)RSr_1ES6q*a@1NwINnbpGYC42cR7m}5K+u6Y)2dNJt|1-{1hxMK=u-0t zD#go6(*-IO9QV6F;H%&KArAlck8#+ye}b=m=SX~2rRl@J^Hb43#h1SMV|?YCKf+hP z^K*RlThjT4=x^ov-#!wDedi}Q;(I^C*S_~teEs__e}==wJ4`zE{nc;%6kqw4^(6bj zFLC&He=htCM|}4e(*FgH_@40HpUUQ^I86Qycl(Oti0>XL+0Ui(a~$#gUq*cG`@g~w zKlnAi{==grGw)aUn(Bvt@0U1S<=2076u$nGWATk6kHy!1d@K%E{qP?ijU#?^G`{hp z-{9*%`Zd1sgJ0n0JMPkWcyx-vK-}1g=BA=?(ICfqQ<}-k^$kh8y$#{d@oxw}(MJI2 zn+H0to(DiG-4L9M_)ASXF&SecDta0i>gxlNgsC>z6#7_CMsx=r;u*SwAAb79_}p=S z)ZKjrF1>Rt?hbu=f3ILFsl<(30}(1jJxO$ei>3jj6ads!H!TuUMNr)Y>&i7uX`ply z)FrIR$J(Td`>TCeF%@v)ZFk{o=U#%tbQk;eRV%S#avBdxR-<+|12jL-rKf@b-9_TJ z1J%87)jDFCBvcDPn${_O^Q|urS+%CasfMazsGx?5;;5>uVmeeJ>a?sXexIO{eW>Zc zs;jIged1N3zHO)F$7L#+VI7w#E75;Y-%_=aO3$bx(IH!r%zmr#Q;|QH)x4B{`Kk%2 zZH2mg8MVMnU-8w2lnLr7BGNRVu1c*o9m}BkPBp%cudeoMYImxhpjN9(WZk;-^u#2+ zpi!+|flXMYdjYOA>Wb7B2l}!~! zvL5QOY|nZg0PTu@4fX!M3I_UzFkKnO-BVQ@cg;$C?)cO3&9j!_!rNElE-e;s%qcCh zR0{;Yv{+1L+sF(+!w-!%m_k4NwF15ZpxqaBQbG$K*`?Pe^D}$Mt*Agu%i}$IQn<1f zaQscT<11%fh#y>Z1unX89qvtrsKbSj4v=NYF6z=62r7IgsL709&K*5%MIC_DfgJ?K ze-Wn%_oNr7Pa&k!!W57S<}1Rovv%5>$S~h!Nb9l}WE+H3{?fXAW^Gvx>A>TFQ~_(C z98V4ztL?M{j@gKE_oxNZkM$H$C;C@=?&GxjG`&Vm)-gRj?J%2A(`j8Nh&V}-K!Yf% zncC}3$-_vw9}lDZvTOI*ATzG+Z5h#)CvEjuz5Mbew1678pveqvfop7|UXfXD6!nL- zbSy#uk!oQXv28_M(_Q60-9>)C{CfP)3BSiLFItZ4AFN}I?mRW!>1k+0$ZS-ior6_1 zsFYiIMFU!KN}&bN6|64<>#G`*v@$*U4)S1V=%P&bc~Bd)rdjYS!=06WoO#a!_}+z= z;s+OAj*IWF;lav)&Kqk&+tPj0dw&SjCD(OQ_gIFSO40fh5adr_DiyWEMEBa*m^1bB z|FicVfR3v{e3S}q?q9{syCNIVoV+;tWf0Jm6T~kbd$up+; zQY?ukc}Yx+zC>e*v3HH4Xh3NL48!z0x1Y1u|NGY3`<#8wJ?GpqcYq}9S>OKk-zs~p zwaXa>lc1A=l}~3yqJTn@PU9B}KpMHX3ZXv)9FlASRGmi1l`lvpk<~I#`T%?BT*lCh zl#z-zE7;3$y-~EuxuQ^<${10CQ2Ge-kk0WW5!6qTur4S^?t!q3bXaGQlnawmXOdAS z+f?dB73VdoL6(iG&b)O-yjf_R^8&URWNL>-5>-$}$5kQKf=W9kxrbbpB(~$6bx4Kq zgeMftBbey&$JUWVu8nF^3;)aa?7?rm?_crWFWic|CIcpNKYG?QUkKV;^V1|keAGn& zEqmS!&^$^qx{qo^mreQ5Cn}oIK61_IX+06_&}+a~_j)6^1%G|Z?YOg{Wy~SnI|Gqv zZ3EP#_Roma1uHXulDtWh1MGrs`)t#QFe@m0kxLk(#%yM5Z}X ztJPpy>K>&)wva&}+2K}7nv^g)j0a2bq&JHEo*=pI_>+2%y?Y9H=f}T}w|?j|_}2a$ z6GJO7qYc3uLkMMS6-Y;kx@Zx$C!G}qioOQVJcR~@7|9yoyPs~xN$hcs_EN80Dy3A= z0O|>rn$>Rgt9wERjrQMV_=fwCPSDL_XMQfYGlfe7fxYOYs3 zk%Myt?Ybcjw7uj|luRN?s3Z*mYBB2!A9+)QX-0a-d*Pc})eVx$!)|p?ndE|fdnQUpo&i-v#13Vx_X6J>XophlQ2hXpG4Eyzg>nr!{!mq#YWB8}r z?!zvOYDTF}EiNq`G3vY)OS}JVPR5?a9tLz$nd{>btM#-LzOJ)i`;c7sbZFsZ`oQIl zz!!ZotKlA1`hRb|4S)Hq+i*{_u3sE7&wpgz2x2bE!%LA-@=4bu3Yq#T-l|SSYdlF` zQn4!K+%oNMb?I5sZo9(MSVyM!$+3oGjnd1ylJBJ6cB-DLB6NCJrIx2BeoJtS@>tiI z9Od|s)hu0352HvD%rwEshpZK6H5z$jR9!SXv*KkB+6ZF3;-}UAokPR;^zMCl#}~eeZ;#Dl zDjU)sq3;29S8P)aATs?yf?f_hDyWYlXcGZ|0E+n13d*ZmC3hC8F6s#iqKKK;=>Teo zLTqVYHOX#E=Bp#(Zf#jNNbyx$qqJH^>wN zP-BU{hpt9n+p-!w(7GZ^&Z%xFHrHCp@nExtzxu?#C1hr6eDat%zmDlI~sQS+JQY~&y zGN`REl2kc+`Z$jvH47@%CFU?AINT81N)^|!72S{{Nl@1nqOl>gQ#)fJTG;`+d#+Vc zI#}n0Zd&U8yHj7m10DmCx=w9$CyWDLUhR^0JN1#tloz_|G(c?EFIa#2FQ3Cd-f|~) z)eb?UUPq8kUPT7Y9+g6f#PxgXFiPnZl*`3Z(8)ekyHv5n=Gvi`F?v)_cC5%T*fLX9 zG%u9Ytavh>5KN^roz|n^ed^l>Zu>qyb@v03&H&=Q7-sWwu^aFgQU_VSndYd-`4HhPj-F1Q2N_e^2<%>gzAGyFJ!%xi`BUU zgW!DBgf3xup(yjtXx?v|t>Nt-`aC{&+cr$r^vD~Ngm})Yopi5_WRg8Go?8++N`M^! zhX?dNtWRD5EntC1C28!t!<0w`&`Aa5Vb_u`pOl&!vmLcM{`t%lG3Id@7e^&CdyG)GrekOax9s>M6jXekPYWQ-x(v@k7+^r~Y?iMoT>t>~2J z-vHFX&X56;XHgGyw}I@|%+2WmajG1|Ob+ax4S3f_KaVfowG$Kd6_8r9I6yDRkwveg zT21J3kWEFgGPpg0xaef+CkEFa6>`i4?LjcCGd0Zjgz`mwLH+j?EGrG1-@Nm?pXLqQ zY|Qe2VSOOX^M0dCc@*Aqv-~*C1Fh~bM)<6L;Z;N_X zHUO1_6<%y~vCfd3iiHeRdq{$!pe%xl80T-pIz|T+XCN`oUIM)j^(h)u4;&;KOrb+O zT(`zX5@_FGF4dj5gL`(rG!iJmd8#9+)^|Z|_6>!KrK}(zt@RE!Wm z1}SfprHVzH2C54A!AD8Ot3^7iNEZai-)X!EBZUs@^@?HNm{O|#g`j*vQ35Iut3D{& zr2xu94pQkGMsl%QOB@ag3Tz7A1df*9C8wQ?(Yh9|ykmbMC3FPS0R5^4k`dBY3dNTY ztKuxGQCy{{A?~vXAa{}=6Hpvv29l)&n2iA`n^~($z`hnxJ=8-x!Um($Mp70^X(#zg z3I(K0MLsC!K+@=vg@OY}b^tmSGUw#hD)u)@1=*cb^~C{8RMuE$>2K9)}h!z63-CayW@@i_DF)fmcWK?ZnP$ec>7gYe&(2YorCBH1cu7HX2n zlmQXwJmkY(`j%HHIEpfP5~3`CIO5PjQfEkC=p>Rlq2D2!O06|@}&000mGNklt1NF;r#=;pApOJ}!C ztWrr*5pSI;0QCn^0El$h7cB`rj>5A@NJ>_zhLD6x0;n8@$bjN8Dlx!qQKm9qY--sc zWk^p|0NHLAnRv%wzGJ|gYsDA&=1&z{*K!*a=6Tj~ESa&fvCa&op${e5(eXKMvPWG> zqtJaSt28x$t@|7Ji;sT^yPD~zK5cJBP_oCFTxeQEcgQ%!BLxV6zB5K9THqr<3YCxq z86pR(Q693Rs_4~z`&b_-&~mp7r7fuqu?i{dFB_}_-~~d_R1!C;*Pqi@ufkQQo`BW) z4C;C&h~dd;&Y4*T)h4~YQVt14v0OlPXF@bs6&alzRzhMbb}*8Z@=Mla&4t$Zi;oMS zMU$t~L3ITvrcBXIWmiFo$jHYL362iZ2+E)8v?UX?5rFny%C2{>pSR9rr-J{ zPU^k?1E2bL+_Pr}`VAbuOM;4aJ+f;(NJzyho6@7Pj9Ee!zuYAsB^Oh8sV(wA9wdv2 zabo3=itMp2OCF)pCQ1?{p;H2U1V|GB*;L|$@VFpER_|+>pbv7$6d-t066Yr!fAkZJ zpunI+H3S@Aui?6NXW~%k&aMu+D-1a@JsH_|4ydSLE!BjYnGOU{vY>i{fGDHmaC-wn zMJNC0r}nztien}nB?}~FrThgq+_Ll#1*8-2x~d=v(#Sx4xTGKTtDvt&8z~RrBcRah z$q>jiu({QuAyJ)UA2eR366X|>b9CJbk{}bRc{+HFQ(l3`&31!Stdja3l!3@J4w-Z~ zz{9=tFjvtprQ4C9;nAGoV*fpWGO?4C{K29D8K8?wsIls0L-H5y*nuzJb`NH=VT7*1 zlMA$((DQH-4LTx#l0<5of#T3aQC0BYBY+)TPnI0~@vWwTtIaks)M#QvkK-$5XEEBC z)ff7P-p8A$%dVC?Qf*Y*9V(;=A2XukkS#hQ$T`6(2}K)#VdXp~Z{X=?osQ#&GYokH zNKP1Zxaou37+YD*p!%y~Pd<-YQqh{kh&d=ikOZ`FBeam=zlA8U3TE;%i17ZBU&nI zw{zvPtF+RTyv!auizJc$KorHnE}BHS0zP>X=RmE|hzol~a~4O28JwaY8!mjzA$ZD( zYw?4pKMv13?-V@m{8RD6XP=1waq4k+@^MFE(_texDQn_rJ)*BtobJIOpuI^6p@WiC z#I*~9*L#wqo#{zLnql?xC~YuTpL7DwI^qzlR9=7a_t+b9iG?J{1S?3we?w483_9c% z&GcD9q~`m8T8M|N8pY#}S&QQza~MuK_6VGKOu|W`CmnkvPS*E{la5`BlQbTtC(6hA z6J;|_cT4liRdeOVu{Bbj*}j9C{8{`^&KPrv4Y}G5`UuF zaKcfmal%n6@p#eGPB;#Sty!&yJKcXZcF;jm=TtmqRU~caxwMzsQZ8v#U-JDZNsx@~ z(ZucTCi@&im#(b4q;vcisnCq;8i5l*H3Hb|M)j&f&bJZMA>%MpFsWv>JFU3b|vY~Z9-bv)zD9v^m}CF}nj4MN;Q> z(GCx?)G1lp)Zzk?JxIfH0Fp|Y9z{M|HlBmmz3OJX@n>(wYk&GiyhbSLtAFYx`1x1- z1YRw?<`p-HUXMtB>IS^-r(c5CiN5wHUyRrO2ThqQ7TP3pFu=;&aiRlMQ_G zYq#n5{!#fd-Ys+8i6q3L;e*@~phL4+^E9d?At(gWna_2%4cb)9TNkvzv^}Hc3}6)+ zShsd1Ua;jny!=TQ;o37##ObSsaI~HRR%;Qi5Jt49>)M3sdIztmvSEFETG^b^m-z`C z6{c|Znh`wd)Z=l(r5ka>=5ulJk%!<2{bW~*8-W@_Riyr@If!*fSzXi92ZJvGu|oOR z>2CJK(@s*}X}B&$A{}jxB*=thLzGe1tCHFV9YO6B=`2iQLE@-H_jc;!5YP6~vxn*l za`G>)b)AOm#BdE55=QF4XdM_GV#LT0utFFeCakx8q#m$R_7W=;KjK&;1I&*~H>%vD z^$d{?i7IBaj+CbsT7LGIS#6Lm%j1Vpg1V#uBxB2~Cz3t&RiAF2TzpKK!((NT&QWR; z4e%dbbBUpVNZ&#_M?znx1sMV;zbscm(e9$l(5(XEzY088eGoNjq~3cq?eVEw?!f)p z1cIIfTw(Ajb|EtHq)Q%Y-;;aX!$^H7gT}#kztPapJ9dsA*?2mx-?9l8uRRP$Ycp8U zn8An^xEH#=C3dIEv}lboeU<~mYWwQOG}h{oeZ!$E@S+Xp;Kduy!}`_3SdCdt)YOZh z$?V_pp(8`e+^hjLEypv4>v)zv`mIGn7A2L>qDrb_Q6c@E*)o-BtuZn^#i(dH%cV4m z?I_wb7V@s$5%UlVq|0ic9$j7<%1F4oYW&9>R$o(*d8j^?R7%h~A6yw6lAX zX+pslE%Mq$y*|wQIvNXYQ-+x45G~a8Yggf>CvL=5#~qEMFpVM3$k>F($^W%oF5jS; z?!|79R4mbbgqn2nr515by{Kscuhvt+`G>E-i!QtX*F63h9Iee^So$D8Z^ViKbdso# zi#d+dqrr9OoPpzN4b;Lc`W>W#D#qY(k!+gl2|~>Ub;{W3Czn=v@g=JIgT`x&yK|TI zn|9llTlO3rkdp&!%V!FpmS7EE``*3Swrc``bDMQwEeUFDK!%`4?FKeI{%E}L(hG3% zXr{Zfe`eI!Y9MnR!jS z=+++BC@#w>bR^-tX$O+>nRi&p;~~N&NZ#-Ow?h1tRG?%tMo14 zVtqybAM4M?aeAj1RvjvEJ*)Li;_4HR#|1|nqSuINK*=)036KtwktypWH7@F7oOmHANvlS6##YxzUB?ps=0w@5 zuI5RCq}c-Mh&D&GP^b@pxSu7QhD`NkSq8(p5+u9YlPn|?vxqavj$B^Uz9J>4TvbH9 z6q+{WmDBZ<6R1BBh~+xyN829BeBFAe54Ni8SkR+B(9j6nyK55Pzker!CZHFeTR>8> zI8lv;m<1G%YQ>ETG*;+Nd+uXb0sJ%&K$cI|=tM#kFIft#rv(7yWC#ruN4m|`OP|CJtw%f0z?9Di1>MzjC-8!dAR(mJTdh|Km zuL#-6L7sA0Vj&4K!6{;Wnn%5;?M7)M+i}(}7nF6;sXU@?*P;VE0vILwkt}kZr>s+K zOY$FWOM^M;(aIR?RkgZN>Yld3CJ6uc{@>IFFdcMn^j$12&Z>XGE2QA&kbWlW!mq|G zu3mpSjvK9ENQ+Uwi2`afR5u13BnMa*W^%iN^Qavo`WSe@5v%dSb!Xv+&OIG#@+oAM zRh-Mm3zj6v1k7{vGP8#=>C)M4>ftg_)e)n%sey<<$|(Vl^rKu%C3Snv8|EJ}c>Er+ z%2GwmMCP3PZUA#U2PjB_DW3YU*1%auAC3)=I~pTwAfu81AZ5qggOpzIq#)UHupA*( ztiGTmQ!de#vzX|shGmqX;+Tv%hQka_K71H!^~JxgzU#LRS=%LOgCg0=NfLfyF_l4%KfiM)+i* zg#5!mWNJdKfUZ9X(z*)DTs>*=^wZPUR(g!8u!W>a3st-MmZ4y*GYav5i1P$p*Ptdu z6xW^bAH;LX1r2ry6i3jQ8x~1<3g!(m$z-C|bt298n!ZwX>XVcua$x76FH*+Bv*@wZ z?Gn^C+;!g$>~C0CC`^=$5k5nMgw_!?@@Xk5jPLlidz}Y8NgPtkamD&GutFC=Pc_OD zv@t*wJr56bxsZA}1SzYKIJn4J(-zKaN4Kq}i=|bnO)P-4#umW!GCr9kxq2qsek2uV zYtYFMQHfkUNsv!;qWDU6i$tTl-HKlk6q_`5QJC46DYH#Wt zzksd>grH5a3O}6%?c^mqL|j^0000mGNklBoIbZ`r8Uc-<;$)~+W1Hq&w4sQQmwwxC;*_*I z!+(>{e$YXx4$*#vBz)&X<#4P~QT1i*XH*@?R3}N0Y?c!|t3J#INuCgGXoLfh>$-&q@yw9hSJyO@pq_Jt zyo9D)ElaR@8S~BS*u#Nj4{clJepS)7R5;~e{1xC$6=hK?;Gm<|ie722`iWfd0 zd{FoY<@twy`5gY?V_(1rKK6O}eGY&BFQ38t|K+oYb;#!fAN?FY5b0;}e*1j<3;5v2 zKaWp;>06j-#)heZ%UgUMdS&dVCwsSp?5*#WyQS0I)eheh4+hiJhvzrFNy`A8hgMvt zB1yl1nqOEg4Cv6D!C7!eyi@_l@1JgB=bmviwE?&~>mrTgs8f(+h(Kb387l7 zNed)n&QekOStgT>Y*Xt?*tdjrWM|t`Ppdl0%@BcU6&`b=98mkr1?d>*?jG>nJMY8$ z{`ueVz7Kr@@B5ce<9#3gH2&^GpN#Orecy*a75VpB_u)_CAO7W&^7%LEJ|X&vC|mdU zAO1J|o$T+|Ch`7{eoBk|Q}}yrD1Wbo{tsI4f2Z7kr_JGg!rx2&d()4k%^}tkH;I44 z(o>#fjm+0q9veln{KK=EK zrYtB)2ZTY1DOGe#Pd9c5I#p=;vX$dl9NH=mHtJ>JOG< zet>iwk;8zrlBEj}uNbA$1|#0GVA=f)a%k$Quqh_jHMGtZHuaidWco-3<-{TmQgzSc z?<;99x}|EvJnjd@?7o&*&I+8fUq1J{pY5RO~vA~nGmCUNPU zu1}{{?#dFNxdm_Ib$whq{jqCN3ymmy5K z)?Tp50Ad2P4u?nhq$?vrwtY&L)wq;MSF@F6UdC-T204-)wG47yu+4QE3l69_l8ln$ zjVSau*=Cd`^G3H^)s?m?&8otI@+3iWL1}c&h=jaiZksI4zr^tA;MIS2Y32NkgXLOnkSWyA@hWjjwJDpspju8?puEp&)kIOHjs6 zSd#K#DxN3CLs7j(xqmeaZbZDgzC$GR&sbX0rOY%X_Rh}4%StjCJ@(FLNvd`mEJ!J$ z;-`GXK%^svIEUX6MGs#wf>jw1A1PH2q$3@f{CzHSn;Kr!rnZsEm((Owa_bHI*lyma z@}+E@(JlAWS-(*DsiErYR+f+E@S>?2BcJO`bw7)cAW9KK#6>JgP-9nxAGb>YR3XR= zK7yVGNXc0Z5QPp66TB}P=A&M=93De}MJ#+s55w2SatZ*beA)mg8bl%ZK?Ct1pn4-a z;1rb07~nF;x zWvOlMi*z;nnh%~KjVUoXF@wB1F{)MSB2-25^vP&37KB1}USG6B*R0YY0+}YYtmQN_ z+XBfJzfi^(grstNQup8R$mCPaOU~6*?apnGtg1VB+dCBV3Z0jjw5uou3t*-3cB#eL06wSGo zJ{oG6j6UXWwJ)PP{>+ynu5N%N;t>;xGZlf=eiT;XRrOjFeZ$Z)m9=yd ztK#}aKsv}=g7rp{dY^448Dq^Gy*+iqQk(nPyY-fh`EqsJ85Ke8iA+3^lx$>?I*+!wBLtK|%7fg*g4g(bS zHwL&ACPv!T!l>&$k&Nx`*7uULT86Av0}bE(=Qz1WV~$|~iiO5?`7zBBkp>tuMn4i&8?}SKbbF5;WE%HD-XvU)3eObOj@#d@5pM?FuoApuPba zY8jEqzcw^Px*~KQ9wVbu+glVsk0%{yYw-V?c@pn?esykC)Y) z)19O!?e=*T2Q~s(ukh9Y`wGN`)yu1`v%k^SER6G=W_YNsT@`WilDfbu<)qN-JbE5( zlTkGmvCwYqrvv}1`amTaI*)$sB?&UY5nlMF-gOQ0hWRoFnfyuL;dD3dY8y$1^n`O% zb5)&eGpf3QysIe(FFINgnbwIUm=Q3D$Xg~QK!*sm*#Tl&zyTjwtp<|tcp4}U*HW;k z@`#c&jxkZ2Liv=413!YUQ59vzs?L0=A4KhE^z$JJk}b1+tLS(ATLE1R+0I3BPHwxC zrJff1qUQ$C^41`=_+@0YM6^tStVRs!w|bH>dz`yEB}q%UWTLe=+1DtgOfuu)q^cr-MAUoj;BuJt>x?@P{X(-HT6Ui7y zGKM-QsqtU~RBtk`x)0D|hMqF-KeZk~R=rM}Et%H5P?x2h#;)G-Jx$0ah^662OF?C@19KuzL7 z2}7JT_Rwr?@s_*cfn@a9JwA=SQ?ugTMP-o5(J?}Nq|12fzR2XlD=A~Wv6x?6vx;8D z>I%L{pk70R3m?u)Mkk9xmA6Px3(t_$Rf@c<0on|5WV&J*f_NjBzV+YxQ?GQAL!{;f z2&Jr#mnaZSIRvz9@>A}hMh6rJnd+kIQ{JrR>si} z0q^_bLDWKyLsqZAkpF`nq{B5Ep1dUGl@P>363T-m17v!YU`AOPmASa_W)t^~jlpr$ z?k-idl_xU!S|$lH!Ls26V@f7HnW%LJnPjp}t1Z3 zQHz6u6^5>&S_cpwbe&R3vAOD&EE_#`Y6}cVA+?J+Ux(l)1mAJ3Fl>yl5I~B0jCDQ5 zMN3RB89^UoO%bHe)edE}ucYW(*fQlXG$QDL>=~L-mnk6Ebyes?R?=9dHdpzDG@$e^ zeY@pSzZB|Ri;e5`U-?#MOLw}U;qKNgpB!|-H5+i`p{t?QccuOuYJ~gf{@25 zq8vG?f*FaCcXK7AlZuV<>QMF=1 z>Sny|m7)&;SI|7 zX7O+O*_YxC%J;^fd71J`FaGtfya|r?|C#s=ueuR$`049$F#xfG zI4+R`=2~%34%btKzg2ZWvsuq>fZAK$C~*Ksb^x(U3su9R9%`zZV9n}L9Dc|O)HK;V zXT5+?9#)jRsKO9~&_0|_^EfKv1@j|-q^6eo-D8uuW7mE(vKlgNFq!mJf=npfr0Fa% zhg76I1d+N9O17g8w@#4GF-IP{5^IGc*Q~O{YT{R~M@mJWl*D@*Qk&M|r^otTrUTcOFNr34fWT&WhExb`qz*aoa8 zW7V<)QfR*m?YmlGvL59je`ZW7EHb@}u>kBNU8%P% z=2E^)wwiKfs@$O7`KdNgHwfG4>nQtDOZWJda!IRsNp+&72kx#snLX4vhy4C@g8(=h<3@Tkd%fcklI6KplvVhzHptAX)~WNKHX?Aht_%uy?ZB zH*tf{B-O-r{=wcotdve5brL(URK_s*%~1eKQ>zVW$FT1J>>05gF{k}<^d-iw-%%EKMc_1*X8aQVEK^AKTa-Ri6o*ttTF%@ zeCsa|B=2ix`1n`9gK_;775|+%W(ceykIB$+xL%_}SqLOSvXBxXJLRP9Jm+eQ+aaQQ zscBw|{{oVKHp`%Rm7oyA?{;oiu0_zV9dhkal*C&1Nl38)r1UBHK=!Vhu5M7Qdw1evn!!di^C&zi_Vw0Umu8U8a)nQvpH&N`<21% zm}6Tmh3aT^>iDA%#nF1_b8d~ViQsOFsFXTS9El#6NXk=Crd$YVmC4RHS;Sx(L-^LV zUHH=Xw_%pLo9Uw$gSr-E70MiorI~JN?n6hM^7#UkNRMG^ne;WaE!T3{S0BMYe)|sm z>;1d2uQr0y~vTXGm7nkClQ z0sPZ9zl-nfozf;yQ|??{(~#&~4I~MYRn;8cgH87Fk=k}6E&ibHztZ+_&|c$5_GIoQuJ}Rk}Om|C}#HAwF#I(+ZrdQsU z4`K?+HP@H(2bwkf?U!%C)>&d&KM|%2=*6jZqM4dxEchVV+gJ5<=bF(1-=R(DQ+I8} zNAK8*z1a|UWyAQ`_wT|jyT>t6A4blsXm8d#Z=rQ=HCG#pDk^j)*0-n~B$PU_?a~q-1Zs?PaWa!*UhY8KutrVi3oAo&Yknk7S2uyUwK76X;BbLm}u&7hD&qu{Ng5 z*ri>X=*Cnd-6TUZ0GXJYzAB&g_#?4aKL<&Su9_E-mTmB07+%mw>lUT2rcvSBNo(6`*_cw@KkKS%q{4StO=1X{j$KS_`ZL>3Lm!#bBnXN-jkd&HgYKHw; z9Us@P5g+>AJ=jyPt8VGF;I|2Xd&_rl>+b!S(x#9jQx+rjI!NkYC{qCuQYUFTN)J`b zE`Mqa)Xp{?^Lah@9v(!Uw-;4`2Iv5|9(KQF({qv zaWhbzzGzZGDO9yN*`;@Kk|5Oz$;mHhkq14)h*~EbgFc%HvmC~D{S^8BTW-V0?!Fg$ zRX+(R8r08Y0mOZ3s@aZJp+0u9b+}w&Skk9_A61fc^rK`ThPU~AIXk(TUU*1 z@$v_#Us;{sr65V|gg1+GA%rT*#&u$%? z!n?lwO?-OWPV8lR%nzXcs15};F-`;A+1pB~bJcb%dgSpekLql7LUqwH~E z%v*dZ-k2yVc_-Iv9)SDoZi zd(duDue@z*e{Laho{L8REXm^GbiPKjp(pyJtDZe0s&b3Zo4GasO(|z+X_ub~{<5sW zc0*1)Vg)vxbS&yYE1^$S_OnSLCWFy6E9vR1z?q?8+%rSG_bcDUJHPyGe0#i!34M{z zwK*8fYRI$@#eUjI zpv4L0Bc(v~knDIPswJBi#B2v*yp5_??dY_1NF736U*GmWnHF5 zHD6UGsi9@nyda)je2f#jZllVVvUT04+N!*(XU3qL&GzmX%b8ETFw>a1S54P+?V4=8 zoDV=pJ#vy6a9-R`P8t@%9aY=c@%y}#G7OFuV$f1-hZzU?0T zkzO%AbjSVJk=M{v--1RtWa^Vvb5s3v8#T7b#AoVerZzP+4&NA`!av?}EA}X$sZB^G zyAD8r^C&IMF|#zl-6lPCK;K-T2owv}>Rxb8>r1L`$MLWZYP(8g=bp-T6tv}Nxy0P4 zw#Ghf31HDw>pMYO#sM8(FeMHs(J}{<2i`Y0M?k36vaP+Er>WUX4a`o>-Y-idP82=T zia%(@-K=F9^lKo_I_7Y!Kk+db@l${dZolD<o(bGFOYGE7cVqRH7|%vAA%40x3g6{- zO5U2+@vZ$0eC)0V@Q%-Y8GrD}FXBUY-;b?Yz_axlykKIRR6X@gARt48>JI`*1T`nN zQ|<94@RdFL@Xz1A9b?qbgEEqoSyxbf^CWc-67;I1?*)W57TK)J?Qe!UDGt=-jfe_F z89J;}TPT{5Fd&NRAvx%$%l(tHxaWagxL3Gu`)+J|a5wH3EN_*(^?}`JLGnG@_u`%h z_u_8RySMK_^4W#E<#&%E+r2yXVe5|l*!tj@un%{O-Yx$-x9x%Bw?4QJ_ei%@@%Kbt zvi$91`(4}j;jRbv;JzJuf#jn6%eqYGtAHdjtq17n z_Rm06VY@*RSR2Nq z7J5@HO^dNwdBK~gORm?fX^Cb=Z89}{ar+K@>ihR#tUiivpVD_Abx=`9%dcB540bhJ znKKpdneu^`pdujPW;kah2Q;i{L=6J1%Byme=hsG z@r!SLH-7nT@4{Q&_HO*j@BKM`Rd|bF{#SnQ-O=`ozx!_d!dw3wza;vLZ~F`U;@jRM z{h#BPfA2kb%kRHe`Q9V`FQoem@qa1)J@`e{^UKO<`&)khFYp%C`73|$Ui{kczZ;*? zHx_8T@emzen8v}Z&WkqJtFdXdo<5hb>N1BXsT)x~8yYh^=NP5vy8(QE?18aHb9SF* zg4_;%VKLSHli*ov*Wl{&PQ%JD6)V<_4e=Ul1ng&^>yQaSo$XM2c1NA9vY3>R2-z$K zD5Dl%F1aC0>TCTz{WiZ%U-1898u;4YS$uWZ1irL$9A6i{y>|w8=;`2I*>`EtkJpFL z&>i0?wPop^?6XHs*;TBE>VOXh8OA?DuK)lL07*naR1$oV<9oB}j&3^5s{Wn&snEX~ zeCD2Q7}q9{m$8oT1;triPM9R7v-Jt3oT#diI<>=bTI-TK3rRHe$}rO;X7U=Qnl(%| zGtoMx_4G5<$T2n3z|?FL)8c2ElEqKX%u1I-4-c4Z)G;BLPBrUj$ZxjMfYE5oN^S_v zh-R~irgAhy8%_H(F{6A9>1Gu-BTP4d*&LW@glL_@sy#d6if^0za?wko=FTSmwy>nm%!t9~V4WGuxBeel7_W;5Kax+=

o0-8>G9H*Y9pw|ab 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 Eg0MVNA{C8!1YU9_st|dnrn6A4M53 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 %95a=x2AB>NI`-QL2pNQu= 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

igJ>p>CE1RbZkm^y_}edb4Q##D*j9PNB$r3 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 From ff086e497c2dc751d72f3a6d72ce5d883b297672 Mon Sep 17 00:00:00 2001 From: PrefacedCorg <1876568293@qq.com> Date: Sun, 31 Aug 2025 11:43:52 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml.cs | 42 +-- Ink Canvas/Helpers/AdvancedBezierSmoothing.cs | 10 +- Ink Canvas/Helpers/AutoUpdateHelper.cs | 78 ++--- Ink Canvas/Helpers/DeviceIdentifier.cs | 66 ++--- Ink Canvas/Helpers/GlobalHotkeyManager.cs | 74 ++--- Ink Canvas/Helpers/ImprovedBezierSmoothing.cs | 12 +- Ink Canvas/Helpers/InkFadeManager.cs | 74 ++--- Ink Canvas/Helpers/InkSmoothingConfig.cs | 20 +- Ink Canvas/Helpers/PPTInkManager.cs | 12 +- Ink Canvas/Helpers/PPTManager.cs | 6 +- Ink Canvas/Helpers/PPTUIManager.cs | 2 +- .../BuiltIn/SuperLauncher/LauncherButton.cs | 2 +- .../BuiltIn/SuperLauncher/LauncherModels.cs | 4 +- .../LauncherSettingsControl.xaml.cs | 4 +- .../Plugins/BuiltIn/SuperLauncherPlugin.cs | 4 +- .../Helpers/Plugins/EnhancedPluginBase.cs | 2 +- Ink Canvas/Helpers/Plugins/IEnhancedPlugin.cs | 2 +- Ink Canvas/Helpers/Plugins/IPluginService.cs | 2 +- .../Plugins/PluginConfigurationManager.cs | 4 +- Ink Canvas/Helpers/Plugins/PluginManager.cs | 4 +- .../Helpers/Plugins/PluginServiceManager.cs | 2 +- Ink Canvas/Helpers/SoftwareLauncher.cs | 4 +- Ink Canvas/MainWindow.xaml.cs | 84 +++--- Ink Canvas/MainWindow_cs/MW_AutoFold.cs | 6 +- Ink Canvas/MainWindow_cs/MW_AutoStart.cs | 4 +- Ink Canvas/MainWindow_cs/MW_AutoTheme.cs | 6 +- Ink Canvas/MainWindow_cs/MW_BoardControls.cs | 14 +- Ink Canvas/MainWindow_cs/MW_BoardIcons.cs | 4 +- .../MainWindow_cs/MW_ClipboardHandler.cs | 10 +- Ink Canvas/MainWindow_cs/MW_Colors.cs | 10 +- .../MainWindow_cs/MW_ElementsControls.cs | 160 +++++------ Ink Canvas/MainWindow_cs/MW_Eraser.cs | 4 +- .../MainWindow_cs/MW_FloatingBarIcons.cs | 161 +++++------ Ink Canvas/MainWindow_cs/MW_Hotkeys.cs | 2 +- Ink Canvas/MainWindow_cs/MW_ImageInsert.cs | 16 +- Ink Canvas/MainWindow_cs/MW_Notification.cs | 4 +- Ink Canvas/MainWindow_cs/MW_PPT.cs | 16 +- Ink Canvas/MainWindow_cs/MW_PageListView.cs | 8 +- .../MainWindow_cs/MW_Save&OpenStrokes.cs | 4 +- .../MainWindow_cs/MW_SelectionGestures.cs | 10 +- Ink Canvas/MainWindow_cs/MW_Settings.cs | 50 ++-- Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 14 +- Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs | 72 ++--- .../MW_SimulatePressure&InkToShape.cs | 12 +- Ink Canvas/MainWindow_cs/MW_TimeMachine.cs | 12 +- Ink Canvas/MainWindow_cs/MW_Timer.cs | 4 +- Ink Canvas/MainWindow_cs/MW_TouchEvents.cs | 270 +++++++++--------- Ink Canvas/MainWindow_cs/MW_TrayIcon.cs | 8 +- Ink Canvas/Resources/Settings.cs | 20 +- .../Windows/AddCustomIconWindow.xaml.cs | 2 +- .../AddPickNameBackgroundWindow.xaml.cs | 2 +- .../Windows/CountdownTimerWindow.xaml.cs | 4 +- Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs | 10 +- .../Windows/HistoryRollbackWindow.xaml.cs | 2 +- Ink Canvas/Windows/HotkeyItem.xaml.cs | 16 +- .../Windows/HotkeySettingsWindow.xaml.cs | 114 ++++---- Ink Canvas/Windows/NamesInputWindow.xaml.cs | 4 +- .../Windows/OperatingGuideWindow.xaml.cs | 4 +- .../Windows/PluginSettingsWindow.xaml.cs | 12 +- Ink Canvas/Windows/RandWindow.xaml.cs | 6 +- .../Windows/ScreenshotSelectorWindow.xaml.cs | 60 ++-- ...vasForClass.csproj.AssemblyReference.cache | Bin 33620 -> 35309 bytes 62 files changed, 826 insertions(+), 825 deletions(-) diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index b662a247..da118e9f 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -1,3 +1,8 @@ +using Hardcodet.Wpf.TaskbarNotification; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern.Controls; +using Microsoft.Win32; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,11 +18,6 @@ using System.Windows; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Threading; -using Hardcodet.Wpf.TaskbarNotification; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern.Controls; -using Microsoft.Win32; -using Newtonsoft.Json; using Application = System.Windows.Application; using MessageBox = System.Windows.MessageBox; using Timer = System.Threading.Timer; @@ -80,7 +80,7 @@ namespace Ink_Canvas args = Environment.GetCommandLineArgs(); bool isUpdateMode = args.Contains("--update-mode"); bool isFinalApp = args.Contains("--final-app"); - + if (CrashAction == CrashActionType.SilentRestart && !isUpdateMode && !isFinalApp) { StartWatchdogIfNeeded(); @@ -465,16 +465,16 @@ namespace Ink_Canvas { // 初始化应用启动时间 appStartTime = DateTime.Now; - + /*if (!StoreHelper.IsStoreApp) */ RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version)); - + // 检查是否为最终应用启动(更新后的应用) bool isFinalApp = e.Args.Contains("--final-app"); bool skipMutexCheck = e.Args.Contains("--skip-mutex-check"); - + // 记录最终应用启动状态 if (isFinalApp) { @@ -499,7 +499,7 @@ namespace Ink_Canvas // 处理更新模式启动 bool isUpdateMode = AutoUpdateHelper.HandleUpdateModeStartup(e.Args); - + // 如果是更新模式,不显示主窗口但保持应用运行 if (isUpdateMode) { @@ -510,10 +510,10 @@ namespace Ink_Canvas // 检查是否存在更新标记文件 string updateMarkerFile = Path.Combine(RootPath, "update_in_progress.tmp"); bool isUpdateInProgress = false; - + // 检查是否以更新模式启动 isUpdateMode = e.Args.Contains("--update-mode"); - + // 如果是最终应用启动,立即清理更新标记文件 if (isFinalApp) { @@ -530,7 +530,7 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"App | 清理更新标记文件失败: {ex.Message}", LogHelper.LogType.Warning); } } - + // 如果不是最终应用启动,才检查更新标记文件 if (!isFinalApp && File.Exists(updateMarkerFile)) { @@ -540,7 +540,7 @@ namespace Ink_Canvas if (int.TryParse(updateProcessIdStr, out int updateProcessId)) { LogHelper.WriteLogToFile($"App | 检测到更新标记文件,更新进程ID: {updateProcessId}"); - + // 检查更新进程是否还在运行 try { @@ -549,18 +549,18 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile("App | 更新进程仍在运行,等待更新完成"); isUpdateInProgress = true; - + // 等待更新进程完成 int waitCount = 0; const int maxWaitCount = 10; // 减少等待时间到10秒 - + while (waitCount < maxWaitCount && !updateProcess.HasExited) { Thread.Sleep(500); // 减少等待间隔到500ms waitCount++; LogHelper.WriteLogToFile($"App | 等待更新进程完成... ({waitCount}/{maxWaitCount})"); } - + if (updateProcess.HasExited) { LogHelper.WriteLogToFile("App | 更新进程已结束"); @@ -592,7 +592,7 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile("App | 更新进程已不存在"); } - + // 无论更新进程是否还在运行,都清理标记文件 try { @@ -668,11 +668,11 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile("App | 更新过程中,跳过重复运行检测"); } - + // 在特殊模式下,创建一个临时的Mutex以避免其他检查出错 string mutexName = isFinalApp ? "InkCanvasForClass CE Final" : "InkCanvasForClass CE Update"; mutex = new Mutex(true, mutexName, out bool tempRet); - + // 额外等待一小段时间确保更新进程完全退出 Thread.Sleep(1000); LogHelper.WriteLogToFile("App | 特殊模式等待完成,继续启动"); @@ -681,7 +681,7 @@ namespace Ink_Canvas _taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon"); StartArgs = e.Args; - + // 在非更新模式下创建主窗口 var mainWindow = new MainWindow(); MainWindow = mainWindow; diff --git a/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs b/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs index 0948fa44..2c61c0cf 100644 --- a/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs +++ b/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs @@ -128,7 +128,7 @@ namespace Ink_Canvas.Helpers if (points.Length < 4) return points; var result = new List(); - + // 添加第一个点 result.Add(points[0]); @@ -142,9 +142,9 @@ namespace Ink_Canvas.Helpers // 计算改进的控制点 var controlPoints = CalculateImprovedControlPoints(p0, p1, p2, p3); - + // 限制插值步数,避免点数爆炸 - int steps = Math.Min(UseAdaptiveInterpolation ? + int steps = Math.Min(UseAdaptiveInterpolation ? CalculateAdaptiveSteps(p0, p1, p2, p3) : InterpolationSteps, 16); // 生成贝塞尔曲线点,但跳过第一个点避免重复 @@ -179,7 +179,7 @@ namespace Ink_Canvas.Helpers // 计算控制点距离(基于点间距离) double dist1 = Math.Sqrt((p1.X - p0.X) * (p1.X - p0.X) + (p1.Y - p0.Y) * (p1.Y - p0.Y)); double dist2 = Math.Sqrt((p3.X - p2.X) * (p3.X - p2.X) + (p3.Y - p2.Y) * (p3.Y - p2.Y)); - + double controlDist1 = dist1 * CurveTension; double controlDist2 = dist2 * CurveTension; @@ -214,7 +214,7 @@ namespace Ink_Canvas.Helpers // 基于长度和曲率计算步数 int baseSteps = Math.Max(8, Math.Min(20, (int)(totalLength / 10))); int curvatureSteps = (int)(curvature * 10); - + return Math.Max(InterpolationSteps, Math.Min(24, baseSteps + curvatureSteps)); } diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index 397a381b..d860f4b8 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -1,3 +1,5 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -15,8 +17,6 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Ink_Canvas.Helpers { @@ -1238,7 +1238,7 @@ namespace Ink_Canvas.Helpers // 查找解压后的主程序文件 string newAppPath = null; string[] possibleExeNames = { "InkCanvasForClass.exe", "Ink Canvas.exe", "InkCanvas.exe" }; - + foreach (string exeName in possibleExeNames) { string testPath = Path.Combine(extractPath, exeName); @@ -1260,12 +1260,12 @@ namespace Ink_Canvas.Helpers try { LogHelper.WriteLogToFile($"AutoUpdate | 准备启动新版本进程: {newAppPath}"); - + // 启动新版本进程(以更新模式) string arguments = $"--update-mode --old-process-id={currentProcessId} --extract-path=\"{extractPath}\" --target-path=\"{currentAppDir}\" --is-silence={isInSilence}"; - + LogHelper.WriteLogToFile($"AutoUpdate | 启动新进程的命令行: {newAppPath} {arguments}"); - + ProcessStartInfo startInfo = new ProcessStartInfo { FileName = newAppPath, @@ -1276,10 +1276,10 @@ namespace Ink_Canvas.Helpers Process.Start(startInfo); LogHelper.WriteLogToFile("AutoUpdate | 新版本进程启动命令已执行"); - + // 等待一小段时间确保新进程启动 Thread.Sleep(2000); - + // 关闭当前旧软件进程 LogHelper.WriteLogToFile("AutoUpdate | 关闭当前旧软件进程"); App.IsAppExitByUser = true; @@ -1312,7 +1312,7 @@ namespace Ink_Canvas.Helpers if (args.Contains("--update-mode")) { LogHelper.WriteLogToFile("AutoUpdate | 检测到更新模式启动"); - + // 解析命令行参数 int oldProcessId = -1; string extractPath = null; @@ -1326,7 +1326,7 @@ namespace Ink_Canvas.Helpers { string arg = args[i]; LogHelper.WriteLogToFile($"AutoUpdate | 处理参数 {i}: {arg}"); - + if (arg.StartsWith("--old-process-id=")) { string processIdStr = arg.Substring("--old-process-id=".Length); @@ -1365,7 +1365,7 @@ namespace Ink_Canvas.Helpers // 启动更新任务 Task.Run(async () => await PerformUpdate(oldProcessId, extractPath, targetPath, isSilence)); return true; // 返回true表示是更新模式 - } + } LogHelper.WriteLogToFile($"AutoUpdate | 参数验证失败 - 老进程ID: {oldProcessId}, 解压路径: {extractPath}, 目标路径: {targetPath}", LogHelper.LogType.Error); return false; @@ -1437,7 +1437,7 @@ namespace Ink_Canvas.Helpers // 复制文件到目标目录 LogHelper.WriteLogToFile($"AutoUpdate | 开始复制文件从 {extractPath} 到 {targetPath}"); - + try { // 使用递归复制方法,支持重试机制 @@ -1445,11 +1445,11 @@ namespace Ink_Canvas.Helpers if (copySuccess) { LogHelper.WriteLogToFile("AutoUpdate | 文件复制完成"); - } - else - { + } + else + { LogHelper.WriteLogToFile("AutoUpdate | 文件复制失败,部分文件可能无法覆盖", LogHelper.LogType.Error); - + if (!isSilence) { MessageBox.Show("更新失败:部分文件无法覆盖,可能是文件正在使用中。\n请关闭所有相关程序后重试。", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error); @@ -1460,7 +1460,7 @@ namespace Ink_Canvas.Helpers catch (Exception ex) { LogHelper.WriteLogToFile($"AutoUpdate | 文件复制失败: {ex.Message}", LogHelper.LogType.Error); - + if (!isSilence) { MessageBox.Show($"更新失败:文件复制时出错\n{ex.Message}", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error); @@ -1472,7 +1472,7 @@ namespace Ink_Canvas.Helpers try { LogHelper.WriteLogToFile("AutoUpdate | 清理临时文件"); - + // 删除解压目录 if (Directory.Exists(extractPath)) { @@ -1503,23 +1503,23 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile("AutoUpdate | 更新操作完成"); - // 启动更新后的应用程序 + // 启动更新后的应用程序 string newAppPath = Path.Combine(targetPath, "InkCanvasForClass.exe"); if (File.Exists(newAppPath)) { try { LogHelper.WriteLogToFile($"AutoUpdate | 准备启动更新后的应用程序: {newAppPath}"); - + // 获取当前更新进程ID int currentUpdateProcessId = Process.GetCurrentProcess().Id; LogHelper.WriteLogToFile($"AutoUpdate | 当前更新进程ID: {currentUpdateProcessId}"); - + // 创建一个临时标记文件,用于新进程检测更新状态 string updateMarkerFile = Path.Combine(targetPath, "update_in_progress.tmp"); File.WriteAllText(updateMarkerFile, currentUpdateProcessId.ToString()); LogHelper.WriteLogToFile($"AutoUpdate | 创建更新标记文件: {updateMarkerFile}"); - + // 启动更新后的应用程序(标记为最终应用,不受相同进程影响) ProcessStartInfo startInfo = new ProcessStartInfo { @@ -1528,24 +1528,24 @@ namespace Ink_Canvas.Helpers WorkingDirectory = targetPath, UseShellExecute = false }; - + Process newProcess = Process.Start(startInfo); LogHelper.WriteLogToFile($"AutoUpdate | 最终应用程序启动成功,PID: {newProcess?.Id},已标记为最终应用"); - + // 等待一小段时间确保最终应用程序启动 Thread.Sleep(2000); - + // 结束当前更新进程 LogHelper.WriteLogToFile("AutoUpdate | 更新流程完成,结束更新进程"); - + // 强制结束当前更新进程 try { LogHelper.WriteLogToFile("AutoUpdate | 强制结束更新进程"); - + // 标记为应用主动退出,避免看门狗重启 App.IsAppExitByUser = true; - + // 写入退出信号文件,确保看门狗不会重启 try { @@ -1557,7 +1557,7 @@ namespace Ink_Canvas.Helpers { LogHelper.WriteLogToFile($"AutoUpdate | 写入看门狗退出信号文件失败: {ex.Message}", LogHelper.LogType.Warning); } - + Environment.Exit(0); } catch (Exception ex) @@ -1569,7 +1569,7 @@ namespace Ink_Canvas.Helpers catch (Exception ex) { LogHelper.WriteLogToFile($"AutoUpdate | 启动更新后的应用程序失败: {ex.Message}", LogHelper.LogType.Error); - + if (!isSilence) { MessageBox.Show($"更新完成,但启动应用程序失败:{ex.Message}\n请手动启动应用程序。", "启动失败", MessageBoxButton.OK, MessageBoxImage.Warning); @@ -1579,7 +1579,7 @@ namespace Ink_Canvas.Helpers else { LogHelper.WriteLogToFile($"AutoUpdate | 更新后的应用程序文件不存在: {newAppPath}", LogHelper.LogType.Error); - + if (!isSilence) { MessageBox.Show($"更新完成,但未找到应用程序文件:{newAppPath}\n请检查更新是否成功。", "文件缺失", MessageBoxButton.OK, MessageBoxImage.Error); @@ -1589,7 +1589,7 @@ namespace Ink_Canvas.Helpers catch (Exception ex) { LogHelper.WriteLogToFile($"AutoUpdate | 执行更新操作时出错: {ex.Message}", LogHelper.LogType.Error); - + if (!isSilence) { MessageBox.Show($"更新失败:{ex.Message}", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error); @@ -1615,7 +1615,7 @@ namespace Ink_Canvas.Helpers { string targetFilePath = Path.Combine(destinationDir, file.Name); bool fileCopied = false; - + // 重试机制,最多重试3次 for (int retry = 0; retry < 3; retry++) { @@ -1638,7 +1638,7 @@ namespace Ink_Canvas.Helpers } } } - + await Task.Run(() => file.CopyTo(targetFilePath)); fileCopied = true; break; @@ -1646,14 +1646,14 @@ namespace Ink_Canvas.Helpers catch (Exception ex) { LogHelper.WriteLogToFile($"AutoUpdate | 复制文件失败 (重试 {retry + 1}/3) {file.FullName} -> {targetFilePath}: {ex.Message}", LogHelper.LogType.Warning); - + if (retry < 2) { Thread.Sleep(1000); // 等待1秒后重试 } } } - + if (!fileCopied) { allFilesCopied = false; @@ -1698,7 +1698,7 @@ namespace Ink_Canvas.Helpers { File.Delete(targetFilePath); } - + await Task.Run(() => file.CopyTo(targetFilePath)); } catch (Exception ex) @@ -1866,7 +1866,7 @@ namespace Ink_Canvas.Helpers } // 执行安装,静默模式 - InstallNewVersionApp(remoteVersion, true); + InstallNewVersionApp(remoteVersion, true); App.IsAppExitByUser = true; Application.Current.Dispatcher.Invoke(() => { @@ -1996,7 +1996,7 @@ namespace Ink_Canvas.Helpers return false; } LogHelper.WriteLogToFile($"AutoUpdate | 手动安装版本: {version}"); - InstallNewVersionApp(version, true); + InstallNewVersionApp(version, true); App.IsAppExitByUser = true; Application.Current.Dispatcher.Invoke(() => { diff --git a/Ink Canvas/Helpers/DeviceIdentifier.cs b/Ink Canvas/Helpers/DeviceIdentifier.cs index f67b5387..c079bc98 100644 --- a/Ink Canvas/Helpers/DeviceIdentifier.cs +++ b/Ink Canvas/Helpers/DeviceIdentifier.cs @@ -1,3 +1,4 @@ +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; @@ -5,7 +6,6 @@ using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; -using Newtonsoft.Json; namespace Ink_Canvas.Helpers { @@ -758,26 +758,26 @@ namespace Ink_Canvas.Helpers // 如果所有文件都不存在或损坏,返回新的统计对象 - var newStats = new UsageStats - { - DeviceId = DeviceId, - LastLaunchTime = DateTime.Now, - LaunchCount = 0, - TotalUsageSeconds = 0, - AverageSessionSeconds = 0, - LastUpdateCheck = DateTime.MinValue, - UpdatePriority = UpdatePriority.Medium, - UsageFrequency = UsageFrequency.Medium - }; + var newStats = new UsageStats + { + DeviceId = DeviceId, + LastLaunchTime = DateTime.Now, + LaunchCount = 0, + TotalUsageSeconds = 0, + AverageSessionSeconds = 0, + LastUpdateCheck = DateTime.MinValue, + UpdatePriority = UpdatePriority.Medium, + UsageFrequency = UsageFrequency.Medium + }; // 保存新统计到文件 SaveUsageStatsToFile(UsageStatsFilePath, newStats); - return newStats; + return newStats; } catch (Exception ex) { LogHelper.WriteLogToFile($"DeviceIdentifier | 加载使用统计失败: {ex.Message}", LogHelper.LogType.Error); - + // 返回默认统计对象 return new UsageStats { @@ -800,7 +800,7 @@ namespace Ink_Canvas.Helpers { // 保存到主文件 SaveUsageStatsToFile(UsageStatsFilePath, stats); - + // 保存到备份文件 SaveUsageStatsToFile(UsageStatsBackupPath, stats); } @@ -822,7 +822,7 @@ namespace Ink_Canvas.Helpers { return stats; } - + } } @@ -843,31 +843,31 @@ namespace Ink_Canvas.Helpers if (File.Exists(filePath)) { byte[] encryptedData = File.ReadAllBytes(filePath); - + if (encryptedData.Length < 32) // SHA256校验和长度为32字节 { LogHelper.WriteLogToFile($"DeviceIdentifier | 加密文件格式错误: {filePath}", LogHelper.LogType.Error); return null; } - + // 提取校验和和加密数据 byte[] checksum = new byte[32]; byte[] data = new byte[encryptedData.Length - 32]; Array.Copy(encryptedData, 0, checksum, 0, 32); Array.Copy(encryptedData, 32, data, 0, data.Length); - + // 使用SHA256生成解密密钥 using (var sha256 = SHA256.Create()) { byte[] keyBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(DeviceId + "ICC_Usage_Stats_Salt")); - + // XOR解密 byte[] decryptedData = new byte[data.Length]; for (int i = 0; i < data.Length; i++) { decryptedData[i] = (byte)(data[i] ^ keyBytes[i % keyBytes.Length]); } - + // 验证校验和 byte[] computedChecksum = sha256.ComputeHash(decryptedData); if (!checksum.SequenceEqual(computedChecksum)) @@ -875,7 +875,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"DeviceIdentifier | 加密文件校验和验证失败: {filePath}", LogHelper.LogType.Error); return null; } - + string json = Encoding.UTF8.GetString(decryptedData); var stats = JsonConvert.DeserializeObject(json); if (stats != null && !string.IsNullOrEmpty(stats.DeviceId)) @@ -909,27 +909,27 @@ namespace Ink_Canvas.Helpers string json = JsonConvert.SerializeObject(stats, Formatting.Indented); byte[] data = Encoding.UTF8.GetBytes(json); - + // 使用SHA256生成加密密钥(基于设备ID) using (var sha256 = SHA256.Create()) { byte[] keyBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(DeviceId + "ICC_Usage_Stats_Salt")); - + // 简单的XOR加密 byte[] encryptedData = new byte[data.Length]; for (int i = 0; i < data.Length; i++) { encryptedData[i] = (byte)(data[i] ^ keyBytes[i % keyBytes.Length]); } - + // 添加SHA256校验和 byte[] checksum = sha256.ComputeHash(data); byte[] finalData = new byte[checksum.Length + encryptedData.Length]; checksum.CopyTo(finalData, 0); encryptedData.CopyTo(finalData, checksum.Length); - + File.WriteAllBytes(filePath, finalData); - + LogHelper.WriteLogToFile($"DeviceIdentifier | 加密使用统计已保存到: {filePath}"); } } @@ -958,7 +958,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"DeviceIdentifier | 记录更新检查失败: {ex.Message}", LogHelper.LogType.Error); } } - + ///

/// 从备份文件恢复使用统计数据 @@ -997,7 +997,7 @@ namespace Ink_Canvas.Helpers try { var status = new List(); - + // 检查主文件 if (File.Exists(UsageStatsFilePath)) { @@ -1339,7 +1339,7 @@ namespace Ink_Canvas.Helpers return descriptions.Count > 0 ? string.Join(", ", descriptions) : "普通用户"; } - + /// /// 关机时保存使用时间数据 /// @@ -1360,7 +1360,7 @@ namespace Ink_Canvas.Helpers // 2. 计算本次会话时长(防止异常值) TimeSpan sessionDuration = DateTime.Now - App.appStartTime; long sessionSeconds = Math.Max(0, (long)sessionDuration.TotalSeconds); - + // 防止异常大的会话时长(超过24小时) if (sessionSeconds > 86400) { @@ -1373,10 +1373,10 @@ namespace Ink_Canvas.Helpers stats.LaunchCount++; stats.AverageSessionSeconds = stats.TotalUsageSeconds / (double)Math.Max(1, stats.LaunchCount); stats.LastLaunchTime = DateTime.Now; - + // 4. 保存数据 SaveUsageStats(stats); - + LogHelper.WriteLogToFile("DeviceIdentifier | 关机保存完成"); } catch (Exception ex) diff --git a/Ink Canvas/Helpers/GlobalHotkeyManager.cs b/Ink Canvas/Helpers/GlobalHotkeyManager.cs index b1f1eefe..b5ba3f40 100644 --- a/Ink Canvas/Helpers/GlobalHotkeyManager.cs +++ b/Ink Canvas/Helpers/GlobalHotkeyManager.cs @@ -1,11 +1,11 @@ +using Newtonsoft.Json; +using NHotkey.Wpf; using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Windows.Input; -using Newtonsoft.Json; -using NHotkey.Wpf; namespace Ink_Canvas.Helpers { @@ -19,7 +19,7 @@ namespace Ink_Canvas.Helpers private readonly MainWindow _mainWindow; private bool _isDisposed; private bool _hotkeysShouldBeRegistered = true; // 启动时注册热键 - + // 配置文件路径 private static readonly string HotkeyConfigFile = Path.Combine(App.RootPath, "HotkeyConfig.json"); #endregion @@ -227,7 +227,7 @@ namespace Ink_Canvas.Helpers try { // 开始注册默认快捷键集合 - + // 基本操作快捷键 RegisterHotkey("Undo", Key.Z, ModifierKeys.Control, () => _mainWindow.SymbolIconUndo_MouseUp(null, null)); RegisterHotkey("Redo", Key.Y, ModifierKeys.Control, () => _mainWindow.SymbolIconRedo_MouseUp(null, null)); @@ -272,14 +272,14 @@ namespace Ink_Canvas.Helpers try { // 开始从配置文件加载快捷键设置 - + // 检查是否应该注册快捷键 if (!_hotkeysShouldBeRegistered) { // 当前状态不允许注册快捷键,跳过加载 return; } - + // 尝试从配置文件加载 if (LoadHotkeysFromConfigFile()) { @@ -319,7 +319,7 @@ namespace Ink_Canvas.Helpers try { LogHelper.WriteLogToFile("开始保存快捷键配置到配置文件", LogHelper.LogType.Event); - + if (SaveHotkeysToConfigFile()) { LogHelper.WriteLogToFile("快捷键配置已成功保存到配置文件", LogHelper.LogType.Event); @@ -347,7 +347,7 @@ namespace Ink_Canvas.Helpers { _hotkeysShouldBeRegistered = true; LogHelper.WriteLogToFile("启用快捷键注册功能"); - + // 立即加载快捷键设置 LoadHotkeysFromSettings(); } @@ -376,7 +376,7 @@ namespace Ink_Canvas.Helpers { _hotkeysShouldBeRegistered = false; LogHelper.WriteLogToFile("禁用快捷键注册功能"); - + // 注销所有快捷键 UnregisterAllHotkeys(); } @@ -438,20 +438,20 @@ namespace Ink_Canvas.Helpers // 获取原有的动作 var originalAction = _registeredHotkeys[hotkeyName].Action; - + // 注销原有快捷键 UnregisterHotkey(hotkeyName); - + // 注册新的快捷键 var success = RegisterHotkey(hotkeyName, key, modifiers, originalAction); - + if (success) { LogHelper.WriteLogToFile($"成功更新快捷键 {hotkeyName}: {modifiers}+{key}", LogHelper.LogType.Event); // 自动保存配置 SaveHotkeysToSettings(); } - + return success; } catch (Exception ex) @@ -472,17 +472,17 @@ namespace Ink_Canvas.Helpers try { // 通过反射访问主窗口的penType字段 - var penTypeField = _mainWindow.GetType().GetField("penType", + var penTypeField = _mainWindow.GetType().GetField("penType", BindingFlags.NonPublic | BindingFlags.Instance); - + if (penTypeField != null) { penTypeField.SetValue(_mainWindow, penTypeIndex); - + // 调用CheckPenTypeUIState方法更新UI状态 - var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState", + var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState", BindingFlags.NonPublic | BindingFlags.Instance); - + if (checkPenTypeMethod != null) { checkPenTypeMethod.Invoke(_mainWindow, null); @@ -604,7 +604,7 @@ namespace Ink_Canvas.Helpers { Formatting = Formatting.Indented }; - + string jsonContent = JsonConvert.SerializeObject(config, settings); // 直接写入原文件,覆盖原有内容 @@ -688,9 +688,9 @@ namespace Ink_Canvas.Helpers try { // 通过反射访问主窗口的FloatingbarSelectionBG字段 - var floatingbarSelectionBGField = _mainWindow.GetType().GetField("FloatingbarSelectionBG", + var floatingbarSelectionBGField = _mainWindow.GetType().GetField("FloatingbarSelectionBG", BindingFlags.NonPublic | BindingFlags.Instance); - + if (floatingbarSelectionBGField != null) { var floatingbarSelectionBG = floatingbarSelectionBGField.GetValue(_mainWindow); @@ -707,7 +707,7 @@ namespace Ink_Canvas.Helpers return true; // 返回true表示应该注销快捷键 } } - + // 通过反射访问Canvas.GetLeft方法来获取高光位置 var canvasType = Type.GetType("System.Windows.Controls.Canvas, PresentationFramework"); if (canvasType != null) @@ -719,7 +719,7 @@ namespace Ink_Canvas.Helpers if (leftPosition != null) { var position = Convert.ToDouble(leftPosition); - + // 根据高光位置判断当前选中的工具 // 位置计算基于SetFloatingBarHighlightPosition方法中的逻辑 bool isMouseMode; @@ -739,20 +739,20 @@ namespace Ink_Canvas.Helpers { isMouseMode = false; } - + return isMouseMode; } } } } } - + // 如果无法获取高光状态,则回退到inkCanvas.EditingMode判断 - + // 通过反射访问主窗口的inkCanvas字段 - var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas", + var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas", BindingFlags.NonPublic | BindingFlags.Instance); - + if (inkCanvasField != null) { var inkCanvas = inkCanvasField.GetValue(_mainWindow); @@ -768,23 +768,23 @@ namespace Ink_Canvas.Helpers // 检查是否为批注模式 var isInkMode = editingMode.ToString().Contains("Ink"); var isSelectMode = editingMode.ToString().Contains("Select"); - + // 如果是批注模式或选择模式,则应该注册快捷键(返回false) // 如果是橡皮擦模式或其他模式,则不应该注册快捷键(返回true) var shouldNotRegisterHotkeys = !isInkMode && !isSelectMode; - + return shouldNotRegisterHotkeys; } } } } - + // 如果无法获取任何状态信息,则回退到原来的判断逻辑 - + // 通过反射访问主窗口的currentMode字段(作为最后的备用方案) - var currentModeField = _mainWindow.GetType().GetField("currentMode", + var currentModeField = _mainWindow.GetType().GetField("currentMode", BindingFlags.NonPublic | BindingFlags.Instance); - + if (currentModeField != null) { var currentMode = currentModeField.GetValue(_mainWindow); @@ -798,7 +798,7 @@ namespace Ink_Canvas.Helpers return isSelectMode; } } - + return false; // 默认允许快捷键 } catch (Exception ex) @@ -816,7 +816,7 @@ namespace Ink_Canvas.Helpers { if (!_isDisposed) { - + _isDisposed = true; } } @@ -861,4 +861,4 @@ namespace Ink_Canvas.Helpers } #endregion } -} +} diff --git a/Ink Canvas/Helpers/ImprovedBezierSmoothing.cs b/Ink Canvas/Helpers/ImprovedBezierSmoothing.cs index f249885d..0e4143d3 100644 --- a/Ink Canvas/Helpers/ImprovedBezierSmoothing.cs +++ b/Ink Canvas/Helpers/ImprovedBezierSmoothing.cs @@ -28,13 +28,13 @@ namespace Ink_Canvas.Helpers return originalStroke; var originalPoints = originalStroke.StylusPoints.ToArray(); - + // 预处理:去除噪声点 var cleanedPoints = RemoveNoisePoints(originalPoints); - + // 使用改进的贝塞尔曲线拟合 var smoothedPoints = ApplyCubicBezierSmoothing(cleanedPoints); - + // 后处理:重采样和优化 var finalPoints = PostProcessPoints(smoothedPoints); @@ -61,7 +61,7 @@ namespace Ink_Canvas.Helpers var next = points[i + 1]; // 计算到前一个点的距离 - double distToPrev = Math.Sqrt((curr.X - prev.X) * (curr.X - prev.X) + + double distToPrev = Math.Sqrt((curr.X - prev.X) * (curr.X - prev.X) + (curr.Y - prev.Y) * (curr.Y - prev.Y)); // 如果距离太近,跳过这个点 @@ -148,7 +148,7 @@ namespace Ink_Canvas.Helpers // 计算控制点距离 double dist1 = CalculateDistance(p0, p1); double dist2 = CalculateDistance(p2, p3); - + double controlDist1 = dist1 * _config.CurveTension; double controlDist2 = dist2 * _config.CurveTension; @@ -322,4 +322,4 @@ namespace Ink_Canvas.Helpers return result.ToArray(); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/InkFadeManager.cs b/Ink Canvas/Helpers/InkFadeManager.cs index 6f8188f8..4490b721 100644 --- a/Ink Canvas/Helpers/InkFadeManager.cs +++ b/Ink Canvas/Helpers/InkFadeManager.cs @@ -63,7 +63,7 @@ namespace Ink_Canvas.Helpers /// 抬笔点 public void AddFadingStroke(Stroke stroke, Point startPoint, Point endPoint) { - if (!IsEnabled || stroke == null) + if (!IsEnabled || stroke == null) { return; } @@ -238,12 +238,12 @@ namespace Ink_Canvas.Helpers public void UpdateFadeTime(int fadeTime) { FadeTime = fadeTime; - + foreach (var kvp in _fadeTimers) { var stroke = kvp.Key; var timer = kvp.Value; - + timer.Stop(); timer.Interval = TimeSpan.FromMilliseconds(FadeTime); timer.Start(); @@ -283,14 +283,14 @@ namespace Ink_Canvas.Helpers { // 创建路径几何,使用墨迹的实际位置 var geometry = stroke.GetGeometry(); - if (geometry == null) + if (geometry == null) { return null; } // 获取绘画属性 var drawingAttribs = stroke.DrawingAttributes; - + // 创建路径元素,确保使用正确的绘画属性 var path = new Path { @@ -302,7 +302,7 @@ namespace Ink_Canvas.Helpers StrokeLineJoin = PenLineJoin.Round, Fill = drawingAttribs.IsHighlighter ? new SolidColorBrush(drawingAttribs.Color) : null, // 高亮笔需要填充 Opacity = 0.95, // 初始透明度更高,显得更自然 - + // 优化渲染质量 UseLayoutRounding = false, SnapsToDevicePixels = false @@ -312,19 +312,19 @@ namespace Ink_Canvas.Helpers if (drawingAttribs.IsHighlighter) { path.Opacity = 0.4; // 高亮笔初始透明度更低,更符合荧光笔特性 - + // 为高亮笔添加特殊的混合效果 // 使用更柔和的笔触样式 path.StrokeStartLineCap = PenLineCap.Flat; path.StrokeEndLineCap = PenLineCap.Flat; path.StrokeLineJoin = PenLineJoin.Miter; - - // 高亮笔通常需要更宽的笔触来覆盖下面的内容 - if (drawingAttribs.Width < 20) - { - path.StrokeThickness = Math.Max(drawingAttribs.Width * 1.5, 20); - } - } + + // 高亮笔通常需要更宽的笔触来覆盖下面的内容 + if (drawingAttribs.Width < 20) + { + path.StrokeThickness = Math.Max(drawingAttribs.Width * 1.5, 20); + } + } // 不设置任何变换,保持墨迹原有粗细 var bounds = geometry.Bounds; @@ -356,7 +356,7 @@ namespace Ink_Canvas.Helpers // 获取当前透明度和判断是否为高亮笔 var currentOpacity = visual.Opacity; var isHighlighter = stroke.DrawingAttributes.IsHighlighter; - + // 根据墨迹类型选择不同的动画效果 if (isHighlighter) { @@ -439,19 +439,19 @@ namespace Ink_Canvas.Helpers { var stylusPoints = stroke.StylusPoints; var totalPoints = stylusPoints.Count; - + // 分段算法 - 确保所有墨迹都有足够的动画效果 var strokeLength = CalculateStrokeLength(stylusPoints); var segmentCount = CalculateOptimalSegmentCount(totalPoints, strokeLength); - + // 强制最小分段数量,确保短墨迹也有动画效果 segmentCount = Math.Max(segmentCount, 4); - + var pointsPerSegment = Math.Max(1, totalPoints / segmentCount); // 隐藏原始视觉元素 originalVisual.Visibility = Visibility.Hidden; - + var segments = new List(); var parent = _mainWindow.inkCanvas?.Parent as Panel; if (parent == null) @@ -465,7 +465,7 @@ namespace Ink_Canvas.Helpers { var startIndex = i * pointsPerSegment; var endIndex = (i == segmentCount - 1) ? totalPoints - 1 : (i + 1) * pointsPerSegment; - + // 确保有足够的点来创建分段,对于短墨迹特殊处理 if (endIndex <= startIndex && totalPoints > 1) { @@ -473,12 +473,12 @@ namespace Ink_Canvas.Helpers startIndex = i; endIndex = Math.Min(i + 1, totalPoints - 1); } - + // 为每个分段添加重叠,确保连接处平滑 var overlap = Math.Max(1, pointsPerSegment / 6); // 15%的重叠,平衡平滑与速度 var actualStartIndex = Math.Max(0, startIndex - overlap); var actualEndIndex = Math.Min(totalPoints - 1, endIndex + overlap); - + var segment = CreateStrokeSegment(stroke, actualStartIndex, actualEndIndex, opacity); if (segment != null) { @@ -576,10 +576,10 @@ namespace Ink_Canvas.Helpers for (int i = 0; i < segments.Count; i++) { var segment = segments[i]; - + // 使用预计算的动画曲线获取延迟时间 var delay = animationCurve[i]; - + // 使用定时器延迟启动每个分段的动画 var timer = new DispatcherTimer { @@ -595,7 +595,7 @@ namespace Ink_Canvas.Helpers lock (completedSegments) { completedSegments.Add(segment); - + // 检查是否所有分段都完成了 if (completedSegments.Count >= totalSegments) { @@ -676,7 +676,7 @@ namespace Ink_Canvas.Helpers { // 移除所有分段 var parent = _mainWindow.inkCanvas?.Parent as Panel; - + foreach (var segment in segments) { if (parent != null && parent.Children.Contains(segment)) @@ -729,7 +729,7 @@ namespace Ink_Canvas.Helpers private double CalculateStrokeLength(StylusPointCollection points) { if (points.Count < 2) return 0; - + double totalLength = 0; for (int i = 1; i < points.Count; i++) { @@ -749,22 +749,22 @@ namespace Ink_Canvas.Helpers const double PIXELS_PER_SEGMENT = 12.0; // 每段适中长度,平衡效果与速度 const int MIN_SEGMENTS = 5; // 适当的最小分段数,确保动画效果 const int MAX_SEGMENTS = 100; // 适中的最大分段数,平衡性能与效果 - + // 根据长度计算基础分段数 var lengthBasedSegments = Math.Max(MIN_SEGMENTS, (int)(strokeLength / PIXELS_PER_SEGMENT)); - + // 根据点密度调整,平衡效果与速度 var density = pointCount > 0 ? strokeLength / pointCount : 1; var densityFactor = Math.Max(0.4, Math.Min(2.5, density / 1.8)); - + var finalSegments = (int)(lengthBasedSegments * densityFactor); - + // 对于短墨迹,确保至少有4个分段 if (pointCount <= 5) { finalSegments = Math.Max(finalSegments, 4); } - + // 限制在合理范围内 return Math.Min(MAX_SEGMENTS, Math.Max(MIN_SEGMENTS, finalSegments)); } @@ -778,7 +778,7 @@ namespace Ink_Canvas.Helpers var baseDuration = totalDuration / Math.Max(segmentCount, 1); var minDuration = 150; // 每段最少150ms,确保动画完整显示 var maxDuration = 500; // 每段最多500ms,平衡速度与完整性 - + return Math.Max(minDuration, Math.Min(maxDuration, baseDuration)); } @@ -788,17 +788,17 @@ namespace Ink_Canvas.Helpers private int[] CreateAppleStyleAnimationCurve(int segmentCount, int totalDuration) { var curve = new int[segmentCount]; - + // 平衡速度与完整性,确保动画有足够时间播放 var availableTime = totalDuration * 0.6; // 使用60%的总时间,给动画留足够缓冲 var delayBetweenSegments = Math.Max(60, availableTime / Math.Max(segmentCount, 1)); - + for (int i = 0; i < segmentCount; i++) { // 线性延迟,确保每个分段都有足够时间 curve[i] = (int)(i * delayBetweenSegments); } - + return curve; } @@ -829,4 +829,4 @@ namespace Ink_Canvas.Helpers } #endregion } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/InkSmoothingConfig.cs b/Ink Canvas/Helpers/InkSmoothingConfig.cs index 83533f0e..dea1df70 100644 --- a/Ink Canvas/Helpers/InkSmoothingConfig.cs +++ b/Ink Canvas/Helpers/InkSmoothingConfig.cs @@ -12,22 +12,22 @@ namespace Ink_Canvas.Helpers public double SmoothingStrength { get; set; } = 0.4; public double ResampleInterval { get; set; } = 2.5; public int InterpolationSteps { get; set; } = 12; - + // 贝塞尔曲线参数 public bool UseAdaptiveInterpolation { get; set; } = true; public double CurveTension { get; set; } = 0.3; public double MinCurvatureThreshold { get; set; } = 0.1; public double MaxCurvatureThreshold { get; set; } = 0.8; - + // 性能参数 public bool UseHardwareAcceleration { get; set; } = true; public bool UseAsyncProcessing { get; set; } = true; public int MaxConcurrentTasks { get; set; } = Environment.ProcessorCount; public int MaxPointsPerStroke { get; set; } = 10000; - + // 质量设置 public SmoothingQuality Quality { get; set; } = SmoothingQuality.Balanced; - + public enum SmoothingQuality { Performance, // 性能优先 @@ -49,7 +49,7 @@ namespace Ink_Canvas.Helpers public static InkSmoothingConfig FromSettings() { var config = new InkSmoothingConfig(); - + try { // 尝试从MainWindow.Settings加载配置(兼容性) @@ -66,7 +66,7 @@ namespace Ink_Canvas.Helpers { Debug.WriteLine($"加载平滑配置失败: {ex.Message}"); } - + return config; } @@ -85,7 +85,7 @@ namespace Ink_Canvas.Helpers CurveTension = 0.2; MaxConcurrentTasks = Math.Max(1, Environment.ProcessorCount / 2); break; - + case SmoothingQuality.Balanced: SmoothingStrength = 0.4; ResampleInterval = 2.5; @@ -94,7 +94,7 @@ namespace Ink_Canvas.Helpers CurveTension = 0.3; MaxConcurrentTasks = Environment.ProcessorCount; break; - + case SmoothingQuality.Quality: SmoothingStrength = 0.6; ResampleInterval = 1.5; @@ -120,7 +120,7 @@ namespace Ink_Canvas.Helpers MainWindow.Settings.Canvas.UseHardwareAcceleration = UseHardwareAcceleration; MainWindow.Settings.Canvas.UseAsyncInkSmoothing = UseAsyncProcessing; MainWindow.Settings.Canvas.MaxConcurrentSmoothingTasks = MaxConcurrentTasks; - + } } catch (Exception ex) @@ -152,4 +152,4 @@ namespace Ink_Canvas.Helpers $"张力: {CurveTension:F2}, 硬件加速: {UseHardwareAcceleration}"; } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/PPTInkManager.cs b/Ink Canvas/Helpers/PPTInkManager.cs index fd43b18f..436f5d71 100644 --- a/Ink Canvas/Helpers/PPTInkManager.cs +++ b/Ink Canvas/Helpers/PPTInkManager.cs @@ -1,9 +1,9 @@ -using System; +using Microsoft.Office.Interop.PowerPoint; +using System; using System.IO; using System.Security.Cryptography; using System.Text; using System.Windows.Ink; -using Microsoft.Office.Interop.PowerPoint; namespace Ink_Canvas.Helpers { @@ -57,11 +57,11 @@ namespace Ink_Canvas.Helpers { // 完全清理之前的墨迹状态 ClearAllStrokes(); - + // 重置墨迹锁定状态 _inkLockUntil = DateTime.MinValue; _lockedSlideIndex = -1; - + // 生成演示文稿唯一标识符 _currentPresentationId = GeneratePresentationId(presentation); @@ -164,7 +164,7 @@ namespace Ink_Canvas.Helpers { // 确定要保存的页面索引 int saveToSlideIndex = _lockedSlideIndex > 0 ? _lockedSlideIndex : slideIndex; - + // 确保页面索引有效 if (saveToSlideIndex > 0 && saveToSlideIndex < _memoryStreams.Length) { @@ -179,7 +179,7 @@ namespace Ink_Canvas.Helpers // 加载新页面的墨迹 var newStrokes = LoadSlideStrokes(slideIndex); LogHelper.WriteLogToFile($"已切换到第{slideIndex}页,加载墨迹数量: {newStrokes.Count}", LogHelper.LogType.Trace); - + return newStrokes; } catch (Exception ex) diff --git a/Ink Canvas/Helpers/PPTManager.cs b/Ink Canvas/Helpers/PPTManager.cs index fb57c16f..d8a03bd4 100644 --- a/Ink Canvas/Helpers/PPTManager.cs +++ b/Ink Canvas/Helpers/PPTManager.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Office.Interop.PowerPoint; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -7,7 +8,6 @@ using System.Text; using System.Threading; using System.Timers; using System.Windows.Threading; -using Microsoft.Office.Interop.PowerPoint; using Application = System.Windows.Application; using Timer = System.Timers.Timer; @@ -219,7 +219,7 @@ namespace Ink_Canvas.Helpers { _lastSlideShowState = currentSlideShowState; SlideShowStateChanged?.Invoke(currentSlideShowState); - + if (!currentSlideShowState) { LogHelper.WriteLogToFile("检测到PPT放映已结束", LogHelper.LogType.Trace); diff --git a/Ink Canvas/Helpers/PPTUIManager.cs b/Ink Canvas/Helpers/PPTUIManager.cs index 5bf4b636..b022a29b 100644 --- a/Ink Canvas/Helpers/PPTUIManager.cs +++ b/Ink Canvas/Helpers/PPTUIManager.cs @@ -157,7 +157,7 @@ namespace Ink_Canvas.Helpers { // 检查是否应该显示PPT按钮 // 不仅要检查按钮设置,还要确保确实在PPT放映模式下 - bool shouldShowButtons = ShowPPTButton && + bool shouldShowButtons = ShowPPTButton && _mainWindow.BtnPPTSlideShowEnd.Visibility == Visibility.Visible && _mainWindow.PPTManager?.IsInSlideShow == true; diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs index 1e91a7de..54eb84bd 100644 --- a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs +++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherButton.cs @@ -1,9 +1,9 @@ +using iNKORE.UI.WPF.Modern.Controls; using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; -using iNKORE.UI.WPF.Modern.Controls; namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher { diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs index 2089ca6c..9b6ac63b 100644 --- a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs +++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherModels.cs @@ -1,3 +1,5 @@ +using Microsoft.Win32; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; @@ -8,8 +10,6 @@ using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; -using Microsoft.Win32; -using Newtonsoft.Json; namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher { diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs index 4b6cda6c..6666f10d 100644 --- a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs +++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml.cs @@ -1,10 +1,10 @@ +using Ink_Canvas.Windows; +using Microsoft.Win32; using System; using System.ComponentModel; using System.IO; using System.Windows; using System.Windows.Controls; -using Ink_Canvas.Windows; -using Microsoft.Win32; namespace Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher { diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncherPlugin.cs b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncherPlugin.cs index 2c504bd0..555c7bf9 100644 --- a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncherPlugin.cs +++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncherPlugin.cs @@ -1,3 +1,5 @@ +using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -5,8 +7,6 @@ using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Media; -using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher; -using Newtonsoft.Json; namespace Ink_Canvas.Helpers.Plugins.BuiltIn { diff --git a/Ink Canvas/Helpers/Plugins/EnhancedPluginBase.cs b/Ink Canvas/Helpers/Plugins/EnhancedPluginBase.cs index 3b62137f..d22ca80e 100644 --- a/Ink Canvas/Helpers/Plugins/EnhancedPluginBase.cs +++ b/Ink Canvas/Helpers/Plugins/EnhancedPluginBase.cs @@ -89,4 +89,4 @@ namespace Ink_Canvas.Helpers.Plugins base.Cleanup(); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/Plugins/IEnhancedPlugin.cs b/Ink Canvas/Helpers/Plugins/IEnhancedPlugin.cs index 6ee5e9d5..312eb10c 100644 --- a/Ink Canvas/Helpers/Plugins/IEnhancedPlugin.cs +++ b/Ink Canvas/Helpers/Plugins/IEnhancedPlugin.cs @@ -45,4 +45,4 @@ namespace Ink_Canvas.Helpers.Plugins /// void OnConfigurationChanged(); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/Plugins/IPluginService.cs b/Ink Canvas/Helpers/Plugins/IPluginService.cs index 2df665f5..ff24ec2b 100644 --- a/Ink Canvas/Helpers/Plugins/IPluginService.cs +++ b/Ink Canvas/Helpers/Plugins/IPluginService.cs @@ -554,4 +554,4 @@ namespace Ink_Canvas.Helpers.Plugins /// Error } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/Plugins/PluginConfigurationManager.cs b/Ink Canvas/Helpers/Plugins/PluginConfigurationManager.cs index be1efddc..9688cd31 100644 --- a/Ink Canvas/Helpers/Plugins/PluginConfigurationManager.cs +++ b/Ink Canvas/Helpers/Plugins/PluginConfigurationManager.cs @@ -1,8 +1,8 @@ +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using Newtonsoft.Json; namespace Ink_Canvas.Helpers.Plugins { @@ -270,4 +270,4 @@ namespace Ink_Canvas.Helpers.Plugins } } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/Plugins/PluginManager.cs b/Ink Canvas/Helpers/Plugins/PluginManager.cs index d1a6559f..27b7742e 100644 --- a/Ink Canvas/Helpers/Plugins/PluginManager.cs +++ b/Ink Canvas/Helpers/Plugins/PluginManager.cs @@ -1,3 +1,5 @@ +using Ink_Canvas.Windows; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -8,8 +10,6 @@ using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using System.Windows; -using Ink_Canvas.Windows; -using Newtonsoft.Json; using Timer = System.Timers.Timer; namespace Ink_Canvas.Helpers.Plugins diff --git a/Ink Canvas/Helpers/Plugins/PluginServiceManager.cs b/Ink Canvas/Helpers/Plugins/PluginServiceManager.cs index fd1b1bf7..3f7ec460 100644 --- a/Ink Canvas/Helpers/Plugins/PluginServiceManager.cs +++ b/Ink Canvas/Helpers/Plugins/PluginServiceManager.cs @@ -452,4 +452,4 @@ namespace Ink_Canvas.Helpers.Plugins #endregion } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Helpers/SoftwareLauncher.cs b/Ink Canvas/Helpers/SoftwareLauncher.cs index 5f2e405d..e3dc7188 100644 --- a/Ink Canvas/Helpers/SoftwareLauncher.cs +++ b/Ink Canvas/Helpers/SoftwareLauncher.cs @@ -1,8 +1,8 @@ -using System; +using Microsoft.Win32; +using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; -using Microsoft.Win32; namespace Ink_Canvas.Helpers { diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index c3ace02e..aceb055a 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -1,3 +1,9 @@ +using Ink_Canvas.Helpers; +using Ink_Canvas.Helpers.Plugins; +using Ink_Canvas.Windows; +using iNKORE.UI.WPF.Modern; +using iNKORE.UI.WPF.Modern.Controls; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; @@ -16,12 +22,6 @@ using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; -using Ink_Canvas.Helpers; -using Ink_Canvas.Helpers.Plugins; -using Ink_Canvas.Windows; -using iNKORE.UI.WPF.Modern; -using iNKORE.UI.WPF.Modern.Controls; -using Microsoft.Win32; using Application = System.Windows.Application; using Brushes = System.Windows.Media.Brushes; using Button = System.Windows.Controls.Button; @@ -42,7 +42,7 @@ namespace Ink_Canvas private int currentPageIndex; private System.Windows.Controls.Canvas currentCanvas; private AutoUpdateHelper.UpdateLineGroup AvailableLatestLineGroup; - + // 全局快捷键管理器 private GlobalHotkeyManager _globalHotkeyManager; @@ -239,11 +239,11 @@ namespace Ink_Canvas // 初始化窗口置顶开关 ToggleSwitchAlwaysOnTop.IsOn = Settings.Advanced.IsAlwaysOnTop; ApplyAlwaysOnTop(); - + // 添加窗口激活事件处理,确保置顶状态在窗口重新激活时得到保持 Activated += Window_Activated; Deactivated += Window_Deactivated; - + // 为浮动栏按钮添加触摸事件支持 AddTouchSupportToFloatingBarButtons(); } @@ -517,7 +517,7 @@ namespace Ink_Canvas // 初始化剪贴板监控 InitializeClipboardMonitoring(); - + // 初始化全局快捷键管理器 InitializeGlobalHotkeyManager(); @@ -651,7 +651,7 @@ namespace Ink_Canvas // 清理剪贴板监控 CleanupClipboardMonitoring(); ClipboardNotification.Stop(); - + // 清理全局快捷键管理器 if (_globalHotkeyManager != null) { @@ -1679,7 +1679,7 @@ namespace Ink_Canvas [DllImport("kernel32.dll")] private static extern uint GetCurrentProcessId(); - + private const int GWL_EXSTYLE = -20; private const int WS_EX_NOACTIVATE = 0x08000000; private const int WS_EX_TOPMOST = 0x00000008; @@ -1718,16 +1718,16 @@ namespace Ink_Canvas { // 先设置WPF的Topmost属性 Topmost = true; - + // 使用更强的Win32 API调用来确保置顶 // 1. 设置窗口样式为置顶 int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_TOPMOST); - + // 2. 使用SetWindowPos确保窗口在最顶层 - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); - + // 3. 如果启用了无焦点模式,需要特殊处理 if (Settings.Advanced.IsNoFocusMode) { @@ -1744,18 +1744,18 @@ namespace Ink_Canvas { // 取消置顶时 // 1. 先使用Win32 API取消置顶 - SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); - + // 2. 移除置顶窗口样式 int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_TOPMOST); - + // 3. 停止置顶维护定时器 StopTopmostMaintenance(); - + // 注意:这里不直接设置Topmost,让其他代码根据模式决定 - + // 添加调试日志 LogHelper.WriteLogToFile("应用窗口置顶: 取消置顶", LogHelper.LogType.Trace); } @@ -1772,14 +1772,14 @@ namespace Ink_Canvas private void StartTopmostMaintenance() { if (isTopmostMaintenanceEnabled) return; - + if (topmostMaintenanceTimer == null) { topmostMaintenanceTimer = new DispatcherTimer(); topmostMaintenanceTimer.Interval = TimeSpan.FromMilliseconds(500); // 每500ms检查一次 topmostMaintenanceTimer.Tick += TopmostMaintenanceTimer_Tick; } - + topmostMaintenanceTimer.Start(); isTopmostMaintenanceEnabled = true; LogHelper.WriteLogToFile("启动置顶维护定时器", LogHelper.LogType.Trace); @@ -1827,17 +1827,17 @@ namespace Ink_Canvas // 检查前景窗口是否是当前应用程序的子窗口 var foregroundWindowProcessId = GetWindowThreadProcessId(foregroundWindow, out uint processId); var currentProcessId = GetCurrentProcessId(); - + if (processId == currentProcessId) { // 如果有子窗口在前景,暂停置顶维护 return; } - + // 如果窗口不在最顶层且没有子窗口,重新设置置顶 - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); - + // 确保窗口样式正确 int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); if ((exStyle & WS_EX_TOPMOST) == 0) @@ -1882,7 +1882,7 @@ namespace Ink_Canvas Settings.Advanced.IsNoFocusMode = toggle != null && toggle.IsOn; SaveSettingsToFile(); ApplyNoFocusMode(); - + // 如果启用了窗口置顶,需要重新应用置顶设置以处理无焦点模式的变化 if (Settings.Advanced.IsAlwaysOnTop) { @@ -1898,7 +1898,7 @@ namespace Ink_Canvas SaveSettingsToFile(); ApplyAlwaysOnTop(); } - + private void Window_Activated(object sender, EventArgs e) { // 窗口激活时,如果启用了置顶功能,重新应用置顶设置 @@ -1911,7 +1911,7 @@ namespace Ink_Canvas }), DispatcherPriority.Loaded); } } - + /// /// 窗口失去焦点时的处理 /// @@ -2010,7 +2010,7 @@ namespace Ink_Canvas { Settings.Canvas.EnableInkFade = ToggleSwitchEnableInkFade.IsOn; _inkFadeManager.IsEnabled = Settings.Canvas.EnableInkFade; - + // 同步批注子面板中的开关状态 if (ToggleSwitchInkFadeInPanel != null) { @@ -2022,7 +2022,7 @@ namespace Ink_Canvas { ToggleSwitchInkFadeInPanel2.IsOn = Settings.Canvas.EnableInkFade; } - + LogHelper.WriteLogToFile($"墨迹渐隐功能已{(Settings.Canvas.EnableInkFade ? "启用" : "禁用")}", LogHelper.LogType.Event); } catch (Exception ex) @@ -2062,7 +2062,7 @@ namespace Ink_Canvas { Settings.Canvas.EnableInkFade = ToggleSwitchInkFadeInPanel.IsOn; _inkFadeManager.IsEnabled = Settings.Canvas.EnableInkFade; - + // 同步设置面板中的开关状态 if (ToggleSwitchEnableInkFade != null) { @@ -2074,7 +2074,7 @@ namespace Ink_Canvas { ToggleSwitchInkFadeInPanel2.IsOn = Settings.Canvas.EnableInkFade; } - + LogHelper.WriteLogToFile($"批注子面板中墨迹渐隐功能已{(Settings.Canvas.EnableInkFade ? "启用" : "禁用")}", LogHelper.LogType.Event); } catch (Exception ex) @@ -2096,21 +2096,21 @@ namespace Ink_Canvas // 查找PPT放映窗口并发送按键 var pptWindows = Process.GetProcessesByName("POWERPNT"); var wpsWindows = Process.GetProcessesByName("wpp"); - + foreach (var process in pptWindows.Concat(wpsWindows)) { if (process.MainWindowHandle != IntPtr.Zero) { // 激活PPT窗口 SetForegroundWindow(process.MainWindowHandle); - + // 发送翻页按键消息 int keyCode = isPrevious ? 0x21 : 0x22; // VK_PRIOR : VK_NEXT - + // 发送按键按下和释放消息 PostMessage(process.MainWindowHandle, 0x0100, (IntPtr)keyCode, IntPtr.Zero); // WM_KEYDOWN PostMessage(process.MainWindowHandle, 0x0101, (IntPtr)keyCode, IntPtr.Zero); // WM_KEYUP - + break; } } @@ -2138,19 +2138,19 @@ namespace Ink_Canvas { // 执行模式切换 inkCanvas.EditingMode = newMode; - + // 根据模式确定是否为鼠标模式(无工具模式) bool isMouseMode = newMode == InkCanvasEditingMode.None; - + // 更新快捷键状态 if (_globalHotkeyManager != null) { _globalHotkeyManager.UpdateHotkeyStateForToolMode(isMouseMode); } - + // 执行额外的操作(如果有) additionalActions?.Invoke(); - + LogHelper.WriteLogToFile($"工具模式已切换到: {newMode}, 鼠标模式: {isMouseMode}", LogHelper.LogType.Trace); } catch (Exception ex) diff --git a/Ink Canvas/MainWindow_cs/MW_AutoFold.cs b/Ink Canvas/MainWindow_cs/MW_AutoFold.cs index a92b0394..76b3bf37 100644 --- a/Ink Canvas/MainWindow_cs/MW_AutoFold.cs +++ b/Ink Canvas/MainWindow_cs/MW_AutoFold.cs @@ -1,4 +1,6 @@ -using System; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern; +using System; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -6,8 +8,6 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern; namespace Ink_Canvas { diff --git a/Ink Canvas/MainWindow_cs/MW_AutoStart.cs b/Ink Canvas/MainWindow_cs/MW_AutoStart.cs index e38c74d1..a86808cc 100644 --- a/Ink Canvas/MainWindow_cs/MW_AutoStart.cs +++ b/Ink Canvas/MainWindow_cs/MW_AutoStart.cs @@ -1,6 +1,6 @@ -using System; +using IWshRuntimeLibrary; +using System; using System.Windows; -using IWshRuntimeLibrary; using Application = System.Windows.Forms.Application; using File = System.IO.File; diff --git a/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs b/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs index e41f79fb..f908c2ad 100644 --- a/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs +++ b/Ink Canvas/MainWindow_cs/MW_AutoTheme.cs @@ -1,8 +1,8 @@ -using System; +using iNKORE.UI.WPF.Modern; +using Microsoft.Win32; +using System; using System.Windows; using System.Windows.Media; -using iNKORE.UI.WPF.Modern; -using Microsoft.Win32; using Application = System.Windows.Application; namespace Ink_Canvas diff --git a/Ink Canvas/MainWindow_cs/MW_BoardControls.cs b/Ink Canvas/MainWindow_cs/MW_BoardControls.cs index 6c1510e3..934c7e25 100644 --- a/Ink Canvas/MainWindow_cs/MW_BoardControls.cs +++ b/Ink Canvas/MainWindow_cs/MW_BoardControls.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; @@ -6,7 +7,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Media; -using Ink_Canvas.Helpers; namespace Ink_Canvas { @@ -140,7 +140,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = previousEditingMode; currentSelectedElement = null; } - + var targetIndex = isBackupMain ? 0 : CurrentWhiteboardIndex; // 先清空当前画布的墨迹 @@ -253,7 +253,7 @@ namespace Ink_Canvas BtnWhiteBoardAdd_Click(sender, e); return; } - + // 隐藏图片选择工具栏 if (currentSelectedElement != null) { @@ -280,7 +280,7 @@ namespace Ink_Canvas if (WhiteboardTotalCount >= 99) return; if (Settings.Automation.IsAutoSaveStrokesAtClear && inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) SaveScreenShot(true); - + // 隐藏图片选择工具栏 if (currentSelectedElement != null) { @@ -291,7 +291,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = previousEditingMode; currentSelectedElement = null; } - + SaveStrokes(); ClearStrokes(true); @@ -330,7 +330,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = previousEditingMode; currentSelectedElement = null; } - + ClearStrokes(true); if (CurrentWhiteboardIndex != WhiteboardTotalCount) diff --git a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs index 6f956a9f..4e41ca79 100644 --- a/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_BoardIcons.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Diagnostics; using System.Windows; using System.Windows.Controls; @@ -6,7 +7,6 @@ using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs b/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs index 99053852..7ff64b76 100644 --- a/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs +++ b/Ink Canvas/MainWindow_cs/MW_ClipboardHandler.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -9,7 +10,6 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; -using Ink_Canvas.Helpers; using Clipboard = System.Windows.Clipboard; using ContextMenu = System.Windows.Controls.ContextMenu; using Cursors = System.Windows.Input.Cursors; @@ -151,7 +151,7 @@ namespace Ink_Canvas // 设置图片属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 if (inkCanvas != null) { @@ -173,7 +173,7 @@ namespace Ink_Canvas { // 先进行缩放居中处理 CenterAndScaleElement(image); - + // 如果有指定位置,调整到指定位置 if (position.HasValue) { @@ -181,7 +181,7 @@ namespace Ink_Canvas InkCanvas.SetLeft(image, position.Value.X - image.Width / 2); InkCanvas.SetTop(image, position.Value.Y - image.Height / 2); } - + // 绑定事件处理器 if (image is FrameworkElement elementForEvents) { diff --git a/Ink Canvas/MainWindow_cs/MW_Colors.cs b/Ink Canvas/MainWindow_cs/MW_Colors.cs index c55e306c..00eee032 100644 --- a/Ink Canvas/MainWindow_cs/MW_Colors.cs +++ b/Ink Canvas/MainWindow_cs/MW_Colors.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; @@ -8,7 +9,6 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; -using Ink_Canvas.Helpers; namespace Ink_Canvas { @@ -28,7 +28,7 @@ namespace Ink_Canvas AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide); AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide); AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide); - + // 在PPT模式下隐藏手势面板和手势按钮 AnimationsHelper.HideWithSlideAndFade(TwoFingerGestureBorder); AnimationsHelper.HideWithSlideAndFade(BoardTwoFingerGestureBorder); @@ -423,7 +423,7 @@ namespace Ink_Canvas } // 更新快捷调色盘选择指示器 - if (penType == 0) + if (penType == 0) { UpdateQuickColorPaletteIndicator(inkCanvas.DefaultDrawingAttributes.Color); } @@ -601,7 +601,7 @@ namespace Ink_Canvas drawingAttributes.Height = Settings.Canvas.HighlighterWidth; drawingAttributes.StylusTip = StylusTip.Rectangle; drawingAttributes.IsHighlighter = true; - + // 确保荧光笔模式切换后正确更新颜色和快捷调色板指示器 ColorSwitchCheck(); } diff --git a/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs b/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs index 378dc86f..1e356ec7 100644 --- a/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs +++ b/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs @@ -1,4 +1,6 @@ -using System; +using Ink_Canvas.Helpers; +using Microsoft.Win32; +using System; using System.Diagnostics; using System.IO; using System.Linq; @@ -10,8 +12,6 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; -using Ink_Canvas.Helpers; -using Microsoft.Win32; namespace Ink_Canvas { @@ -42,10 +42,10 @@ namespace Ink_Canvas // 设置图片属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 InitializeInkCanvasSelectionSettings(); - + // 先添加到画布 inkCanvas.Children.Add(image); @@ -62,7 +62,7 @@ namespace Ink_Canvas // 最后绑定事件处理器 BindElementEvents(image); - + LogHelper.WriteLogToFile($"图片插入完成: {image.Name}"); }), DispatcherPriority.Loaded); }; @@ -98,7 +98,7 @@ namespace Ink_Canvas // 设置光标 element.Cursor = Cursors.Hand; - + // 禁用InkCanvas对图片的选择处理 element.IsHitTestVisible = true; element.Focusable = false; @@ -121,7 +121,7 @@ namespace Ink_Canvas // 选中当前元素 SelectElement(element); - + // 开始拖动 isDragging = true; dragStartPoint = e.GetPosition(inkCanvas); @@ -151,7 +151,7 @@ namespace Ink_Canvas if (sender is FrameworkElement element && isDragging && element.IsMouseCaptured) { var currentPoint = e.GetPosition(inkCanvas); - + // 使用鼠标拖动的完整实现机制 ApplyMouseDragTransform(element, currentPoint, dragStartPoint); @@ -172,7 +172,7 @@ namespace Ink_Canvas if (sender is FrameworkElement element) { - + // 使用滚轮缩放的核心机制 ApplyWheelScaleTransform(element, e); @@ -264,7 +264,7 @@ namespace Ink_Canvas private void SelectElement(FrameworkElement element) { currentSelectedElement = element; - + // 根据元素类型显示不同的选择工具栏 if (element is Image) { @@ -275,7 +275,7 @@ namespace Ink_Canvas UpdateImageSelectionToolbarPosition(element); BorderImageSelectionControl.Visibility = Visibility.Visible; } - + // 隐藏笔画选择工具栏 if (BorderStrokeSelectionControl != null) { @@ -289,20 +289,20 @@ namespace Ink_Canvas { BorderStrokeSelectionControl.Visibility = Visibility.Visible; } - + // 隐藏图片选择工具栏 if (BorderImageSelectionControl != null) { BorderImageSelectionControl.Visibility = Visibility.Collapsed; } } - + // 确保选择框不显示,避免蓝色边框 if (GridInkCanvasSelectionCover != null) { GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; } - + // 禁用InkCanvas的选择功能,去除控制点 if (inkCanvas != null) { @@ -317,24 +317,24 @@ namespace Ink_Canvas private void UnselectElement(FrameworkElement element) { // 去除选中效果 - + // 隐藏所有选择工具栏 if (BorderImageSelectionControl != null) { BorderImageSelectionControl.Visibility = Visibility.Collapsed; } - + if (BorderStrokeSelectionControl != null) { BorderStrokeSelectionControl.Visibility = Visibility.Collapsed; } - + // 确保选择框隐藏 if (GridInkCanvasSelectionCover != null) { GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; } - + } @@ -345,7 +345,7 @@ namespace Ink_Canvas { // 创建MatrixTransform var matrixTransform = new MatrixTransform(matrix); - + // 将MatrixTransform添加到TransformGroup transformGroup.Children.Add(matrixTransform); } @@ -358,25 +358,25 @@ namespace Ink_Canvas { // 根据滚轮方向确定缩放比例(向上1.1倍,向下0.9倍) double scaleFactor = e.Delta > 0 ? 1.1 : 0.9; - + // 计算选中元素的中心点作为缩放中心 var elementCenter = new Point(element.ActualWidth / 2, element.ActualHeight / 2); - + // 创建 Matrix 对象并应用 ScaleAt 变换 var matrix = new Matrix(); matrix.ScaleAt(scaleFactor, scaleFactor, elementCenter.X, elementCenter.Y); - + // 对选中的图片元素调用 ApplyElementMatrixTransform ApplyElementMatrixTransform(element, matrix); - + // 对选中的笔画应用 Transform 方法(如果有选中的笔画) var selectedStrokes = inkCanvas.GetSelectedStrokes(); foreach (var stroke in selectedStrokes) { stroke.Transform(matrix, false); } - - + + } catch (Exception ex) { @@ -399,20 +399,20 @@ namespace Ink_Canvas // 保存初始变换状态用于历史记录 var initialTransform = transformGroup.Clone(); - + // 创建新的 TransformGroup 并添加 MatrixTransform var newTransformGroup = new TransformGroup(); newTransformGroup.Children.Add(new MatrixTransform(matrix)); - + // 将新的变换组添加到现有的变换组中 transformGroup.Children.Add(newTransformGroup); - + // 如果启用了历史记录,提交变换历史 if (saveHistory) { CommitTransformHistory(element, initialTransform, transformGroup); } - + } catch (Exception ex) @@ -428,24 +428,24 @@ namespace Ink_Canvas { // 计算鼠标移动的位移向量 var delta = currentPoint - startPoint; - + // 创建 Matrix 对象并应用 Translate 变换 var matrix = new Matrix(); matrix.Translate(delta.X, delta.Y); - + // 对选中的图片元素应用矩阵变换 ApplyMatrixTransformToElement(element, matrix, false); - + // 对选中的笔画应用变换 var selectedStrokes = inkCanvas.GetSelectedStrokes(); foreach (var stroke in selectedStrokes) { stroke.Transform(matrix, false); } - + // 更新选择框的位置(如果有选择框) UpdateSelectionBorderPosition(delta); - + } catch (Exception ex) @@ -503,7 +503,7 @@ namespace Ink_Canvas // 支持单指拖动和多指手势 // 可以同时进行平移、旋转和缩放 - + // 通过 ManipulationDelta 获取手势变化信息 var translation = md.Translation; var rotation = md.Rotation; @@ -519,13 +519,13 @@ namespace Ink_Canvas if (e.Manipulators.Count() >= 2) { var center = e.ManipulationOrigin; - + // 应用缩放 if (scale.X != 1.0 || scale.Y != 1.0) { matrix.ScaleAt(scale.X, scale.Y, center.X, center.Y); } - + // 应用旋转 if (rotation != 0) { @@ -535,15 +535,15 @@ namespace Ink_Canvas // 应用变换到元素 ApplyMatrixTransformToElement(element, matrix, false); - + // 应用变换到选中的笔画 var selectedStrokes = inkCanvas.GetSelectedStrokes(); foreach (var stroke in selectedStrokes) { stroke.Transform(matrix, false); } - - + + } catch (Exception ex) { @@ -1087,19 +1087,19 @@ namespace Ink_Canvas { // 创建克隆图片 Image clonedImage = CloneImage(originalImage); - + // 添加到画布 inkCanvas.Children.Add(clonedImage); - + // 初始化变换 InitializeElementTransform(clonedImage); - + // 绑定事件 BindElementEvents(clonedImage); - + // 记录历史 timeMachine.CommitElementInsertHistory(clonedImage); - + LogHelper.WriteLogToFile($"图片克隆完成: {clonedImage.Name}"); } } @@ -1118,10 +1118,10 @@ namespace Ink_Canvas { // 创建新页面 BtnWhiteBoardAdd_Click(null, null); - + // 创建克隆图片(不添加到当前画布,因为已经创建了新页面) Image clonedImage = CreateClonedImage(originalImage); - + if (clonedImage != null) { // 设置图片属性,避免被InkCanvas选择系统处理 @@ -1139,7 +1139,7 @@ namespace Ink_Canvas // 记录历史 timeMachine.CommitElementInsertHistory(clonedImage); - + LogHelper.WriteLogToFile($"图片克隆到新页面完成: {clonedImage.Name}"); } } @@ -1158,13 +1158,13 @@ namespace Ink_Canvas if (currentSelectedElement != null) { ApplyRotateTransform(currentSelectedElement, -45); - + // 更新工具栏位置 if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible) { UpdateImageSelectionToolbarPosition(currentSelectedElement); } - + LogHelper.WriteLogToFile("图片左旋转完成"); } } @@ -1182,13 +1182,13 @@ namespace Ink_Canvas if (currentSelectedElement != null) { ApplyRotateTransform(currentSelectedElement, 45); - + // 更新工具栏位置 if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible) { UpdateImageSelectionToolbarPosition(currentSelectedElement); } - + LogHelper.WriteLogToFile("图片右旋转完成"); } } @@ -1207,13 +1207,13 @@ namespace Ink_Canvas { var elementCenter = new Point(currentSelectedElement.ActualWidth / 2, currentSelectedElement.ActualHeight / 2); ApplyScaleTransform(currentSelectedElement, 0.9, elementCenter); - + // 更新工具栏位置 if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible) { UpdateImageSelectionToolbarPosition(currentSelectedElement); } - + LogHelper.WriteLogToFile("图片缩放减小完成"); } } @@ -1229,23 +1229,23 @@ namespace Ink_Canvas try { if (currentSelectedElement != null) - { - var elementCenter = new Point(currentSelectedElement.ActualWidth / 2, currentSelectedElement.ActualHeight / 2); - ApplyScaleTransform(currentSelectedElement, 1.1, elementCenter); - - // 更新工具栏位置 - if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible) { - UpdateImageSelectionToolbarPosition(currentSelectedElement); + var elementCenter = new Point(currentSelectedElement.ActualWidth / 2, currentSelectedElement.ActualHeight / 2); + ApplyScaleTransform(currentSelectedElement, 1.1, elementCenter); + + // 更新工具栏位置 + if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible) + { + UpdateImageSelectionToolbarPosition(currentSelectedElement); + } + + LogHelper.WriteLogToFile("图片缩放增大完成"); } - - LogHelper.WriteLogToFile("图片缩放增大完成"); } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"图片缩放增大失败: {ex.Message}", LogHelper.LogType.Error); - } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"图片缩放增大失败: {ex.Message}", LogHelper.LogType.Error); + } } // 图片删除 @@ -1257,20 +1257,20 @@ namespace Ink_Canvas { // 保存删除前的编辑模式 var previousEditingMode = inkCanvas.EditingMode; - + // 记录删除历史 timeMachine.CommitElementRemoveHistory(currentSelectedElement); - + // 从画布中移除 inkCanvas.Children.Remove(currentSelectedElement); - + // 清除选中状态 UnselectElement(currentSelectedElement); currentSelectedElement = null; - + // 恢复到删除前的编辑模式 inkCanvas.EditingMode = previousEditingMode; - + LogHelper.WriteLogToFile($"图片删除完成,已恢复到编辑模式: {previousEditingMode}"); } } @@ -1286,35 +1286,35 @@ namespace Ink_Canvas try { Image clonedImage = new Image(); - + // 复制图片源 if (originalImage.Source is BitmapSource bitmapSource) { clonedImage.Source = bitmapSource; } - + // 复制属性 clonedImage.Width = originalImage.Width; clonedImage.Height = originalImage.Height; clonedImage.Stretch = originalImage.Stretch; clonedImage.StretchDirection = originalImage.StretchDirection; - + // 复制位置(在新页面中居中显示) double left = InkCanvas.GetLeft(originalImage); double top = InkCanvas.GetTop(originalImage); InkCanvas.SetLeft(clonedImage, left + 20); // 稍微偏移位置 InkCanvas.SetTop(clonedImage, top + 20); - + // 复制变换 if (originalImage.RenderTransform is TransformGroup originalTransformGroup) { clonedImage.RenderTransform = originalTransformGroup.Clone(); } - + // 设置名称 string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff"); clonedImage.Name = timestamp; - + return clonedImage; } catch (Exception ex) diff --git a/Ink Canvas/MainWindow_cs/MW_Eraser.cs b/Ink Canvas/MainWindow_cs/MW_Eraser.cs index 4295d9ce..d49cfe1a 100644 --- a/Ink Canvas/MainWindow_cs/MW_Eraser.cs +++ b/Ink Canvas/MainWindow_cs/MW_Eraser.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Diagnostics; using System.Linq; using System.Windows; @@ -6,7 +7,6 @@ using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 35b1f2a5..7ac341a1 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1,3 +1,5 @@ +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern; using System; using System.Diagnostics; using System.Threading; @@ -11,8 +13,6 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern; using Application = System.Windows.Application; using Button = System.Windows.Controls.Button; using Cursors = System.Windows.Input.Cursors; @@ -441,7 +441,7 @@ namespace Ink_Canvas case "select": { LassoSelectIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138)); - LassoSelectIconGeometry.Geometry = + LassoSelectIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.SolidLassoSelectIcon); BoardSelect.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235)); BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(37, 99, 235)); @@ -454,7 +454,7 @@ namespace Ink_Canvas case "cursor": { CursorIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138)); - CursorIconGeometry.Geometry = + CursorIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedCursorIcon); BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245)); BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170)); @@ -873,7 +873,7 @@ namespace Ink_Canvas break; case "QuickColorGreen": case "QuickColorGreenSingle": - border.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74)); + border.Background = new SolidColorBrush(Color.FromRgb(22, 163, 74)); break; case "QuickColorPurple": border.Background = new SolidColorBrush(Color.FromRgb(147, 51, 234)); @@ -893,7 +893,8 @@ namespace Ink_Canvas HideSubPanels(); BtnSettings_Click(null, null); } - private async void SymbolIconScreenshot_MouseUp(object sender, MouseButtonEventArgs e) { + private async void SymbolIconScreenshot_MouseUp(object sender, MouseButtonEventArgs e) + { HideSubPanelsImmediately(); await Task.Delay(50); SaveScreenShotToDesktop(); @@ -1326,10 +1327,10 @@ namespace Ink_Canvas double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); - + // 计算浮动栏位置,考虑快捷调色盘的显示状态 double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX; - + // 如果快捷调色盘显示,确保有足够空间 if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) || (QuickColorPaletteSingleRowPanel != null && QuickColorPaletteSingleRowPanel.Visibility == Visibility.Visible)) @@ -1346,7 +1347,7 @@ namespace Ink_Canvas floatingBarWidth = Math.Max(floatingBarWidth, 820 * ViewboxFloatingBarScaleTransform.ScaleX); } } - + pos.X = (screenWidth - floatingBarWidth) / 2; if (!PosXCaculatedWithTaskbarHeight) @@ -1447,10 +1448,10 @@ namespace Ink_Canvas double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); - + // 计算浮动栏位置,考虑快捷调色盘的显示状态 double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX; - + // 如果快捷调色盘显示,确保有足够空间 if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) || (QuickColorPaletteSingleRowPanel != null && QuickColorPaletteSingleRowPanel.Visibility == Visibility.Visible)) @@ -1467,7 +1468,7 @@ namespace Ink_Canvas floatingBarWidth = Math.Max(floatingBarWidth, 850 * ViewboxFloatingBarScaleTransform.ScaleX); } } - + pos.X = (screenWidth - floatingBarWidth) / 2; // 如果任务栏高度为0(隐藏状态),则使用固定边距 @@ -1529,10 +1530,10 @@ namespace Ink_Canvas double screenWidth = screen.Bounds.Width / dpiScaleX, screenHeight = screen.Bounds.Height / dpiScaleY; // 仅计算Windows任务栏高度,不考虑其他程序对工作区的影响 var toolbarHeight = ForegroundWindowInfo.GetTaskbarHeight(screen, dpiScaleY); - + // 计算浮动栏位置,考虑快捷调色盘的显示状态 double floatingBarWidth = ViewboxFloatingBar.ActualWidth * ViewboxFloatingBarScaleTransform.ScaleX; - + // 如果快捷调色盘显示,确保有足够空间 if ((QuickColorPalettePanel != null && QuickColorPalettePanel.Visibility == Visibility.Visible) || (QuickColorPaletteSingleRowPanel != null && QuickColorPaletteSingleRowPanel.Visibility == Visibility.Visible)) @@ -1549,7 +1550,7 @@ namespace Ink_Canvas floatingBarWidth = Math.Max(floatingBarWidth, 820 * ViewboxFloatingBarScaleTransform.ScaleX); } } - + pos.X = (screenWidth - floatingBarWidth) / 2; pos.Y = screenHeight - 55 * ViewboxFloatingBarScaleTransform.ScaleY; @@ -1664,7 +1665,7 @@ namespace Ink_Canvas StackPanelCanvasControls.Visibility = Visibility.Collapsed; - + // 在鼠标模式下隐藏快捷调色盘 if (QuickColorPalettePanel != null) { @@ -1751,7 +1752,7 @@ namespace Ink_Canvas CheckEnableTwoFingerGestureBtnVisibility(true); // 使用集中化的工具模式切换方法 SetCurrentToolMode(InkCanvasEditingMode.Ink); - + // 在批注模式下显示快捷调色盘(如果设置中启用了) if (Settings.Appearance.IsShowQuickColorPalette && QuickColorPalettePanel != null && QuickColorPaletteSingleRowPanel != null) { @@ -1775,7 +1776,7 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - + // 保持之前的笔类型状态,而不是强制重置 if (!wasHighlighter) { @@ -1806,7 +1807,7 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - + // 保持之前的笔类型状态,而不是强制重置 if (!wasHighlighter) { @@ -1878,7 +1879,7 @@ namespace Ink_Canvas forceEraser = false; forcePointEraser = false; drawingShapeMode = 0; - + // 保持之前的笔类型状态,而不是强制重置 if (!wasHighlighter) { @@ -1899,7 +1900,7 @@ namespace Ink_Canvas HideSubPanels("pen", true); } } - + // 修复:从线擦切换到批注时,保持之前的笔类型状态 forceEraser = false; @@ -2044,7 +2045,7 @@ namespace Ink_Canvas private void QuickColorOrange_Click(object sender, RoutedEventArgs e) { - SetQuickColor(Color.FromRgb(251, 150, 80)); // 橙色 + SetQuickColor(Color.FromRgb(251, 150, 80)); // 橙色 } private void QuickColorYellow_Click(object sender, RoutedEventArgs e) @@ -2067,14 +2068,14 @@ namespace Ink_Canvas SetQuickColor(Colors.Red); } - private void QuickColorGreen_Click(object sender, RoutedEventArgs e) + private void QuickColorGreen_Click(object sender, RoutedEventArgs e) { SetQuickColor(Color.FromRgb(22, 163, 74)); } private void QuickColorPurple_Click(object sender, RoutedEventArgs e) { - SetQuickColor(Color.FromRgb(147, 51, 234)); + SetQuickColor(Color.FromRgb(147, 51, 234)); } private void SetQuickColor(Color color) @@ -2137,12 +2138,12 @@ namespace Ink_Canvas drawingAttributes.Height = Settings.Canvas.HighlighterWidth; drawingAttributes.StylusTip = StylusTip.Rectangle; drawingAttributes.IsHighlighter = true; - + inkCanvas.DefaultDrawingAttributes.Width = Settings.Canvas.HighlighterWidth / 2; inkCanvas.DefaultDrawingAttributes.Height = Settings.Canvas.HighlighterWidth; inkCanvas.DefaultDrawingAttributes.StylusTip = StylusTip.Rectangle; inkCanvas.DefaultDrawingAttributes.IsHighlighter = true; - + // 确保荧光笔颜色索引正确更新 inkCanvas.DefaultDrawingAttributes.Color = drawingAttributes.Color; } @@ -2157,7 +2158,7 @@ namespace Ink_Canvas else if (color == Colors.Black) lastDesktopInkColor = 0; else if (color == Color.FromRgb(37, 99, 235)) lastDesktopInkColor = 3; // 蓝色 else if (color == Colors.Red) lastDesktopInkColor = 1; - else if (color == Colors.Green || color == Color.FromRgb(22, 163, 74)) lastDesktopInkColor = 2; + else if (color == Colors.Green || color == Color.FromRgb(22, 163, 74)) lastDesktopInkColor = 2; else if (color == Color.FromRgb(147, 51, 234)) lastDesktopInkColor = 6; // 紫色 } else @@ -2169,7 +2170,7 @@ namespace Ink_Canvas else if (color == Colors.Black) lastBoardInkColor = 0; else if (color == Color.FromRgb(37, 99, 235)) lastBoardInkColor = 3; // 蓝色 else if (color == Colors.Red) lastBoardInkColor = 1; - else if (color == Colors.Green || color == Color.FromRgb(22, 163, 74)) lastBoardInkColor = 2; + else if (color == Colors.Green || color == Color.FromRgb(22, 163, 74)) lastBoardInkColor = 2; else if (color == Color.FromRgb(147, 51, 234)) lastBoardInkColor = 6; // 紫色 } @@ -2178,7 +2179,7 @@ namespace Ink_Canvas // 更新颜色显示 ColorSwitchCheck(); - + // 如果当前是荧光笔模式,调用ColorSwitchCheck确保颜色索引正确更新 if (penType == 1) { @@ -2197,7 +2198,7 @@ namespace Ink_Canvas QuickColorRedCheck.Visibility = Visibility.Collapsed; QuickColorGreenCheck.Visibility = Visibility.Collapsed; QuickColorPurpleCheck.Visibility = Visibility.Collapsed; - + // 隐藏所有check图标(单行显示) QuickColorWhiteCheckSingle.Visibility = Visibility.Collapsed; QuickColorOrangeCheckSingle.Visibility = Visibility.Collapsed; @@ -2209,7 +2210,7 @@ namespace Ink_Canvas // 显示当前选中颜色的check图标 // 在荧光笔模式下,使用更宽松的颜色匹配 int tolerance = (penType == 1) ? 25 : 15; // 荧光笔模式使用更大的容差 - + if (IsColorSimilar(selectedColor, Colors.White, tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(250, 250, 250), tolerance)) { QuickColorWhiteCheck.Visibility = Visibility.Visible; @@ -2220,7 +2221,7 @@ namespace Ink_Canvas QuickColorBlackCheck.Visibility = Visibility.Visible; QuickColorBlackCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Colors.Yellow, tolerance) || + else if (IsColorSimilar(selectedColor, Colors.Yellow, tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(234, 179, 8), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(250, 204, 21), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(253, 224, 71), tolerance)) @@ -2228,7 +2229,7 @@ namespace Ink_Canvas QuickColorYellowCheck.Visibility = Visibility.Visible; QuickColorYellowCheckSingle.Visibility = Visibility.Visible; } - else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), tolerance) || + else if (IsColorSimilar(selectedColor, Color.FromRgb(255, 165, 0), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(251, 150, 80), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(249, 115, 22), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(234, 88, 12), tolerance) || @@ -2243,7 +2244,7 @@ namespace Ink_Canvas QuickColorBlueCheck.Visibility = Visibility.Visible; // 单行显示模式没有蓝色,所以不设置单行的check } - else if (IsColorSimilar(selectedColor, Colors.Red, tolerance) || + else if (IsColorSimilar(selectedColor, Colors.Red, tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(220, 38, 38), tolerance) || IsColorSimilar(selectedColor, Color.FromRgb(239, 68, 68), tolerance)) { @@ -2270,7 +2271,7 @@ namespace Ink_Canvas int rDiff = Math.Abs(color1.R - color2.R); int gDiff = Math.Abs(color1.G - color2.G); int bDiff = Math.Abs(color1.B - color2.B); - + return rDiff <= tolerance && gDiff <= tolerance && bDiff <= tolerance; } @@ -2767,7 +2768,7 @@ namespace Ink_Canvas StackPanelCanvasControls.Visibility = Visibility.Collapsed; CheckEnableTwoFingerGestureBtnVisibility(false); HideSubPanels("cursor"); - + // 新增:在屏幕模式下显示基础浮动栏 if (currentMode == 0) { @@ -2778,7 +2779,7 @@ namespace Ink_Canvas { AnimationsHelper.ShowWithSlideFromLeftAndFade(StackPanelCanvasControls); CheckEnableTwoFingerGestureBtnVisibility(true); - + // 新增:在批注模式下显示基础浮动栏 if (currentMode == 0) { @@ -2815,7 +2816,7 @@ namespace Ink_Canvas { // Check if the image options panel is currently visible bool isImagePanelVisible = BoardImageOptionsPanel.Visibility == Visibility.Visible; - + // Toggle the image options panel if (isImagePanelVisible) { @@ -2877,11 +2878,11 @@ namespace Ink_Canvas } CenterAndScaleElement(image); - + // 设置图片属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 if (inkCanvas != null) { @@ -2890,7 +2891,7 @@ namespace Ink_Canvas // 同时通过图片的IsHitTestVisible和Focusable属性来避免InkCanvas选择系统的干扰 inkCanvas.EditingMode = InkCanvasEditingMode.None; } - + inkCanvas.Children.Add(image); // 绑定事件处理器 @@ -2943,11 +2944,11 @@ namespace Ink_Canvas } CenterAndScaleElement(image); - + // 设置图片属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 if (inkCanvas != null) { @@ -2956,7 +2957,7 @@ namespace Ink_Canvas // 设置编辑模式为非选择模式 inkCanvas.EditingMode = InkCanvasEditingMode.None; } - + inkCanvas.Children.Add(image); // 绑定事件处理器 @@ -3009,11 +3010,11 @@ namespace Ink_Canvas } CenterAndScaleElement(image); - + // 设置图片属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 if (inkCanvas != null) { @@ -3022,7 +3023,7 @@ namespace Ink_Canvas // 设置编辑模式为非选择模式 inkCanvas.EditingMode = InkCanvasEditingMode.None; } - + inkCanvas.Children.Add(image); // 绑定事件处理器 @@ -3064,7 +3065,7 @@ namespace Ink_Canvas if (floatingBarPanel == null) return 0; double currentPosition = 0; - + // 遍历浮动栏中的所有子元素 foreach (var child in floatingBarPanel.Children) { @@ -3075,12 +3076,12 @@ namespace Ink_Canvas { return currentPosition; } - + // 累加当前元素的位置 currentPosition += GetElementWidth(element); } } - + return 0; } catch (Exception ex) @@ -3114,7 +3115,7 @@ namespace Ink_Canvas { return fe.ActualWidth > 0 ? fe.ActualWidth : 28; // 默认宽度28 } - + // 对于其他元素,使用其宽度或默认宽度 return fe.ActualWidth > 0 ? fe.ActualWidth : 28; } @@ -3134,7 +3135,7 @@ namespace Ink_Canvas double position = 0; double buttonWidth = 28; // 每个按钮的默认宽度 double highlightWidth = 28; // 高光的默认宽度 - + // 检查快捷调色盘是否显示及其实际宽度 bool isQuickColorPaletteVisible = false; double quickColorPaletteWidth = 0; @@ -3160,12 +3161,12 @@ namespace Ink_Canvas // 获取高光的实际宽度 double actualHighlightWidth = FloatingbarSelectionBG.ActualWidth > 0 ? FloatingbarSelectionBG.ActualWidth : highlightWidth; - - double marginOffset = 0; - + + double marginOffset = 0; + // 快捷调色盘的Margin:Margin="4,0,4,0",所以总宽度需要加上8像素 double quickColorPaletteTotalWidth = isQuickColorPaletteVisible ? quickColorPaletteWidth + 8 : 0; - + // 根据模式计算位置,确保高光居中对齐按钮 switch (mode) { @@ -3304,7 +3305,7 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile($"获取当前选中模式失败: {ex.Message}", LogHelper.LogType.Error); } - + return string.Empty; } @@ -3323,134 +3324,134 @@ namespace Ink_Canvas SymbolIconSelect.TouchDown += (s, e) => SymbolIconSelect_MouseUp(s, null); SymbolIconSelect.StylusDown += (s, e) => SymbolIconSelect_MouseUp(s, null); } - + if (SymbolIconUndo != null) { SymbolIconUndo.TouchDown += (s, e) => SymbolIconUndo_MouseUp(s, null); SymbolIconUndo.StylusDown += (s, e) => SymbolIconUndo_MouseUp(s, null); } - + if (SymbolIconRedo != null) { SymbolIconRedo.TouchDown += (s, e) => SymbolIconRedo_MouseUp(s, null); SymbolIconRedo.StylusDown += (s, e) => SymbolIconRedo_MouseUp(s, null); } - + if (SymbolIconDelete != null) { SymbolIconDelete.TouchDown += (s, e) => SymbolIconDelete_MouseUp(s, null); SymbolIconDelete.StylusDown += (s, e) => SymbolIconDelete_MouseUp(s, null); } - + if (ToolsFloatingBarBtn != null) { ToolsFloatingBarBtn.TouchDown += (s, e) => SymbolIconTools_MouseUp(s, null); ToolsFloatingBarBtn.StylusDown += (s, e) => SymbolIconTools_MouseUp(s, null); } - + if (RandomDrawPanel != null) { RandomDrawPanel.TouchDown += (s, e) => SymbolIconRand_MouseUp(s, null); RandomDrawPanel.StylusDown += (s, e) => SymbolIconRand_MouseUp(s, null); } - + if (SingleDrawPanel != null) { SingleDrawPanel.TouchDown += (s, e) => SymbolIconRandOne_MouseUp(s, null); SingleDrawPanel.StylusDown += (s, e) => SymbolIconRandOne_MouseUp(s, null); } - + // 注意:Screenshot和Settings按钮在XAML中没有直接的Name属性,需要通过其他方式绑定 // 这些按钮的事件处理已经在XAML中通过MouseUp绑定 - + if (BorderFloatingBarMoveControls != null) { BorderFloatingBarMoveControls.TouchDown += (s, e) => SymbolIconEmoji_MouseUp(s, null); BorderFloatingBarMoveControls.StylusDown += (s, e) => SymbolIconEmoji_MouseUp(s, null); } - + // 白板模式下的按钮不添加触摸事件支持,保持原有的鼠标事件处理 - + // 为快捷调色盘按钮添加触摸和手写笔事件支持 if (QuickColorWhite != null) { QuickColorWhite.TouchDown += (s, e) => QuickColorWhite_Click(s, null); QuickColorWhite.StylusDown += (s, e) => QuickColorWhite_Click(s, null); } - + if (QuickColorOrange != null) { QuickColorOrange.TouchDown += (s, e) => QuickColorOrange_Click(s, null); QuickColorOrange.StylusDown += (s, e) => QuickColorOrange_Click(s, null); } - + if (QuickColorYellow != null) { QuickColorYellow.TouchDown += (s, e) => QuickColorYellow_Click(s, null); QuickColorYellow.StylusDown += (s, e) => QuickColorYellow_Click(s, null); } - + if (QuickColorBlack != null) { QuickColorBlack.TouchDown += (s, e) => QuickColorBlack_Click(s, null); QuickColorBlack.StylusDown += (s, e) => QuickColorBlack_Click(s, null); } - + if (QuickColorBlue != null) { QuickColorBlue.TouchDown += (s, e) => QuickColorBlue_Click(s, null); QuickColorBlue.StylusDown += (s, e) => QuickColorBlue_Click(s, null); } - + if (QuickColorRed != null) { QuickColorRed.TouchDown += (s, e) => QuickColorRed_Click(s, null); QuickColorRed.StylusDown += (s, e) => QuickColorRed_Click(s, null); } - + if (QuickColorGreen != null) { QuickColorGreen.TouchDown += (s, e) => QuickColorGreen_Click(s, null); QuickColorGreen.StylusDown += (s, e) => QuickColorGreen_Click(s, null); } - + if (QuickColorPurple != null) { QuickColorPurple.TouchDown += (s, e) => QuickColorPurple_Click(s, null); QuickColorPurple.StylusDown += (s, e) => QuickColorPurple_Click(s, null); } - + // 单行快捷调色盘 if (QuickColorWhiteSingle != null) { QuickColorWhiteSingle.TouchDown += (s, e) => QuickColorWhite_Click(s, null); QuickColorWhiteSingle.StylusDown += (s, e) => QuickColorWhite_Click(s, null); } - + if (QuickColorOrangeSingle != null) { QuickColorOrangeSingle.TouchDown += (s, e) => QuickColorOrange_Click(s, null); QuickColorOrangeSingle.StylusDown += (s, e) => QuickColorOrange_Click(s, null); } - + if (QuickColorYellowSingle != null) { QuickColorYellowSingle.TouchDown += (s, e) => QuickColorYellow_Click(s, null); QuickColorYellowSingle.StylusDown += (s, e) => QuickColorYellow_Click(s, null); } - + if (QuickColorBlackSingle != null) { QuickColorBlackSingle.TouchDown += (s, e) => QuickColorBlack_Click(s, null); QuickColorBlackSingle.StylusDown += (s, e) => QuickColorBlack_Click(s, null); } - + if (QuickColorRedSingle != null) { QuickColorRedSingle.TouchDown += (s, e) => QuickColorRed_Click(s, null); QuickColorRedSingle.StylusDown += (s, e) => QuickColorRed_Click(s, null); } - + if (QuickColorGreenSingle != null) { QuickColorGreenSingle.TouchDown += (s, e) => QuickColorGreen_Click(s, null); diff --git a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs index 81df3421..61fbaaf7 100644 --- a/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs +++ b/Ink Canvas/MainWindow_cs/MW_Hotkeys.cs @@ -8,7 +8,7 @@ namespace Ink_Canvas private void Window_MouseWheel(object sender, MouseWheelEventArgs e) { if (StackPanelPPTControls.Visibility != Visibility.Visible || currentMode != 0) return; - + // 直接发送翻页请求到PPT放映软件,不通过软件处理 if (e.Delta >= 120) { diff --git a/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs b/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs index 9b1a6592..9e7c89d5 100644 --- a/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs +++ b/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs @@ -1,3 +1,4 @@ +using Ink_Canvas.Helpers; using System; using System.Collections.Generic; using System.Drawing; @@ -11,7 +12,6 @@ using System.Windows.Forms; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; -using Ink_Canvas.Helpers; using Application = System.Windows.Application; using Color = System.Drawing.Color; using Cursors = System.Windows.Input.Cursors; @@ -190,11 +190,11 @@ namespace Ink_Canvas // 初始化TransformGroup InitializeScreenshotTransform(image); - + // 设置截图属性,避免被InkCanvas选择系统处理 image.IsHitTestVisible = true; image.Focusable = false; - + // 初始化InkCanvas选择设置 InitializeInkCanvasSelectionSettings(); @@ -251,7 +251,7 @@ namespace Ink_Canvas // 设置光标 image.Cursor = Cursors.Hand; - + // 禁用InkCanvas对截图的选择处理 image.IsHitTestVisible = true; image.Focusable = false; @@ -360,13 +360,13 @@ namespace Ink_Canvas // 创建结果位图,确保支持透明度 var resultBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); - + // 首先将整个位图设置为透明 using (var resultGraphics = Graphics.FromImage(resultBitmap)) { // 清除位图,设置为完全透明 resultGraphics.Clear(Color.Transparent); - + // 设置高质量渲染 resultGraphics.SmoothingMode = SmoothingMode.AntiAlias; resultGraphics.CompositingQuality = CompositingQuality.HighQuality; @@ -406,7 +406,7 @@ namespace Ink_Canvas // 在裁剪区域内绘制原始图像 resultGraphics.DrawImage(bitmap, 0, 0); - + // 重置裁剪区域,确保后续操作不受影响 resultGraphics.ResetClip(); } @@ -466,4 +466,4 @@ namespace Ink_Canvas return 1.0; // 默认DPI } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/MainWindow_cs/MW_Notification.cs b/Ink Canvas/MainWindow_cs/MW_Notification.cs index c473b859..e1e69945 100644 --- a/Ink Canvas/MainWindow_cs/MW_Notification.cs +++ b/Ink Canvas/MainWindow_cs/MW_Notification.cs @@ -1,8 +1,8 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Linq; using System.Threading; using System.Windows; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 065def08..ce8bdd48 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -1,4 +1,8 @@ -using System; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern; +using Microsoft.Office.Core; +using Microsoft.Office.Interop.PowerPoint; +using System; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; @@ -8,10 +12,6 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Threading; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern; -using Microsoft.Office.Core; -using Microsoft.Office.Interop.PowerPoint; using Application = System.Windows.Application; using File = System.IO.File; using MessageBox = System.Windows.MessageBox; @@ -265,13 +265,13 @@ namespace Ink_Canvas { // 在初始化墨迹管理器之前,先清理画布上的所有墨迹 ClearStrokes(true); - + // 清理备份历史记录,防止旧演示文稿的墨迹影响新演示文稿 if (TimeMachineHistories != null && TimeMachineHistories.Length > 0) { TimeMachineHistories[0] = null; } - + // 初始化墨迹管理器 _pptInkManager?.InitializePresentation(pres); @@ -291,7 +291,7 @@ namespace Ink_Canvas } _pptUIManager?.UpdateConnectionStatus(true); - + LogHelper.WriteLogToFile($"已打开新演示文稿: {pres.Name},墨迹状态已清理", LogHelper.LogType.Event); }); } diff --git a/Ink Canvas/MainWindow_cs/MW_PageListView.cs b/Ink Canvas/MainWindow_cs/MW_PageListView.cs index c7ea6c80..27d0e8e7 100644 --- a/Ink Canvas/MainWindow_cs/MW_PageListView.cs +++ b/Ink Canvas/MainWindow_cs/MW_PageListView.cs @@ -1,10 +1,10 @@ -using System.Collections.ObjectModel; +using Ink_Canvas.Helpers; +using System.Collections.ObjectModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; -using Ink_Canvas.Helpers; namespace Ink_Canvas { @@ -96,7 +96,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = previousEditingMode; currentSelectedElement = null; } - + SaveStrokes(); ClearStrokes(true); CurrentWhiteboardIndex = index + 1; @@ -129,7 +129,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = previousEditingMode; currentSelectedElement = null; } - + SaveStrokes(); ClearStrokes(true); CurrentWhiteboardIndex = index + 1; diff --git a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs index fb242d97..347c8644 100644 --- a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs +++ b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs @@ -1,3 +1,5 @@ +using Ink_Canvas.Helpers; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; @@ -12,8 +14,6 @@ using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; -using Ink_Canvas.Helpers; -using Newtonsoft.Json; using Color = System.Drawing.Color; using File = System.IO.File; using Image = System.Windows.Controls.Image; diff --git a/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs index f8547b85..e3ea3b83 100644 --- a/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs +++ b/Ink Canvas/MainWindow_cs/MW_SelectionGestures.cs @@ -1,3 +1,4 @@ +using iNKORE.UI.WPF.Modern.Controls; using System; using System.Collections.Generic; using System.Linq; @@ -6,7 +7,6 @@ using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; -using iNKORE.UI.WPF.Modern.Controls; using Point = System.Windows.Point; namespace Ink_Canvas @@ -305,18 +305,18 @@ namespace Ink_Canvas private void inkCanvas_SelectionChanged(object sender, EventArgs e) { if (isProgramChangeStrokeSelection) return; - + // 检查是否有图片元素被选中 var selectedElements = inkCanvas.GetSelectedElements(); bool hasImageElement = selectedElements.Any(element => element is Image); - + // 如果有图片元素被选中,不显示选择框 if (hasImageElement) { GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; return; } - + if (inkCanvas.GetSelectedStrokes().Count == 0) { GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; @@ -520,7 +520,7 @@ namespace Ink_Canvas } #region UIElement Selection and Resize - + private Rect GetUIElementBounds(UIElement element) { if (element is FrameworkElement fe) diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index 803000f5..0094a72c 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -1,3 +1,7 @@ +using Hardcodet.Wpf.TaskbarNotification; +using Ink_Canvas.Helpers; +using Newtonsoft.Json; +using OSVersionExtension; using System; using System.Diagnostics; using System.IO; @@ -10,10 +14,6 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; -using Hardcodet.Wpf.TaskbarNotification; -using Ink_Canvas.Helpers; -using Newtonsoft.Json; -using OSVersionExtension; using Application = System.Windows.Application; using CheckBox = System.Windows.Controls.CheckBox; using ComboBox = System.Windows.Controls.ComboBox; @@ -984,7 +984,7 @@ namespace Ink_Canvas PPTBtnPreviewRSTransform.Y = -(Settings.PowerPointSettings.PPTRSButtonPosition * 0.5); PPTBtnPreviewLSTransform.Y = -(Settings.PowerPointSettings.PPTLSButtonPosition * 0.5); - + PPTBtnPreviewLBTransform.X = -(Settings.PowerPointSettings.PPTLBButtonPosition * 0.5); PPTBtnPreviewRBTransform.X = -(Settings.PowerPointSettings.PPTRBButtonPosition * 0.5); } @@ -1918,7 +1918,7 @@ namespace Ink_Canvas Settings.Appearance.ViewboxFloatingBarOpacityValue = 1.0; Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue = 1.0; Settings.Appearance.EnableTrayIcon = true; - + // 浮动栏按钮显示控制默认值 Settings.Appearance.IsShowShapeButton = true; Settings.Appearance.IsShowUndoButton = true; @@ -1929,8 +1929,8 @@ namespace Ink_Canvas Settings.Appearance.IsShowLassoSelectButton = true; Settings.Appearance.IsShowClearAndMouseButton = true; Settings.Appearance.IsShowQuickColorPalette = false; - Settings.Appearance.QuickColorPaletteDisplayMode = 1; - Settings.Appearance.EraserDisplayOption = 0; + Settings.Appearance.QuickColorPaletteDisplayMode = 1; + Settings.Appearance.EraserDisplayOption = 0; Settings.Automation.IsAutoFoldInEasiNote = true; Settings.Automation.IsAutoFoldInEasiNoteIgnoreDesktopAnno = true; @@ -2032,7 +2032,7 @@ namespace Ink_Canvas LoadSettings(); isLoaded = true; - ToggleSwitchRunAtStartup.IsOn = false; + ToggleSwitchRunAtStartup.IsOn = false; } catch { } @@ -2488,7 +2488,7 @@ namespace Ink_Canvas UpdateFloatingBarButtonsVisibility(); SaveSettingsToFile(); } - + private void CheckBoxShowLassoSelectButton_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; @@ -2577,33 +2577,33 @@ namespace Ink_Canvas // 形状按钮 if (ShapeDrawFloatingBarBtn != null) ShapeDrawFloatingBarBtn.Visibility = Settings.Appearance.IsShowShapeButton ? Visibility.Visible : Visibility.Collapsed; - + // 撤销按钮 if (SymbolIconUndo != null) SymbolIconUndo.Visibility = Settings.Appearance.IsShowUndoButton ? Visibility.Visible : Visibility.Collapsed; - + // 重做按钮 if (SymbolIconRedo != null) SymbolIconRedo.Visibility = Settings.Appearance.IsShowRedoButton ? Visibility.Visible : Visibility.Collapsed; - + // 清空按钮 if (SymbolIconDelete != null) SymbolIconDelete.Visibility = Settings.Appearance.IsShowClearButton ? Visibility.Visible : Visibility.Collapsed; - + // 白板按钮 if (WhiteboardFloatingBarBtn != null) WhiteboardFloatingBarBtn.Visibility = Settings.Appearance.IsShowWhiteboardButton ? Visibility.Visible : Visibility.Collapsed; - + // 隐藏按钮 if (Fold_Icon != null) Fold_Icon.Visibility = Settings.Appearance.IsShowHideButton ? Visibility.Visible : Visibility.Collapsed; - - // 快捷调色盘 + + // 快捷调色盘 if (QuickColorPalettePanel != null && QuickColorPaletteSingleRowPanel != null) { bool shouldShow = Settings.Appearance.IsShowQuickColorPalette && inkCanvas.EditingMode == InkCanvasEditingMode.Ink; bool wasVisible = QuickColorPalettePanel.Visibility == Visibility.Visible || QuickColorPaletteSingleRowPanel.Visibility == Visibility.Visible; - + if (shouldShow) { // 根据显示模式选择显示哪个面板 @@ -2625,7 +2625,7 @@ namespace Ink_Canvas QuickColorPalettePanel.Visibility = Visibility.Collapsed; QuickColorPaletteSingleRowPanel.Visibility = Visibility.Collapsed; } - + // 如果快捷调色盘的可见性发生变化,重新计算浮动栏位置 if (wasVisible != shouldShow && !isFloatingBarFolded) { @@ -2647,15 +2647,15 @@ namespace Ink_Canvas } } } - + // 套索选择按钮 if (SymbolIconSelect != null) SymbolIconSelect.Visibility = Settings.Appearance.IsShowLassoSelectButton ? Visibility.Visible : Visibility.Collapsed; - + // 清并鼠按钮 if (CursorWithDelFloatingBarBtn != null) CursorWithDelFloatingBarBtn.Visibility = Settings.Appearance.IsShowClearAndMouseButton ? Visibility.Visible : Visibility.Collapsed; - + // 橡皮按钮显示控制 if (Eraser_Icon != null && EraserByStrokes_Icon != null) { @@ -2679,7 +2679,7 @@ namespace Ink_Canvas break; } } - + // 在按钮可见性更新后,重新计算当前高光位置 // 延迟执行以确保UI更新完成 Dispatcher.BeginInvoke(new Action(async () => @@ -2688,14 +2688,14 @@ namespace Ink_Canvas { // 等待UI完全更新 await Task.Delay(100); - + // 获取当前选中的模式并重新设置高光位置 string selectedToolMode = GetCurrentSelectedMode(); if (!string.IsNullOrEmpty(selectedToolMode)) { SetFloatingBarHighlightPosition(selectedToolMode); } - + // 重新计算浮动栏位置,因为按钮可见性变化会影响浮动栏宽度 if (!isFloatingBarFolded && currentMode == 0) // 新增:只在屏幕模式下重新计算浮动栏位置 { diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index 5501b884..e4c5c6b1 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -1,4 +1,8 @@ -using System; +using Hardcodet.Wpf.TaskbarNotification; +using Ink_Canvas.Helpers; +using Newtonsoft.Json; +using OSVersionExtension; +using System; using System.Reflection; using System.Windows; using System.Windows.Controls; @@ -6,10 +10,6 @@ using System.Windows.Ink; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; -using Hardcodet.Wpf.TaskbarNotification; -using Ink_Canvas.Helpers; -using Newtonsoft.Json; -using OSVersionExtension; using File = System.IO.File; using OperatingSystem = OSVersionExtension.OperatingSystem; @@ -327,10 +327,10 @@ namespace Ink_Canvas CheckBoxShowClearAndMouseButton.IsChecked = Settings.Appearance.IsShowClearAndMouseButton; ComboBoxEraserDisplayOption.SelectedIndex = Settings.Appearance.EraserDisplayOption; ComboBoxQuickColorPaletteDisplayMode.SelectedIndex = Settings.Appearance.QuickColorPaletteDisplayMode; - + // 初始化快捷调色盘指示器 UpdateQuickColorPaletteIndicator(inkCanvas.DefaultDrawingAttributes.Color); - + // 应用浮动栏按钮可见性设置 UpdateFloatingBarButtonsVisibility(); diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs index 4b8ca738..0644f141 100644 --- a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs +++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs @@ -1,4 +1,6 @@ -using System; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern.Controls; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; @@ -8,8 +10,6 @@ using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern.Controls; using MessageBox = System.Windows.MessageBox; using Point = System.Windows.Point; @@ -178,12 +178,12 @@ namespace Ink_Canvas await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(1); lastMouseDownSender = null; - + // 先保存长按状态,避免被CancelSingleFingerDragMode重置 bool wasLongPressed = isLongPressSelected; - + CancelSingleFingerDragMode(); - + if (wasLongPressed) { if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); @@ -200,12 +200,12 @@ namespace Ink_Canvas await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(8); lastMouseDownSender = null; - + // 先保存长按状态,避免被CancelSingleFingerDragMode重置 bool wasLongPressed = isLongPressSelected; - + CancelSingleFingerDragMode(); - + if (wasLongPressed) { if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); @@ -222,12 +222,12 @@ namespace Ink_Canvas await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(18); lastMouseDownSender = null; - + // 先保存长按状态,避免被CancelSingleFingerDragMode重置 bool wasLongPressed = isLongPressSelected; - + CancelSingleFingerDragMode(); - + if (wasLongPressed) { if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); @@ -244,12 +244,12 @@ namespace Ink_Canvas await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(2); lastMouseDownSender = null; - + // 先保存长按状态,避免被CancelSingleFingerDragMode重置 bool wasLongPressed = isLongPressSelected; - + CancelSingleFingerDragMode(); - + if (wasLongPressed) { if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); @@ -266,12 +266,12 @@ namespace Ink_Canvas await CheckIsDrawingShapesInMultiTouchMode(); EnterShapeDrawingMode(15); lastMouseDownSender = null; - + // 先保存长按状态,避免被CancelSingleFingerDragMode重置 bool wasLongPressed = isLongPressSelected; - + CancelSingleFingerDragMode(); - + if (wasLongPressed) { if (ToggleSwitchDrawShapeBorderAutoHide.IsOn) CollapseBorderDrawShape(); @@ -484,7 +484,7 @@ namespace Ink_Canvas { // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 inkCanvas.EditingMode = InkCanvasEditingMode.None; - + if (isWaitUntilNextTouchDown && dec.Count > 1) return; if (dec.Count > 1) { @@ -512,7 +512,7 @@ namespace Ink_Canvas } return; } - + // 修复:双曲线绘制时,第二笔应该基于第一笔的起点,而不是触摸实时位置 Point touchPoint = e.GetTouchPoint(inkCanvas).Position; if ((drawingShapeMode == 24 || drawingShapeMode == 25) && drawMultiStepShapeCurrentStep == 1) @@ -526,7 +526,7 @@ namespace Ink_Canvas // 其他情况正常处理 MouseTouchMove(touchPoint); } - + return; // 处理完几何绘制后直接返回,不执行后面的代码 } @@ -890,7 +890,7 @@ namespace Ink_Canvas lastTempStroke = stroke; inkCanvas.Strokes.Add(stroke); - + // 如果启用了圆心标记功能,则绘制圆心 if (Settings.Canvas.ShowCircleCenter) { @@ -995,7 +995,7 @@ namespace Ink_Canvas lastTempStrokeCollection = strokes; inkCanvas.Strokes.Add(strokes); - + // 如果启用了圆心标记功能,则绘制圆心 if (Settings.Canvas.ShowCircleCenter) { @@ -1021,7 +1021,7 @@ namespace Ink_Canvas new Point(endP.X, 2 * iniP.Y - endP.Y))); drawMultiStepShapeSpecialParameter3 = k; drawMultiStepShapeSpecialStrokeCollection = strokes; - + // 修复:第一笔绘制的辅助线应该立即显示在画布上 try { @@ -1120,10 +1120,10 @@ namespace Ink_Canvas { // 删除第二笔的临时笔画 inkCanvas.Strokes.Remove(lastTempStrokeCollection); - + // 创建包含辅助线和双曲线的完整笔画集合 var completeStrokes = new StrokeCollection(); - + // 添加第一笔的辅助线 if (drawMultiStepShapeSpecialStrokeCollection != null && drawMultiStepShapeSpecialStrokeCollection.Count > 0) { @@ -1132,13 +1132,13 @@ namespace Ink_Canvas completeStrokes.Add(stroke1.Clone()); } } - + // 添加第二笔的双曲线 foreach (var stroke1 in strokes) { completeStrokes.Add(stroke1.Clone()); } - + lastTempStrokeCollection = completeStrokes; inkCanvas.Strokes.Add(completeStrokes); } @@ -1523,7 +1523,7 @@ namespace Ink_Canvas return pointList; } - + private StrokeCollection GenerateDashedLineEllipseStrokeCollection(Point st, Point ed, bool isDrawTop = true, bool isDrawBottom = true) { @@ -1671,14 +1671,14 @@ namespace Ink_Canvas var mousePoint = e.GetPosition(this); var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); - + // 如果鼠标点击发生在浮动栏区域,不阻止事件传播,让浮动栏按钮能够接收鼠标事件 if (floatingBarBounds.Contains(mousePoint)) { // 不设置 ViewboxFloatingBar.IsHitTestVisible = false,让浮动栏按钮能够接收鼠标事件 return; } - + inkCanvas.CaptureMouse(); ViewboxFloatingBar.IsHitTestVisible = false; BlackboardUIGridForInkReplay.IsHitTestVisible = false; @@ -1968,7 +1968,7 @@ namespace Ink_Canvas } } } - + private void EnterShapeDrawingMode(int mode) { forceEraser = true; @@ -1988,7 +1988,7 @@ namespace Ink_Canvas { // 创建一个点作为圆心标记 var centerSize = 0.5; // 圆心标记的大小 - + // 创建一个小圆作为圆心标记 var circlePoints = new List(); for (double angle = 0; angle <= 2 * Math.PI; angle += 0.1) @@ -1998,18 +1998,18 @@ namespace Ink_Canvas centerPoint.Y + centerSize * Math.Sin(angle) )); } - + // 绘制圆心点 var point = new StylusPointCollection(circlePoints); var stroke = new Stroke(point) { DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() }; - + // 设置圆心点的样式 stroke.DrawingAttributes.Width = 2.0; stroke.DrawingAttributes.Height = 2.0; - + // 添加到画布 inkCanvas.Strokes.Add(stroke); } diff --git a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs index 8e14c503..15f866e3 100644 --- a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs +++ b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,7 +9,6 @@ using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; -using Ink_Canvas.Helpers; using Point = System.Windows.Point; namespace Ink_Canvas @@ -62,13 +62,13 @@ namespace Ink_Canvas // 获取墨迹的起点和终点 var startPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[0].ToPoint() : new Point(); var endPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1].ToPoint() : new Point(); - + // 从InkCanvas中移除墨迹,因为我们要用渐隐管理器来管理它 if (inkCanvas.Strokes.Contains(e.Stroke)) { inkCanvas.Strokes.Remove(e.Stroke); } - + // 添加到墨迹渐隐管理器 if (_inkFadeManager != null) { @@ -78,11 +78,11 @@ namespace Ink_Canvas { LogHelper.WriteLogToFile("StrokeCollected: 墨迹渐隐管理器为空,无法添加墨迹", LogHelper.LogType.Error); } - + // 墨迹渐隐模式下不参与墨迹纠正和其他处理,直接返回 return; } - + // 标记是否进行了直线拉直 bool wasStraightened = false; diff --git a/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs b/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs index 541d2068..1ad265d0 100644 --- a/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs +++ b/Ink Canvas/MainWindow_cs/MW_TimeMachine.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; @@ -6,7 +7,6 @@ using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; -using Ink_Canvas.Helpers; namespace Ink_Canvas { @@ -193,13 +193,13 @@ namespace Ink_Canvas // 检查图片是否有位置信息,如果没有则应用居中 double left = InkCanvas.GetLeft(img); double top = InkCanvas.GetTop(img); - + if (double.IsNaN(left) || double.IsNaN(top)) { // 图片没有位置信息,应用居中 CenterAndScaleElement(img); } - + // 重新绑定事件处理器 BindElementEvents(img); } @@ -208,13 +208,13 @@ namespace Ink_Canvas // 检查媒体元素是否有位置信息,如果没有则应用居中 double left = InkCanvas.GetLeft(media); double top = InkCanvas.GetTop(media); - + if (double.IsNaN(left) || double.IsNaN(top)) { // 媒体元素没有位置信息,应用居中 CenterAndScaleElement(media); } - + // 重新绑定事件处理器 BindElementEvents(media); } diff --git a/Ink Canvas/MainWindow_cs/MW_Timer.cs b/Ink Canvas/MainWindow_cs/MW_Timer.cs index 4988c444..3c9e0e4b 100644 --- a/Ink Canvas/MainWindow_cs/MW_Timer.cs +++ b/Ink Canvas/MainWindow_cs/MW_Timer.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.ComponentModel; using System.Diagnostics; using System.IO; @@ -11,7 +12,6 @@ using System.Threading.Tasks; using System.Timers; using System.Windows; using System.Windows.Controls; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 7aedfd43..bfba3b73 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -1,3 +1,4 @@ +using Ink_Canvas.Helpers; using System; using System.Collections.Generic; using System.Linq; @@ -8,7 +9,6 @@ using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; -using Ink_Canvas.Helpers; using Point = System.Windows.Point; namespace Ink_Canvas @@ -113,14 +113,14 @@ namespace Ink_Canvas var touchPoint = e.GetTouchPoint(this); var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); - + // 如果触摸发生在浮动栏区域,不阻止事件传播,让浮动栏按钮能够接收触摸事件 if (floatingBarBounds.Contains(touchPoint.Position)) { // 不设置 ViewboxFloatingBar.IsHitTestVisible = false,让浮动栏按钮能够接收触摸事件 return; } - + if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke || inkCanvas.EditingMode == InkCanvasEditingMode.Select) return; @@ -142,7 +142,7 @@ namespace Ink_Canvas // 只保留普通橡皮逻辑 TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None; inkCanvas.EraserShape = new EllipseStylusShape(50, 50); - if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke) { inkCanvas.EditingMode = InkCanvasEditingMode.None; @@ -155,16 +155,16 @@ namespace Ink_Canvas var stylusPoint = e.GetPosition(this); var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); - + // 如果手写笔点击发生在浮动栏区域,不阻止事件传播,让浮动栏按钮能够接收手写笔事件 if (floatingBarBounds.Contains(stylusPoint)) { // 不设置 ViewboxFloatingBar.IsHitTestVisible = false,让浮动栏按钮能够接收手写笔事件 return; } - + LogHelper.WriteLogToFile($"MainWindow_StylusDown 被调用,笔尾状态: {e.StylusDevice.Inverted}, 当前 drawingShapeMode: {drawingShapeMode}, 当前 EditingMode: {inkCanvas.EditingMode}"); - + // 新增:根据是否为笔尾自动切换橡皮擦/画笔模式 if (e.StylusDevice.Inverted) { @@ -232,14 +232,14 @@ namespace Ink_Canvas try { LogHelper.WriteLogToFile($"MainWindow_StylusUp 被调用,EditingMode: {inkCanvas.EditingMode}, EnableInkFade: {Settings.Canvas.EnableInkFade}"); - + var stroke = GetStrokeVisual(e.StylusDevice.Id).Stroke; LogHelper.WriteLogToFile($"获取到墨迹,StylusPoints数量: {stroke.StylusPoints.Count}"); - + // 正常模式:添加到画布并参与墨迹纠正 // 墨迹渐隐功能现在在 StrokeCollected 事件中统一处理所有输入方式 LogHelper.WriteLogToFile("StylusUp: 添加墨迹到画布"); - + inkCanvas.Strokes.Add(stroke); await Task.Delay(5); // 避免渲染墨迹完成前预览墨迹被删除导致墨迹闪烁 inkCanvas.Children.Remove(GetVisualCanvas(e.StylusDevice.Id)); @@ -351,14 +351,14 @@ namespace Ink_Canvas var touchPoint = e.GetTouchPoint(this); var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); - + // 如果触摸发生在浮动栏区域,不阻止事件传播,让浮动栏按钮能够接收触摸事件 if (floatingBarBounds.Contains(touchPoint.Position)) { // 不设置 ViewboxFloatingBar.IsHitTestVisible = false,让浮动栏按钮能够接收触摸事件 return; } - + SetCursorBasedOnEditingMode(inkCanvas); inkCanvas.CaptureTouch(e.TouchDevice); @@ -411,14 +411,14 @@ namespace Ink_Canvas var touchPoint = e.GetTouchPoint(this); var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); - + // 如果触摸发生在浮动栏区域,不阻止事件传播,让浮动栏按钮能够接收触摸事件 if (floatingBarBounds.Contains(touchPoint.Position)) { // 不设置 ViewboxFloatingBar.IsHitTestVisible = false,让浮动栏按钮能够接收触摸事件 return; } - + // 橡皮状态下不做任何切换,直接return,保证橡皮可持续 if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke) @@ -435,7 +435,7 @@ namespace Ink_Canvas inkCanvas.CaptureTouch(e.TouchDevice); ViewboxFloatingBar.IsHitTestVisible = false; BlackboardUIGridForInkReplay.IsHitTestVisible = false; - + // 修复:几何绘制模式下,只记录几何绘制的起点,不记录触摸轨迹 if (dec.Count == 0) { @@ -460,108 +460,108 @@ namespace Ink_Canvas dec.Add(e.TouchDevice.Id); return; } - + // 非几何绘制模式下的正常触摸处理 SetCursorBasedOnEditingMode(inkCanvas); inkCanvas.CaptureTouch(e.TouchDevice); ViewboxFloatingBar.IsHitTestVisible = false; BlackboardUIGridForInkReplay.IsHitTestVisible = false; dec.Add(e.TouchDevice.Id); - - // Palm Eraser 逻辑 - 优化:改进手掌判定条件,提高精度 - if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive && !palmEraserTouchDownHandled) - { - var bounds = e.GetTouchPoint(inkCanvas).Bounds; - - // 根据敏感度设置调整判定参数 - double palmThreshold; - double aspectRatioThreshold; - int minTouchPoints; - - switch (Settings.Canvas.PalmEraserSensitivity) - { - case 0: // 低敏感度 - 更严格的判定 - palmThreshold = 80; - aspectRatioThreshold = 0.4; - minTouchPoints = 4; - break; - case 1: // 中敏感度 - 平衡的判定 - palmThreshold = 60; - aspectRatioThreshold = 0.3; - minTouchPoints = 3; - break; - case 2: // 高敏感度 - 较宽松的判定 - default: - palmThreshold = 50; - aspectRatioThreshold = 0.25; - minTouchPoints = 2; - break; - } - - // 计算宽高比 - double aspectRatio = Math.Min(bounds.Width, bounds.Height) / Math.Max(bounds.Width, bounds.Height); - - // 更严格的手掌判定条件 - bool isLargeTouch = bounds.Width >= palmThreshold && bounds.Height >= palmThreshold; - bool isPalmLikeShape = aspectRatio >= aspectRatioThreshold; - bool hasMultipleTouchPoints = dec.Count >= minTouchPoints; - - if (isLargeTouch && isPalmLikeShape && hasMultipleTouchPoints) - { - // 记录当前编辑模式和高光状态 - palmEraserLastEditingMode = inkCanvas.EditingMode; - palmEraserLastIsHighlighter = drawingAttributes.IsHighlighter; - - // 记录参与手掌擦的触摸点ID - palmEraserTouchIds.Clear(); - foreach (int touchId in dec) - { - palmEraserTouchIds.Add(touchId); - } - - // 切换为橡皮擦 - EraserIcon_Click(null, null); - isPalmEraserActive = true; - palmEraserActivationTime = DateTime.Now; // 记录激活时间 - palmEraserTouchDownHandled = true; // 标记已处理 - - // 启动恢复定时器,防止卡死 - StartPalmEraserRecoveryTimer(); - - // 记录日志 - LogHelper.WriteLogToFile($"Palm eraser activated - Sensitivity: {Settings.Canvas.PalmEraserSensitivity}, Touch bounds: {bounds.Width}x{bounds.Height}, Aspect ratio: {aspectRatio:F2}, Touch points: {dec.Count}"); - } - } - - // 设备1个的时候,记录中心点 - if (dec.Count == 1) - { - touchPoint = e.GetTouchPoint(inkCanvas); - centerPoint = touchPoint.Position; - // 修复:只允许在此处赋值iniP,防止TouchMove等其他地方覆盖,保证几何绘制起点一致 - if (drawingShapeMode != 0) + // Palm Eraser 逻辑 - 优化:改进手掌判定条件,提高精度 + if (Settings.Canvas.EnablePalmEraser && dec.Count >= 2 && !isPalmEraserActive && !palmEraserTouchDownHandled) { - // 对于双曲线绘制,第一笔时记录起点,第二笔时不更新起点 - if (drawingShapeMode == 24 || drawingShapeMode == 25) + var bounds = e.GetTouchPoint(inkCanvas).Bounds; + + // 根据敏感度设置调整判定参数 + double palmThreshold; + double aspectRatioThreshold; + int minTouchPoints; + + switch (Settings.Canvas.PalmEraserSensitivity) { - // 双曲线绘制:第一笔记录起点,第二笔保持第一笔的起点 - if (drawMultiStepShapeCurrentStep == 0) + case 0: // 低敏感度 - 更严格的判定 + palmThreshold = 80; + aspectRatioThreshold = 0.4; + minTouchPoints = 4; + break; + case 1: // 中敏感度 - 平衡的判定 + palmThreshold = 60; + aspectRatioThreshold = 0.3; + minTouchPoints = 3; + break; + case 2: // 高敏感度 - 较宽松的判定 + default: + palmThreshold = 50; + aspectRatioThreshold = 0.25; + minTouchPoints = 2; + break; + } + + // 计算宽高比 + double aspectRatio = Math.Min(bounds.Width, bounds.Height) / Math.Max(bounds.Width, bounds.Height); + + // 更严格的手掌判定条件 + bool isLargeTouch = bounds.Width >= palmThreshold && bounds.Height >= palmThreshold; + bool isPalmLikeShape = aspectRatio >= aspectRatioThreshold; + bool hasMultipleTouchPoints = dec.Count >= minTouchPoints; + + if (isLargeTouch && isPalmLikeShape && hasMultipleTouchPoints) + { + // 记录当前编辑模式和高光状态 + palmEraserLastEditingMode = inkCanvas.EditingMode; + palmEraserLastIsHighlighter = drawingAttributes.IsHighlighter; + + // 记录参与手掌擦的触摸点ID + palmEraserTouchIds.Clear(); + foreach (int touchId in dec) { + palmEraserTouchIds.Add(touchId); + } + + // 切换为橡皮擦 + EraserIcon_Click(null, null); + isPalmEraserActive = true; + palmEraserActivationTime = DateTime.Now; // 记录激活时间 + palmEraserTouchDownHandled = true; // 标记已处理 + + // 启动恢复定时器,防止卡死 + StartPalmEraserRecoveryTimer(); + + // 记录日志 + LogHelper.WriteLogToFile($"Palm eraser activated - Sensitivity: {Settings.Canvas.PalmEraserSensitivity}, Touch bounds: {bounds.Width}x{bounds.Height}, Aspect ratio: {aspectRatio:F2}, Touch points: {dec.Count}"); + } + } + + // 设备1个的时候,记录中心点 + if (dec.Count == 1) + { + touchPoint = e.GetTouchPoint(inkCanvas); + centerPoint = touchPoint.Position; + + // 修复:只允许在此处赋值iniP,防止TouchMove等其他地方覆盖,保证几何绘制起点一致 + if (drawingShapeMode != 0) + { + // 对于双曲线绘制,第一笔时记录起点,第二笔时不更新起点 + if (drawingShapeMode == 24 || drawingShapeMode == 25) + { + // 双曲线绘制:第一笔记录起点,第二笔保持第一笔的起点 + if (drawMultiStepShapeCurrentStep == 0) + { + iniP = touchPoint.Position; + } + // 第二笔时不更新iniP,保持第一笔的起点 + } + else + { + // 其他图形正常记录起点 iniP = touchPoint.Position; } - // 第二笔时不更新iniP,保持第一笔的起点 } - else - { - // 其他图形正常记录起点 - iniP = touchPoint.Position; - } - } - // 记录第一根手指点击时的 StrokeCollection - lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); - } + // 记录第一根手指点击时的 StrokeCollection + lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); + } //设备两个及两个以上,将画笔功能关闭 if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) { @@ -571,7 +571,7 @@ namespace Ink_Canvas lastInkCanvasEditingMode = inkCanvas.EditingMode; // 修复:几何绘制模式下禁止切回Ink if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint - && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke + && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke && drawingShapeMode == 0) { inkCanvas.EditingMode = InkCanvasEditingMode.None; @@ -592,19 +592,19 @@ namespace Ink_Canvas // Palm Eraser 逻辑:优化状态恢复机制 dec.Remove(e.TouchDevice.Id); - + // 如果是手掌擦的触摸点,从记录中移除 if (palmEraserTouchIds.Contains(e.TouchDevice.Id)) { palmEraserTouchIds.Remove(e.TouchDevice.Id); } - + // 当所有手掌擦触摸点都抬起时,恢复原编辑模式 if (isPalmEraserActive && palmEraserTouchIds.Count == 0) { // 恢复高光状态 drawingAttributes.IsHighlighter = palmEraserLastIsHighlighter; - + // 恢复编辑模式 - 优化:改进状态恢复逻辑 try { @@ -623,7 +623,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = palmEraserLastEditingMode; break; } - + LogHelper.WriteLogToFile($"Palm eraser recovered to mode: {palmEraserLastEditingMode}"); } } @@ -633,25 +633,25 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"Palm eraser recovery failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } - + // 重置手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; palmEraserTouchIds.Clear(); - + // 停止恢复定时器 StopPalmEraserRecoveryTimer(); - + // 确保触摸事件能正常响应 inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; - + ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; - + LogHelper.WriteLogToFile("Palm eraser state reset completed"); } - + // 新增:超时检测 - 如果手掌擦激活时间过长,强制重置状态 if (isPalmEraserActive) { @@ -659,7 +659,7 @@ namespace Ink_Canvas if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) { LogHelper.WriteLogToFile($"Palm eraser timeout detected ({timeSinceActivation.TotalMilliseconds}ms), forcing recovery", LogHelper.LogType.Warning); - + // 强制恢复状态 try { @@ -684,20 +684,20 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"Palm eraser timeout recovery failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } - + // 重置所有手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; palmEraserTouchIds.Clear(); inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; - + ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; - + // 停止恢复定时器 StopPalmEraserRecoveryTimer(); - + LogHelper.WriteLogToFile("Palm eraser timeout recovery completed"); } } @@ -760,7 +760,7 @@ namespace Ink_Canvas { inkCanvas.EditingMode = lastInkCanvasEditingMode; } - + // 修复:确保手掌擦除后触摸事件能正常响应 if (isPalmEraserActive) { @@ -770,7 +770,7 @@ namespace Ink_Canvas palmEraserTouchIds.Clear(); // 确保清空触摸点ID inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; - + ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; } @@ -799,7 +799,7 @@ namespace Ink_Canvas { if (e.Manipulators.Count() != 0) return; // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 - if (drawingShapeMode == 0 + if (drawingShapeMode == 0 && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke) { @@ -924,7 +924,7 @@ namespace Ink_Canvas inkCanvas.TouchDown -= MainWindow_TouchDown; inkCanvas.TouchDown += Main_Grid_TouchDown; // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 - if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke && drawingShapeMode == 0) { @@ -958,7 +958,7 @@ namespace Ink_Canvas inkCanvas.TouchDown -= Main_Grid_TouchDown; // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint - && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke + && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke && drawingShapeMode == 0) { inkCanvas.EditingMode = InkCanvasEditingMode.None; @@ -976,7 +976,7 @@ namespace Ink_Canvas ToggleSwitchEnablePalmEraser.IsOn = false; } } - + /// /// 启动手掌擦恢复定时器,防止卡死状态 /// @@ -988,10 +988,10 @@ namespace Ink_Canvas palmEraserRecoveryTimer.Interval = TimeSpan.FromMilliseconds(1000); // 每秒检查一次 palmEraserRecoveryTimer.Tick += PalmEraserRecoveryTimer_Tick; } - + palmEraserRecoveryTimer.Start(); } - + /// /// 停止手掌擦恢复定时器 /// @@ -1002,20 +1002,20 @@ namespace Ink_Canvas palmEraserRecoveryTimer.Stop(); } } - + /// /// 手掌擦恢复定时器事件处理 /// private void PalmEraserRecoveryTimer_Tick(object sender, EventArgs e) { if (!isPalmEraserActive) return; - + // 检查是否超时 var timeSinceActivation = DateTime.Now - palmEraserActivationTime; if (timeSinceActivation.TotalMilliseconds > PALM_ERASER_TIMEOUT_MS) { LogHelper.WriteLogToFile($"Palm eraser recovery timer triggered, forcing recovery after {timeSinceActivation.TotalMilliseconds}ms", LogHelper.LogType.Warning); - + // 强制恢复状态 try { @@ -1033,7 +1033,7 @@ namespace Ink_Canvas inkCanvas.EditingMode = palmEraserLastEditingMode; break; } - + LogHelper.WriteLogToFile($"Palm eraser timer recovery to mode: {palmEraserLastEditingMode}"); } } @@ -1042,20 +1042,20 @@ namespace Ink_Canvas LogHelper.WriteLogToFile($"Palm eraser recovery timer failed: {ex.Message}, forcing to Ink mode", LogHelper.LogType.Error); inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } - + // 重置所有手掌擦状态 isPalmEraserActive = false; palmEraserTouchDownHandled = false; palmEraserTouchIds.Clear(); inkCanvas.IsHitTestVisible = true; inkCanvas.IsManipulationEnabled = true; - + ViewboxFloatingBar.IsHitTestVisible = true; BlackboardUIGridForInkReplay.IsHitTestVisible = true; - + // 停止定时器 StopPalmEraserRecoveryTimer(); - + LogHelper.WriteLogToFile("Palm eraser timer recovery completed"); } } diff --git a/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs index b20cb2d7..96796023 100644 --- a/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs +++ b/Ink Canvas/MainWindow_cs/MW_TrayIcon.cs @@ -1,12 +1,12 @@ -using System; +using Hardcodet.Wpf.TaskbarNotification; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern.Controls; +using System; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; using System.Windows.Interop; -using Hardcodet.Wpf.TaskbarNotification; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern.Controls; using Application = System.Windows.Application; using ContextMenu = System.Windows.Controls.ContextMenu; using MenuItem = System.Windows.Controls.MenuItem; diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index 8efdf432..2216016d 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -1,7 +1,7 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.IO; -using Newtonsoft.Json; namespace Ink_Canvas { @@ -93,14 +93,14 @@ namespace Ink_Canvas [JsonProperty("clearCanvasAlsoClearImages")] public bool ClearCanvasAlsoClearImages { get; set; } = true; [JsonProperty("showCircleCenter")] - public bool ShowCircleCenter { get; set; } + public bool ShowCircleCenter { get; set; } // 墨迹渐隐功能设置 [JsonProperty("enableInkFade")] public bool EnableInkFade { get; set; } // 是否启用墨迹渐隐功能 [JsonProperty("inkFadeTime")] public int InkFadeTime { get; set; } = 3000; // 墨迹渐隐时间(毫秒) - + } public enum OptionalOperation @@ -152,7 +152,7 @@ namespace Ink_Canvas [JsonProperty("skippedVersion")] public string SkippedVersion { get; set; } = ""; [JsonProperty("isEnableNibMode")] - public bool IsEnableNibMode { get; set; } + public bool IsEnableNibMode { get; set; } [JsonProperty("isFoldAtStartup")] public bool IsFoldAtStartup { get; set; } [JsonProperty("crashAction")] @@ -205,7 +205,7 @@ namespace Ink_Canvas public bool IsShowModeFingerToggleSwitch { get; set; } = true; [JsonProperty("theme")] public int Theme { get; set; } - + // 浮动栏按钮显示控制 [JsonProperty("isShowShapeButton")] public bool IsShowShapeButton { get; set; } = true; @@ -218,7 +218,7 @@ namespace Ink_Canvas [JsonProperty("isShowWhiteboardButton")] public bool IsShowWhiteboardButton { get; set; } = true; [JsonProperty("isShowHideButton")] - public bool IsShowHideButton { get; set; } = true; + public bool IsShowHideButton { get; set; } = true; [JsonProperty("isShowLassoSelectButton")] public bool IsShowLassoSelectButton { get; set; } = true; [JsonProperty("isShowClearAndMouseButton")] @@ -226,12 +226,12 @@ namespace Ink_Canvas [JsonProperty("eraserDisplayOption")] public int EraserDisplayOption { get; set; } - + [JsonProperty("isShowQuickColorPalette")] public bool IsShowQuickColorPalette { get; set; } - + [JsonProperty("quickColorPaletteDisplayMode")] - public int QuickColorPaletteDisplayMode { get; set; } = 1; + public int QuickColorPaletteDisplayMode { get; set; } = 1; } diff --git a/Ink Canvas/Windows/AddCustomIconWindow.xaml.cs b/Ink Canvas/Windows/AddCustomIconWindow.xaml.cs index 060c5b9d..a214c9f2 100644 --- a/Ink Canvas/Windows/AddCustomIconWindow.xaml.cs +++ b/Ink Canvas/Windows/AddCustomIconWindow.xaml.cs @@ -1,8 +1,8 @@ +using Microsoft.Win32; using System; using System.IO; using System.Windows; using System.Windows.Media.Imaging; -using Microsoft.Win32; namespace Ink_Canvas { diff --git a/Ink Canvas/Windows/AddPickNameBackgroundWindow.xaml.cs b/Ink Canvas/Windows/AddPickNameBackgroundWindow.xaml.cs index f9aa8951..bc602748 100644 --- a/Ink Canvas/Windows/AddPickNameBackgroundWindow.xaml.cs +++ b/Ink Canvas/Windows/AddPickNameBackgroundWindow.xaml.cs @@ -1,8 +1,8 @@ +using Microsoft.Win32; using System; using System.IO; using System.Windows; using System.Windows.Media.Imaging; -using Microsoft.Win32; namespace Ink_Canvas { diff --git a/Ink Canvas/Windows/CountdownTimerWindow.xaml.cs b/Ink Canvas/Windows/CountdownTimerWindow.xaml.cs index 6e00b4c5..03e38cc6 100644 --- a/Ink Canvas/Windows/CountdownTimerWindow.xaml.cs +++ b/Ink Canvas/Windows/CountdownTimerWindow.xaml.cs @@ -1,4 +1,5 @@ -using System; +using Ink_Canvas.Helpers; +using System; using System.ComponentModel; using System.Media; using System.Timers; @@ -7,7 +8,6 @@ using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; -using Ink_Canvas.Helpers; using Application = System.Windows.Application; using MouseEventArgs = System.Windows.Input.MouseEventArgs; using Timer = System.Timers.Timer; diff --git a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs index 41a7b7c8..09b0010b 100644 --- a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs +++ b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs @@ -1,4 +1,7 @@ -using System; +using Ink_Canvas.Helpers; +using iNKORE.UI.WPF.Modern.Controls; +using MdXaml; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -10,9 +13,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Interop; using System.Windows.Media; -using Ink_Canvas.Helpers; -using iNKORE.UI.WPF.Modern.Controls; -using MdXaml; namespace Ink_Canvas { @@ -340,7 +340,7 @@ namespace Ink_Canvas downloadUrl = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); } LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}"); - AutoUpdateHelper.InstallNewVersionApp(version, true); + AutoUpdateHelper.InstallNewVersionApp(version, true); App.IsAppExitByUser = true; Application.Current.Dispatcher.Invoke(() => { diff --git a/Ink Canvas/Windows/HistoryRollbackWindow.xaml.cs b/Ink Canvas/Windows/HistoryRollbackWindow.xaml.cs index b9a749a4..1fb83a07 100644 --- a/Ink Canvas/Windows/HistoryRollbackWindow.xaml.cs +++ b/Ink Canvas/Windows/HistoryRollbackWindow.xaml.cs @@ -1,3 +1,4 @@ +using Ink_Canvas.Helpers; using System; using System.Collections.Generic; using System.ComponentModel; @@ -7,7 +8,6 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Ink_Canvas.Helpers; // Added for OrderByDescending diff --git a/Ink Canvas/Windows/HotkeyItem.xaml.cs b/Ink Canvas/Windows/HotkeyItem.xaml.cs index 146791e3..47bce516 100644 --- a/Ink Canvas/Windows/HotkeyItem.xaml.cs +++ b/Ink Canvas/Windows/HotkeyItem.xaml.cs @@ -33,7 +33,7 @@ namespace Ink_Canvas.Windows public string DefaultKey { get; set; } public string DefaultModifiers { get; set; } - + /// /// 快捷键名称(用于标识,如"Undo") /// @@ -94,10 +94,10 @@ namespace Ink_Canvas.Windows { BtnSetHotkey.Content = "请按键..."; BtnSetHotkey.Background = Brushes.Orange; - + // 设置焦点以捕获键盘事件 Focus(); - + // 添加键盘事件处理器 KeyDown += HotkeyItem_KeyDown; KeyUp += HotkeyItem_KeyUp; @@ -107,7 +107,7 @@ namespace Ink_Canvas.Windows { BtnSetHotkey.Content = "设置"; BtnSetHotkey.Background = Brushes.DodgerBlue; - + // 移除键盘事件处理器 KeyDown -= HotkeyItem_KeyDown; KeyUp -= HotkeyItem_KeyUp; @@ -116,7 +116,7 @@ namespace Ink_Canvas.Windows private void HotkeyItem_KeyDown(object sender, KeyEventArgs e) { e.Handled = true; - + // 忽略某些特殊键 if (e.Key == Key.LeftShift || e.Key == Key.RightShift || e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl || @@ -140,10 +140,10 @@ namespace Ink_Canvas.Windows // 设置新的快捷键 var oldKey = _currentKey; var oldModifiers = _currentModifiers; - + _currentKey = e.Key; _currentModifiers = modifiers; - + UpdateHotkeyDisplay(); StopHotkeyCapture(); @@ -169,4 +169,4 @@ namespace Ink_Canvas.Windows } #endregion } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Windows/HotkeySettingsWindow.xaml.cs b/Ink Canvas/Windows/HotkeySettingsWindow.xaml.cs index b21ee2c5..f4d1895e 100644 --- a/Ink Canvas/Windows/HotkeySettingsWindow.xaml.cs +++ b/Ink Canvas/Windows/HotkeySettingsWindow.xaml.cs @@ -1,10 +1,10 @@ +using Ink_Canvas.Helpers; using System; using System.Collections.Generic; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Ink_Canvas.Helpers; namespace Ink_Canvas.Windows { @@ -30,15 +30,15 @@ namespace Ink_Canvas.Windows // 隐藏主窗口的设置页面 HideMainWindowSettings(); InitializeHotkeyItems(); - + // 延迟加载快捷键,确保快捷键管理器已完全初始化 - Loaded += (s, e) => + Loaded += (s, e) => { try { // 不启用快捷键注册功能,只读取配置文件中的快捷键信息用于显示 // 这样用户可以看到配置文件中保存的快捷键,但不会自动注册 - + // 加载当前快捷键(包括配置文件中的) LoadCurrentHotkeys(); SetupEventHandlers(); @@ -60,62 +60,62 @@ namespace Ink_Canvas.Windows try { LogHelper.WriteLogToFile("开始初始化快捷键项"); - + // 初始化快捷键项并设置HotkeyName _hotkeyItems["Undo"] = UndoHotkey; UndoHotkey.HotkeyName = "Undo"; - + _hotkeyItems["Redo"] = RedoHotkey; RedoHotkey.HotkeyName = "Redo"; - + _hotkeyItems["Clear"] = ClearHotkey; ClearHotkey.HotkeyName = "Clear"; - + _hotkeyItems["Paste"] = PasteHotkey; PasteHotkey.HotkeyName = "Paste"; - + _hotkeyItems["SelectTool"] = SelectToolHotkey; SelectToolHotkey.HotkeyName = "SelectTool"; - + _hotkeyItems["DrawTool"] = DrawToolHotkey; DrawToolHotkey.HotkeyName = "DrawTool"; - + _hotkeyItems["EraserTool"] = EraserToolHotkey; EraserToolHotkey.HotkeyName = "EraserTool"; - + _hotkeyItems["BlackboardTool"] = BlackboardToolHotkey; BlackboardToolHotkey.HotkeyName = "BlackboardTool"; - + _hotkeyItems["QuitDrawTool"] = QuitDrawToolHotkey; QuitDrawToolHotkey.HotkeyName = "QuitDrawTool"; - + _hotkeyItems["Pen1"] = Pen1Hotkey; Pen1Hotkey.HotkeyName = "Pen1"; - + _hotkeyItems["Pen2"] = Pen2Hotkey; Pen2Hotkey.HotkeyName = "Pen2"; - + _hotkeyItems["Pen3"] = Pen3Hotkey; Pen3Hotkey.HotkeyName = "Pen3"; - + _hotkeyItems["Pen4"] = Pen4Hotkey; Pen4Hotkey.HotkeyName = "Pen4"; - + _hotkeyItems["Pen5"] = Pen5Hotkey; Pen5Hotkey.HotkeyName = "Pen5"; - + _hotkeyItems["DrawLine"] = DrawLineHotkey; DrawLineHotkey.HotkeyName = "DrawLine"; - + _hotkeyItems["Screenshot"] = ScreenshotHotkey; ScreenshotHotkey.HotkeyName = "Screenshot"; - + _hotkeyItems["Hide"] = HideHotkey; HideHotkey.HotkeyName = "Hide"; - + _hotkeyItems["Exit"] = ExitHotkey; ExitHotkey.HotkeyName = "Exit"; - + LogHelper.WriteLogToFile($"成功初始化 {_hotkeyItems.Count} 个快捷键项"); } catch (Exception ex) @@ -131,7 +131,7 @@ namespace Ink_Canvas.Windows // 首先尝试从配置文件获取快捷键信息 var configHotkeys = _hotkeyManager.GetHotkeysFromConfigFile(); LogHelper.WriteLogToFile($"配置文件中的快捷键数量: {configHotkeys.Count}"); - + // 显示配置文件中的快捷键 foreach (var hotkey in configHotkeys) { @@ -141,7 +141,7 @@ namespace Ink_Canvas.Windows LogHelper.WriteLogToFile($"从配置文件设置快捷键项: {hotkey.Name} -> {hotkey.Modifiers}+{hotkey.Key}"); } } - + // 为没有快捷键的项目设置默认显示值(仅用于UI显示,不实际注册) foreach (var kvp in _hotkeyItems) { @@ -246,11 +246,11 @@ namespace Ink_Canvas.Windows try { LogHelper.WriteLogToFile($"收到快捷键变更事件: {e.HotkeyName} -> {e.Modifiers}+{e.Key}"); - + // 检查快捷键冲突 if (IsHotkeyConflict(e.Key, e.Modifiers, e.HotkeyName)) { - MessageBox.Show($"快捷键 {e.Modifiers}+{e.Key} 已被其他功能使用,请选择其他组合。", + MessageBox.Show($"快捷键 {e.Modifiers}+{e.Key} 已被其他功能使用,请选择其他组合。", "快捷键冲突", MessageBoxButton.OK, MessageBoxImage.Warning); return; } @@ -270,14 +270,14 @@ namespace Ink_Canvas.Windows var registeredHotkeys = _hotkeyManager.GetRegisteredHotkeys(); foreach (var hotkey in registeredHotkeys) { - if (hotkey.Name != excludeHotkeyName && - hotkey.Key == key && + if (hotkey.Name != excludeHotkeyName && + hotkey.Key == key && hotkey.Modifiers == modifiers) { return true; } } - + // 检查是否与默认快捷键冲突(如果当前快捷键项还没有注册) if (excludeHotkeyName != null && _hotkeyItems.TryGetValue(excludeHotkeyName, out var currentItem)) { @@ -299,7 +299,7 @@ namespace Ink_Canvas.Windows } } } - + return false; } @@ -308,30 +308,30 @@ namespace Ink_Canvas.Windows try { LogHelper.WriteLogToFile($"开始更新快捷键: {hotkeyName} -> {modifiers}+{key}"); - + // 先注销原有的快捷键(如果存在) _hotkeyManager.UnregisterHotkey(hotkeyName); LogHelper.WriteLogToFile($"已注销原有快捷键: {hotkeyName}"); - + // 根据快捷键名称获取对应的动作 var action = GetActionForHotkey(hotkeyName); if (action != null) { LogHelper.WriteLogToFile($"找到快捷键动作: {hotkeyName}"); - + // 直接注册新的快捷键 if (_hotkeyManager.RegisterHotkey(hotkeyName, key, modifiers, action)) { LogHelper.WriteLogToFile($"成功注册新快捷键: {hotkeyName} -> {modifiers}+{key}"); - + // 立即保存到配置文件 _hotkeyManager.SaveHotkeysToSettings(); LogHelper.WriteLogToFile("已保存快捷键配置"); - + // 更新UI显示 LoadCurrentHotkeys(); LogHelper.WriteLogToFile("已更新UI显示"); - + LogHelper.WriteLogToFile($"快捷键 {hotkeyName} 已更新为 {modifiers}+{key} 并保存", LogHelper.LogType.Event); } else @@ -404,17 +404,17 @@ namespace Ink_Canvas.Windows try { // 通过反射访问主窗口的penType字段 - var penTypeField = _mainWindow.GetType().GetField("penType", + var penTypeField = _mainWindow.GetType().GetField("penType", BindingFlags.NonPublic | BindingFlags.Instance); - + if (penTypeField != null) { penTypeField.SetValue(_mainWindow, penTypeIndex); - + // 调用CheckPenTypeUIState方法更新UI状态 - var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState", + var checkPenTypeMethod = _mainWindow.GetType().GetMethod("CheckPenTypeUIState", BindingFlags.NonPublic | BindingFlags.Instance); - + if (checkPenTypeMethod != null) { checkPenTypeMethod.Invoke(_mainWindow, null); @@ -437,18 +437,18 @@ namespace Ink_Canvas.Windows try { // 通过反射访问主窗口的设置面板 - var settingsBorder = _mainWindow.GetType().GetField("BorderSettings", + var settingsBorder = _mainWindow.GetType().GetField("BorderSettings", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(_mainWindow) as Border; - + if (settingsBorder != null) { settingsBorder.Visibility = Visibility.Collapsed; } // 隐藏设置蒙版 - var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask", + var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(_mainWindow) as Border; - + if (settingsMask != null) { settingsMask.Visibility = Visibility.Collapsed; @@ -468,18 +468,18 @@ namespace Ink_Canvas.Windows try { // 通过反射访问主窗口的设置面板 - var settingsBorder = _mainWindow.GetType().GetField("BorderSettings", + var settingsBorder = _mainWindow.GetType().GetField("BorderSettings", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(_mainWindow) as Border; - + if (settingsBorder != null) { settingsBorder.Visibility = Visibility.Visible; } // 显示设置蒙版 - var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask", + var settingsMask = _mainWindow.GetType().GetField("BorderSettingsMask", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(_mainWindow) as Border; - + if (settingsMask != null) { settingsMask.Visibility = Visibility.Visible; @@ -513,22 +513,22 @@ namespace Ink_Canvas.Windows { try { - var result = MessageBox.Show("确定要重置所有快捷键为默认设置吗?", + var result = MessageBox.Show("确定要重置所有快捷键为默认设置吗?", "确认重置", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { // 先注销所有现有快捷键 _hotkeyManager.UnregisterAllHotkeys(); - + // 重置为默认快捷键 _hotkeyManager.RegisterDefaultHotkeys(); - + // 立即保存到配置文件 _hotkeyManager.SaveHotkeysToSettings(); - + // 更新UI显示 LoadCurrentHotkeys(); - + MessageBox.Show("快捷键已重置为默认设置。", "重置完成", MessageBoxButton.OK, MessageBoxImage.Information); } } @@ -545,7 +545,7 @@ namespace Ink_Canvas.Windows { // 保存快捷键配置 _hotkeyManager.SaveHotkeysToSettings(); - + MessageBox.Show("快捷键设置已保存。", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information); Close(); } @@ -569,4 +569,4 @@ namespace Ink_Canvas.Windows public ModifierKeys Modifiers { get; set; } } #endregion -} \ No newline at end of file +} \ No newline at end of file diff --git a/Ink Canvas/Windows/NamesInputWindow.xaml.cs b/Ink Canvas/Windows/NamesInputWindow.xaml.cs index 9e9a637a..ab020adc 100644 --- a/Ink Canvas/Windows/NamesInputWindow.xaml.cs +++ b/Ink Canvas/Windows/NamesInputWindow.xaml.cs @@ -1,7 +1,7 @@ -using System.ComponentModel; +using Ink_Canvas.Helpers; +using System.ComponentModel; using System.IO; using System.Windows; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/Windows/OperatingGuideWindow.xaml.cs b/Ink Canvas/Windows/OperatingGuideWindow.xaml.cs index 566ab053..68db15de 100644 --- a/Ink Canvas/Windows/OperatingGuideWindow.xaml.cs +++ b/Ink Canvas/Windows/OperatingGuideWindow.xaml.cs @@ -1,6 +1,6 @@ -using System.Windows; +using Ink_Canvas.Helpers; +using System.Windows; using System.Windows.Input; -using Ink_Canvas.Helpers; namespace Ink_Canvas { diff --git a/Ink Canvas/Windows/PluginSettingsWindow.xaml.cs b/Ink Canvas/Windows/PluginSettingsWindow.xaml.cs index 96395e9b..cdaecc4e 100644 --- a/Ink Canvas/Windows/PluginSettingsWindow.xaml.cs +++ b/Ink Canvas/Windows/PluginSettingsWindow.xaml.cs @@ -1,3 +1,9 @@ +using Ink_Canvas.Helpers; +using Ink_Canvas.Helpers.Plugins; +using Ink_Canvas.Helpers.Plugins.BuiltIn; +using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher; +using iNKORE.UI.WPF.Modern.Controls; +using Microsoft.Win32; using System; using System.Collections.ObjectModel; using System.ComponentModel; @@ -6,12 +12,6 @@ using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; -using Ink_Canvas.Helpers; -using Ink_Canvas.Helpers.Plugins; -using Ink_Canvas.Helpers.Plugins.BuiltIn; -using Ink_Canvas.Helpers.Plugins.BuiltIn.SuperLauncher; -using iNKORE.UI.WPF.Modern.Controls; -using Microsoft.Win32; using MessageBox = System.Windows.MessageBox; namespace Ink_Canvas.Windows diff --git a/Ink Canvas/Windows/RandWindow.xaml.cs b/Ink Canvas/Windows/RandWindow.xaml.cs index c4e07ac7..26810734 100644 --- a/Ink Canvas/Windows/RandWindow.xaml.cs +++ b/Ink Canvas/Windows/RandWindow.xaml.cs @@ -1,4 +1,6 @@ -using System; +using Ink_Canvas.Helpers; +using Microsoft.VisualBasic; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -8,8 +10,6 @@ using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; -using Ink_Canvas.Helpers; -using Microsoft.VisualBasic; using MessageBox = iNKORE.UI.WPF.Modern.Controls.MessageBox; namespace Ink_Canvas diff --git a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs index 454a79e3..1dab3dc2 100644 --- a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs +++ b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs @@ -81,7 +81,7 @@ namespace Ink_Canvas private void BindControlPointEvents() { // 绑定所有控制点的鼠标事件 - var controlPoints = new[] + var controlPoints = new[] { TopLeftControl, TopRightControl, BottomLeftControl, BottomRightControl, TopControl, BottomControl, LeftControl, RightControl @@ -92,11 +92,11 @@ namespace Ink_Canvas control.MouseLeftButtonDown += ControlPoint_MouseLeftButtonDown; control.MouseLeftButtonUp += ControlPoint_MouseLeftButtonUp; control.MouseMove += ControlPoint_MouseMove; - + // 确保控制点能够接收鼠标事件 control.IsHitTestVisible = true; control.Focusable = false; - + // 设置控制点的Z-index,确保它们在最上层 WpfCanvas.SetZIndex(control, 1003); } @@ -142,7 +142,7 @@ namespace Ink_Canvas { // 重置所有选择状态 ResetSelectionState(); - + _isFreehandMode = false; RectangleModeButton.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235)); // 蓝色 FreehandModeButton.Background = new SolidColorBrush(Color.FromRgb(107, 114, 128)); // 灰色 @@ -154,7 +154,7 @@ namespace Ink_Canvas { // 重置所有选择状态 ResetSelectionState(); - + _isFreehandMode = true; FreehandModeButton.Background = new SolidColorBrush(Color.FromRgb(37, 99, 235)); // 蓝色 RectangleModeButton.Background = new SolidColorBrush(Color.FromRgb(107, 114, 128)); // 灰色 @@ -169,7 +169,7 @@ namespace Ink_Canvas { return; } - + ConfirmSelection(); } @@ -183,10 +183,10 @@ namespace Ink_Canvas // 检查是否点击了UI元素,如果是则不处理选择 var hitElement = e.Source as FrameworkElement; if (hitElement != null && ( - hitElement is Ellipse || - hitElement is System.Windows.Controls.Button || - hitElement is Border || - hitElement is TextBlock || + hitElement is Ellipse || + hitElement is System.Windows.Controls.Button || + hitElement is Border || + hitElement is TextBlock || hitElement is StackPanel || hitElement is Separator || hitElement.Name == "SizeInfoBorder" || @@ -221,7 +221,7 @@ namespace Ink_Canvas _freehandPolyline.Points.Clear(); _freehandPoints.Add(_startPoint); _freehandPolyline.Points.Add(_startPoint); - + // 确保自由绘制路径可见 _freehandPolyline.Visibility = Visibility.Visible; } @@ -252,7 +252,7 @@ namespace Ink_Canvas // 自由绘制模式:添加点到路径 _freehandPoints.Add(_currentPoint); _freehandPolyline.Points.Add(_currentPoint); - + // 确保自由绘制路径可见 _freehandPolyline.Visibility = Visibility.Visible; } @@ -278,7 +278,7 @@ namespace Ink_Canvas { // 创建路径的副本,避免修改原始列表 var pathPoints = new List(_freehandPoints); - + // 简化路径处理,不强制闭合 // 如果路径没有闭合,自动添加起始点 if (pathPoints.Count > 0) @@ -288,13 +288,13 @@ namespace Ink_Canvas // 优化路径:移除重复点和过于接近的点,提高路径质量 var optimizedPath = OptimizePath(pathPoints); - + // 保存选择的路径 SelectedPath = optimizedPath; // 计算边界矩形用于截图 var bounds = CalculatePathBounds(optimizedPath); - + // 确保边界矩形有效 if (bounds.Width >= 0 && bounds.Height >= 0) { @@ -312,7 +312,7 @@ namespace Ink_Canvas return; } } - + // 如果自由绘制失败,清除路径并继续 _freehandPoints.Clear(); _freehandPolyline.Points.Clear(); @@ -350,7 +350,7 @@ namespace Ink_Canvas _isMoving = true; _lastMousePosition = e.GetPosition(this); - + // 确定当前控制点类型 var ellipse = sender as Ellipse; if (ellipse == TopLeftControl) _activeControlPoint = ControlPointType.TopLeft; @@ -467,26 +467,26 @@ namespace Ink_Canvas // 更新角控制点位置 WpfCanvas.SetLeft(TopLeftControl, rect.Left - 4); WpfCanvas.SetTop(TopLeftControl, rect.Top - 4); - + WpfCanvas.SetLeft(TopRightControl, rect.Right - 4); WpfCanvas.SetTop(TopRightControl, rect.Top - 4); - + WpfCanvas.SetLeft(BottomLeftControl, rect.Left - 4); WpfCanvas.SetTop(BottomLeftControl, rect.Bottom - 4); - + WpfCanvas.SetLeft(BottomRightControl, rect.Right - 4); WpfCanvas.SetTop(BottomRightControl, rect.Bottom - 4); // 更新边控制点位置 WpfCanvas.SetLeft(TopControl, rect.Left + rect.Width / 2 - 4); WpfCanvas.SetTop(TopControl, rect.Top - 4); - + WpfCanvas.SetLeft(BottomControl, rect.Left + rect.Width / 2 - 4); WpfCanvas.SetTop(BottomControl, rect.Bottom - 4); - + WpfCanvas.SetLeft(LeftControl, rect.Left - 4); WpfCanvas.SetTop(LeftControl, rect.Top + rect.Height / 2 - 4); - + WpfCanvas.SetLeft(RightControl, rect.Right - 4); WpfCanvas.SetTop(RightControl, rect.Top + rect.Height / 2 - 4); } @@ -522,7 +522,7 @@ namespace Ink_Canvas { // 更新选择区域的几何体 SelectionClipGeometry.Rect = selectionRect; - + // 显示透明遮罩,隐藏原始遮罩 TransparentSelectionMask.Visibility = Visibility.Visible; OverlayRectangle.Visibility = Visibility.Collapsed; @@ -580,7 +580,7 @@ namespace Ink_Canvas { return; } - + if (_isAdjusting) { // 转换为屏幕坐标,考虑DPI缩放 @@ -701,29 +701,29 @@ namespace Ink_Canvas _isAdjusting = false; _isMoving = false; _activeControlPoint = ControlPointType.None; - + // 清除自由绘制的内容 _freehandPoints.Clear(); _freehandPolyline.Points.Clear(); _freehandPolyline.Visibility = Visibility.Collapsed; - + // 清除矩形选择的内容 SelectionRectangle.Visibility = Visibility.Collapsed; ControlPointsCanvas.Visibility = Visibility.Collapsed; SizeInfoBorder.Visibility = Visibility.Collapsed; SelectionPath.Visibility = Visibility.Collapsed; AdjustModeHint.Visibility = Visibility.Collapsed; - + // 重置遮罩 TransparentSelectionMask.Visibility = Visibility.Collapsed; OverlayRectangle.Visibility = Visibility.Visible; - + // 释放鼠标捕获 if (IsMouseCaptured) { ReleaseMouseCapture(); } - + // 重置选择区域 _currentSelection = new Rect(); SelectedArea = null; diff --git a/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache b/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache index 09499edb3a752fe8c5fb554f321725a922732760..e30091c894a532a9d72b5db5c6031ca33407681b 100644 GIT binary patch delta 2768 zcmcK6O>7%Q6aZk4)jd0 zvzx?FDJ_ReAQ4f9ie8W`gg92HtKJZSGY2lYa46!y2?+!eQX>@!X4g1BcvIC?bFnSY zdfw+ZZ)V=c)!=VD*c}Eh1p)yeb2&15ZGLfZJTY3FWw^$Qxf(9ZDlR2xO)H+Is%>Io zvEqboP1*{d4?lJ7@1F42KYi1)`~yD(VmXj0>joZ02qi|5HwD@`1=^YdHK#x-HBFo7 zRvjftr(;^;*CBxvavF9BPJR2OGd~j25n#v_ybAJzj_+z&YtP9_rZhj}& z$6o}8r$O$~D7WLdPOgD9=c~}CU~uArtuKT>pK)>g{cyh$bQfV&yo4@`58@qUAB}TP zC*$W@>GYV@gV)bUZ}~F$GpVa@d(n4MwEI&au{CU=s;pLI4KpM!$p$63q+93&9D)(} zas(N=f(W+aCt`@FQ%CtJcHH?f^-D-H{2?3J>j3c0p1vucO8S4m1-VvIX$f19P)je@ zb(IphTrHz0jKb~MBO>;pT%Q-ak(=t06#v*zImutir&rq(aj~;R=%nJ-vaP!qXbNGC zAdwCj8`(<8a171VnT1VQkPRE>?W*BbKWOmNY=E!l?@DAZ<~aZT!a<%cbo2hg#6mlF zX+HlHpTV^POo-U9C|@%N7*{sbWd8!c1FeF0?$u==P5VpOyTojloPQ{ZcNy)enG=`8fBg=>S6_3! zytEmV^8TvZtBd^GdT4cbuTbnvMcI;Q@N{uUuUPF#%FYy;qhl+U>+;%>07&foo~JLb xOY{E3{wp780Cy&0%_~qe4mP&jD-gw@*pNuHpkCWB;(tkct=D?~Lyq4o{|o;IjK%-} delta 953 zcmaDmndwR!69*fk9s>gdW8&lh$;F*9$n0lUOxUPfNF zUy+6Tw``lNz-YwCFnJ-r>gMB&a!g|8I5mm;A%Y{*_K&$ zvMr-1#FWX$8T&RDu})_cGs9()8e70#u+=f_N|UAd1(7sP=9uavp5Sa16Iz^FR2<`& zlAD>ASzJ<-Sdw2f+0MI72xu<@V?B^yX#g^SG{ou2K2KQ0b8+a44V;RwX7jutUuN-S z97-9(S|-PKKwPwW^49Q7@qC;rEhcYB<(s@Ff`4*nggcT2b&(%g#M209J00hO&@#C$ zvTw6ff&!~}JYH=saJQ*~wJ4+mz2b#k%cKJF$+NON5teMu$*yA&kHV$80-O4FCWD From cdcb2d2af0a00f6fe5e8138da09d62310e8227e6 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 31 Aug 2025 11:49:00 +0800 Subject: [PATCH 04/10] =?UTF-8?q?add:=E6=96=87=E4=BB=B6=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/App.xaml.cs | 46 ++- Ink Canvas/Helpers/FileAssociationManager.cs | 380 ++++++++++++++++++ Ink Canvas/MainWindow.xaml.cs | 40 ++ .../MainWindow_cs/MW_Save&OpenStrokes.cs | 2 +- 4 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 Ink Canvas/Helpers/FileAssociationManager.cs diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index b662a247..0808e85a 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -633,7 +633,28 @@ namespace Ink_Canvas if (!ret && !e.Args.Contains("-m")) //-m multiple { LogHelper.NewLog("Detected existing instance"); - MessageBox.Show("已有一个程序实例正在运行"); + + // 检查是否有.icstk文件参数 + string icstkFile = FileAssociationManager.GetIcstkFileFromArgs(e.Args); + if (!string.IsNullOrEmpty(icstkFile)) + { + LogHelper.WriteLogToFile($"检测到已运行实例,尝试通过IPC发送文件: {icstkFile}", LogHelper.LogType.Event); + + // 尝试通过IPC发送文件路径给已运行实例 + if (FileAssociationManager.TrySendFileToExistingInstance(icstkFile)) + { + LogHelper.WriteLogToFile("文件路径已通过IPC发送给已运行实例", LogHelper.LogType.Event); + } + else + { + LogHelper.WriteLogToFile("通过IPC发送文件路径失败", LogHelper.LogType.Warning); + } + } + else + { + LogHelper.WriteLogToFile("检测到已运行实例,但无文件参数", LogHelper.LogType.Event); + } + LogHelper.NewLog("Ink Canvas automatically closed"); IsAppExitByUser = true; // 多开时标记为用户主动退出 // 写入退出信号,确保看门狗不会重启 @@ -687,6 +708,29 @@ namespace Ink_Canvas MainWindow = mainWindow; mainWindow.Show(); + // 新增:注册.icstk文件关联 + try + { + LogHelper.WriteLogToFile("开始注册.icstk文件关联"); + FileAssociationManager.RegisterFileAssociation(); + FileAssociationManager.ShowFileAssociationStatus(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注册文件关联时出错: {ex.Message}", LogHelper.LogType.Error); + } + + // 新增:启动IPC监听器 + try + { + LogHelper.WriteLogToFile("启动IPC监听器"); + FileAssociationManager.StartIpcListener(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"启动IPC监听器时出错: {ex.Message}", LogHelper.LogType.Error); + } + // 新增:Office注册表检测 try { diff --git a/Ink Canvas/Helpers/FileAssociationManager.cs b/Ink Canvas/Helpers/FileAssociationManager.cs new file mode 100644 index 00000000..e950e521 --- /dev/null +++ b/Ink Canvas/Helpers/FileAssociationManager.cs @@ -0,0 +1,380 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Security; +using System.Windows; +using Microsoft.Win32; +using System.Threading; +using System.Text; + +namespace Ink_Canvas.Helpers +{ + /// + /// 文件关联管理器,用于注册和处理.icstk文件的关联 + /// + public static class FileAssociationManager + { + private const string FileExtension = ".icstk"; + private const string FileTypeName = "InkCanvasStrokesFile"; + private const string AppName = "Ink Canvas"; + private const string AppDescription = "Ink Canvas Strokes File"; + + // IPC相关常量 + private const string IpcMutexName = "InkCanvasFileAssociationIpc"; + private const string IpcEventName = "InkCanvasFileAssociationEvent"; + private const string IpcFilePrefix = "InkCanvasFileAssociation_"; + private const int IpcTimeout = 5000; // 5秒超时 + + /// + /// 注册.icstk文件关联 + /// + public static bool RegisterFileAssociation() + { + try + { + string exePath = Process.GetCurrentProcess().MainModule.FileName; + + // 注册文件类型 + using (RegistryKey fileTypeKey = Registry.ClassesRoot.CreateSubKey(FileTypeName)) + { + fileTypeKey.SetValue("", AppDescription); + fileTypeKey.SetValue("FriendlyTypeName", AppDescription); + + // 设置默认图标 + using (RegistryKey defaultIconKey = fileTypeKey.CreateSubKey("DefaultIcon")) + { + defaultIconKey.SetValue("", $"\"{exePath}\",0"); + } + + // 设置打开命令 + using (RegistryKey shellKey = fileTypeKey.CreateSubKey("shell")) + using (RegistryKey openKey = shellKey.CreateSubKey("open")) + using (RegistryKey commandKey = openKey.CreateSubKey("command")) + { + commandKey.SetValue("", $"\"{exePath}\" \"%1\""); + } + } + + // 注册文件扩展名 + using (RegistryKey extensionKey = Registry.ClassesRoot.CreateSubKey(FileExtension)) + { + extensionKey.SetValue("", FileTypeName); + } + + // 刷新系统文件关联缓存 + RefreshSystemFileAssociations(); + + LogHelper.WriteLogToFile($"成功注册{FileExtension}文件关联", LogHelper.LogType.Event); + return true; + } + catch (SecurityException ex) + { + LogHelper.WriteLogToFile($"注册文件关联时权限不足: {ex.Message}", LogHelper.LogType.Error); + return false; + } + catch (UnauthorizedAccessException ex) + { + LogHelper.WriteLogToFile($"注册文件关联时访问被拒绝: {ex.Message}", LogHelper.LogType.Error); + return false; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注册文件关联时出错: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + /// + /// 注销.icstk文件关联 + /// + public static bool UnregisterFileAssociation() + { + try + { + // 删除文件扩展名关联 + Registry.ClassesRoot.DeleteSubKeyTree(FileExtension, false); + + // 删除文件类型定义 + Registry.ClassesRoot.DeleteSubKeyTree(FileTypeName, false); + + // 刷新系统文件关联缓存 + RefreshSystemFileAssociations(); + + LogHelper.WriteLogToFile($"成功注销{FileExtension}文件关联", LogHelper.LogType.Event); + return true; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"注销文件关联时出错: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + /// + /// 检查文件关联是否已注册 + /// + public static bool IsFileAssociationRegistered() + { + try + { + using (RegistryKey extensionKey = Registry.ClassesRoot.OpenSubKey(FileExtension)) + { + if (extensionKey == null) return false; + + string fileType = extensionKey.GetValue("") as string; + if (string.IsNullOrEmpty(fileType)) return false; + + using (RegistryKey fileTypeKey = Registry.ClassesRoot.OpenSubKey(fileType)) + { + if (fileTypeKey == null) return false; + + using (RegistryKey shellKey = fileTypeKey.OpenSubKey("shell\\open\\command")) + { + if (shellKey == null) return false; + + string command = shellKey.GetValue("") as string; + if (string.IsNullOrEmpty(command)) return false; + + // 检查命令是否指向当前应用程序 + string currentExePath = Process.GetCurrentProcess().MainModule.FileName; + return command.Contains(currentExePath); + } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"检查文件关联状态时出错: {ex.Message}", LogHelper.LogType.Error); + } + + return false; + } + + /// + /// 显示文件关联状态 + /// + public static void ShowFileAssociationStatus() + { + bool isRegistered = IsFileAssociationRegistered(); + LogHelper.WriteLogToFile($"{FileExtension}文件关联状态: {(isRegistered ? "已注册" : "未注册")}", LogHelper.LogType.Event); + } + + /// + /// 刷新系统文件关联缓存 + /// + private static void RefreshSystemFileAssociations() + { + try + { + // 通知系统文件关联已更改 + SHChangeNotify(0x08000000, 0, IntPtr.Zero, IntPtr.Zero); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"刷新文件关联缓存时出错: {ex.Message}", LogHelper.LogType.Warning); + } + } + + /// + /// 处理命令行参数中的文件路径 + /// + /// 命令行参数 + /// 找到的.icstk文件路径,如果没有找到则返回null + public static string GetIcstkFileFromArgs(string[] args) + { + if (args == null || args.Length == 0) return null; + + foreach (string arg in args) + { + if (string.IsNullOrEmpty(arg)) continue; + + // 检查是否为.icstk文件 + if (Path.GetExtension(arg).Equals(FileExtension, StringComparison.OrdinalIgnoreCase)) + { + // 检查文件是否存在 + if (File.Exists(arg)) + { + LogHelper.WriteLogToFile($"从命令行参数中找到.icstk文件: {arg}", LogHelper.LogType.Event); + return arg; + } + else + { + LogHelper.WriteLogToFile($"命令行参数中的.icstk文件不存在: {arg}", LogHelper.LogType.Warning); + } + } + } + + return null; + } + + /// + /// 尝试通过IPC将文件路径发送给已运行的实例 + /// + /// 要打开的文件路径 + /// 是否成功发送 + public static bool TrySendFileToExistingInstance(string filePath) + { + try + { + LogHelper.WriteLogToFile($"尝试通过IPC发送文件路径给已运行实例: {filePath}", LogHelper.LogType.Event); + + // 创建IPC文件 + string tempDir = Path.GetTempPath(); + string ipcFileName = IpcFilePrefix + Guid.NewGuid().ToString("N") + ".tmp"; + string ipcFilePath = Path.Combine(tempDir, ipcFileName); + + // 写入文件路径到IPC文件 + File.WriteAllText(ipcFilePath, filePath, Encoding.UTF8); + + // 创建事件通知已运行实例 + using (EventWaitHandle ipcEvent = new EventWaitHandle(false, EventResetMode.ManualReset, IpcEventName)) + { + ipcEvent.Set(); + } + + // 等待一段时间让已运行实例处理文件 + Thread.Sleep(1000); + + // 清理IPC文件 + try + { + if (File.Exists(ipcFilePath)) + { + File.Delete(ipcFilePath); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"清理IPC文件失败: {ex.Message}", LogHelper.LogType.Warning); + } + + LogHelper.WriteLogToFile("IPC文件路径发送完成", LogHelper.LogType.Event); + return true; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"通过IPC发送文件路径失败: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + /// + /// 启动IPC监听器,等待其他实例发送文件路径 + /// + public static void StartIpcListener() + { + try + { + Thread ipcThread = new Thread(() => + { + try + { + LogHelper.WriteLogToFile("启动IPC监听器", LogHelper.LogType.Event); + + using (EventWaitHandle ipcEvent = new EventWaitHandle(false, EventResetMode.ManualReset, IpcEventName)) + { + while (true) + { + // 等待IPC事件 + if (ipcEvent.WaitOne(IpcTimeout)) + { + // 处理IPC文件 + ProcessIpcFiles(); + + // 重置事件 + ipcEvent.Reset(); + } + + // 检查应用是否还在运行 + if (Application.Current == null || Application.Current.Dispatcher == null) + { + break; + } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"IPC监听器出错: {ex.Message}", LogHelper.LogType.Error); + } + }); + + ipcThread.IsBackground = true; + ipcThread.Start(); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"启动IPC监听器失败: {ex.Message}", LogHelper.LogType.Error); + } + } + + /// + /// 处理IPC文件 + /// + private static void ProcessIpcFiles() + { + try + { + string tempDir = Path.GetTempPath(); + string[] ipcFiles = Directory.GetFiles(tempDir, IpcFilePrefix + "*.tmp"); + + foreach (string ipcFile in ipcFiles) + { + try + { + // 读取文件路径 + string filePath = File.ReadAllText(ipcFile, Encoding.UTF8); + + if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath)) + { + LogHelper.WriteLogToFile($"IPC接收到文件路径: {filePath}", LogHelper.LogType.Event); + + // 在UI线程中处理文件打开 + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + try + { + // 获取主窗口并打开文件 + if (Application.Current.MainWindow is MainWindow mainWindow) + { + mainWindow.OpenSingleStrokeFile(filePath); + mainWindow.ShowNotification($"已加载墨迹文件: {Path.GetFileName(filePath)}"); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"IPC处理文件打开失败: {ex.Message}", LogHelper.LogType.Error); + } + })); + } + + // 删除IPC文件 + File.Delete(ipcFile); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"处理IPC文件失败: {ex.Message}", LogHelper.LogType.Warning); + + // 尝试删除损坏的IPC文件 + try + { + if (File.Exists(ipcFile)) + { + File.Delete(ipcFile); + } + } + catch { } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"处理IPC文件时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + [DllImport("shell32.dll")] + private static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); + } +} \ No newline at end of file diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index c3ace02e..e3185c6f 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -523,6 +523,9 @@ namespace Ink_Canvas // 初始化墨迹渐隐管理器 InitializeInkFadeManager(); + + // 处理命令行参数中的文件路径 + HandleCommandLineFileOpen(); } private void SystemEventsOnDisplaySettingsChanged(object sender, EventArgs e) @@ -2126,6 +2129,43 @@ namespace Ink_Canvas } #endregion + /// + /// 处理命令行参数中的文件路径 + /// + private void HandleCommandLineFileOpen() + { + try + { + // 检查启动参数中是否有.icstk文件 + string icstkFile = FileAssociationManager.GetIcstkFileFromArgs(App.StartArgs); + + if (!string.IsNullOrEmpty(icstkFile)) + { + LogHelper.WriteLogToFile($"检测到命令行参数中的.icstk文件: {icstkFile}", LogHelper.LogType.Event); + + // 延迟执行,确保UI已完全加载 + Dispatcher.BeginInvoke(new Action(() => + { + try + { + // 打开文件 + OpenSingleStrokeFile(icstkFile); + ShowNotification($"已加载墨迹文件: {Path.GetFileName(icstkFile)}"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"打开命令行参数中的文件失败: {ex.Message}", LogHelper.LogType.Error); + ShowNotification("打开墨迹文件失败"); + } + }), DispatcherPriority.Loaded); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"处理命令行文件打开时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + /// /// 集中管理工具模式切换和快捷键状态更新 /// 避免在每个工具按钮点击时重复刷新快捷键状态 diff --git a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs index fb242d97..b2b0d2a6 100644 --- a/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs +++ b/Ink Canvas/MainWindow_cs/MW_Save&OpenStrokes.cs @@ -643,7 +643,7 @@ namespace Ink_Canvas /// /// 打开单个墨迹文件 /// - private void OpenSingleStrokeFile(string filePath) + public void OpenSingleStrokeFile(string filePath) { var fileStreamHasNoStroke = false; using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) From 147b4fc5edb60faae8cbeae878ad6bdabf489e41 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 31 Aug 2025 12:03:58 +0800 Subject: [PATCH 05/10] =?UTF-8?q?improve:=E6=96=87=E4=BB=B6=E5=85=B3?= =?UTF-8?q?=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 20 +++++++ Ink Canvas/MainWindow.xaml.cs | 30 ++++++++++ Ink Canvas/MainWindow_cs/MW_Settings.cs | 80 +++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 00b1ac61..42bc95ac 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -2659,6 +2659,26 @@ + + + +