The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitattributes
├── .gitignore
├── ClickShow.sln
├── ClickShow.sln.DotSettings
├── ClickShow
    ├── App.xaml
    ├── App.xaml.cs
    ├── ClickShow.csproj
    ├── ClickShow.csproj.DotSettings
    ├── Entities
    │   └── MouseButtonState.cs
    ├── MouseHook
    │   ├── GlobalHook.cs
    │   ├── HookType.cs
    │   ├── MouseHook.cs
    │   └── NativeMethods.cs
    ├── Properties
    │   ├── Annotations.cs
    │   ├── AssemblyInfo.cs
    │   ├── Resources.Designer.cs
    │   ├── Resources.resx
    │   ├── Settings.Designer.cs
    │   └── Settings.settings
    ├── Settings
    │   ├── AppSetting.cs
    │   └── ButtonSetting.cs
    ├── UI
    │   ├── ClickIndicator.xaml
    │   ├── ClickIndicator.xaml.cs
    │   ├── HoverDot.xaml
    │   ├── HoverDot.xaml.cs
    │   ├── MainWindow.xaml
    │   ├── MainWindow.xaml.cs
    │   ├── SettingsWindow.xaml
    │   └── SettingsWindow.xaml.cs
    ├── Utility
    │   ├── DebounceDispatcher.cs
    │   ├── Extensions.cs
    │   ├── MyJsonConverter.cs
    │   └── WindowHelper.cs
    ├── app.manifest
    ├── app.manifest.elevate
    ├── app.manifest.normal
    └── clickshow.ico
├── LICENSE
├── README.md
└── version.txt


/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
  1 | ## Ignore Visual Studio temporary files, build results, and
  2 | ## files generated by popular Visual Studio add-ons.
  3 | ##
  4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
  5 | 
  6 | # User-specific files
  7 | *.rsuser
  8 | *.suo
  9 | *.user
 10 | *.userosscache
 11 | *.sln.docstates
 12 | 
 13 | # User-specific files (MonoDevelop/Xamarin Studio)
 14 | *.userprefs
 15 | 
 16 | # Build results
 17 | [Dd]ebug/
 18 | [Dd]ebugPublic/
 19 | [Rr]elease/
 20 | [Rr]eleases/
 21 | x64/
 22 | x86/
 23 | bld/
 24 | [Bb]in/
 25 | [Oo]bj/
 26 | [Ll]og/
 27 | 
 28 | # Visual Studio 2015/2017 cache/options directory
 29 | .vs/
 30 | # Uncomment if you have tasks that create the project's static files in wwwroot
 31 | #wwwroot/
 32 | 
 33 | # Visual Studio 2017 auto generated files
 34 | Generated\ Files/
 35 | 
 36 | # MSTest test Results
 37 | [Tt]est[Rr]esult*/
 38 | [Bb]uild[Ll]og.*
 39 | 
 40 | # NUNIT
 41 | *.VisualState.xml
 42 | TestResult.xml
 43 | 
 44 | # Build Results of an ATL Project
 45 | [Dd]ebugPS/
 46 | [Rr]eleasePS/
 47 | dlldata.c
 48 | 
 49 | # Benchmark Results
 50 | BenchmarkDotNet.Artifacts/
 51 | 
 52 | # .NET Core
 53 | project.lock.json
 54 | project.fragment.lock.json
 55 | artifacts/
 56 | 
 57 | # StyleCop
 58 | StyleCopReport.xml
 59 | 
 60 | # Files built by Visual Studio
 61 | *_i.c
 62 | *_p.c
 63 | *_h.h
 64 | *.ilk
 65 | *.meta
 66 | *.obj
 67 | *.iobj
 68 | *.pch
 69 | *.pdb
 70 | *.ipdb
 71 | *.pgc
 72 | *.pgd
 73 | *.rsp
 74 | *.sbr
 75 | *.tlb
 76 | *.tli
 77 | *.tlh
 78 | *.tmp
 79 | *.tmp_proj
 80 | *_wpftmp.csproj
 81 | *.log
 82 | *.vspscc
 83 | *.vssscc
 84 | .builds
 85 | *.pidb
 86 | *.svclog
 87 | *.scc
 88 | 
 89 | # Chutzpah Test files
 90 | _Chutzpah*
 91 | 
 92 | # Visual C++ cache files
 93 | ipch/
 94 | *.aps
 95 | *.ncb
 96 | *.opendb
 97 | *.opensdf
 98 | *.sdf
 99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 | 
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 | 
109 | # Visual Studio Trace Files
110 | *.e2e
111 | 
112 | # TFS 2012 Local Workspace
113 | $tf/
114 | 
115 | # Guidance Automation Toolkit
116 | *.gpState
117 | 
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 | 
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 | 
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 | 
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 | 
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 | 
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 | 
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 | 
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 | 
149 | # Web workbench (sass)
150 | .sass-cache/
151 | 
152 | # Installshield output folder
153 | [Ee]xpress/
154 | 
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 | 
165 | # Click-Once directory
166 | publish/
167 | 
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 | 
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 | 
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 | 
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 | 
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 | 
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 | 
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 | 
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 | 
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 | 
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 | 
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 | 
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 | 
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 | 
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 | 
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 | 
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 | 
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 | 
267 | # Visual Studio 6 build log
268 | *.plg
269 | 
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 | 
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 | 
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 | 
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 | 
288 | # FAKE - F# Make
289 | .fake/
290 | 
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 | 
295 | # CodeRush personal settings
296 | .cr/personal
297 | 
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 | 
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 | 
306 | # Tabs Studio
307 | *.tss
308 | 
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 | 
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 | 
318 | # OpenCover UI analysis results
319 | OpenCover/
320 | 
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 | 
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 | 
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 | 
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 | 
333 | # Local History for Visual Studio
334 | .localhistory/
335 | 


--------------------------------------------------------------------------------
/ClickShow.sln:
--------------------------------------------------------------------------------
 1 | 
 2 | Microsoft Visual Studio Solution File, Format Version 12.00
 3 | # Visual Studio Version 16
 4 | VisualStudioVersion = 16.0.31229.75
 5 | MinimumVisualStudioVersion = 10.0.40219.1
 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClickShow", "ClickShow\ClickShow.csproj", "{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}"
 7 | EndProject
 8 | Global
 9 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | 		Debug|Any CPU = Debug|Any CPU
11 | 		Release|Any CPU = Release|Any CPU
12 | 		ReleaseElevated|Any CPU = ReleaseElevated|Any CPU
13 | 	EndGlobalSection
14 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
16 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
17 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.Release|Any CPU.Build.0 = Release|Any CPU
19 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.ReleaseElevated|Any CPU.ActiveCfg = ReleaseElevated|Any CPU
20 | 		{AC458140-2584-4E45-ACE8-CEAA18A4DBD0}.ReleaseElevated|Any CPU.Build.0 = ReleaseElevated|Any CPU
21 | 	EndGlobalSection
22 | 	GlobalSection(SolutionProperties) = preSolution
23 | 		HideSolutionNode = FALSE
24 | 	EndGlobalSection
25 | 	GlobalSection(ExtensibilityGlobals) = postSolution
26 | 		SolutionGuid = {161DA95D-5645-4DA5-94CD-33D4AD029A55}
27 | 	EndGlobalSection
28 | EndGlobal
29 | 


--------------------------------------------------------------------------------
/ClickShow.sln.DotSettings:
--------------------------------------------------------------------------------
1 | <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2 | 	<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=ClickShow_002EAnnotations/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>


--------------------------------------------------------------------------------
/ClickShow/App.xaml:
--------------------------------------------------------------------------------
1 | <Application
2 |     x:Class="ClickShow.App"
3 |     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 |     xmlns:local="clr-namespace:ClickShow"
6 |     StartupUri="UI/MainWindow.xaml">
7 |     <Application.Resources />
8 | </Application>
9 | 


--------------------------------------------------------------------------------
/ClickShow/App.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Configuration;
 4 | using System.Linq;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | 
 8 | namespace ClickShow
 9 | {
10 |     /// <summary>
11 |     /// Interaction logic for App.xaml
12 |     /// </summary>
13 |     public partial class App : Application
14 |     {
15 |     }
16 | }
17 | 


--------------------------------------------------------------------------------
/ClickShow/ClickShow.csproj:
--------------------------------------------------------------------------------
 1 | <Project Sdk="Microsoft.NET.Sdk">
 2 |   <PropertyGroup>
 3 |     <TargetFramework>net472</TargetFramework>
 4 |     <OutputType>WinExe</OutputType>
 5 |     <PublishUrl>publish\</PublishUrl>
 6 |     <Install>true</Install>
 7 |     <InstallFrom>Disk</InstallFrom>
 8 |     <UpdateEnabled>false</UpdateEnabled>
 9 |     <UpdateMode>Foreground</UpdateMode>
10 |     <UpdateInterval>7</UpdateInterval>
11 |     <UpdateIntervalUnits>Days</UpdateIntervalUnits>
12 |     <UpdatePeriodically>false</UpdatePeriodically>
13 |     <UpdateRequired>false</UpdateRequired>
14 |     <MapFileExtensions>true</MapFileExtensions>
15 |     <ApplicationRevision>0</ApplicationRevision>
16 |     <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
17 |     <IsWebBootstrapper>false</IsWebBootstrapper>
18 |     <UseApplicationTrust>false</UseApplicationTrust>
19 |     <BootstrapperEnabled>true</BootstrapperEnabled>
20 |     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
21 |     <UseWindowsForms>true</UseWindowsForms>
22 |     <UseWPF>true</UseWPF>
23 |     <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
24 |     <Configurations>Debug;Release;ReleaseElevated</Configurations>
25 |   </PropertyGroup>
26 |   <PropertyGroup>
27 |     <ApplicationIcon>clickshow.ico</ApplicationIcon>
28 |   </PropertyGroup>
29 |   <PropertyGroup>
30 |     <ApplicationManifest>app.manifest</ApplicationManifest>
31 |   </PropertyGroup>
32 |   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
33 |     <WarningLevel>5</WarningLevel>
34 |   </PropertyGroup>
35 |   <ItemGroup>
36 |     <Compile Remove="NotifyIcon\**" />
37 |     <EmbeddedResource Remove="NotifyIcon\**" />
38 |     <None Remove="NotifyIcon\**" />
39 |     <Page Remove="NotifyIcon\**" />
40 |   </ItemGroup>
41 |   <ItemGroup>
42 |     <BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
43 |       <Visible>False</Visible>
44 |       <ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
45 |       <Install>true</Install>
46 |     </BootstrapperPackage>   
47 |   </ItemGroup>
48 |   <ItemGroup>
49 |     <PackageReference Include="DotNetProjects.Extended.Wpf.Toolkit" Version="4.6.97" />
50 |   </ItemGroup>
51 |   <ItemGroup>
52 |     <Resource Include="clickshow.ico" />
53 |   </ItemGroup>
54 |   <ItemGroup>
55 |     <Compile Update="Properties\Settings.Designer.cs">
56 |       <DesignTimeSharedInput>True</DesignTimeSharedInput>
57 |       <AutoGen>True</AutoGen>
58 |       <DependentUpon>Settings.settings</DependentUpon>
59 |     </Compile>
60 |   </ItemGroup>
61 |   <ItemGroup>
62 |     <None Update="Properties\Settings.settings">
63 |       <Generator>SettingsSingleFileGenerator</Generator>
64 |       <LastGenOutput>Settings.Designer.cs</LastGenOutput>
65 |     </None>
66 |   </ItemGroup>
67 |   <ItemGroup>
68 |     <Folder Include="3rd\" />
69 |   </ItemGroup>
70 |   <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
71 |     <Exec Command="if  $(ConfigurationName) == ReleaseElevated (&#xD;&#xA;      copy /Y &quot;$(ProjectDir)app.manifest.elevate&quot; &quot;$(ProjectDir)app.manifest&quot;&#xD;&#xA;) ELSE (&#xD;&#xA;      copy /Y &quot;$(ProjectDir)app.manifest.normal&quot; &quot;$(ProjectDir)app.manifest&quot;&#xD;&#xA;)" />
72 |   </Target>
73 |   
74 | </Project>


--------------------------------------------------------------------------------
/ClickShow/ClickShow.csproj.DotSettings:
--------------------------------------------------------------------------------
1 | <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2 | 	<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ui/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>


--------------------------------------------------------------------------------
/ClickShow/Entities/MouseButtonState.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Drawing;
 4 | using System.Linq;
 5 | using System.Text;
 6 | using System.Threading.Tasks;
 7 | 
 8 | namespace ClickShow.Entities
 9 | {
10 |     /// <summary>
11 |     /// 鼠标按键状态
12 |     /// </summary>
13 |     class MouseButtonState
14 |     {
15 |         /// <summary>
16 |         /// 按下时间
17 |         /// </summary>
18 |         public long? DownTimeTicks { get; set; }
19 | 
20 |         /// <summary>
21 |         /// 按下位置
22 |         /// </summary>
23 |         public Point DownPosition { get; set; }
24 | 
25 | 
26 |     }
27 | }
28 | 


--------------------------------------------------------------------------------
/ClickShow/MouseHook/GlobalHook.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Diagnostics;
  3 | using System.Reflection;
  4 | using System.Runtime.InteropServices;
  5 | using System.Windows;
  6 | 
  7 | namespace ClickShow.MouseHook
  8 | {
  9 |     /// <summary>  
 10 |     /// Abstract base class for Mouse and Keyboard hooks  
 11 |     /// </summary>  
 12 |     public abstract class GlobalHook
 13 |     {
 14 |         #region Private Variables  
 15 | 
 16 |         protected HookType HookType { get; set; }
 17 |         protected IntPtr HandleToHook { get; set; }
 18 |         protected NativeMethods.HookProc HookCallback { get; set; }
 19 |         public bool IsStarted { get; set; }
 20 |         #endregion
 21 | 
 22 | 
 23 | 
 24 |         #region Constructor  
 25 | 
 26 |         public GlobalHook()
 27 |         {
 28 | 
 29 | 
 30 |             //Application.Current.Exit += CurrentApplicationOnExit;
 31 |         }
 32 | 
 33 |         private void CurrentApplicationOnExit(object sender, ExitEventArgs e)
 34 |         {
 35 |             if (IsStarted)
 36 |             {
 37 |                 Stop();
 38 |             }
 39 | 
 40 |         }
 41 | 
 42 |         #endregion
 43 | 
 44 |         #region Methods  
 45 | 
 46 |         public void Start()
 47 |         {
 48 | 
 49 |             if (!IsStarted &&
 50 |                 HookType != 0)
 51 |             {
 52 | 
 53 |                 // Make sure we keep a reference to this delegate!  
 54 |                 // If not, GC randomly collects it, and a NullReference exception is thrown  
 55 |                 HookCallback = new NativeMethods.HookProc(HookCallbackProcedure);
 56 | 
 57 |                 HandleToHook = NativeMethods.SetWindowsHookEx(
 58 |                     HookType,
 59 |                     HookCallback,
 60 |                     Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
 61 |                     0);
 62 | 
 63 |                 // Were we able to sucessfully start hook?  
 64 |                 if (HandleToHook != IntPtr.Zero)
 65 |                 {
 66 |                     IsStarted = true;
 67 |                 }
 68 |                 else
 69 |                 {
 70 | #if DEBUG
 71 |                     throw new InvalidOperationException("鼠标hook建立失败。");
 72 | #endif
 73 |                 }
 74 | 
 75 |             }
 76 | 
 77 |         }
 78 | 
 79 |         public virtual void Stop()
 80 |         {
 81 | 
 82 |             if (IsStarted)
 83 |             {
 84 | 
 85 | #pragma warning disable CA1806 // Do not ignore method results
 86 |                 NativeMethods.UnhookWindowsHookEx(HandleToHook);
 87 | #pragma warning restore CA1806 // Do not ignore method results
 88 | 
 89 |                 IsStarted = false;
 90 | 
 91 |             }
 92 | 
 93 |         }
 94 | 
 95 |         protected virtual IntPtr HookCallbackProcedure(int nCode, IntPtr wParam, IntPtr lParam)
 96 |         {
 97 | 
 98 |             // This method must be overriden by each extending hook  
 99 |             return (IntPtr)0;
100 | 
101 |         }
102 | 
103 |         //protected void Application_ApplicationExit(object sender, EventArgs e)
104 |         //{
105 | 
106 |         //    if (IsStarted)
107 |         //    {
108 |         //        Stop();
109 |         //    }
110 | 
111 |         //}
112 | 
113 |         #endregion
114 | 
115 | 
116 |         public void Restart()
117 |         {
118 |             Debug.WriteLine("重新加载挂钩!");
119 |             Stop();
120 |             Start();
121 |         }
122 |     }
123 | }
124 | 


--------------------------------------------------------------------------------
/ClickShow/MouseHook/HookType.cs:
--------------------------------------------------------------------------------
 1 | namespace ClickShow.MouseHook
 2 | {
 3 |     public enum HookType : int
 4 |     {
 5 |         WH_JOURNALRECORD = 0,
 6 |         WH_JOURNALPLAYBACK = 1,
 7 |         WH_KEYBOARD = 2,
 8 |         WH_GETMESSAGE = 3,
 9 |         WH_CALLWNDPROC = 4,
10 |         WH_CBT = 5,
11 |         WH_SYSMSGFILTER = 6,
12 |         WH_MOUSE = 7,
13 |         WH_HARDWARE = 8,
14 |         WH_DEBUG = 9,
15 |         WH_SHELL = 10,
16 |         WH_FOREGROUNDIDLE = 11,
17 |         WH_CALLWNDPROCRET = 12,
18 |         WH_KEYBOARD_LL = 13,
19 |         WH_MOUSE_LL = 14
20 |     }
21 | }


--------------------------------------------------------------------------------
/ClickShow/MouseHook/MouseHook.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Diagnostics;
  3 | using System.Runtime.InteropServices;
  4 | using System.Windows.Forms;
  5 | using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
  6 | using MouseEventHandler = System.Windows.Forms.MouseEventHandler;
  7 | 
  8 | namespace ClickShow.MouseHook
  9 | {
 10 |     /*************************************************************************************
 11 |  * 文件名:MouseHook.cs
 12 |  * 创建人:CMF
 13 |  * 日期:2018-5-20
 14 |  * 描述:实现鼠标钩子安装
 15 |  * 使用:
 16 |         MouseHook mouseHook = new MouseHook();  //实例化鼠标钩子类
 17 |         KeyboardHook keyboardHook = new KeyboardHook();  //实例化键盘钩子类
 18 |         mouseHook.MouseMove += new MouseEventHandler(mouseHook_MouseMove);  
 19 |         mouseHook.MouseDown += new MouseEventHandler(mouseHook_MouseDown);  
 20 |         mouseHook.MouseUp += new MouseEventHandler(mouseHook_MouseUp);  
 21 |         mouseHook.MouseWheel += new MouseEventHandler(mouseHook_MouseWheel);  
 22 |         keyboardHook.KeyDown += new KeyEventHandler(keyboardHook_KeyDown);  
 23 |         keyboardHook.KeyUp += new KeyEventHandler(keyboardHook_KeyUp);  
 24 |         keyboardHook.KeyPress += new KeyPressEventHandler(keyboardHook_KeyPress);  
 25 |         mouseHook.Start();  
 26 |         keyboardHook.Start(); 
 27 | ************************************************************************************/
 28 | 
 29 |     
 30 | 
 31 |     /// <summary>  
 32 |     /// Captures global mouse events  
 33 |     /// </summary>  
 34 |     public class MouseHook : GlobalHook
 35 |     {
 36 | 
 37 |         
 38 | 
 39 |         #region MouseEventType Enum  
 40 | 
 41 |         private enum MouseEventType
 42 |         {
 43 |             None,
 44 |             MouseDown,
 45 |             MouseUp,
 46 |             DoubleClick,
 47 |             MouseWheel,
 48 |             MouseMove,
 49 |             MouseHWheel, // 水平滚动
 50 |         }
 51 | 
 52 |         #endregion
 53 | 
 54 |         #region Events  
 55 | 
 56 |         public event MouseEventHandler MouseDown;
 57 |         public event MouseEventHandler MouseUp;
 58 |         public event MouseEventHandler MouseMove;
 59 |         public event MouseEventHandler MouseWheel;
 60 |         public event MouseEventHandler MouseHWheel;
 61 | 
 62 |         public event EventHandler Click;
 63 |         public event EventHandler DoubleClick;
 64 | 
 65 |         #endregion
 66 | 
 67 |         #region Constructor  
 68 | 
 69 |         public MouseHook()
 70 |         {
 71 | 
 72 |             HookType = HookType.WH_MOUSE_LL;
 73 | 
 74 |         }
 75 | 
 76 |         #endregion
 77 | 
 78 |         #region Methods  
 79 | 
 80 |         protected override IntPtr HookCallbackProcedure(int nCode, IntPtr wParam, IntPtr lParam)
 81 |         {
 82 |             bool handled = false;
 83 | 
 84 |             try
 85 |             {
 86 |                 handled = ProcessHook(nCode, wParam, lParam);
 87 |             }
 88 |             catch (Exception ex)
 89 |             {
 90 |                 Debug.WriteLine("处理鼠标回调消息出错!" + ex.Message, ex);
 91 | #if DEBUG
 92 |                 throw;
 93 | #endif
 94 |             }
 95 | 
 96 | 
 97 | 
 98 |             if (handled)
 99 |             {
100 |                 return (IntPtr)1;
101 |             }
102 |             else
103 |             {
104 |                 return NativeMethods.CallNextHookEx(HandleToHook, nCode, wParam, lParam);
105 |             }
106 |         }
107 | 
108 |         /// <summary>
109 |         /// 处理回调消息
110 |         /// </summary>
111 |         /// <param name="nCode"></param>
112 |         /// <param name="wParam"></param>
113 |         /// <param name="lParam"></param>
114 |         /// <returns></returns>
115 |         private bool ProcessHook(int nCode, IntPtr wParam, IntPtr lParam)
116 |         {
117 |             bool handled = false;
118 | 
119 | 
120 |             if (nCode > -1 && (MouseDown != null || MouseUp != null || MouseMove != null || MouseWheel != null ||
121 |                                MouseHWheel != null))
122 |             {
123 |                 // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmsllhookstruct
124 |                 // https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-msllhookstruct?redirectedfrom=MSDN
125 |                 NativeMethods.MouseLLHookStruct mouseHookStruct =
126 |                     (NativeMethods.MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(NativeMethods.MouseLLHookStruct));
127 | 
128 |                 MouseButtons button = GetButton((int)wParam, mouseHookStruct);
129 |                 MouseEventType eventType = GetEventType((int)wParam);
130 | 
131 |                 //  https://docs.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
132 |                 const uint MI_WP_SIGNATURE = 0xFF515700;
133 |                 const uint SIGNATURE_MASK = 0xFFFFFF00;
134 |                 bool isPenOrTouch = ((uint)mouseHookStruct.dwExtraInfo & SIGNATURE_MASK) == MI_WP_SIGNATURE;
135 | 
136 |                 var e = new MouseEventArgs(
137 |                     button,
138 |                     (eventType == MouseEventType.DoubleClick ? 2 : 1),
139 |                     mouseHookStruct.pt.x,
140 |                     mouseHookStruct.pt.y,
141 |                     (eventType == MouseEventType.MouseWheel || eventType == MouseEventType.MouseHWheel
142 |                         ? (short)((mouseHookStruct.mouseData >> 16) & 0xffff)
143 |                         : 0))
144 |                 {
145 |                   
146 |                 };
147 | 
148 | 
149 | 
150 |                 switch (eventType)
151 |                 {
152 |                     case MouseEventType.MouseDown:
153 |                         MouseDown?.Invoke(this, e);
154 |                         break;
155 |                     case MouseEventType.MouseUp:
156 |                         MouseUp?.Invoke(this, e);
157 |                         Click?.Invoke(this, e);
158 |                         break;
159 |                     case MouseEventType.DoubleClick:
160 |                         DoubleClick?.Invoke(this, e);
161 |                         break;
162 |                     case MouseEventType.MouseWheel:
163 |                         MouseWheel?.Invoke(this, e);
164 |                         break;
165 |                     case MouseEventType.MouseHWheel:
166 |                         MouseHWheel?.Invoke(this, e);
167 |                         break;
168 |                     case MouseEventType.MouseMove:
169 |                         MouseMove?.Invoke(this, e);
170 |                         break;
171 |                     default:
172 | 
173 |                         Debug.WriteLine("未处理的鼠标消息:" + eventType);
174 | 
175 |                         break;
176 |                 }
177 | 
178 | 
179 |             }
180 | 
181 |             return handled;
182 |         }
183 | 
184 |         private static MouseButtons GetButton(int wParam, NativeMethods.MouseLLHookStruct mouseHookStruct)
185 |         {
186 | 
187 |             switch (wParam)
188 |             {
189 | 
190 |                 case NativeMethods.WM_LBUTTONDOWN:
191 |                 case NativeMethods.WM_LBUTTONUP:
192 |                 case NativeMethods.WM_LBUTTONDBLCLK:
193 |                     return MouseButtons.Left;
194 |                 case NativeMethods.WM_RBUTTONDOWN:
195 |                 case NativeMethods.WM_RBUTTONUP:
196 |                 case NativeMethods.WM_RBUTTONDBLCLK:
197 |                     return MouseButtons.Right;
198 |                 case NativeMethods.WM_MBUTTONDOWN:
199 |                 case NativeMethods.WM_MBUTTONUP:
200 |                 case NativeMethods.WM_MBUTTONDBLCLK:
201 |                     return MouseButtons.Middle;
202 |                 case NativeMethods.WM_XBUTTONDOWN:
203 |                 case NativeMethods.WM_XBUTTONUP:
204 |                     if ((mouseHookStruct.mouseData & 0x010000) > 0)
205 |                     {
206 |                         return MouseButtons.XButton1;
207 |                     }
208 |                     else if ((mouseHookStruct.mouseData & 0x020000) > 0)
209 |                     {
210 |                         return MouseButtons.XButton2;
211 |                     }
212 |                     else
213 |                     {
214 |                         return MouseButtons.XButton1;
215 |                     }
216 | 
217 |                 default:
218 |                     return MouseButtons.None;
219 | 
220 |             }
221 |         }
222 | 
223 |         private static MouseEventType GetEventType(int wParam)
224 |         {
225 | 
226 |             switch (wParam)
227 |             {
228 | 
229 |                 case NativeMethods.WM_LBUTTONDOWN:
230 |                 case NativeMethods.WM_RBUTTONDOWN:
231 |                 case NativeMethods.WM_MBUTTONDOWN:
232 |                 case NativeMethods.WM_XBUTTONDOWN:
233 |                     return MouseEventType.MouseDown;
234 |                 case NativeMethods.WM_LBUTTONUP:
235 |                 case NativeMethods.WM_RBUTTONUP:
236 |                 case NativeMethods.WM_MBUTTONUP:
237 |                 case NativeMethods.WM_XBUTTONUP:
238 |                     return MouseEventType.MouseUp;
239 | 
240 |                 case NativeMethods.WM_LBUTTONDBLCLK:
241 |                 case NativeMethods.WM_RBUTTONDBLCLK:
242 |                 case NativeMethods.WM_MBUTTONDBLCLK:
243 |                     return MouseEventType.DoubleClick;
244 |                 case NativeMethods.WM_MOUSEWHEEL:
245 |                     return MouseEventType.MouseWheel;
246 |                 case NativeMethods.WM_MOUSEHWHEEL:
247 |                     return MouseEventType.MouseHWheel;
248 |                 case NativeMethods.WM_MOUSEMOVE:
249 |                     return MouseEventType.MouseMove;
250 |                 default:
251 |                     return MouseEventType.None;
252 | 
253 |             }
254 |         }
255 | 
256 |         #endregion
257 | 
258 |         /// <summary>
259 |         /// 停止挂钩处理
260 |         /// </summary>
261 |         public override void Stop()
262 |         {
263 |             base.Stop();
264 | 
265 |         }
266 | 
267 | 
268 |     }
269 | }
270 | 


--------------------------------------------------------------------------------
/ClickShow/MouseHook/NativeMethods.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Runtime.InteropServices;
  3 | 
  4 | namespace ClickShow.MouseHook
  5 | {
  6 |     public static class NativeMethods
  7 |     {
  8 | 
  9 |         public const int WH_MOUSE_LL = 14;
 10 |         public const int WH_KEYBOARD_LL = 13;
 11 | 
 12 |         public const int WH_MOUSE = 7;
 13 |         public const int WH_KEYBOARD = 2;
 14 |         public const int WM_MOUSEMOVE = 0x200;
 15 | 
 16 |         public const int WM_LBUTTONDOWN = 0x201;
 17 |         public const int WM_LBUTTONUP = 0x202;
 18 | 
 19 |         public const int WM_RBUTTONDOWN = 0x204;
 20 |         public const int WM_RBUTTONUP = 0x205;
 21 | 
 22 | 
 23 |         public const int WM_MBUTTONDOWN = 0x207;
 24 |         public const int WM_MBUTTONUP = 0x208;
 25 | 
 26 |         public const int WM_XBUTTONDOWN = 0x020B;
 27 |         public const int WM_XBUTTONUP = 0x020C;
 28 | 
 29 |         public const int WM_LBUTTONDBLCLK = 0x203;
 30 |         public const int WM_RBUTTONDBLCLK = 0x206;
 31 |         public const int WM_MBUTTONDBLCLK = 0x209;
 32 |         public const int WM_MOUSEWHEEL = 0x020A;
 33 |         public const int WM_MOUSEHWHEEL = 0x020E;
 34 |         public const int WM_KEYDOWN = 0x100;
 35 |         public const int WM_KEYUP = 0x101;
 36 |         public const int WM_SYSKEYDOWN = 0x104;
 37 |         public const int WM_SYSKEYUP = 0x105;
 38 | 
 39 |         public const byte VK_SHIFT = 0x10;
 40 |         public const byte VK_CAPITAL = 0x14;
 41 |         public const byte VK_NUMLOCK = 0x90;
 42 | 
 43 |         public const byte VK_LSHIFT = 0xA0;
 44 |         public const byte VK_RSHIFT = 0xA1;
 45 |         public const byte VK_LCONTROL = 0xA2;
 46 |         public const byte VK_RCONTROL = 0x3;
 47 |         public const byte VK_LALT = 0xA4;
 48 |         public const byte VK_RALT = 0xA5;
 49 | 
 50 |         public const byte LLKHF_ALTDOWN = 0x20;
 51 | 
 52 | 
 53 |         public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
 54 | 
 55 | 
 56 | 
 57 |         [StructLayout(LayoutKind.Sequential)]
 58 |         public class POINT
 59 |         {
 60 |             public int x;
 61 |             public int y;
 62 |         }
 63 | 
 64 |         [StructLayout(LayoutKind.Sequential)]
 65 |         public class MouseHookStruct
 66 |         {
 67 |             public POINT pt;
 68 |             public int hwnd;
 69 |             public int wHitTestCode;
 70 |             public int dwExtraInfo;
 71 |         }
 72 | 
 73 |         [StructLayout(LayoutKind.Sequential)]
 74 |         public class MouseLLHookStruct
 75 |         {
 76 |             public POINT pt;
 77 |             public int mouseData;
 78 |             public int flags;
 79 |             public int time;
 80 |             public UIntPtr dwExtraInfo;
 81 |         }
 82 | 
 83 |         [StructLayout(LayoutKind.Sequential)]
 84 |         public class KeyboardHookStruct
 85 |         {
 86 |             public int vkCode;
 87 |             public int scanCode;
 88 |             public int flags;
 89 |             public int time;
 90 |             public int dwExtraInfo;
 91 |         }
 92 | 
 93 |         [DllImport("user32.dll", CharSet = CharSet.Auto,
 94 |             CallingConvention = CallingConvention.StdCall, SetLastError = true)]
 95 |         public static extern IntPtr SetWindowsHookEx(
 96 |             HookType hookType,
 97 |             HookProc lpfn,
 98 |             IntPtr hMod,
 99 |             uint dwThreadId);
100 | 
101 |         [DllImport("user32.dll", CharSet = CharSet.Auto,
102 |             CallingConvention = CallingConvention.StdCall, SetLastError = true)]
103 |         public static extern bool UnhookWindowsHookEx(IntPtr idHook);
104 | 
105 | 
106 |         [DllImport("user32.dll", CharSet = CharSet.Unicode,
107 |             CallingConvention = CallingConvention.StdCall)]
108 |         public static extern IntPtr CallNextHookEx(
109 |             IntPtr idHook,
110 |             int nCode,
111 |             IntPtr wParam,
112 |             IntPtr lParam);
113 | 
114 | 
115 |         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
116 |         public static extern short GetKeyState(int vKey);
117 | 
118 | 
119 |         [DllImport("user32")]
120 |         public static extern int GetKeyboardState(byte[] pbKeyState);
121 | 
122 | 
123 |         [DllImport("user32")]
124 |         public static extern int ToAscii(
125 |             int uVirtKey,
126 |             int uScanCode,
127 |             byte[] lpbKeyState,
128 |             byte[] lpwTransKey,
129 |             int fuState);
130 | 
131 | 
132 |         [DllImport("user32.dll")]
133 |         public static extern long GetClipboardSequenceNumber();
134 |     }
135 | }
136 | 


--------------------------------------------------------------------------------
/ClickShow/Properties/Annotations.cs:
--------------------------------------------------------------------------------
   1 | /* MIT License
   2 | 
   3 | Copyright (c) 2016 JetBrains http://www.jetbrains.com
   4 | 
   5 | Permission is hereby granted, free of charge, to any person obtaining a copy
   6 | of this software and associated documentation files (the "Software"), to deal
   7 | in the Software without restriction, including without limitation the rights
   8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   9 | copies of the Software, and to permit persons to whom the Software is
  10 | furnished to do so, subject to the following conditions:
  11 | 
  12 | The above copyright notice and this permission notice shall be included in all
  13 | copies or substantial portions of the Software.
  14 | 
  15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 | SOFTWARE. */
  22 | 
  23 | using System;
  24 | // ReSharper disable UnusedType.Global
  25 | 
  26 | #pragma warning disable 1591
  27 | // ReSharper disable UnusedMember.Global
  28 | // ReSharper disable MemberCanBePrivate.Global
  29 | // ReSharper disable UnusedAutoPropertyAccessor.Global
  30 | // ReSharper disable IntroduceOptionalParameters.Global
  31 | // ReSharper disable MemberCanBeProtected.Global
  32 | // ReSharper disable InconsistentNaming
  33 | 
  34 | namespace ClickShow.Annotations
  35 | {
  36 |   /// <summary>
  37 |   /// Indicates that the value of the marked element could be <c>null</c> sometimes,
  38 |   /// so checking for <c>null</c> is required before its usage.
  39 |   /// </summary>
  40 |   /// <example><code>
  41 |   /// [CanBeNull] object Test() => null;
  42 |   /// 
  43 |   /// void UseTest() {
  44 |   ///   var p = Test();
  45 |   ///   var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
  46 |   /// }
  47 |   /// </code></example>
  48 |   [AttributeUsage(
  49 |     AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
  50 |     AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
  51 |     AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
  52 |   public sealed class CanBeNullAttribute : Attribute { }
  53 | 
  54 |   /// <summary>
  55 |   /// Indicates that the value of the marked element can never be <c>null</c>.
  56 |   /// </summary>
  57 |   /// <example><code>
  58 |   /// [NotNull] object Foo() {
  59 |   ///   return null; // Warning: Possible 'null' assignment
  60 |   /// }
  61 |   /// </code></example>
  62 |   [AttributeUsage(
  63 |     AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
  64 |     AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
  65 |     AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
  66 |   public sealed class NotNullAttribute : Attribute { }
  67 | 
  68 |   /// <summary>
  69 |   /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task
  70 |   /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property
  71 |   /// or of the Lazy.Value property can never be null.
  72 |   /// </summary>
  73 |   /// <example><code>
  74 |   /// public void Foo([ItemNotNull]List&lt;string&gt; books)
  75 |   /// {
  76 |   ///   foreach (var book in books) {
  77 |   ///     if (book != null) // Warning: Expression is always true
  78 |   ///      Console.WriteLine(book.ToUpper());
  79 |   ///   }
  80 |   /// }
  81 |   /// </code></example>
  82 |   [AttributeUsage(
  83 |     AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
  84 |     AttributeTargets.Delegate | AttributeTargets.Field)]
  85 |   public sealed class ItemNotNullAttribute : Attribute { }
  86 | 
  87 |   /// <summary>
  88 |   /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task
  89 |   /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property
  90 |   /// or of the Lazy.Value property can be null.
  91 |   /// </summary>
  92 |   /// <example><code>
  93 |   /// public void Foo([ItemCanBeNull]List&lt;string&gt; books)
  94 |   /// {
  95 |   ///   foreach (var book in books)
  96 |   ///   {
  97 |   ///     // Warning: Possible 'System.NullReferenceException'
  98 |   ///     Console.WriteLine(book.ToUpper());
  99 |   ///   }
 100 |   /// }
 101 |   /// </code></example>
 102 |   [AttributeUsage(
 103 |     AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
 104 |     AttributeTargets.Delegate | AttributeTargets.Field)]
 105 |   public sealed class ItemCanBeNullAttribute : Attribute { }
 106 | 
 107 |   /// <summary>
 108 |   /// Indicates that the marked method builds string by the format pattern and (optional) arguments.
 109 |   /// The parameter, which contains the format string, should be given in the constructor. The format string
 110 |   /// should be in <see cref="string.Format(IFormatProvider,string,object[])"/>-like form.
 111 |   /// </summary>
 112 |   /// <example><code>
 113 |   /// [StringFormatMethod("message")]
 114 |   /// void ShowError(string message, params object[] args) { /* do something */ }
 115 |   /// 
 116 |   /// void Foo() {
 117 |   ///   ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
 118 |   /// }
 119 |   /// </code></example>
 120 |   [AttributeUsage(
 121 |     AttributeTargets.Constructor | AttributeTargets.Method |
 122 |     AttributeTargets.Property | AttributeTargets.Delegate)]
 123 |   public sealed class StringFormatMethodAttribute : Attribute
 124 |   {
 125 |     /// <param name="formatParameterName">
 126 |     /// Specifies which parameter of an annotated method should be treated as the format string
 127 |     /// </param>
 128 |     public StringFormatMethodAttribute([NotNull] string formatParameterName)
 129 |     {
 130 |       FormatParameterName = formatParameterName;
 131 |     }
 132 | 
 133 |     [NotNull] public string FormatParameterName { get; }
 134 |   }
 135 | 
 136 |   /// <summary>
 137 |   /// Indicates that the marked parameter is a message template where placeholders are to be replaced by the following arguments
 138 |   /// in the order in which they appear
 139 |   /// </summary>
 140 |   /// <example><code>
 141 |   /// void LogInfo([StructuredMessageTemplate]string message, params object[] args) { /* do something */ }
 142 |   /// 
 143 |   /// void Foo() {
 144 |   ///   LogInfo("User created: {username}"); // Warning: Non-existing argument in format string
 145 |   /// }
 146 |   /// </code></example>
 147 |   [AttributeUsage(AttributeTargets.Parameter)]
 148 |   public sealed class StructuredMessageTemplateAttribute : Attribute {}
 149 | 
 150 |   /// <summary>
 151 |   /// Use this annotation to specify a type that contains static or const fields
 152 |   /// with values for the annotated property/field/parameter.
 153 |   /// The specified type will be used to improve completion suggestions.
 154 |   /// </summary>
 155 |   /// <example><code>
 156 |   /// namespace TestNamespace
 157 |   /// {
 158 |   ///   public class Constants
 159 |   ///   {
 160 |   ///     public static int INT_CONST = 1;
 161 |   ///     public const string STRING_CONST = "1";
 162 |   ///   }
 163 |   ///
 164 |   ///   public class Class1
 165 |   ///   {
 166 |   ///     [ValueProvider("TestNamespace.Constants")] public int myField;
 167 |   ///     public void Foo([ValueProvider("TestNamespace.Constants")] string str) { }
 168 |   ///
 169 |   ///     public void Test()
 170 |   ///     {
 171 |   ///       Foo(/*try completion here*/);//
 172 |   ///       myField = /*try completion here*/
 173 |   ///     }
 174 |   ///   }
 175 |   /// }
 176 |   /// </code></example>
 177 |   [AttributeUsage(
 178 |     AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field,
 179 |     AllowMultiple = true)]
 180 |   public sealed class ValueProviderAttribute : Attribute
 181 |   {
 182 |     public ValueProviderAttribute([NotNull] string name)
 183 |     {
 184 |       Name = name;
 185 |     }
 186 | 
 187 |     [NotNull] public string Name { get; }
 188 |   }
 189 | 
 190 |   /// <summary>
 191 |   /// Indicates that the integral value falls into the specified interval.
 192 |   /// It's allowed to specify multiple non-intersecting intervals.
 193 |   /// Values of interval boundaries are inclusive.
 194 |   /// </summary>
 195 |   /// <example><code>
 196 |   /// void Foo([ValueRange(0, 100)] int value) {
 197 |   ///   if (value == -1) { // Warning: Expression is always 'false'
 198 |   ///     ...
 199 |   ///   }
 200 |   /// }
 201 |   /// </code></example>
 202 |   [AttributeUsage(
 203 |     AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property |
 204 |     AttributeTargets.Method | AttributeTargets.Delegate,
 205 |     AllowMultiple = true)]
 206 |   public sealed class ValueRangeAttribute : Attribute
 207 |   {
 208 |     public object From { get; }
 209 |     public object To { get; }
 210 | 
 211 |     public ValueRangeAttribute(long from, long to)
 212 |     {
 213 |       From = from;
 214 |       To = to;
 215 |     }
 216 | 
 217 |     public ValueRangeAttribute(ulong from, ulong to)
 218 |     {
 219 |       From = from;
 220 |       To = to;
 221 |     }
 222 | 
 223 |     public ValueRangeAttribute(long value)
 224 |     {
 225 |       From = To = value;
 226 |     }
 227 | 
 228 |     public ValueRangeAttribute(ulong value)
 229 |     {
 230 |       From = To = value;
 231 |     }
 232 |   }
 233 | 
 234 |   /// <summary>
 235 |   /// Indicates that the integral value never falls below zero.
 236 |   /// </summary>
 237 |   /// <example><code>
 238 |   /// void Foo([NonNegativeValue] int value) {
 239 |   ///   if (value == -1) { // Warning: Expression is always 'false'
 240 |   ///     ...
 241 |   ///   }
 242 |   /// }
 243 |   /// </code></example>
 244 |   [AttributeUsage(
 245 |     AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property |
 246 |     AttributeTargets.Method | AttributeTargets.Delegate)]
 247 |   public sealed class NonNegativeValueAttribute : Attribute { }
 248 | 
 249 |   /// <summary>
 250 |   /// Indicates that the function argument should be a string literal and match one
 251 |   /// of the parameters of the caller function. For example, ReSharper annotates
 252 |   /// the parameter of <see cref="System.ArgumentNullException"/>.
 253 |   /// </summary>
 254 |   /// <example><code>
 255 |   /// void Foo(string param) {
 256 |   ///   if (param == null)
 257 |   ///     throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
 258 |   /// }
 259 |   /// </code></example>
 260 |   [AttributeUsage(AttributeTargets.Parameter)]
 261 |   public sealed class InvokerParameterNameAttribute : Attribute { }
 262 | 
 263 |   /// <summary>
 264 |   /// Indicates that the method is contained in a type that implements
 265 |   /// <c>System.ComponentModel.INotifyPropertyChanged</c> interface and this method
 266 |   /// is used to notify that some property value changed.
 267 |   /// </summary>
 268 |   /// <remarks>
 269 |   /// The method should be non-static and conform to one of the supported signatures:
 270 |   /// <list>
 271 |   /// <item><c>NotifyChanged(string)</c></item>
 272 |   /// <item><c>NotifyChanged(params string[])</c></item>
 273 |   /// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
 274 |   /// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
 275 |   /// <item><c>SetProperty{T}(ref T, T, string)</c></item>
 276 |   /// </list>
 277 |   /// </remarks>
 278 |   /// <example><code>
 279 |   /// public class Foo : INotifyPropertyChanged {
 280 |   ///   public event PropertyChangedEventHandler PropertyChanged;
 281 |   /// 
 282 |   ///   [NotifyPropertyChangedInvocator]
 283 |   ///   protected virtual void NotifyChanged(string propertyName) { ... }
 284 |   ///
 285 |   ///   string _name;
 286 |   /// 
 287 |   ///   public string Name {
 288 |   ///     get { return _name; }
 289 |   ///     set { _name = value; NotifyChanged("LastName"); /* Warning */ }
 290 |   ///   }
 291 |   /// }
 292 |   /// </code>
 293 |   /// Examples of generated notifications:
 294 |   /// <list>
 295 |   /// <item><c>NotifyChanged("Property")</c></item>
 296 |   /// <item><c>NotifyChanged(() =&gt; Property)</c></item>
 297 |   /// <item><c>NotifyChanged((VM x) =&gt; x.Property)</c></item>
 298 |   /// <item><c>SetProperty(ref myField, value, "Property")</c></item>
 299 |   /// </list>
 300 |   /// </example>
 301 |   [AttributeUsage(AttributeTargets.Method)]
 302 |   public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
 303 |   {
 304 |     public NotifyPropertyChangedInvocatorAttribute() { }
 305 |     public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName)
 306 |     {
 307 |       ParameterName = parameterName;
 308 |     }
 309 | 
 310 |     [CanBeNull] public string ParameterName { get; }
 311 |   }
 312 | 
 313 |   /// <summary>
 314 |   /// Describes dependency between method input and output.
 315 |   /// </summary>
 316 |   /// <syntax>
 317 |   /// <p>Function Definition Table syntax:</p>
 318 |   /// <list>
 319 |   /// <item>FDT      ::= FDTRow [;FDTRow]*</item>
 320 |   /// <item>FDTRow   ::= Input =&gt; Output | Output &lt;= Input</item>
 321 |   /// <item>Input    ::= ParameterName: Value [, Input]*</item>
 322 |   /// <item>Output   ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
 323 |   /// <item>Value    ::= true | false | null | notnull | canbenull</item>
 324 |   /// </list>
 325 |   /// If the method has a single input parameter, its name could be omitted.<br/>
 326 |   /// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same) for the method output
 327 |   /// means that the method doesn't return normally (throws or terminates the process).<br/>
 328 |   /// Value <c>canbenull</c> is only applicable for output parameters.<br/>
 329 |   /// You can use multiple <c>[ContractAnnotation]</c> for each FDT row, or use single attribute
 330 |   /// with rows separated by the semicolon. There is no notion of order rows, all rows are checked
 331 |   /// for applicability and applied per each program state tracked by the analysis engine.<br/>
 332 |   /// </syntax>
 333 |   /// <examples><list>
 334 |   /// <item><code>
 335 |   /// [ContractAnnotation("=&gt; halt")]
 336 |   /// public void TerminationMethod()
 337 |   /// </code></item>
 338 |   /// <item><code>
 339 |   /// [ContractAnnotation("null &lt;= param:null")] // reverse condition syntax
 340 |   /// public string GetName(string surname)
 341 |   /// </code></item>
 342 |   /// <item><code>
 343 |   /// [ContractAnnotation("s:null =&gt; true")]
 344 |   /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
 345 |   /// </code></item>
 346 |   /// <item><code>
 347 |   /// // A method that returns null if the parameter is null,
 348 |   /// // and not null if the parameter is not null
 349 |   /// [ContractAnnotation("null =&gt; null; notnull =&gt; notnull")]
 350 |   /// public object Transform(object data)
 351 |   /// </code></item>
 352 |   /// <item><code>
 353 |   /// [ContractAnnotation("=&gt; true, result: notnull; =&gt; false, result: null")]
 354 |   /// public bool TryParse(string s, out Person result)
 355 |   /// </code></item>
 356 |   /// </list></examples>
 357 |   [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
 358 |   public sealed class ContractAnnotationAttribute : Attribute
 359 |   {
 360 |     public ContractAnnotationAttribute([NotNull] string contract)
 361 |       : this(contract, false) { }
 362 | 
 363 |     public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
 364 |     {
 365 |       Contract = contract;
 366 |       ForceFullStates = forceFullStates;
 367 |     }
 368 | 
 369 |     [NotNull] public string Contract { get; }
 370 | 
 371 |     public bool ForceFullStates { get; }
 372 |   }
 373 | 
 374 |   /// <summary>
 375 |   /// Indicates whether the marked element should be localized.
 376 |   /// </summary>
 377 |   /// <example><code>
 378 |   /// [LocalizationRequiredAttribute(true)]
 379 |   /// class Foo {
 380 |   ///   string str = "my string"; // Warning: Localizable string
 381 |   /// }
 382 |   /// </code></example>
 383 |   [AttributeUsage(AttributeTargets.All)]
 384 |   public sealed class LocalizationRequiredAttribute : Attribute
 385 |   {
 386 |     public LocalizationRequiredAttribute() : this(true) { }
 387 | 
 388 |     public LocalizationRequiredAttribute(bool required)
 389 |     {
 390 |       Required = required;
 391 |     }
 392 | 
 393 |     public bool Required { get; }
 394 |   }
 395 | 
 396 |   /// <summary>
 397 |   /// Indicates that the value of the marked type (or its derivatives)
 398 |   /// cannot be compared using '==' or '!=' operators and <c>Equals()</c>
 399 |   /// should be used instead. However, using '==' or '!=' for comparison
 400 |   /// with <c>null</c> is always permitted.
 401 |   /// </summary>
 402 |   /// <example><code>
 403 |   /// [CannotApplyEqualityOperator]
 404 |   /// class NoEquality { }
 405 |   /// 
 406 |   /// class UsesNoEquality {
 407 |   ///   void Test() {
 408 |   ///     var ca1 = new NoEquality();
 409 |   ///     var ca2 = new NoEquality();
 410 |   ///     if (ca1 != null) { // OK
 411 |   ///       bool condition = ca1 == ca2; // Warning
 412 |   ///     }
 413 |   ///   }
 414 |   /// }
 415 |   /// </code></example>
 416 |   [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)]
 417 |   public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
 418 | 
 419 |   /// <summary>
 420 |   /// When applied to a target attribute, specifies a requirement for any type marked
 421 |   /// with the target attribute to implement or inherit specific type or types.
 422 |   /// </summary>
 423 |   /// <example><code>
 424 |   /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
 425 |   /// class ComponentAttribute : Attribute { }
 426 |   /// 
 427 |   /// [Component] // ComponentAttribute requires implementing IComponent interface
 428 |   /// class MyComponent : IComponent { }
 429 |   /// </code></example>
 430 |   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
 431 |   [BaseTypeRequired(typeof(Attribute))]
 432 |   public sealed class BaseTypeRequiredAttribute : Attribute
 433 |   {
 434 |     public BaseTypeRequiredAttribute([NotNull] Type baseType)
 435 |     {
 436 |       BaseType = baseType;
 437 |     }
 438 | 
 439 |     [NotNull] public Type BaseType { get; }
 440 |   }
 441 | 
 442 |   /// <summary>
 443 |   /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library),
 444 |   /// so this symbol will be ignored by usage-checking inspections. <br/>
 445 |   /// You can use <see cref="ImplicitUseKindFlags"/> and <see cref="ImplicitUseTargetFlags"/>
 446 |   /// to configure how this attribute is applied.
 447 |   /// </summary>
 448 |   /// <example><code>
 449 |   /// [UsedImplicitly]
 450 |   /// public class TypeConverter {}
 451 |   /// 
 452 |   /// public class SummaryData
 453 |   /// {
 454 |   ///   [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
 455 |   ///   public SummaryData() {}
 456 |   /// }
 457 |   /// 
 458 |   /// [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors | ImplicitUseTargetFlags.Default)]
 459 |   /// public interface IService {}
 460 |   /// </code></example>
 461 |   [AttributeUsage(AttributeTargets.All)]
 462 |   public sealed class UsedImplicitlyAttribute : Attribute
 463 |   {
 464 |     public UsedImplicitlyAttribute()
 465 |       : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
 466 | 
 467 |     public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
 468 |       : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
 469 | 
 470 |     public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
 471 |       : this(ImplicitUseKindFlags.Default, targetFlags) { }
 472 | 
 473 |     public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
 474 |     {
 475 |       UseKindFlags = useKindFlags;
 476 |       TargetFlags = targetFlags;
 477 |     }
 478 | 
 479 |     public ImplicitUseKindFlags UseKindFlags { get; }
 480 | 
 481 |     public ImplicitUseTargetFlags TargetFlags { get; }
 482 |   }
 483 | 
 484 |   /// <summary>
 485 |   /// Can be applied to attributes, type parameters, and parameters of a type assignable from <see cref="System.Type"/> .
 486 |   /// When applied to an attribute, the decorated attribute behaves the same as <see cref="UsedImplicitlyAttribute"/>.
 487 |   /// When applied to a type parameter or to a parameter of type <see cref="System.Type"/>,
 488 |   /// indicates that the corresponding type is used implicitly.
 489 |   /// </summary>
 490 |   [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)]
 491 |   public sealed class MeansImplicitUseAttribute : Attribute
 492 |   {
 493 |     public MeansImplicitUseAttribute()
 494 |       : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
 495 | 
 496 |     public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
 497 |       : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
 498 | 
 499 |     public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
 500 |       : this(ImplicitUseKindFlags.Default, targetFlags) { }
 501 | 
 502 |     public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
 503 |     {
 504 |       UseKindFlags = useKindFlags;
 505 |       TargetFlags = targetFlags;
 506 |     }
 507 | 
 508 |     [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; }
 509 | 
 510 |     [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; }
 511 |   }
 512 | 
 513 |   /// <summary>
 514 |   /// Specifies the details of implicitly used symbol when it is marked
 515 |   /// with <see cref="MeansImplicitUseAttribute"/> or <see cref="UsedImplicitlyAttribute"/>.
 516 |   /// </summary>
 517 |   [Flags]
 518 |   public enum ImplicitUseKindFlags
 519 |   {
 520 |     Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
 521 |     /// <summary>Only entity marked with attribute considered used.</summary>
 522 |     Access = 1,
 523 |     /// <summary>Indicates implicit assignment to a member.</summary>
 524 |     Assign = 2,
 525 |     /// <summary>
 526 |     /// Indicates implicit instantiation of a type with fixed constructor signature.
 527 |     /// That means any unused constructor parameters won't be reported as such.
 528 |     /// </summary>
 529 |     InstantiatedWithFixedConstructorSignature = 4,
 530 |     /// <summary>Indicates implicit instantiation of a type.</summary>
 531 |     InstantiatedNoFixedConstructorSignature = 8,
 532 |   }
 533 | 
 534 |   /// <summary>
 535 |   /// Specifies what is considered to be used implicitly when marked
 536 |   /// with <see cref="MeansImplicitUseAttribute"/> or <see cref="UsedImplicitlyAttribute"/>.
 537 |   /// </summary>
 538 |   [Flags]
 539 |   public enum ImplicitUseTargetFlags
 540 |   {
 541 |     Default = Itself,
 542 |     Itself = 1,
 543 |     /// <summary>Members of the type marked with the attribute are considered used.</summary>
 544 |     Members = 2,
 545 |     /// <summary> Inherited entities are considered used. </summary>
 546 |     WithInheritors = 4,
 547 |     /// <summary>Entity marked with the attribute and all its members considered used.</summary>
 548 |     WithMembers = Itself | Members
 549 |   }
 550 | 
 551 |   /// <summary>
 552 |   /// This attribute is intended to mark publicly available API,
 553 |   /// which should not be removed and so is treated as used.
 554 |   /// </summary>
 555 |   [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)]
 556 |   [AttributeUsage(AttributeTargets.All, Inherited = false)]
 557 |   public sealed class PublicAPIAttribute : Attribute
 558 |   {
 559 |     public PublicAPIAttribute() { }
 560 | 
 561 |     public PublicAPIAttribute([NotNull] string comment)
 562 |     {
 563 |       Comment = comment;
 564 |     }
 565 | 
 566 |     [CanBeNull] public string Comment { get; }
 567 |   }
 568 | 
 569 |   /// <summary>
 570 |   /// Tells the code analysis engine if the parameter is completely handled when the invoked method is on stack.
 571 |   /// If the parameter is a delegate, indicates that delegate is executed while the method is executed.
 572 |   /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed.
 573 |   /// </summary>
 574 |   [AttributeUsage(AttributeTargets.Parameter)]
 575 |   public sealed class InstantHandleAttribute : Attribute { }
 576 | 
 577 |   /// <summary>
 578 |   /// Indicates that a method does not make any observable state changes.
 579 |   /// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>.
 580 |   /// </summary>
 581 |   /// <example><code>
 582 |   /// [Pure] int Multiply(int x, int y) => x * y;
 583 |   /// 
 584 |   /// void M() {
 585 |   ///   Multiply(123, 42); // Warning: Return value of pure method is not used
 586 |   /// }
 587 |   /// </code></example>
 588 |   [AttributeUsage(AttributeTargets.Method)]
 589 |   public sealed class PureAttribute : Attribute { }
 590 | 
 591 |   /// <summary>
 592 |   /// Indicates that the return value of the method invocation must be used.
 593 |   /// </summary>
 594 |   /// <remarks>
 595 |   /// Methods decorated with this attribute (in contrast to pure methods) might change state,
 596 |   /// but make no sense without using their return value. <br/>
 597 |   /// Similarly to <see cref="PureAttribute"/>, this attribute
 598 |   /// will help to detect usages of the method when the return value is not used.
 599 |   /// Optionally, you can specify a message to use when showing warnings, e.g.
 600 |   /// <code>[MustUseReturnValue("Use the return value to...")]</code>.
 601 |   /// </remarks>
 602 |   [AttributeUsage(AttributeTargets.Method)]
 603 |   public sealed class MustUseReturnValueAttribute : Attribute
 604 |   {
 605 |     public MustUseReturnValueAttribute() { }
 606 | 
 607 |     public MustUseReturnValueAttribute([NotNull] string justification)
 608 |     {
 609 |       Justification = justification;
 610 |     }
 611 | 
 612 |     [CanBeNull] public string Justification { get; }
 613 |   }
 614 | 
 615 |   /// <summary>
 616 |   /// This annotation allows to enforce allocation-less usage patterns of delegates for performance-critical APIs.
 617 |   /// When this annotation is applied to the parameter of delegate type, IDE checks the input argument of this parameter:
 618 |   /// * When lambda expression or anonymous method is passed as an argument, IDE verifies that the passed closure
 619 |   ///   has no captures of the containing local variables and the compiler is able to cache the delegate instance
 620 |   ///   to avoid heap allocations. Otherwise the warning is produced.
 621 |   /// * IDE warns when method name or local function name is passed as an argument as this always results
 622 |   ///   in heap allocation of the delegate instance.
 623 |   /// </summary>
 624 |   /// <remarks>
 625 |   /// In C# 9.0 code IDE would also suggest to annotate the anonymous function with 'static' modifier
 626 |   /// to make use of the similar analysis provided by the language/compiler.
 627 |   /// </remarks>
 628 |   [AttributeUsage(AttributeTargets.Parameter)]
 629 |   public class RequireStaticDelegateAttribute : Attribute
 630 |   {
 631 |     public bool IsError { get; set; }
 632 |   }
 633 | 
 634 |   /// <summary>
 635 |   /// Indicates the type member or parameter of some type, that should be used instead of all other ways
 636 |   /// to get the value of that type. This annotation is useful when you have some "context" value evaluated
 637 |   /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one.
 638 |   /// </summary>
 639 |   /// <example><code>
 640 |   /// class Foo {
 641 |   ///   [ProvidesContext] IBarService _barService = ...;
 642 |   /// 
 643 |   ///   void ProcessNode(INode node) {
 644 |   ///     DoSomething(node, node.GetGlobalServices().Bar);
 645 |   ///     //              ^ Warning: use value of '_barService' field
 646 |   ///   }
 647 |   /// }
 648 |   /// </code></example>
 649 |   [AttributeUsage(
 650 |     AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method |
 651 |     AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)]
 652 |   public sealed class ProvidesContextAttribute : Attribute { }
 653 | 
 654 |   /// <summary>
 655 |   /// Indicates that a parameter is a path to a file or a folder within a web project.
 656 |   /// Path can be relative or absolute, starting from web root (~).
 657 |   /// </summary>
 658 |   [AttributeUsage(AttributeTargets.Parameter)]
 659 |   public sealed class PathReferenceAttribute : Attribute
 660 |   {
 661 |     public PathReferenceAttribute() { }
 662 | 
 663 |     public PathReferenceAttribute([NotNull, PathReference] string basePath)
 664 |     {
 665 |       BasePath = basePath;
 666 |     }
 667 | 
 668 |     [CanBeNull] public string BasePath { get; }
 669 |   }
 670 | 
 671 |   /// <summary>
 672 |   /// An extension method marked with this attribute is processed by code completion
 673 |   /// as a 'Source Template'. When the extension method is completed over some expression, its source code
 674 |   /// is automatically expanded like a template at call site.
 675 |   /// </summary>
 676 |   /// <remarks>
 677 |   /// Template method body can contain valid source code and/or special comments starting with '
#39;.
 678 |   /// Text inside these comments is added as source code when the template is applied. Template parameters
 679 |   /// can be used either as additional method parameters or as identifiers wrapped in two '
#39; signs.
 680 |   /// Use the <see cref="MacroAttribute"/> attribute to specify macros for parameters.
 681 |   /// </remarks>
 682 |   /// <example>
 683 |   /// In this example, the 'forEach' method is a source template available over all values
 684 |   /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block:
 685 |   /// <code>
 686 |   /// [SourceTemplate]
 687 |   /// public static void forEach&lt;T&gt;(this IEnumerable&lt;T&gt; xs) {
 688 |   ///   foreach (var x in xs) {
 689 |   ///      //$ $END$
 690 |   ///   }
 691 |   /// }
 692 |   /// </code>
 693 |   /// </example>
 694 |   [AttributeUsage(AttributeTargets.Method)]
 695 |   public sealed class SourceTemplateAttribute : Attribute { }
 696 | 
 697 |   /// <summary>
 698 |   /// Allows specifying a macro for a parameter of a <see cref="SourceTemplateAttribute">source template</see>.
 699 |   /// </summary>
 700 |   /// <remarks>
 701 |   /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression
 702 |   /// is defined in the <see cref="MacroAttribute.Expression"/> property. When applied on a method, the target
 703 |   /// template parameter is defined in the <see cref="MacroAttribute.Target"/> property. To apply the macro silently
 704 |   /// for the parameter, set the <see cref="MacroAttribute.Editable"/> property value = -1.
 705 |   /// </remarks>
 706 |   /// <example>
 707 |   /// Applying the attribute on a source template method:
 708 |   /// <code>
 709 |   /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")]
 710 |   /// public static void forEach&lt;T&gt;(this IEnumerable&lt;T&gt; collection) {
 711 |   ///   foreach (var item in collection) {
 712 |   ///     //$ $END$
 713 |   ///   }
 714 |   /// }
 715 |   /// </code>
 716 |   /// Applying the attribute on a template method parameter:
 717 |   /// <code>
 718 |   /// [SourceTemplate]
 719 |   /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) {
 720 |   ///   /*$ var $x$Id = "$newguid
quot; + x.ToString();
 721 |   ///   x.DoSomething($x$Id); */
 722 |   /// }
 723 |   /// </code>
 724 |   /// </example>
 725 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)]
 726 |   public sealed class MacroAttribute : Attribute
 727 |   {
 728 |     /// <summary>
 729 |     /// Allows specifying a macro that will be executed for a <see cref="SourceTemplateAttribute">source template</see>
 730 |     /// parameter when the template is expanded.
 731 |     /// </summary>
 732 |     [CanBeNull] public string Expression { get; set; }
 733 | 
 734 |     /// <summary>
 735 |     /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed.
 736 |     /// </summary>
 737 |     /// <remarks>
 738 |     /// If the target parameter is used several times in the template, only one occurrence becomes editable;
 739 |     /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence,
 740 |     /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1.
 741 |     /// </remarks>
 742 |     public int Editable { get; set; }
 743 | 
 744 |     /// <summary>
 745 |     /// Identifies the target parameter of a <see cref="SourceTemplateAttribute">source template</see> if the
 746 |     /// <see cref="MacroAttribute"/> is applied on a template method.
 747 |     /// </summary>
 748 |     [CanBeNull] public string Target { get; set; }
 749 |   }
 750 | 
 751 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 752 |   public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute
 753 |   {
 754 |     public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format)
 755 |     {
 756 |       Format = format;
 757 |     }
 758 | 
 759 |     [NotNull] public string Format { get; }
 760 |   }
 761 | 
 762 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 763 |   public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute
 764 |   {
 765 |     public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format)
 766 |     {
 767 |       Format = format;
 768 |     }
 769 | 
 770 |     [NotNull] public string Format { get; }
 771 |   }
 772 | 
 773 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 774 |   public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute
 775 |   {
 776 |     public AspMvcAreaViewLocationFormatAttribute([NotNull] string format)
 777 |     {
 778 |       Format = format;
 779 |     }
 780 | 
 781 |     [NotNull] public string Format { get; }
 782 |   }
 783 | 
 784 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 785 |   public sealed class AspMvcMasterLocationFormatAttribute : Attribute
 786 |   {
 787 |     public AspMvcMasterLocationFormatAttribute([NotNull] string format)
 788 |     {
 789 |       Format = format;
 790 |     }
 791 | 
 792 |     [NotNull] public string Format { get; }
 793 |   }
 794 | 
 795 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 796 |   public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute
 797 |   {
 798 |     public AspMvcPartialViewLocationFormatAttribute([NotNull] string format)
 799 |     {
 800 |       Format = format;
 801 |     }
 802 | 
 803 |     [NotNull] public string Format { get; }
 804 |   }
 805 | 
 806 |   [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
 807 |   public sealed class AspMvcViewLocationFormatAttribute : Attribute
 808 |   {
 809 |     public AspMvcViewLocationFormatAttribute([NotNull] string format)
 810 |     {
 811 |       Format = format;
 812 |     }
 813 | 
 814 |     [NotNull] public string Format { get; }
 815 |   }
 816 | 
 817 |   /// <summary>
 818 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
 819 |   /// is an MVC action. If applied to a method, the MVC action name is calculated
 820 |   /// implicitly from the context. Use this attribute for custom wrappers similar to
 821 |   /// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>.
 822 |   /// </summary>
 823 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
 824 |   public sealed class AspMvcActionAttribute : Attribute
 825 |   {
 826 |     public AspMvcActionAttribute() { }
 827 | 
 828 |     public AspMvcActionAttribute([NotNull] string anonymousProperty)
 829 |     {
 830 |       AnonymousProperty = anonymousProperty;
 831 |     }
 832 | 
 833 |     [CanBeNull] public string AnonymousProperty { get; }
 834 |   }
 835 | 
 836 |   /// <summary>
 837 |   /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area.
 838 |   /// Use this attribute for custom wrappers similar to
 839 |   /// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>.
 840 |   /// </summary>
 841 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 842 |   public sealed class AspMvcAreaAttribute : Attribute
 843 |   {
 844 |     public AspMvcAreaAttribute() { }
 845 | 
 846 |     public AspMvcAreaAttribute([NotNull] string anonymousProperty)
 847 |     {
 848 |       AnonymousProperty = anonymousProperty;
 849 |     }
 850 | 
 851 |     [CanBeNull] public string AnonymousProperty { get; }
 852 |   }
 853 | 
 854 |   /// <summary>
 855 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is
 856 |   /// an MVC controller. If applied to a method, the MVC controller name is calculated
 857 |   /// implicitly from the context. Use this attribute for custom wrappers similar to
 858 |   /// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)</c>.
 859 |   /// </summary>
 860 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
 861 |   public sealed class AspMvcControllerAttribute : Attribute
 862 |   {
 863 |     public AspMvcControllerAttribute() { }
 864 | 
 865 |     public AspMvcControllerAttribute([NotNull] string anonymousProperty)
 866 |     {
 867 |       AnonymousProperty = anonymousProperty;
 868 |     }
 869 | 
 870 |     [CanBeNull] public string AnonymousProperty { get; }
 871 |   }
 872 | 
 873 |   /// <summary>
 874 |   /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute
 875 |   /// for custom wrappers similar to <c>System.Web.Mvc.Controller.View(String, String)</c>.
 876 |   /// </summary>
 877 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 878 |   public sealed class AspMvcMasterAttribute : Attribute { }
 879 | 
 880 |   /// <summary>
 881 |   /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute
 882 |   /// for custom wrappers similar to <c>System.Web.Mvc.Controller.View(String, Object)</c>.
 883 |   /// </summary>
 884 |   [AttributeUsage(AttributeTargets.Parameter)]
 885 |   public sealed class AspMvcModelTypeAttribute : Attribute { }
 886 | 
 887 |   /// <summary>
 888 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC
 889 |   /// partial view. If applied to a method, the MVC partial view name is calculated implicitly
 890 |   /// from the context. Use this attribute for custom wrappers similar to
 891 |   /// <c>System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)</c>.
 892 |   /// </summary>
 893 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
 894 |   public sealed class AspMvcPartialViewAttribute : Attribute { }
 895 | 
 896 |   /// <summary>
 897 |   /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method.
 898 |   /// </summary>
 899 |   [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
 900 |   public sealed class AspMvcSuppressViewErrorAttribute : Attribute { }
 901 | 
 902 |   /// <summary>
 903 |   /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
 904 |   /// Use this attribute for custom wrappers similar to
 905 |   /// <c>System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)</c>.
 906 |   /// </summary>
 907 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 908 |   public sealed class AspMvcDisplayTemplateAttribute : Attribute { }
 909 | 
 910 |   /// <summary>
 911 |   /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template.
 912 |   /// Use this attribute for custom wrappers similar to
 913 |   /// <c>System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)</c>.
 914 |   /// </summary>
 915 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 916 |   public sealed class AspMvcEditorTemplateAttribute : Attribute { }
 917 | 
 918 |   /// <summary>
 919 |   /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template.
 920 |   /// Use this attribute for custom wrappers similar to
 921 |   /// <c>System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)</c>.
 922 |   /// </summary>
 923 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 924 |   public sealed class AspMvcTemplateAttribute : Attribute { }
 925 | 
 926 |   /// <summary>
 927 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
 928 |   /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly
 929 |   /// from the context. Use this attribute for custom wrappers similar to
 930 |   /// <c>System.Web.Mvc.Controller.View(Object)</c>.
 931 |   /// </summary>
 932 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
 933 |   public sealed class AspMvcViewAttribute : Attribute { }
 934 | 
 935 |   /// <summary>
 936 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
 937 |   /// is an MVC view component name.
 938 |   /// </summary>
 939 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 940 |   public sealed class AspMvcViewComponentAttribute : Attribute { }
 941 | 
 942 |   /// <summary>
 943 |   /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
 944 |   /// is an MVC view component view. If applied to a method, the MVC view component view name is default.
 945 |   /// </summary>
 946 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
 947 |   public sealed class AspMvcViewComponentViewAttribute : Attribute { }
 948 | 
 949 |   /// <summary>
 950 |   /// ASP.NET MVC attribute. When applied to a parameter of an attribute,
 951 |   /// indicates that this parameter is an MVC action name.
 952 |   /// </summary>
 953 |   /// <example><code>
 954 |   /// [ActionName("Foo")]
 955 |   /// public ActionResult Login(string returnUrl) {
 956 |   ///   ViewBag.ReturnUrl = Url.Action("Foo"); // OK
 957 |   ///   return RedirectToAction("Bar"); // Error: Cannot resolve action
 958 |   /// }
 959 |   /// </code></example>
 960 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
 961 |   public sealed class AspMvcActionSelectorAttribute : Attribute { }
 962 | 
 963 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)]
 964 |   public sealed class HtmlElementAttributesAttribute : Attribute
 965 |   {
 966 |     public HtmlElementAttributesAttribute() { }
 967 | 
 968 |     public HtmlElementAttributesAttribute([NotNull] string name)
 969 |     {
 970 |       Name = name;
 971 |     }
 972 | 
 973 |     [CanBeNull] public string Name { get; }
 974 |   }
 975 | 
 976 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
 977 |   public sealed class HtmlAttributeValueAttribute : Attribute
 978 |   {
 979 |     public HtmlAttributeValueAttribute([NotNull] string name)
 980 |     {
 981 |       Name = name;
 982 |     }
 983 | 
 984 |     [NotNull] public string Name { get; }
 985 |   }
 986 | 
 987 |   /// <summary>
 988 |   /// Razor attribute. Indicates that the marked parameter or method is a Razor section.
 989 |   /// Use this attribute for custom wrappers similar to
 990 |   /// <c>System.Web.WebPages.WebPageBase.RenderSection(String)</c>.
 991 |   /// </summary>
 992 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
 993 |   public sealed class RazorSectionAttribute : Attribute { }
 994 | 
 995 |   /// <summary>
 996 |   /// Indicates how method, constructor invocation, or property access
 997 |   /// over collection type affects the contents of the collection.
 998 |   /// Use <see cref="CollectionAccessType"/> to specify the access type.
 999 |   /// </summary>
1000 |   /// <remarks>
1001 |   /// Using this attribute only makes sense if all collection methods are marked with this attribute.
1002 |   /// </remarks>
1003 |   /// <example><code>
1004 |   /// public class MyStringCollection : List&lt;string&gt;
1005 |   /// {
1006 |   ///   [CollectionAccess(CollectionAccessType.Read)]
1007 |   ///   public string GetFirstString()
1008 |   ///   {
1009 |   ///     return this.ElementAt(0);
1010 |   ///   }
1011 |   /// }
1012 |   /// class Test
1013 |   /// {
1014 |   ///   public void Foo()
1015 |   ///   {
1016 |   ///     // Warning: Contents of the collection is never updated
1017 |   ///     var col = new MyStringCollection();
1018 |   ///     string x = col.GetFirstString();
1019 |   ///   }
1020 |   /// }
1021 |   /// </code></example>
1022 |   [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
1023 |   public sealed class CollectionAccessAttribute : Attribute
1024 |   {
1025 |     public CollectionAccessAttribute(CollectionAccessType collectionAccessType)
1026 |     {
1027 |       CollectionAccessType = collectionAccessType;
1028 |     }
1029 | 
1030 |     public CollectionAccessType CollectionAccessType { get; }
1031 |   }
1032 | 
1033 |   /// <summary>
1034 |   /// Provides a value for the <see cref="CollectionAccessAttribute"/> to define
1035 |   /// how the collection method invocation affects the contents of the collection.
1036 |   /// </summary>
1037 |   [Flags]
1038 |   public enum CollectionAccessType
1039 |   {
1040 |     /// <summary>Method does not use or modify content of the collection.</summary>
1041 |     None = 0,
1042 |     /// <summary>Method only reads content of the collection but does not modify it.</summary>
1043 |     Read = 1,
1044 |     /// <summary>Method can change content of the collection but does not add new elements.</summary>
1045 |     ModifyExistingContent = 2,
1046 |     /// <summary>Method can add new elements to the collection.</summary>
1047 |     UpdatedContent = ModifyExistingContent | 4
1048 |   }
1049 | 
1050 |   /// <summary>
1051 |   /// Indicates that the marked method is assertion method, i.e. it halts the control flow if
1052 |   /// one of the conditions is satisfied. To set the condition, mark one of the parameters with
1053 |   /// <see cref="AssertionConditionAttribute"/> attribute.
1054 |   /// </summary>
1055 |   [AttributeUsage(AttributeTargets.Method)]
1056 |   public sealed class AssertionMethodAttribute : Attribute { }
1057 | 
1058 |   /// <summary>
1059 |   /// Indicates the condition parameter of the assertion method. The method itself should be
1060 |   /// marked by <see cref="AssertionMethodAttribute"/> attribute. The mandatory argument of
1061 |   /// the attribute is the assertion type.
1062 |   /// </summary>
1063 |   [AttributeUsage(AttributeTargets.Parameter)]
1064 |   public sealed class AssertionConditionAttribute : Attribute
1065 |   {
1066 |     public AssertionConditionAttribute(AssertionConditionType conditionType)
1067 |     {
1068 |       ConditionType = conditionType;
1069 |     }
1070 | 
1071 |     public AssertionConditionType ConditionType { get; }
1072 |   }
1073 | 
1074 |   /// <summary>
1075 |   /// Specifies assertion type. If the assertion method argument satisfies the condition,
1076 |   /// then the execution continues. Otherwise, execution is assumed to be halted.
1077 |   /// </summary>
1078 |   public enum AssertionConditionType
1079 |   {
1080 |     /// <summary>Marked parameter should be evaluated to true.</summary>
1081 |     IS_TRUE = 0,
1082 |     /// <summary>Marked parameter should be evaluated to false.</summary>
1083 |     IS_FALSE = 1,
1084 |     /// <summary>Marked parameter should be evaluated to null value.</summary>
1085 |     IS_NULL = 2,
1086 |     /// <summary>Marked parameter should be evaluated to not null value.</summary>
1087 |     IS_NOT_NULL = 3,
1088 |   }
1089 | 
1090 |   /// <summary>
1091 |   /// Indicates that the marked method unconditionally terminates control flow execution.
1092 |   /// For example, it could unconditionally throw exception.
1093 |   /// </summary>
1094 |   [Obsolete("Use [ContractAnnotation('=> halt')] instead")]
1095 |   [AttributeUsage(AttributeTargets.Method)]
1096 |   public sealed class TerminatesProgramAttribute : Attribute { }
1097 | 
1098 |   /// <summary>
1099 |   /// Indicates that the method is a pure LINQ method, with postponed enumeration (like Enumerable.Select,
1100 |   /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters
1101 |   /// of delegate type by analyzing LINQ method chains.
1102 |   /// </summary>
1103 |   [AttributeUsage(AttributeTargets.Method)]
1104 |   public sealed class LinqTunnelAttribute : Attribute { }
1105 | 
1106 |   /// <summary>
1107 |   /// Indicates that IEnumerable passed as a parameter is not enumerated.
1108 |   /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection.
1109 |   /// </summary>
1110 |   /// <example><code>
1111 |   /// static void ThrowIfNull&lt;T&gt;([NoEnumeration] T v, string n) where T : class
1112 |   /// {
1113 |   ///   // custom check for null but no enumeration
1114 |   /// }
1115 |   /// 
1116 |   /// void Foo(IEnumerable&lt;string&gt; values)
1117 |   /// {
1118 |   ///   ThrowIfNull(values, nameof(values));
1119 |   ///   var x = values.ToList(); // No warnings about multiple enumeration
1120 |   /// }
1121 |   /// </code></example>
1122 |   [AttributeUsage(AttributeTargets.Parameter)]
1123 |   public sealed class NoEnumerationAttribute : Attribute { }
1124 | 
1125 |   /// <summary>
1126 |   /// Indicates that the marked parameter, field, or property is a regular expression pattern.
1127 |   /// </summary>
1128 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
1129 |   public sealed class RegexPatternAttribute : Attribute { }
1130 | 
1131 |   /// <summary>
1132 |   /// Prevents the Member Reordering feature from tossing members of the marked class.
1133 |   /// </summary>
1134 |   /// <remarks>
1135 |   /// The attribute must be mentioned in your member reordering patterns.
1136 |   /// </remarks>
1137 |   [AttributeUsage(
1138 |     AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)]
1139 |   public sealed class NoReorderAttribute : Attribute { }
1140 | 
1141 |   /// <summary>
1142 |   /// XAML attribute. Indicates the type that has <c>ItemsSource</c> property and should be treated
1143 |   /// as <c>ItemsControl</c>-derived type, to enable inner items <c>DataContext</c> type resolve.
1144 |   /// </summary>
1145 |   [AttributeUsage(AttributeTargets.Class)]
1146 |   public sealed class XamlItemsControlAttribute : Attribute { }
1147 | 
1148 |   /// <summary>
1149 |   /// XAML attribute. Indicates the property of some <c>BindingBase</c>-derived type, that
1150 |   /// is used to bind some item of <c>ItemsControl</c>-derived type. This annotation will
1151 |   /// enable the <c>DataContext</c> type resolve for XAML bindings for such properties.
1152 |   /// </summary>
1153 |   /// <remarks>
1154 |   /// Property should have the tree ancestor of the <c>ItemsControl</c> type or
1155 |   /// marked with the <see cref="XamlItemsControlAttribute"/> attribute.
1156 |   /// </remarks>
1157 |   [AttributeUsage(AttributeTargets.Property)]
1158 |   public sealed class XamlItemBindingOfItemsControlAttribute : Attribute { }
1159 | 
1160 |   /// <summary>
1161 |   /// XAML attribute. Indicates the property of some <c>Style</c>-derived type, that
1162 |   /// is used to style items of <c>ItemsControl</c>-derived type. This annotation will
1163 |   /// enable the <c>DataContext</c> type resolve for XAML bindings for such properties.
1164 |   /// </summary>
1165 |   /// <remarks>
1166 |   /// Property should have the tree ancestor of the <c>ItemsControl</c> type or
1167 |   /// marked with the <see cref="XamlItemsControlAttribute"/> attribute.
1168 |   /// </remarks>
1169 |   [AttributeUsage(AttributeTargets.Property)]
1170 |   public sealed class XamlItemStyleOfItemsControlAttribute : Attribute { }
1171 | 
1172 |   /// <summary>
1173 |   /// XAML attribute. Indicates that DependencyProperty has <c>OneWay</c> binding mode by default.
1174 |   /// </summary>
1175 |   /// <remarks>
1176 |   /// This attribute must be applied to DependencyProperty's CLR accessor property if it is present, to DependencyProperty descriptor field otherwise.
1177 |   /// </remarks>
1178 |   [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
1179 |   public sealed class XamlOneWayBindingModeByDefaultAttribute : Attribute { }
1180 | 
1181 |   /// <summary>
1182 |   /// XAML attribute. Indicates that DependencyProperty has <c>TwoWay</c> binding mode by default.
1183 |   /// </summary>
1184 |   /// <remarks>
1185 |   /// This attribute must be applied to DependencyProperty's CLR accessor property if it is present, to DependencyProperty descriptor field otherwise.
1186 |   /// </remarks>
1187 |   [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
1188 |   public sealed class XamlTwoWayBindingModeByDefaultAttribute : Attribute { }
1189 | 
1190 |   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
1191 |   public sealed class AspChildControlTypeAttribute : Attribute
1192 |   {
1193 |     public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType)
1194 |     {
1195 |       TagName = tagName;
1196 |       ControlType = controlType;
1197 |     }
1198 | 
1199 |     [NotNull] public string TagName { get; }
1200 | 
1201 |     [NotNull] public Type ControlType { get; }
1202 |   }
1203 | 
1204 |   [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
1205 |   public sealed class AspDataFieldAttribute : Attribute { }
1206 | 
1207 |   [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
1208 |   public sealed class AspDataFieldsAttribute : Attribute { }
1209 | 
1210 |   [AttributeUsage(AttributeTargets.Property)]
1211 |   public sealed class AspMethodPropertyAttribute : Attribute { }
1212 | 
1213 |   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
1214 |   public sealed class AspRequiredAttributeAttribute : Attribute
1215 |   {
1216 |     public AspRequiredAttributeAttribute([NotNull] string attribute)
1217 |     {
1218 |       Attribute = attribute;
1219 |     }
1220 | 
1221 |     [NotNull] public string Attribute { get; }
1222 |   }
1223 | 
1224 |   [AttributeUsage(AttributeTargets.Property)]
1225 |   public sealed class AspTypePropertyAttribute : Attribute
1226 |   {
1227 |     public bool CreateConstructorReferences { get; }
1228 | 
1229 |     public AspTypePropertyAttribute(bool createConstructorReferences)
1230 |     {
1231 |       CreateConstructorReferences = createConstructorReferences;
1232 |     }
1233 |   }
1234 | 
1235 |   [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
1236 |   public sealed class RazorImportNamespaceAttribute : Attribute
1237 |   {
1238 |     public RazorImportNamespaceAttribute([NotNull] string name)
1239 |     {
1240 |       Name = name;
1241 |     }
1242 | 
1243 |     [NotNull] public string Name { get; }
1244 |   }
1245 | 
1246 |   [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
1247 |   public sealed class RazorInjectionAttribute : Attribute
1248 |   {
1249 |     public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName)
1250 |     {
1251 |       Type = type;
1252 |       FieldName = fieldName;
1253 |     }
1254 | 
1255 |     [NotNull] public string Type { get; }
1256 | 
1257 |     [NotNull] public string FieldName { get; }
1258 |   }
1259 | 
1260 |   [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
1261 |   public sealed class RazorDirectiveAttribute : Attribute
1262 |   {
1263 |     public RazorDirectiveAttribute([NotNull] string directive)
1264 |     {
1265 |       Directive = directive;
1266 |     }
1267 | 
1268 |     [NotNull] public string Directive { get; }
1269 |   }
1270 | 
1271 |   [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
1272 |   public sealed class RazorPageBaseTypeAttribute : Attribute
1273 |   {
1274 |       public RazorPageBaseTypeAttribute([NotNull] string baseType)
1275 |       {
1276 |         BaseType = baseType;
1277 |       }
1278 |       public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName)
1279 |       {
1280 |           BaseType = baseType;
1281 |           PageName = pageName;
1282 |       }
1283 | 
1284 |       [NotNull] public string BaseType { get; }
1285 |       [CanBeNull] public string PageName { get; }
1286 |   }
1287 | 
1288 |   [AttributeUsage(AttributeTargets.Method)]
1289 |   public sealed class RazorHelperCommonAttribute : Attribute { }
1290 | 
1291 |   [AttributeUsage(AttributeTargets.Property)]
1292 |   public sealed class RazorLayoutAttribute : Attribute { }
1293 | 
1294 |   [AttributeUsage(AttributeTargets.Method)]
1295 |   public sealed class RazorWriteLiteralMethodAttribute : Attribute { }
1296 | 
1297 |   [AttributeUsage(AttributeTargets.Method)]
1298 |   public sealed class RazorWriteMethodAttribute : Attribute { }
1299 | 
1300 |   [AttributeUsage(AttributeTargets.Parameter)]
1301 |   public sealed class RazorWriteMethodParameterAttribute : Attribute { }
1302 | 
1303 |   /// <summary>
1304 |   /// Indicates that the marked parameter, field, or property is a route template.
1305 |   /// </summary>
1306 |   /// <remarks>
1307 |   /// This attribute allows IDE to recognize the use of web frameworks' route templates
1308 |   /// to enable syntax highlighting, code completion, navigation, rename and other features in string literals.
1309 |   /// </remarks>
1310 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
1311 |   public sealed class RouteTemplateAttribute : Attribute { }
1312 | 
1313 |   /// <summary>
1314 |   /// Indicates that the marked type is custom route parameter constraint,
1315 |   /// which is registered in application's Startup with name <c>ConstraintName</c>
1316 |   /// </summary>
1317 |   /// <remarks>
1318 |   /// You can specify <c>ProposedType</c> if target constraint matches only route parameters of specific type,
1319 |   /// it will allow IDE to create method's parameter from usage in route template
1320 |   /// with specified type instead of default <c>System.String</c>
1321 |   /// and check if constraint's proposed type conflicts with matched parameter's type
1322 |   /// </remarks>
1323 |   [AttributeUsage(AttributeTargets.Class)]
1324 |   public sealed class RouteParameterConstraintAttribute : Attribute
1325 |   {
1326 |     [NotNull] public string ConstraintName { get; }
1327 |     [CanBeNull] public Type ProposedType { get; set; }
1328 | 
1329 |     public RouteParameterConstraintAttribute([NotNull] string constraintName)
1330 |     {
1331 |       ConstraintName = constraintName;
1332 |     }
1333 |   }
1334 | 
1335 |   /// <summary>
1336 |   /// Indicates that the marked parameter, field, or property is an URI string.
1337 |   /// </summary>
1338 |   /// <remarks>
1339 |   /// This attribute enables code completion, navigation, rename and other features
1340 |   /// in URI string literals assigned to annotated parameter, field or property.
1341 |   /// </remarks>
1342 |   [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
1343 |   public sealed class UriStringAttribute : Attribute
1344 |   {
1345 |     public UriStringAttribute() { }
1346 | 
1347 |     public UriStringAttribute(string httpVerb)
1348 |     {
1349 |       HttpVerb = httpVerb;
1350 |     }
1351 | 
1352 |     [CanBeNull] public string HttpVerb { get; }
1353 |   }
1354 | }
1355 | 


--------------------------------------------------------------------------------
/ClickShow/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
 1 | using System.Reflection;
 2 | using System.Resources;
 3 | using System.Runtime.CompilerServices;
 4 | using System.Runtime.InteropServices;
 5 | using System.Windows;
 6 | 
 7 | // General Information about an assembly is controlled through the following
 8 | // set of attributes. Change these attribute values to modify the information
 9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("ClickShow")]
11 | [assembly: AssemblyDescription("Show Mouse Clicks.")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("https://github.com/cuiliang")]
14 | [assembly: AssemblyProduct("ClickShow")]
15 | [assembly: AssemblyCopyright("Copyright ©  2021 By CuiLiang")]
16 | [assembly: AssemblyTrademark("https://github.com/cuiliang")]
17 | [assembly: AssemblyCulture("")]
18 | 
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components.  If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 | 
24 | //In order to begin building localizable applications, set
25 | //<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
26 | //inside a <PropertyGroup>.  For example, if you are using US english
27 | //in your source files, set the <UICulture> to en-US.  Then uncomment
28 | //the NeutralResourceLanguage attribute below.  Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 | 
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 | 
33 | 
34 | [assembly: ThemeInfo(
35 |     ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 |                                      //(used if a resource is not found in the page,
37 |                                      // or application resource dictionaries)
38 |     ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 |                                               //(used if a resource is not found in the page,
40 |                                               // app, or any theme specific resource dictionaries)
41 | )]
42 | 
43 | 
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | //      Major Version
47 | //      Minor Version
48 | //      Build Number
49 | //      Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.4.1.0")]
55 | [assembly: AssemblyFileVersion("1.4.1.0")]
56 | 


--------------------------------------------------------------------------------
/ClickShow/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
 1 | //------------------------------------------------------------------------------
 2 | // <auto-generated>
 3 | //     This code was generated by a tool.
 4 | //     Runtime Version:4.0.30319.42000
 5 | //
 6 | //     Changes to this file may cause incorrect behavior and will be lost if
 7 | //     the code is regenerated.
 8 | // </auto-generated>
 9 | //------------------------------------------------------------------------------
10 | 
11 | 
12 | namespace ClickShow.Properties
13 | {
14 |     /// <summary>
15 |     ///   A strongly-typed resource class, for looking up localized strings, etc.
16 |     /// </summary>
17 |     // This class was auto-generated by the StronglyTypedResourceBuilder
18 |     // class via a tool like ResGen or Visual Studio.
19 |     // To add or remove a member, edit your .ResX file then rerun ResGen
20 |     // with the /str option, or rebuild your VS project.
21 |     [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 |     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 |     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 |     internal class Resources
25 |     {
26 | 
27 |         private static global::System.Resources.ResourceManager resourceMan;
28 | 
29 |         private static global::System.Globalization.CultureInfo resourceCulture;
30 | 
31 |         [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 |         internal Resources()
33 |         {
34 |         }
35 | 
36 |         /// <summary>
37 |         ///   Returns the cached ResourceManager instance used by this class.
38 |         /// </summary>
39 |         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
40 |         internal static global::System.Resources.ResourceManager ResourceManager
41 |         {
42 |             get
43 |             {
44 |                 if ((resourceMan == null))
45 |                 {
46 |                     global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClickShow.Properties.Resources", typeof(Resources).Assembly);
47 |                     resourceMan = temp;
48 |                 }
49 |                 return resourceMan;
50 |             }
51 |         }
52 | 
53 |         /// <summary>
54 |         ///   Overrides the current thread's CurrentUICulture property for all
55 |         ///   resource lookups using this strongly typed resource class.
56 |         /// </summary>
57 |         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
58 |         internal static global::System.Globalization.CultureInfo Culture
59 |         {
60 |             get
61 |             {
62 |                 return resourceCulture;
63 |             }
64 |             set
65 |             {
66 |                 resourceCulture = value;
67 |             }
68 |         }
69 |     }
70 | }
71 | 


--------------------------------------------------------------------------------
/ClickShow/Properties/Resources.resx:
--------------------------------------------------------------------------------
  1 | <?xml version="1.0" encoding="utf-8"?>
  2 | <root>
  3 |   <!-- 
  4 |     Microsoft ResX Schema 
  5 |     
  6 |     Version 2.0
  7 |     
  8 |     The primary goals of this format is to allow a simple XML format 
  9 |     that is mostly human readable. The generation and parsing of the 
 10 |     various data types are done through the TypeConverter classes 
 11 |     associated with the data types.
 12 |     
 13 |     Example:
 14 |     
 15 |     ... ado.net/XML headers & schema ...
 16 |     <resheader name="resmimetype">text/microsoft-resx</resheader>
 17 |     <resheader name="version">2.0</resheader>
 18 |     <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
 19 |     <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
 20 |     <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
 21 |     <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
 22 |     <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
 23 |         <value>[base64 mime encoded serialized .NET Framework object]</value>
 24 |     </data>
 25 |     <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
 26 |         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
 27 |         <comment>This is a comment</comment>
 28 |     </data>
 29 |                 
 30 |     There are any number of "resheader" rows that contain simple 
 31 |     name/value pairs.
 32 |     
 33 |     Each data row contains a name, and value. The row also contains a 
 34 |     type or mimetype. Type corresponds to a .NET class that support 
 35 |     text/value conversion through the TypeConverter architecture. 
 36 |     Classes that don't support this are serialized and stored with the 
 37 |     mimetype set.
 38 |     
 39 |     The mimetype is used for serialized objects, and tells the 
 40 |     ResXResourceReader how to depersist the object. This is currently not 
 41 |     extensible. For a given mimetype the value must be set accordingly:
 42 |     
 43 |     Note - application/x-microsoft.net.object.binary.base64 is the format 
 44 |     that the ResXResourceWriter will generate, however the reader can 
 45 |     read any of the formats listed below.
 46 |     
 47 |     mimetype: application/x-microsoft.net.object.binary.base64
 48 |     value   : The object must be serialized with 
 49 |             : System.Serialization.Formatters.Binary.BinaryFormatter
 50 |             : and then encoded with base64 encoding.
 51 |     
 52 |     mimetype: application/x-microsoft.net.object.soap.base64
 53 |     value   : The object must be serialized with 
 54 |             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
 55 |             : and then encoded with base64 encoding.
 56 | 
 57 |     mimetype: application/x-microsoft.net.object.bytearray.base64
 58 |     value   : The object must be serialized into a byte array 
 59 |             : using a System.ComponentModel.TypeConverter
 60 |             : and then encoded with base64 encoding.
 61 |     -->
 62 |   <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
 63 |     <xsd:element name="root" msdata:IsDataSet="true">
 64 |       <xsd:complexType>
 65 |         <xsd:choice maxOccurs="unbounded">
 66 |           <xsd:element name="metadata">
 67 |             <xsd:complexType>
 68 |               <xsd:sequence>
 69 |                 <xsd:element name="value" type="xsd:string" minOccurs="0" />
 70 |               </xsd:sequence>
 71 |               <xsd:attribute name="name" type="xsd:string" />
 72 |               <xsd:attribute name="type" type="xsd:string" />
 73 |               <xsd:attribute name="mimetype" type="xsd:string" />
 74 |             </xsd:complexType>
 75 |           </xsd:element>
 76 |           <xsd:element name="assembly">
 77 |             <xsd:complexType>
 78 |               <xsd:attribute name="alias" type="xsd:string" />
 79 |               <xsd:attribute name="name" type="xsd:string" />
 80 |             </xsd:complexType>
 81 |           </xsd:element>
 82 |           <xsd:element name="data">
 83 |             <xsd:complexType>
 84 |               <xsd:sequence>
 85 |                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
 86 |                 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
 87 |               </xsd:sequence>
 88 |               <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
 89 |               <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
 90 |               <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
 91 |             </xsd:complexType>
 92 |           </xsd:element>
 93 |           <xsd:element name="resheader">
 94 |             <xsd:complexType>
 95 |               <xsd:sequence>
 96 |                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
 97 |               </xsd:sequence>
 98 |               <xsd:attribute name="name" type="xsd:string" use="required" />
 99 |             </xsd:complexType>
100 |           </xsd:element>
101 |         </xsd:choice>
102 |       </xsd:complexType>
103 |     </xsd:element>
104 |   </xsd:schema>
105 |   <resheader name="resmimetype">
106 |     <value>text/microsoft-resx</value>
107 |   </resheader>
108 |   <resheader name="version">
109 |     <value>2.0</value>
110 |   </resheader>
111 |   <resheader name="reader">
112 |     <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
113 |   </resheader>
114 |   <resheader name="writer">
115 |     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116 |   </resheader>
117 | </root>


--------------------------------------------------------------------------------
/ClickShow/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
 1 | //------------------------------------------------------------------------------
 2 | // <auto-generated>
 3 | //     This code was generated by a tool.
 4 | //     Runtime Version:4.0.30319.42000
 5 | //
 6 | //     Changes to this file may cause incorrect behavior and will be lost if
 7 | //     the code is regenerated.
 8 | // </auto-generated>
 9 | //------------------------------------------------------------------------------
10 | 
11 | namespace ClickShow.Properties {
12 |     
13 |     
14 |     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 |     [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
16 |     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |         
18 |         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |         
20 |         public static Settings Default {
21 |             get {
22 |                 return defaultInstance;
23 |             }
24 |         }
25 |     }
26 | }
27 | 


--------------------------------------------------------------------------------
/ClickShow/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 | <?xml version='1.0' encoding='utf-8'?>
2 | <SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
3 |   <Profiles>
4 |     <Profile Name="(Default)" />
5 |   </Profiles>
6 |   <Settings />
7 | </SettingsFile>


--------------------------------------------------------------------------------
/ClickShow/Settings/AppSetting.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.CodeDom;
  3 | using System.Collections.Generic;
  4 | using System.ComponentModel;
  5 | using System.Linq;
  6 | using System.Runtime.CompilerServices;
  7 | using System.Text;
  8 | using System.Threading.Tasks;
  9 | using System.Windows.Forms;
 10 | using System.Windows.Media;
 11 | using ClickShow.Annotations;
 12 | using ClickShow.Utility;
 13 | 
 14 | namespace ClickShow.Settings
 15 | {
 16 |     /// <summary>
 17 |     /// 设置信息
 18 |     /// </summary>
 19 |     public class AppSetting : INotifyPropertyChanged
 20 |     {
 21 |         private bool _enableClickCircle = true;
 22 |         private bool _enableHoverDot = false;
 23 |         private Dictionary<MouseButtons, ButtonSetting> _mouseButtonSettings = new Dictionary<MouseButtons, ButtonSetting>()
 24 |         {
 25 |             {MouseButtons.Left, new ButtonSetting(Colors.DodgerBlue.ToArgb())},
 26 |             {MouseButtons.Middle, new ButtonSetting(Colors.Green.ToArgb())},
 27 |             {MouseButtons.Right, new ButtonSetting(Colors.OrangeRed.ToArgb())},
 28 |             {MouseButtons.XButton1, new ButtonSetting(Colors.Gray.ToArgb())},
 29 |             {MouseButtons.XButton2, new ButtonSetting(Colors.BlueViolet.ToArgb())}   
 30 |         };
 31 | 
 32 |         private double _indicatorSize = 150;
 33 |         private double _hoverDotSize = 60;
 34 |         private string _hoverDotFill = "#60FFFF5A";
 35 | 
 36 |         /// <summary>
 37 |         /// 开启波纹特效
 38 |         /// </summary>
 39 |         public bool EnableClickCircle
 40 |         {
 41 |             get => _enableClickCircle;
 42 |             set
 43 |             {
 44 |                 _enableClickCircle = value;
 45 |                 OnPropertyChanged();
 46 |             }
 47 |         }
 48 | 
 49 |         /// <summary>
 50 |         /// 开启浮标显示
 51 |         /// </summary>
 52 |         public bool EnableHoverDot
 53 |         {
 54 |             get => _enableHoverDot;
 55 |             set
 56 |             {
 57 |                 _enableHoverDot = value;
 58 |                 OnPropertyChanged();
 59 |             }
 60 |         }
 61 | 
 62 |         /// <summary>
 63 |         /// 鼠标按键设置
 64 |         /// </summary>
 65 |         public Dictionary<MouseButtons, ButtonSetting> MouseButtonSettings
 66 |         {
 67 |             get => _mouseButtonSettings;
 68 |             set => _mouseButtonSettings = value;
 69 |         }
 70 | 
 71 |         /// <summary>
 72 |         /// 波纹尺寸
 73 |         /// </summary>
 74 |         public double IndicatorSize
 75 |         {
 76 |             get => _indicatorSize;
 77 |             set
 78 |             {
 79 |                 _indicatorSize = value;
 80 |                 OnPropertyChanged();
 81 |             }
 82 |         }
 83 | 
 84 |         /// <summary>
 85 |         /// 浮标尺寸
 86 |         /// </summary>
 87 |         public double HoverDotSize
 88 |         {
 89 |             get => _hoverDotSize;
 90 |             set
 91 |             {
 92 |                 _hoverDotSize = value;
 93 |                 OnPropertyChanged();
 94 |             }
 95 |         }
 96 | 
 97 |         /// <summary>
 98 |         /// 浮标颜色
 99 |         /// </summary>
100 |         public string HoverDotFill
101 |         {
102 |             get => _hoverDotFill;
103 |             set
104 |             {
105 |                 _hoverDotFill = value; 
106 |                 OnPropertyChanged();
107 |             }
108 |         }
109 | 
110 |         public event PropertyChangedEventHandler PropertyChanged;
111 | 
112 |         [NotifyPropertyChangedInvocator]
113 |         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
114 |         {
115 |             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
116 |         }
117 | 
118 |         /// <summary>
119 |         /// 上次提醒的最新版本,避免重复提醒。
120 |         /// </summary>
121 |         public string LastNotifiedVersion { get; set; }
122 |     }
123 | }
124 | 


--------------------------------------------------------------------------------
/ClickShow/Settings/ButtonSetting.cs:
--------------------------------------------------------------------------------
 1 | using System.ComponentModel;
 2 | using System.Runtime.CompilerServices;
 3 | using ClickShow.Annotations;
 4 | 
 5 | namespace ClickShow.Settings
 6 | {
 7 |     /// <summary>
 8 |     /// 单个鼠标按钮的设置
 9 |     /// </summary>
10 |     public class ButtonSetting: INotifyPropertyChanged
11 |     {
12 |         private bool _isEnabled = true;
13 |         private string _color;
14 | 
15 |         public ButtonSetting()
16 |         {
17 |         }
18 | 
19 |         public ButtonSetting(bool isEnabled, string color)
20 |         {
21 |             IsEnabled = isEnabled;
22 |             Color = color;
23 |         }
24 | 
25 |         public ButtonSetting(string color)
26 |             :this(true, color)
27 |         {
28 |             
29 |         }
30 | 
31 |         /// <summary>
32 |         /// 是否启用
33 |         /// </summary>
34 |         public bool IsEnabled
35 |         {
36 |             get => _isEnabled;
37 |             set
38 |             {
39 |                 _isEnabled = value; 
40 |                 OnPropertyChanged();
41 |             }
42 |         }
43 | 
44 |         /// <summary>
45 |         /// 波纹颜色
46 |         /// </summary>
47 |         public string Color
48 |         {
49 |             get => _color;
50 |             set
51 |             {
52 |                 _color = value;
53 |                 OnPropertyChanged();
54 |             }
55 |         }
56 | 
57 |         public event PropertyChangedEventHandler PropertyChanged;
58 | 
59 |         [NotifyPropertyChangedInvocator]
60 |         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
61 |         {
62 |             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
63 |         }
64 |     }
65 | }


--------------------------------------------------------------------------------
/ClickShow/UI/ClickIndicator.xaml:
--------------------------------------------------------------------------------
 1 | <Window
 2 |     x:Class="ClickShow.ClickIndicator"
 3 |     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4 |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5 |     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6 |     xmlns:local="clr-namespace:ClickShow"
 7 |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8 |     Title="点击查看器"
 9 |     Width="150"
10 |     Height="150"
11 |     AllowsTransparency="True"
12 |     Background="Transparent"
13 |     ShowInTaskbar="False"
14 |     Topmost="True"
15 |     WindowStartupLocation="CenterScreen"
16 |     WindowStyle="None"
17 |     mc:Ignorable="d">
18 |     <Grid>
19 |         <Ellipse
20 |             Name="TheCircle"
21 |             Width="0"
22 |             Height="0"
23 |             HorizontalAlignment="Center"
24 |             VerticalAlignment="Center"
25 |             Stroke="Blue"
26 |             StrokeThickness="3" />
27 |     </Grid>
28 | </Window>
29 | 


--------------------------------------------------------------------------------
/ClickShow/UI/ClickIndicator.xaml.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.Diagnostics;
  4 | using System.Linq;
  5 | using System.Text;
  6 | using System.Threading.Tasks;
  7 | using System.Windows;
  8 | using System.Windows.Controls;
  9 | using System.Windows.Data;
 10 | using System.Windows.Documents;
 11 | using System.Windows.Input;
 12 | using System.Windows.Interop;
 13 | using System.Windows.Media;
 14 | using System.Windows.Media.Animation;
 15 | using System.Windows.Media.Imaging;
 16 | using System.Windows.Shapes;
 17 | 
 18 | namespace ClickShow
 19 | {
 20 |     /// <summary>
 21 |     /// Interaction logic for ClickIndicator.xaml
 22 |     /// </summary>
 23 |     public partial class ClickIndicator : Window
 24 |     {
 25 |         private Storyboard _mouseDownStoryBoard;
 26 |         private Storyboard _mouseUpStoryBoard;
 27 |         public int LastLiveTime { get; set; } = Environment.TickCount;
 28 | 
 29 |         public ClickIndicator(double size)
 30 |         {
 31 |             ShowActivated = false;
 32 |             InitializeComponent();
 33 | 
 34 |             this.Width = size;
 35 |             this.Height = size;
 36 | 
 37 |             SourceInitialized += OnSourceInitialized;
 38 |             DpiChanged += OnDpiChanged;
 39 | 
 40 |             RenderOptions.SetBitmapScalingMode(TheCircle, BitmapScalingMode.LowQuality);
 41 | 
 42 |             CreateMouseDownStoryBoard();
 43 |             CreateMouseUpStoryBoard();
 44 |             //Play();
 45 |         }
 46 | 
 47 |         /// <summary>
 48 |         /// 鼠标抬起特效
 49 |         /// </summary>
 50 |         private void CreateMouseUpStoryBoard()
 51 |         {
 52 |             // 初始化动画
 53 |             double interval = 0.3;
 54 |             _mouseUpStoryBoard = new Storyboard();
 55 |             _mouseUpStoryBoard.FillBehavior = FillBehavior.Stop;
 56 | 
 57 | 
 58 |             var widthAnimation = new DoubleAnimation(toValue: this.Width / 2, new Duration(TimeSpan.FromSeconds(interval)));
 59 |             Storyboard.SetTargetProperty(widthAnimation, new PropertyPath("Width"));
 60 |             Storyboard.SetTarget(widthAnimation, TheCircle);
 61 |             _mouseUpStoryBoard.Children.Add(widthAnimation);
 62 | 
 63 |             var heightAnimation = new DoubleAnimation(toValue: this.Height / 2, new Duration(TimeSpan.FromSeconds(interval)));
 64 |             Storyboard.SetTargetProperty(heightAnimation, new PropertyPath("Height"));
 65 |             Storyboard.SetTarget(heightAnimation, TheCircle);
 66 |             _mouseUpStoryBoard.Children.Add(heightAnimation);
 67 | 
 68 |             var opacityAnimation = new DoubleAnimation(toValue: 0, new Duration(TimeSpan.FromSeconds(interval)));
 69 |             Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity"));
 70 |             Storyboard.SetTarget(opacityAnimation, TheCircle);
 71 |             _mouseUpStoryBoard.Children.Add(opacityAnimation);
 72 | 
 73 |             _mouseUpStoryBoard.Completed += MouseDownStoryBoardOnCompleted;
 74 |             if (_mouseUpStoryBoard.CanFreeze)
 75 |             {
 76 |                 _mouseUpStoryBoard.Freeze();
 77 |             }
 78 |         }
 79 | 
 80 |         /// <summary>
 81 |         /// 鼠标按下特效
 82 |         /// </summary>
 83 |         private void CreateMouseDownStoryBoard()
 84 |         {
 85 |             // 初始化动画
 86 |             double interval = 0.4;
 87 |             _mouseDownStoryBoard = new Storyboard();
 88 |             _mouseDownStoryBoard.FillBehavior = FillBehavior.Stop;
 89 | 
 90 | 
 91 |             var widthAnimation = new DoubleAnimation(toValue: this.Width, new Duration(TimeSpan.FromSeconds(interval)));
 92 |             Storyboard.SetTargetProperty(widthAnimation, new PropertyPath("Width"));
 93 |             Storyboard.SetTarget(widthAnimation, TheCircle);
 94 |             _mouseDownStoryBoard.Children.Add(widthAnimation);
 95 | 
 96 |             var heightAnimation = new DoubleAnimation(toValue: this.Height, new Duration(TimeSpan.FromSeconds(interval)));
 97 |             Storyboard.SetTargetProperty(heightAnimation, new PropertyPath("Height"));
 98 |             Storyboard.SetTarget(heightAnimation, TheCircle);
 99 |             _mouseDownStoryBoard.Children.Add(heightAnimation);
100 | 
101 |             var opacityAnimation = new DoubleAnimation(toValue: 0, new Duration(TimeSpan.FromSeconds(interval)));
102 |             Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity"));
103 |             Storyboard.SetTarget(opacityAnimation, TheCircle);
104 |             _mouseDownStoryBoard.Children.Add(opacityAnimation);
105 | 
106 |             _mouseDownStoryBoard.Completed += MouseDownStoryBoardOnCompleted;
107 |             if (_mouseDownStoryBoard.CanFreeze)
108 |             {
109 |                 _mouseDownStoryBoard.Freeze();
110 |             }
111 |         }
112 | 
113 |         private void OnDpiChanged(object sender, DpiChangedEventArgs e)
114 |         {
115 |             DpiHasChanged = true;
116 |             _currentDpi = e.NewDpi;
117 |         }
118 | 
119 |         public double GetDpiScale()
120 |         {
121 |             if (_currentDpi.DpiScaleX < 0.1)
122 |             {
123 |                 _currentDpi = VisualTreeHelper.GetDpi(this);
124 | 
125 | 
126 |             }
127 | 
128 |             return _currentDpi.DpiScaleX;
129 |         }
130 | 
131 | 
132 |         public bool IsIdle { get; private set; } = false;
133 | 
134 |         private DpiScale _currentDpi;
135 | 
136 | 
137 | 
138 |         public bool DpiHasChanged { get; private set; } = false;
139 | 
140 |         public void Prepare()
141 |         {
142 |             IsIdle = false;
143 |         }
144 | 
145 |         public void Play(Brush circleBrush, bool isDown)
146 |         {
147 |             this.LastLiveTime = Environment.TickCount;
148 |             Opacity = isDown ? 0.95 : 0.7;
149 | 
150 |             // 抬起特效
151 | 
152 | 
153 |             TheCircle.Stroke = circleBrush;
154 | 
155 |             IsIdle = false;
156 | 
157 |             if (isDown)
158 |             {
159 |                 TheCircle.Width = this.Width * 0.2;
160 |                 TheCircle.Height = this.Height * 0.2;
161 |                 _mouseDownStoryBoard.Begin();
162 |             }
163 |             else
164 |             {
165 |                 _mouseUpStoryBoard.Begin();
166 |             }
167 | 
168 | 
169 |             this.Show();
170 |         }
171 | 
172 | 
173 | 
174 |         private void OnSourceInitialized(object sender, EventArgs e)
175 |         {
176 |             WindowHelper.SetWindowExTransparent(new WindowInteropHelper(this).Handle);
177 |         }
178 | 
179 |         private void MouseDownStoryBoardOnCompleted(object sender, EventArgs e)
180 |         {
181 | 
182 |             TheCircle.Width = 0;
183 |             TheCircle.Height = 0;
184 |             this.Opacity = 0;
185 | 
186 |             IsIdle = true;
187 |             DpiHasChanged = false;
188 |         }
189 |     }
190 | }
191 | 


--------------------------------------------------------------------------------
/ClickShow/UI/HoverDot.xaml:
--------------------------------------------------------------------------------
 1 | <Window
 2 |     x:Class="ClickShow.HoverDot"
 3 |     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4 |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5 |     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6 |     xmlns:local="clr-namespace:ClickShow"
 7 |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8 |     Title="HoverDot"
 9 |     Width="60"
10 |     Height="60"
11 |     x:Name="DotWindow"
12 |     AllowsTransparency="True"
13 |     Background="Transparent"
14 |     ShowActivated="False"
15 |     ShowInTaskbar="False"
16 |     Topmost="True"
17 |     WindowStartupLocation="Manual"
18 |     WindowStyle="None"
19 |     mc:Ignorable="d">
20 |     <Grid>
21 |         <Ellipse
22 |             x:Name="Dot"
23 |             Width="{Binding Width, ElementName=DotWindow}"
24 |             Height="{Binding Height, ElementName=DotWindow}"
25 |             HorizontalAlignment="Center"
26 |             VerticalAlignment="Center"
27 |             Fill="#FFFF5a" />
28 |     </Grid>
29 | </Window>
30 | 


--------------------------------------------------------------------------------
/ClickShow/UI/HoverDot.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | using System.Windows.Controls;
 8 | using System.Windows.Data;
 9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Interop;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Shapes;
15 | 
16 | namespace ClickShow
17 | {
18 |     /// <summary>
19 |     /// Interaction logic for HoverDot.xaml
20 |     /// </summary>
21 |     public partial class HoverDot : Window
22 |     {
23 |         public HoverDot()
24 |         {
25 |             InitializeComponent();
26 | 
27 |             SourceInitialized += OnSourceInitialized;
28 |             DpiChanged += OnDpiChanged;
29 |         }
30 | 
31 |         private void OnDpiChanged(object sender, DpiChangedEventArgs e)
32 |         {
33 |             _currentDpi = e.NewDpi;
34 |         }
35 | 
36 |         private DpiScale _currentDpi;
37 | 
38 |         public double GetDpiScale()
39 |         {
40 |             if (_currentDpi.DpiScaleX < 0.1)
41 |             {
42 |                 _currentDpi = VisualTreeHelper.GetDpi(this);
43 |             }
44 |             
45 |             return _currentDpi.DpiScaleX;
46 |         }
47 | 
48 |         private void OnSourceInitialized(object sender, EventArgs e)
49 |         {
50 |             WindowHelper.SetWindowExTransparent(new WindowInteropHelper(this).Handle);
51 |         }
52 | 
53 |         /// <summary>
54 |         /// 设置填充画刷
55 |         /// </summary>
56 |         /// <param name="brush"></param>
57 |         public void SetDotBrush(Brush brush)
58 |         {
59 |             Dot.Fill = brush;
60 |         }
61 |     }
62 | }
63 | 


--------------------------------------------------------------------------------
/ClickShow/UI/MainWindow.xaml:
--------------------------------------------------------------------------------
 1 | <Window
 2 |     x:Class="ClickShow.MainWindow"
 3 |     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4 |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5 |     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6 |     xmlns:local="clr-namespace:ClickShow"
 7 |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8 |     xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
 9 |     Name="TheWindow"
10 |     Title="ClickShow"
11 |     Width="450"
12 |     Height="450"
13 |     MinWidth="250"
14 |     MinHeight="100"
15 |     ResizeMode="CanMinimize"
16 |     SizeToContent="Height"
17 |     WindowStartupLocation="CenterScreen"
18 |     mc:Ignorable="d">
19 |     <Grid Margin="20,30,20,40">
20 |         <Grid.ColumnDefinitions>
21 |             <ColumnDefinition Width="*" />
22 |             <ColumnDefinition Width="*" />
23 |         </Grid.ColumnDefinitions>
24 |         <StackPanel
25 |             Grid.Column="0"
26 |             HorizontalAlignment="Left"
27 |             VerticalAlignment="Center"
28 |             Orientation="Vertical">
29 | 
30 |             <CheckBox
31 |                 Name="ChkStartWithWindows"
32 |                 Margin="5"
33 |                 VerticalContentAlignment="Center"
34 |                 Click="ChkStartWithWindows_OnClick"
35 |                 Content="开机自动启动(_S)"
36 |                 ToolTip="是否开机自动启动" />
37 | 
38 |             <StackPanel Name="PnlSettings" DataContext="{Binding ElementName=TheWindow, Path=AppSetting}">
39 |                 <CheckBox
40 |                     Name="ChkEnableClickCircle"
41 |                     Margin="5"
42 |                     VerticalContentAlignment="Center"
43 |                     Content="显示点击特效(_C)"
44 |                     IsChecked="{Binding Path=EnableClickCircle}"
45 |                     ToolTip="点击时显示波纹特效" />
46 | 
47 | 
48 |                 <CheckBox
49 |                     Name="ChkEnableHoverDot"
50 |                     Margin="5"
51 |                     VerticalContentAlignment="Center"
52 |                     Content="显示位置提示浮标(_F)"
53 |                     IsChecked="{Binding Path=EnableHoverDot}"
54 |                     ToolTip="在鼠标指针周围显示原点,跟随鼠标移动" />
55 | 
56 | 
57 |             </StackPanel>
58 | 
59 | 
60 |         </StackPanel>
61 |         <StackPanel Grid.Column="1" VerticalAlignment="Center">
62 |             <TextBlock Margin="10" HorizontalAlignment="Center">
63 |                 <Hyperlink NavigateUri="https://github.com/cuiliang/clickshow" RequestNavigate="HyperlinkOpenHomepage_OnRequestNavigate">反馈与更新 / Homepage</Hyperlink>                
64 |                 <LineBreak></LineBreak>
65 |                 <TextBlock Name="LblNewVersion" Foreground="OrangeRed" FontWeight="Bold" Visibility="Collapsed" Text="已有新版本!"/>
66 |             </TextBlock>
67 |             
68 | 
69 |             <Grid>
70 |                 <Grid.ColumnDefinitions>
71 |                     <ColumnDefinition Width="*" />
72 |                     <ColumnDefinition Width="Auto" />
73 |                 </Grid.ColumnDefinitions>
74 |                 <Button
75 |                     Name="BtnSettings"
76 |                     Margin="5"
77 |                     Padding="10,7"
78 |                     Click="BtnSettings_OnClick"
79 |                     Content="更多设置(_S)..." />
80 | 
81 |                 <Button
82 |                     Name="BtnClose"
83 |                     Grid.Column="1"
84 |                     Margin="5"
85 |                     Padding="10,7"
86 |                     Click="BtnClose_OnClick"
87 |                     Content="退出(_X)" />
88 |             </Grid>
89 | 
90 | 
91 |         </StackPanel>
92 |     </Grid>
93 | 
94 | </Window>
95 | 


--------------------------------------------------------------------------------
/ClickShow/UI/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.ComponentModel;
  4 | using System.Diagnostics;
  5 | using System.IO;
  6 | using System.Linq;
  7 | using System.Net;
  8 | using System.Reflection;
  9 | using System.Runtime.InteropServices;
 10 | using System.Threading.Tasks;
 11 | using System.Windows;
 12 | using System.Windows.Forms;
 13 | using System.Windows.Interop;
 14 | using System.Windows.Media;
 15 | using System.Windows.Navigation;
 16 | using System.Windows.Threading;
 17 | using ClickShow.Settings;
 18 | using ClickShow.UI;
 19 | using ClickShow.Utility;
 20 | using Microsoft.Win32;
 21 | using Brush = System.Windows.Media.Brush;
 22 | using Brushes = System.Windows.Media.Brushes;
 23 | using Exception = System.Exception;
 24 | using MessageBox = System.Windows.MessageBox;
 25 | using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
 26 | using MouseButtonState = ClickShow.Entities.MouseButtonState;
 27 | using Point = System.Drawing.Point;
 28 | 
 29 | namespace ClickShow
 30 | {
 31 | 
 32 | 
 33 |     /// <summary>
 34 |     /// Interaction logic for MainWindow.xaml
 35 |     /// </summary>
 36 |     public partial class MainWindow : Window
 37 |     {
 38 |         private const long UP_SHOW_DISTANCE = 200;  //移动超过多少像素后显示抬起特效
 39 |         private const long UP_TICKS_DELTA = 500;   //长按多久后抬起显示抬起特效
 40 | 
 41 | 
 42 |         private MouseHook.MouseHook _mouseHook;
 43 | 
 44 |         // 窗口缓存,解决连续点击的显示问题
 45 | 
 46 | 
 47 |         private NotifyIcon _notifyIcon = null;
 48 | 
 49 |         /// <summary>
 50 |         /// 强制关闭窗口
 51 |         /// </summary>
 52 |         private bool _forceClose = false;
 53 | 
 54 |         /// <summary>
 55 |         /// 程序设置
 56 |         /// </summary>
 57 |         public AppSetting AppSetting { get; private set; }
 58 | 
 59 | 
 60 |         #region 窗口事件
 61 | 
 62 |         public MainWindow()
 63 |         {
 64 |             InitializeComponent();
 65 | 
 66 | 
 67 |             Loaded += OnLoaded;
 68 |             Closing += OnClosing;
 69 |             Closed += OnClosed;
 70 |             StateChanged += OnStateChanged;
 71 | 
 72 |             CreateNotifyIcon();
 73 |         }
 74 | 
 75 |         private void OnLoaded(object sender, RoutedEventArgs e)
 76 |         {
 77 |             LoadSettings();
 78 | 
 79 |             WindowState = WindowState.Minimized;
 80 | 
 81 |             // update auto startup checkbox
 82 |             LoadAutoStartStatus();
 83 | 
 84 |             // 设置
 85 |             PnlSettings.DataContext = AppSetting;
 86 |             
 87 | 
 88 |             //
 89 |             Title = 
quot;ClickShow {Assembly.GetExecutingAssembly().GetName().Version.ToString()}";
 90 | 
 91 | 
 92 |             ApplySettings();
 93 | 
 94 | 
 95 |             // 最后启动挂钩
 96 |             _mouseHook = new MouseHook.MouseHook();
 97 |             _mouseHook.MouseDown += MouseHookOnMouseDown;
 98 |             _mouseHook.MouseMove += MouseHookOnMouseMove;
 99 |             _mouseHook.MouseUp += MouseHookOnMouseUp;
100 |             _mouseHook.Start();
101 | 
102 |             // 检查版本更新
103 |             Task.Run(async () =>
104 |             {
105 |                 await Task.Delay(1000 * 10 );
106 |                 CheckUpdate();
107 |             });
108 |             
109 |         }
110 | 
111 |         public Version NewVersion { get; set; }
112 | 
113 |         /// <summary>
114 |         /// 检查版本更新
115 |         /// </summary>
116 |         private void CheckUpdate()
117 |         {
118 |             // 版本号检查网址
119 |             string url = "https://helperservice.getquicker.cn/clickshow/version";
120 |             string updateUrl = "https://github.com/cuiliang/ClickShow/releases";
121 | 
122 |             try
123 |             {
124 |                 var client = new WebClient();
125 |                 
126 |                 // 下载版本信息字符串。可能格式:(1)只有版本号。 (2)版本号|网址
127 |                 var versionStr = client.DownloadString(url);
128 | 
129 |                 if (versionStr.Contains("|"))
130 |                 {
131 |                     string[] parts = versionStr.Split('|');
132 |                     NewVersion = new Version(parts[0]);
133 |                     updateUrl = String.IsNullOrEmpty(parts[1]) ? updateUrl : parts[1];
134 |                 }
135 |                 else
136 |                 {
137 |                     NewVersion = new Version(versionStr);
138 |                 }
139 | 
140 | 
141 |               
142 | 
143 |                 // 版本落后了
144 |                 if (NewVersion > Assembly.GetExecutingAssembly().GetName().Version)
145 |                 {
146 |                     // 如果之前已经提示了此版本,则不再提示,不然每次开机都会有一个提示了。
147 |                     if (String.Equals(AppSetting.LastNotifiedVersion, versionStr))
148 |                     {
149 |                         Dispatcher.InvokeAsync(() =>
150 |                         {
151 |                             LblNewVersion.Visibility = Visibility.Visible;
152 | 
153 |                         });
154 |                     }
155 |                     else
156 |                     {
157 |                         AppSetting.LastNotifiedVersion = versionStr;
158 |                         SaveSettings();
159 | 
160 |                         if (MessageBox.Show(
quot;ClickShow有新版本({versionStr}),是否立即打开网页?", "ClickShow", MessageBoxButton.YesNo, MessageBoxImage.Information) != MessageBoxResult.Yes)
161 |                         {
162 |                             return;
163 |                         }
164 |                         try
165 |                         {
166 |                             Process.Start(updateUrl);
167 |                         }
168 |                         catch
169 |                         {
170 |                             MessageBox.Show(
quot;无法打开网址:{updateUrl}");
171 |                         }
172 |                     }
173 |                 }
174 |             }
175 |             catch (Exception ex)
176 |             {
177 |                 // ignore error
178 |             }
179 | 
180 |         }
181 | 
182 |         /// <summary>
183 |         /// 如果是点了x关闭窗口,则隐藏窗口而不是退出程序。
184 |         /// </summary>
185 |         private void OnClosing(object sender, CancelEventArgs e)
186 |         {
187 |             if (!_forceClose)
188 |             {
189 |                 e.Cancel = true;
190 |                 this.Hide();
191 |             }
192 |         }
193 | 
194 |         private void OnClosed(object sender, EventArgs e)
195 |         {
196 |             SaveSettings();
197 |             _mouseHook.MouseMove -= MouseHookOnMouseMove;
198 |             _mouseHook.MouseDown -= MouseHookOnMouseDown;
199 |             _mouseHook.Stop();
200 | 
201 |             _notifyIcon.Visible = false;
202 | 
203 |             foreach (var x in _clickIndicators)
204 |             {
205 |                 x.Close();
206 |             }
207 | 
208 |             _hoverDot?.Close();
209 | 
210 | 
211 |         }
212 | 
213 |         /// <summary>
214 |         /// 窗口状态改变了
215 |         /// </summary>
216 |         private void OnStateChanged(object sender, EventArgs e)
217 |         {
218 |             if (WindowState == WindowState.Minimized)
219 |             {
220 |                 this.Hide();
221 |             }
222 |         }
223 | 
224 |         private void BtnClose_OnClick(object sender, RoutedEventArgs e)
225 |         {
226 |             _forceClose = true;
227 |             this.Close();
228 |         }
229 | 
230 |         /// <summary>
231 |         /// 打开主页
232 |         /// </summary>
233 |         private void HyperlinkOpenHomepage_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
234 |         {
235 |             try
236 |             {
237 |                 Process.Start("https://github.com/cuiliang/clickshow");
238 |             }
239 |             catch
240 |             {
241 |                 MessageBox.Show("无法打开网址:https://github.com/cuiliang/clickshow");
242 |             }
243 |         }
244 | 
245 |         #endregion
246 | 
247 |         #region 鼠标位置浮标
248 | 
249 |         // 浮标窗口
250 |         private HoverDot _hoverDot = null;
251 | 
252 |         /// <summary>
253 |         /// 更新浮标的可见性
254 |         /// </summary>
255 |         private void UpdateHoverDot()
256 |         {
257 |             if (AppSetting.EnableHoverDot)
258 |             {
259 |                 if (_hoverDot == null)
260 |                 {
261 |                     _hoverDot = new HoverDot();
262 |                 }
263 | 
264 |                 _hoverDot.Width = _hoverDot.Height = AppSetting.HoverDotSize;
265 |                 _hoverDot.SetDotBrush(AppSetting.HoverDotFill.ToBrush());
266 | 
267 |                 _hoverDot.Show();
268 |             }
269 |             else
270 |             {
271 |                 if (_hoverDot != null)
272 |                 {
273 |                     _hoverDot.Close();
274 |                     _hoverDot = null;
275 |                 }
276 |             }
277 |         }
278 | 
279 |         #endregion
280 | 
281 |         #region 点击波纹效果
282 | 
283 |         /// <summary>
284 |         /// 可用的波纹窗口
285 |         /// </summary>
286 |         private IList<ClickIndicator> _clickIndicators = new List<ClickIndicator>();
287 | 
288 |         /// <summary>
289 |         /// 各个鼠标按键对应的颜色画刷
290 |         /// </summary>
291 |         private IDictionary<MouseButtons, Brush> _buttonBrushes = new Dictionary<MouseButtons, Brush>()
292 |         {
293 |             {MouseButtons.None, Brushes.Black},
294 |             {MouseButtons.Left, Brushes.DodgerBlue},
295 |             {MouseButtons.Middle, Brushes.Green},
296 |             {MouseButtons.Right, Brushes.OrangeRed},
297 |             {MouseButtons.XButton1, Brushes.Gray},
298 |             {MouseButtons.XButton2, Brushes.BlueViolet},
299 |         };
300 | 
301 |         /// <summary>
302 |         /// 各按键的状态,用于判断是否应该显示抬起特效。
303 |         /// </summary>
304 |         private readonly IDictionary<MouseButtons, MouseButtonState> _buttonStates =
305 |             new Dictionary<MouseButtons, MouseButtonState>()
306 |             {
307 |                 {MouseButtons.Left, new MouseButtonState()},
308 |                 {MouseButtons.Middle, new MouseButtonState()},
309 |                 {MouseButtons.Right, new MouseButtonState()},
310 |                 {MouseButtons.XButton1, new MouseButtonState()},
311 |                 {MouseButtons.XButton2, new MouseButtonState()},
312 |             };
313 | 
314 |         /// <summary>
315 |         /// 获取一个可用的波纹窗口。
316 |         /// </summary>
317 |         /// <returns>波纹窗口对象</returns>
318 |         private ClickIndicator GetClickIndicatorWindow()
319 |         {
320 | 
321 |             var indicator = _clickIndicators.FirstOrDefault(x => x.IsIdle 
322 |                                                                  && x.Width > AppSetting.IndicatorSize -1
323 |                                                                  && x.Width < AppSetting.IndicatorSize +1);
324 |             if (indicator != null)
325 |             {
326 |                 indicator.Prepare();
327 | 
328 |                 KillDeadWindow();
329 |                 return indicator;
330 |             }
331 |             else
332 |             {
333 |                 indicator = new ClickIndicator(AppSetting.IndicatorSize)
334 |                 {
335 |                     WindowStartupLocation = WindowStartupLocation.Manual,
336 |                     Topmost = true,
337 |                     ShowActivated = false
338 |                 };
339 |                 _clickIndicators.Add(indicator);
340 | 
341 |                 KillDeadWindow();
342 |                 return indicator;
343 |             }
344 |         }
345 | 
346 |         /// <summary>
347 |         /// 显示波纹特效
348 |         /// </summary>
349 |         /// <param name="button">按键</param>
350 |         /// <param name="point">位置</param>
351 |         /// <param name="isDown">是否按下</param>
352 |         private void ShowIndicator(MouseButtons button, Point point, bool isDown)
353 |         {
354 |             try
355 |             {
356 |                 var indicator = GetClickIndicatorWindow();
357 | 
358 |                 Brush brush = _buttonBrushes[button];
359 | 
360 |                 indicator.Play(brush, isDown);
361 | 
362 |                 var size = (int)(AppSetting.IndicatorSize * indicator.GetDpiScale());
363 | 
364 |                 MoveWindowWrapper(indicator,
365 |                     point.X - (int)(size / 2),
366 |                     point.Y - (int)(size / 2), size, size);
367 | 
368 |                 if (indicator.DpiHasChanged)
369 |                 {
370 |                     size = (int)(AppSetting.IndicatorSize * indicator.GetDpiScale());
371 |                     // 
372 |                     MoveWindowWrapper(indicator,
373 |                         point.X - (int)(size / 2),
374 |                         point.Y - (int)(size / 2), size, size);
375 |                 }
376 |             }
377 |             catch
378 |             {
379 |             }
380 |         }
381 | 
382 |         /// <summary>
383 |         /// 关闭长时间未使用的indicator
384 |         /// </summary>
385 |         private void KillDeadWindow()
386 |         {
387 |             var deadIndicators = _clickIndicators
388 |                 .Where(x => x.IsIdle 
389 |                             && (Environment.TickCount - x.LastLiveTime) / 1000 > 5)
390 |                 .ToList();
391 | 
392 |             foreach (var i in deadIndicators)
393 |             {
394 |                 i.Close();
395 |                 _clickIndicators.Remove(i);
396 |             }
397 |         }
398 | 
399 | 
400 |         #endregion
401 | 
402 |         #region 鼠标hook处理
403 | 
404 | 
405 |         /// <summary>
406 |         /// 鼠标按下事件
407 |         /// </summary>
408 |         private void MouseHookOnMouseDown(object sender, MouseEventArgs e)
409 |         {
410 |             if (!AppSetting.EnableClickCircle
411 |                 || !AppSetting.MouseButtonSettings[e.Button].IsEnabled)
412 |             {
413 |                 return;
414 |             }
415 | 
416 | 
417 |             var point = e.Location;
418 | 
419 |             var button = e.Button;
420 | 
421 |             // 记录按下状态(时间与位置)
422 |             _buttonStates[button].DownPosition = point;
423 |             _buttonStates[button].DownTimeTicks = Environment.TickCount;
424 | 
425 | 
426 |             // 显示特效
427 |             Dispatcher.InvokeAsync(() => { ShowIndicator(button, point, true); });
428 |         }
429 | 
430 |         /// <summary>
431 |         /// 鼠标抬起
432 |         /// </summary>
433 |         private void MouseHookOnMouseUp(object sender, MouseEventArgs e)
434 |         {
435 |             if (!AppSetting.EnableClickCircle
436 |                 || !AppSetting.MouseButtonSettings[e.Button].IsEnabled)
437 |             {
438 |                 return;
439 |             }
440 | 
441 |             var point = e.Location;
442 | 
443 |             var downState = _buttonStates[e.Button];
444 |             // 距离超过设定,或者抬起时间超过设定,显示抬起特效。
445 |             if (((point.X - downState.DownPosition.X) * (point.X - downState.DownPosition.X)
446 |                  + (point.Y - downState.DownPosition.Y) * (point.Y - downState.DownPosition.Y)) > UP_SHOW_DISTANCE * UP_SHOW_DISTANCE
447 |                 || (Environment.TickCount > (downState.DownTimeTicks + UP_TICKS_DELTA))
448 |                 )
449 |             {
450 |                 Dispatcher.InvokeAsync(() =>
451 |                 {
452 |                     ShowIndicator(e.Button, point, false);
453 |                 });
454 |             }
455 |         }
456 | 
457 |         /// <summary>
458 |         /// 鼠标移动处理
459 |         /// </summary>
460 |         /// <param name="sender"></param>
461 |         /// <param name="e"></param>
462 |         private void MouseHookOnMouseMove(object sender, MouseEventArgs e)
463 |         {
464 |             if (AppSetting.EnableHoverDot
465 |                 && _hoverDot != null)
466 |             {
467 |                 Dispatcher.InvokeAsync(() =>
468 |                 {
469 |                     var size = (int)(AppSetting.HoverDotSize * _hoverDot.GetDpiScale());
470 |                     MoveWindowWrapper(_hoverDot,
471 |                         e.Location.X - (int)(size / 2),
472 |                         e.Location.Y - (int)(size / 2), size, size);
473 |                 });
474 |             }
475 |         }
476 | 
477 | 
478 |         #endregion
479 | 
480 |         #region 托盘图标
481 | 
482 |         private void CreateNotifyIcon()
483 |         {
484 |             _notifyIcon = new System.Windows.Forms.NotifyIcon();
485 |             using (Stream iconStream = System.Windows.Application
486 |                 .GetResourceStream(new Uri(
487 |                     
quot;pack://application:,,,/{Assembly.GetEntryAssembly().GetName().Name};component/clickshow.ico"))
488 |                 .Stream)
489 |             {
490 |                 _notifyIcon.Icon = new System.Drawing.Icon(iconStream);
491 |             }
492 | 
493 |             _notifyIcon.BalloonTipText = "ClickShow\n鼠标点击提示器\n点击打开";
494 |             _notifyIcon.Click += NotifyIconOnClick;
495 |             _notifyIcon.Visible = true;
496 | 
497 |             var contextMenu = new System.Windows.Forms.ContextMenu();
498 |             var menuItem = new System.Windows.Forms.MenuItem("退出(Exit)", (sender, args) =>
499 |             {
500 |                 _forceClose = true;
501 |                 this.Close();
502 |             });
503 |             contextMenu.MenuItems.Add(menuItem);
504 | 
505 |             _notifyIcon.ContextMenu = contextMenu;
506 |         }
507 | 
508 |         private void NotifyIconOnClick(object sender, EventArgs e)
509 |         {
510 | 
511 |             this.Show();
512 |             this.Activate();
513 |             this.WindowState = WindowState.Normal;
514 |         }
515 | 
516 |         #endregion
517 | 
518 | 
519 |         #region 自动启动
520 | 
521 |         // The path to the key where Windows looks for startup applications
522 |         RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
523 |         private string AppName = "ClickShow";
524 |         private void LoadAutoStartStatus()
525 |         {
526 |             try
527 |             {
528 |                 // Check to see the current state (running at startup or not)
529 |                 if (rkApp.GetValue(AppName) == null)
530 |                 {
531 |                     // The value doesn't exist, the application is not set to run at startup
532 |                     ChkStartWithWindows.IsChecked = false;
533 |                 }
534 |                 else
535 |                 {
536 |                     // The value exists, the application is set to run at startup
537 |                     ChkStartWithWindows.IsChecked = true;
538 |                 }
539 |             }
540 |             catch (Exception ex)
541 |             {
542 |                 MessageBox.Show("无法加载开机自动启动状态。" + ex.Message);
543 |             }
544 |         }
545 | 
546 | 
547 |         private void SaveAutoStart()
548 |         {
549 |             try
550 |             {
551 |                 if (ChkStartWithWindows.IsChecked == true)
552 |                 {
553 |                     // Add the value in the registry so that the application runs at startup
554 |                     rkApp.SetValue(AppName, Process.GetCurrentProcess().MainModule.FileName);
555 |                 }
556 |                 else
557 |                 {
558 |                     // Remove the value from the registry so that the application doesn't start
559 |                     rkApp.DeleteValue(AppName, false);
560 |                 }
561 |             }
562 |             catch (Exception ex)
563 |             {
564 |                 MessageBox.Show("无法保存开机自动启动状态。" + ex.Message);
565 |             }
566 | 
567 |         }
568 | 
569 |         /// <summary>
570 |         /// 点击切换了自动启动选项
571 |         /// </summary>
572 |         /// <param name="sender"></param>
573 |         /// <param name="e"></param>
574 |         private void ChkStartWithWindows_OnClick(object sender, RoutedEventArgs e)
575 |         {
576 |             SaveAutoStart();
577 |         }
578 |         #endregion
579 | 
580 | 
581 |         #region Native 调用
582 | 
583 |         public void MoveWindowWrapper(Window window, int X, int Y, int nWidth, int nHeight)
584 |         {
585 |             var handle = new WindowInteropHelper(window).Handle;
586 | 
587 |             WindowHelper.SetWindowPos(handle,
588 |                 (IntPtr)WindowHelper.SpecialWindowHandles.HWND_TOPMOST,
589 |                 X, Y,
590 |                 nWidth, nHeight,
591 |                 WindowHelper.SetWindowPosFlags.SWP_NOACTIVATE
592 |                 );
593 | 
594 |             //MoveWindow(handle, X, Y, nWidth, nHeight, false);
595 |         }
596 | 
597 |         [DllImport("user32.dll", SetLastError = true)]
598 |         internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
599 | 
600 | 
601 |         #endregion
602 | 
603 |         #region 设置读写
604 | 
605 |         /// <summary>
606 |         /// 配置文件位置
607 |         /// </summary>
608 |         /// <returns></returns>
609 |         private string GetSettingFilePath()
610 |         {
611 |             var docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
612 |             return Path.Combine(docPath, "ClickShow.setting");
613 |         }
614 | 
615 |         /// <summary>
616 |         /// 读取设置
617 |         /// </summary>
618 |         private void LoadSettings()
619 |         {
620 |             string settingFilePath = GetSettingFilePath();
621 |             if (File.Exists(settingFilePath))
622 |             {
623 |                 try
624 |                 {
625 |                     var data = File.ReadAllText(settingFilePath);
626 |                     AppSetting = MyJsonConverter.Deserialize<AppSetting>(data);
627 |                 }
628 |                 catch (Exception ex)
629 |                 {
630 |                     MessageBox.Show("配置文件损坏了,设置已恢复为默认值。" + ex.Message);
631 |                     AppSetting = new AppSetting();
632 | 
633 |                     SaveSettings();
634 |                 }
635 | 
636 |             }
637 |             else
638 |             {
639 |                 AppSetting = new AppSetting();
640 |             }
641 | 
642 |             // 监听设置变更消息
643 |             AppSetting.PropertyChanged += OnAppSettingChanged;
644 |             foreach (var item in AppSetting.MouseButtonSettings)
645 |             {
646 |                 item.Value.PropertyChanged += OnAppSettingChanged;
647 |             }
648 |         }
649 | 
650 | 
651 |         /// <summary>
652 |         /// 延迟更新
653 |         /// </summary>
654 |         private DebounceDispatcher _settingDebounceDispatcher;
655 | 
656 |         /// <summary>
657 |         /// 设置改变后立即应用并保存
658 |         /// </summary>
659 |         /// <param name="sender"></param>
660 |         /// <param name="e"></param>
661 |         private void OnAppSettingChanged(object sender, PropertyChangedEventArgs e)
662 |         {
663 |             if (_settingDebounceDispatcher == null)
664 |             {
665 |                 _settingDebounceDispatcher = new DebounceDispatcher();
666 |             }
667 | 
668 |             _settingDebounceDispatcher.Debounce(100, o =>
669 |             {
670 |                 SaveSettings();
671 |                 ApplySettings();
672 |             });
673 |         }
674 | 
675 |         /// <summary>
676 |         /// 应用设置
677 |         /// </summary>
678 |         private void ApplySettings()
679 |         {
680 |             void ApplySettingsInternal()
681 |             {
682 |                 UpdateHoverDot();
683 | 
684 |                 foreach (var pair in AppSetting.MouseButtonSettings)
685 |                 {
686 |                     _buttonBrushes[pair.Key] = pair.Value.Color.ToBrush();
687 |                 }
688 |             }
689 | 
690 |             try
691 |             {
692 |                 ApplySettingsInternal();
693 |             }
694 |             catch (Exception ex)
695 |             {
696 | 
697 |                 _notifyIcon.ShowBalloonTip(2000,"ClickShow", "应用设置出错,已重置设置。错误:" + ex.Message, ToolTipIcon.Warning);
698 | 
699 |                 //如果遇到了问题,重置设置
700 |                 AppSetting = new AppSetting();
701 | 
702 |                 ApplySettingsInternal();
703 | 
704 |                 SaveSettings();
705 |             }
706 | 
707 |         }
708 | 
709 |         /// <summary>
710 |         /// 保存设置
711 |         /// </summary>
712 |         private void SaveSettings()
713 |         {
714 |             try
715 |             {
716 |                 File.WriteAllText(GetSettingFilePath(), MyJsonConverter.Serialize(AppSetting));
717 |             }
718 |             catch (Exception ex)
719 |             {
720 |                 _notifyIcon.ShowBalloonTip(2000, "ClickShow", "设置保存出错:" + ex.Message, ToolTipIcon.Warning);
721 |             }
722 |             
723 |         }
724 | 
725 | #endregion
726 | 
727 | 
728 | 
729 |         private void BtnSettings_OnClick(object sender, RoutedEventArgs e)
730 |         {
731 |             var dlg = new SettingsWindow(AppSetting);
732 |             dlg.Owner = this;
733 | 
734 |             dlg.ShowDialog();
735 |         }
736 | 
737 |     }
738 | }
739 | 


--------------------------------------------------------------------------------
/ClickShow/UI/SettingsWindow.xaml:
--------------------------------------------------------------------------------
  1 | <Window
  2 |     x:Class="ClickShow.UI.SettingsWindow"
  3 |     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4 |     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5 |     xmlns:clickShow="clr-namespace:ClickShow"
  6 |     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7 |     xmlns:local="clr-namespace:ClickShow.UI"
  8 |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9 |     xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
 10 |     Title="设置"
 11 |     Width="400"
 12 |     Height="450"
 13 |     ResizeMode="NoResize"
 14 |     SizeToContent="Height"
 15 |     WindowStartupLocation="CenterOwner"
 16 |     mc:Ignorable="d">
 17 |     <Window.Resources>
 18 |         <Style x:Key="Label" TargetType="TextBlock">
 19 |             <Setter Property="Foreground" Value="Gray" />
 20 |             <Setter Property="FontWeight" Value="Bold" />
 21 |         </Style>
 22 |     </Window.Resources>
 23 |     <Grid Margin="15,5,15,15">
 24 | 
 25 |         <StackPanel Margin="0">
 26 |             <GroupBox>
 27 |                 <GroupBox.Header>点击波纹外观设置</GroupBox.Header>
 28 |                 <StackPanel Margin="10">
 29 |                     <TextBlock
 30 |                         Margin="0,0,0,0"
 31 |                         Style="{StaticResource Label}"
 32 |                         Text="波纹大小:" />
 33 |                     <Slider
 34 |                         x:Name="IndicatorSizeSlider"
 35 |                         Margin="5"
 36 |                         AutoToolTipPlacement="BottomRight"
 37 |                         AutoToolTipPrecision="0"
 38 |                         IsSnapToTickEnabled="True"
 39 |                         Maximum="400"
 40 |                         Minimum="50"
 41 |                         TickFrequency="5"
 42 |                         Value="{Binding Path=IndicatorSize}" />
 43 | 
 44 | 
 45 |                     <TextBlock
 46 |                         Margin="0,10,0,0"
 47 |                         Style="{StaticResource Label}"
 48 |                         Text="各按键波纹颜色:" />
 49 |                     <Grid Margin="0,5">
 50 |                         <Grid.RowDefinitions>
 51 |                             <RowDefinition Height="Auto" />
 52 |                             <RowDefinition Height="5" />
 53 |                             <RowDefinition Height="Auto" />
 54 |                             <RowDefinition Height="5" />
 55 |                             <RowDefinition Height="Auto" />
 56 |                             <RowDefinition Height="5" />
 57 |                             <RowDefinition Height="Auto" />
 58 |                             <RowDefinition Height="5" />
 59 |                             <RowDefinition Height="Auto" />
 60 |                         </Grid.RowDefinitions>
 61 |                         <Grid.ColumnDefinitions>
 62 |                             <ColumnDefinition Width="Auto" />
 63 |                             <ColumnDefinition Width="10" />
 64 |                             <ColumnDefinition Width="Auto" />
 65 |                             <ColumnDefinition Width="10" />
 66 |                             <ColumnDefinition Width="Auto" />
 67 |                         </Grid.ColumnDefinitions>
 68 | 
 69 |                         <!--  Left  -->
 70 |                         <TextBlock
 71 |                             Grid.Row="0"
 72 |                             Grid.Column="0"
 73 |                             VerticalAlignment="Center"
 74 |                             Text="左:" />
 75 |                         <CheckBox
 76 |                             Grid.Row="0"
 77 |                             Grid.Column="2"
 78 |                             VerticalAlignment="Center"
 79 |                             Content="启用"
 80 |                             IsChecked="{Binding MouseButtonSettings[Left].IsEnabled}" />
 81 |                         <xctk:ColorPicker
 82 |                             Grid.Row="0"
 83 |                             Grid.Column="4"
 84 |                             Width="80"
 85 |                             Height="23"
 86 |                             VerticalAlignment="Center"
 87 |                             ColorMode="ColorCanvas"
 88 |                             SelectedColor="{Binding MouseButtonSettings[Left].Color}" />
 89 | 
 90 |                         <!--  Middle  -->
 91 |                         <TextBlock
 92 |                             Grid.Row="2"
 93 |                             Grid.Column="0"
 94 |                             VerticalAlignment="Center"
 95 |                             Text="中:" />
 96 |                         <CheckBox
 97 |                             Grid.Row="2"
 98 |                             Grid.Column="2"
 99 |                             VerticalAlignment="Center"
100 |                             Content="启用"
101 |                             IsChecked="{Binding MouseButtonSettings[Middle].IsEnabled}" />
102 |                         <xctk:ColorPicker
103 |                             Grid.Row="2"
104 |                             Grid.Column="4"
105 |                             Width="80"
106 |                             Height="23"
107 |                             VerticalAlignment="Center"
108 |                             ColorMode="ColorCanvas"
109 |                             SelectedColor="{Binding MouseButtonSettings[Middle].Color}" />
110 | 
111 |                         <!--  Right  -->
112 |                         <TextBlock
113 |                             Grid.Row="4"
114 |                             Grid.Column="0"
115 |                             VerticalAlignment="Center"
116 |                             Text="右:" />
117 |                         <CheckBox
118 |                             Grid.Row="4"
119 |                             Grid.Column="2"
120 |                             VerticalAlignment="Center"
121 |                             Content="启用"
122 |                             IsChecked="{Binding MouseButtonSettings[Right].IsEnabled}" />
123 |                         <xctk:ColorPicker
124 |                             Grid.Row="4"
125 |                             Grid.Column="4"
126 |                             Width="80"
127 |                             Height="23"
128 |                             VerticalAlignment="Center"
129 |                             ColorMode="ColorCanvas"
130 |                             SelectedColor="{Binding MouseButtonSettings[Right].Color}" />
131 | 
132 |                         <!--  XButton1  -->
133 |                         <TextBlock
134 |                             Grid.Row="6"
135 |                             Grid.Column="0"
136 |                             VerticalAlignment="Center"
137 |                             Text="侧键(后退):" />
138 |                         <CheckBox
139 |                             Grid.Row="6"
140 |                             Grid.Column="2"
141 |                             VerticalAlignment="Center"
142 |                             Content="启用"
143 |                             IsChecked="{Binding MouseButtonSettings[XButton1].IsEnabled}" />
144 |                         <xctk:ColorPicker
145 |                             Grid.Row="6"
146 |                             Grid.Column="4"
147 |                             Width="80"
148 |                             Height="23"
149 |                             VerticalAlignment="Center"
150 |                             ColorMode="ColorCanvas"
151 |                             SelectedColor="{Binding MouseButtonSettings[XButton1].Color}" />
152 | 
153 | 
154 |                         <!--  XButton2  -->
155 |                         <TextBlock
156 |                             Grid.Row="8"
157 |                             Grid.Column="0"
158 |                             VerticalAlignment="Center"
159 |                             Text="侧键(前进):" />
160 |                         <CheckBox
161 |                             Grid.Row="8"
162 |                             Grid.Column="2"
163 |                             VerticalAlignment="Center"
164 |                             Content="启用"
165 |                             IsChecked="{Binding MouseButtonSettings[XButton2].IsEnabled}" />
166 |                         <xctk:ColorPicker
167 |                             Grid.Row="8"
168 |                             Grid.Column="4"
169 |                             Width="80"
170 |                             Height="23"
171 |                             VerticalAlignment="Center"
172 |                             ColorMode="ColorCanvas"
173 |                             SelectedColor="{Binding MouseButtonSettings[XButton2].Color}" />
174 | 
175 |                     </Grid>
176 |                 </StackPanel>
177 |             </GroupBox>
178 |             <GroupBox Margin="0,10,0,0" Header="位置浮标外观">
179 |                 <StackPanel Margin="10">
180 |                     <TextBlock
181 |                         Margin="0,5,0,5"
182 |                         Style="{StaticResource Label}"
183 |                         Text="悬浮标大小:" />
184 | 
185 |                     <Slider
186 |                         x:Name="HoverDotSizeSlider"
187 |                         Margin="0"
188 |                         AutoToolTipPlacement="BottomRight"
189 |                         AutoToolTipPrecision="0"
190 |                         IsSnapToTickEnabled="True"
191 |                         Maximum="150"
192 |                         Minimum="10"
193 |                         TickFrequency="5"
194 |                         Value="{Binding Path=HoverDotSize}" />
195 | 
196 |                     <TextBlock
197 |                         Margin="0,5,0,5"
198 |                         Style="{StaticResource Label}"
199 |                         Text="悬浮标颜色:" />
200 |                     <xctk:ColorPicker
201 |                         Width="100"
202 |                         Height="23"
203 |                         HorizontalAlignment="Left"
204 |                         VerticalAlignment="Center"
205 |                         ColorMode="ColorCanvas"
206 |                         SelectedColor="{Binding HoverDotFill}" />
207 |                 </StackPanel>
208 |             </GroupBox>
209 | 
210 |             <Grid Margin="0,10,0,0">
211 |                 <Grid.ColumnDefinitions>
212 |                     <ColumnDefinition Width="1*" />
213 |                     <ColumnDefinition Width="10" />
214 |                     <ColumnDefinition Width="1*" />
215 |                 </Grid.ColumnDefinitions>
216 | 
217 |                 <Button
218 |                     Name="BtnRestoreDefault"
219 |                     Padding="30,7"
220 |                     Click="BtnRestoreDefault_OnClick"
221 |                     Content="默认值" />
222 | 
223 |                 <Button
224 |                     Name="BtnClose"
225 |                     Grid.Column="2"
226 |                     Padding="30,7"
227 |                     Click="BtnClose_OnClick"
228 |                     Content="关闭(_C)"
229 |                     IsCancel="True"
230 |                     IsDefault="True" />
231 | 
232 |             </Grid>
233 | 
234 |         </StackPanel>
235 |     </Grid>
236 | </Window>
237 | 


--------------------------------------------------------------------------------
/ClickShow/UI/SettingsWindow.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | using System.Windows.Data;
 8 | using System.Windows.Documents;
 9 | using System.Windows.Forms;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 | using ClickShow.Settings;
15 | using Button = System.Windows.Controls.Button;
16 | 
17 | namespace ClickShow.UI
18 | {
19 |     /// <summary>
20 |     /// Interaction logic for SettingsWindow.xaml
21 |     /// </summary>
22 |     public partial class SettingsWindow : Window
23 |     {
24 |         private readonly AppSetting _settings;
25 | 
26 |         public SettingsWindow(AppSetting appSetting)
27 |         {
28 |             _settings = appSetting;
29 |             InitializeComponent();
30 | 
31 |             this.DataContext = appSetting;
32 |         }
33 | 
34 |         
35 | 
36 |         private void BtnClose_OnClick(object sender, RoutedEventArgs e)
37 |         {
38 |             Close();
39 |         }
40 | 
41 |         private void BtnRestoreDefault_OnClick(object sender, RoutedEventArgs e)
42 |         {
43 |             var defaultSetting = new AppSetting();
44 | 
45 |             _settings.IndicatorSize = defaultSetting.IndicatorSize;
46 |             foreach (var key in _settings.MouseButtonSettings.Keys.ToList())
47 |             {
48 |                 _settings.MouseButtonSettings[key].IsEnabled = defaultSetting.MouseButtonSettings[key].IsEnabled;
49 |                 _settings.MouseButtonSettings[key].Color = defaultSetting.MouseButtonSettings[key].Color;
50 |             }
51 | 
52 |             _settings.HoverDotSize = defaultSetting.HoverDotSize;
53 |             _settings.HoverDotFill = defaultSetting.HoverDotFill;
54 |         }
55 |     }
56 | }
57 | 


--------------------------------------------------------------------------------
/ClickShow/Utility/DebounceDispatcher.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows.Threading;
 7 | 
 8 | namespace ClickShow.Utility
 9 | {
10 |     class DebounceDispatcher
11 |     {
12 |         private DispatcherTimer timer;
13 |         private DateTime timerStarted { get; set; } = DateTime.UtcNow.AddYears(-1);
14 | 
15 |         /// <summary>
16 |         /// Debounce an event by resetting the event timeout every time the event is 
17 |         /// fired. The behavior is that the Action passed is fired only after events
18 |         /// stop firing for the given timeout period.
19 |         /// 
20 |         /// Use Debounce when you want events to fire only after events stop firing
21 |         /// after the given interval timeout period.
22 |         /// 
23 |         /// Wrap the logic you would normally use in your event code into
24 |         /// the  Action you pass to this method to debounce the event.
25 |         /// Example: https://gist.github.com/RickStrahl/0519b678f3294e27891f4d4f0608519a
26 |         /// </summary>
27 |         /// <param name="interval">Timeout in Milliseconds</param>
28 |         /// <param name="action">Action<object> to fire when debounced event fires</object></param>
29 |         /// <param name="param">optional parameter</param>
30 |         /// <param name="priority">optional priorty for the dispatcher</param>
31 |         /// <param name="disp">optional dispatcher. If not passed or null CurrentDispatcher is used.</param>        
32 |         public void Debounce(int interval, Action<object> action,
33 |             object param = null,
34 |             DispatcherPriority priority = DispatcherPriority.ApplicationIdle,
35 |             Dispatcher disp = null)
36 |         {
37 |             // kill pending timer and pending ticks
38 |             timer?.Stop();
39 |             timer = null;
40 | 
41 |             if (disp == null)
42 |                 disp = Dispatcher.CurrentDispatcher;
43 | 
44 |             // timer is recreated for each event and effectively
45 |             // resets the timeout. Action only fires after timeout has fully
46 |             // elapsed without other events firing in between
47 |             timer = new DispatcherTimer(TimeSpan.FromMilliseconds(interval), priority, (s, e) =>
48 |             {
49 |                 if (timer == null)
50 |                     return;
51 | 
52 |                 timer?.Stop();
53 |                 timer = null;
54 |                 action.Invoke(param);
55 |             }, disp);
56 | 
57 |             timer.Start();
58 |         }
59 | 
60 |     }
61 | }
62 | 


--------------------------------------------------------------------------------
/ClickShow/Utility/Extensions.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | using System.Windows.Media;
 8 | 
 9 | namespace ClickShow.Utility
10 | {
11 |     public static class Extensions
12 |     {
13 |         /// <summary>
14 |         /// 转换颜色为ARGB格式
15 |         /// </summary>
16 |         /// <param name="c">颜色值</param>
17 |         /// <returns>#AARRGGBB文本</returns>
18 |         public static string ToArgb(this System.Windows.Media.Color c)
19 |         {
20 |             return 
quot;#{c.A:X2}{c.R:X2}{c.G:X2}{c.B:X2}";
21 |         }
22 | 
23 |         /// <summary>
24 |         /// 颜色值转换为画刷对象
25 |         /// </summary>
26 |         /// <param name="colorStr">颜色值</param>
27 |         /// <returns></returns>
28 |         public static SolidColorBrush ToBrush(this string colorStr)
29 |         {
30 |             return new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorStr));
31 |         }
32 |     }
33 | }
34 | 


--------------------------------------------------------------------------------
/ClickShow/Utility/MyJsonConverter.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.IO;
 4 | using System.Linq;
 5 | using System.Runtime.Serialization.Json;
 6 | using System.Text;
 7 | using System.Threading.Tasks;
 8 | 
 9 | namespace ClickShow.Utility
10 | {
11 |     public static class MyJsonConverter
12 |     {
13 |         /// <summary>
14 |         /// Deserialize an from json string
15 |         /// </summary>
16 |         public static T Deserialize<T>(string body)
17 |         {
18 |             using (var stream = new MemoryStream())
19 |             using (var writer = new StreamWriter(stream))
20 |             {
21 |                 writer.Write(body);
22 |                 writer.Flush();
23 |                 stream.Position = 0;
24 |                 return (T)new DataContractJsonSerializer(typeof(T)).ReadObject(stream);
25 |             }
26 |         }
27 | 
28 |         /// <summary>
29 |         /// Serialize an object to json
30 |         /// </summary>
31 |         public static string Serialize<T>(T item)
32 |         {
33 |             using (MemoryStream ms = new MemoryStream())
34 |             {
35 |                 new DataContractJsonSerializer(typeof(T)).WriteObject(ms, item);
36 |                 return Encoding.Default.GetString(ms.ToArray());
37 |             }
38 |         }
39 |     }
40 | }
41 | 


--------------------------------------------------------------------------------
/ClickShow/Utility/WindowHelper.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Runtime.InteropServices;
  3 | 
  4 | namespace ClickShow
  5 | {
  6 |     public class WindowHelper
  7 |     {
  8 |         private const int WS_EX_TRANSPARENT = 0x00000020;
  9 |         private const int WS_EX_NOACTIVATE = 0x08000000;
 10 |         private const int GWL_EXSTYLE = (-20);
 11 | 
 12 |         [DllImport("user32.dll")]
 13 |         private static extern int GetWindowLong(IntPtr hwnd, int index);
 14 | 
 15 |         [DllImport("user32.dll")]
 16 |         private static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
 17 | 
 18 |         /// <summary>
 19 |         /// 让鼠标事件穿透
 20 |         /// https://stackoverflow.com/questions/2842667/how-to-create-a-semi-transparent-window-in-wpf-that-allows-mouse-events-to-pass
 21 |         /// </summary>
 22 |         /// <param name="hwnd"></param>
 23 |         public static void SetWindowExTransparent(IntPtr hwnd)
 24 |         {
 25 |             var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
 26 |             SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE);
 27 |         }
 28 | 
 29 |         #region SetWindowPos
 30 | 
 31 |         /// <summary>
 32 |         ///     Special window handles
 33 |         /// </summary>
 34 |         public enum SpecialWindowHandles
 35 |         {
 36 |             // ReSharper disable InconsistentNaming
 37 |             /// <summary>
 38 |             ///     Places the window at the top of the Z order.
 39 |             /// </summary>
 40 |             HWND_TOP = 0,
 41 |             /// <summary>
 42 |             ///     Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
 43 |             /// </summary>
 44 |             HWND_BOTTOM = 1,
 45 |             /// <summary>
 46 |             ///     Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
 47 |             /// </summary>
 48 |             HWND_TOPMOST = -1,
 49 |             /// <summary>
 50 |             ///     Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.
 51 |             /// </summary>
 52 |             HWND_NOTOPMOST = -2
 53 |             // ReSharper restore InconsistentNaming
 54 |         }
 55 | 
 56 |         [Flags]
 57 |         public enum SetWindowPosFlags : uint
 58 |         {
 59 |             // ReSharper disable InconsistentNaming
 60 | 
 61 |             /// <summary>
 62 |             ///     If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.
 63 |             /// </summary>
 64 |             SWP_ASYNCWINDOWPOS = 0x4000,
 65 | 
 66 |             /// <summary>
 67 |             ///     Prevents generation of the WM_SYNCPAINT message.
 68 |             /// </summary>
 69 |             SWP_DEFERERASE = 0x2000,
 70 | 
 71 |             /// <summary>
 72 |             ///     Draws a frame (defined in the window's class description) around the window.
 73 |             /// </summary>
 74 |             SWP_DRAWFRAME = 0x0020,
 75 | 
 76 |             /// <summary>
 77 |             ///     Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.
 78 |             /// </summary>
 79 |             SWP_FRAMECHANGED = 0x0020,
 80 | 
 81 |             /// <summary>
 82 |             ///     Hides the window.
 83 |             /// </summary>
 84 |             SWP_HIDEWINDOW = 0x0080,
 85 | 
 86 |             /// <summary>
 87 |             ///     Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
 88 |             /// </summary>
 89 |             SWP_NOACTIVATE = 0x0010,
 90 | 
 91 |             /// <summary>
 92 |             ///     Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
 93 |             /// </summary>
 94 |             SWP_NOCOPYBITS = 0x0100,
 95 | 
 96 |             /// <summary>
 97 |             ///     Retains the current position (ignores X and Y parameters).
 98 |             /// </summary>
 99 |             SWP_NOMOVE = 0x0002,
100 | 
101 |             /// <summary>
102 |             ///     Does not change the owner window's position in the Z order.
103 |             /// </summary>
104 |             SWP_NOOWNERZORDER = 0x0200,
105 | 
106 |             /// <summary>
107 |             ///     Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
108 |             /// </summary>
109 |             SWP_NOREDRAW = 0x0008,
110 | 
111 |             /// <summary>
112 |             ///     Same as the SWP_NOOWNERZORDER flag.
113 |             /// </summary>
114 |             SWP_NOREPOSITION = 0x0200,
115 | 
116 |             /// <summary>
117 |             ///     Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
118 |             /// </summary>
119 |             SWP_NOSENDCHANGING = 0x0400,
120 | 
121 |             /// <summary>
122 |             ///     Retains the current size (ignores the cx and cy parameters).
123 |             /// </summary>
124 |             SWP_NOSIZE = 0x0001,
125 | 
126 |             /// <summary>
127 |             ///     Retains the current Z order (ignores the hWndInsertAfter parameter).
128 |             /// </summary>
129 |             SWP_NOZORDER = 0x0004,
130 | 
131 |             /// <summary>
132 |             ///     Displays the window.
133 |             /// </summary>
134 |             SWP_SHOWWINDOW = 0x0040,
135 | 
136 |             // ReSharper restore InconsistentNaming
137 |         }
138 | 
139 |         [DllImport("user32.dll", SetLastError = true)]
140 |         internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
141 |         #endregion
142 | 
143 |     }
144 | }


--------------------------------------------------------------------------------
/ClickShow/app.manifest:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
 3 |   <assemblyIdentity version="1.3.0.0" name="ClickShow"/>
 4 |   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
 5 | 	  <security>
 6 | 		  <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
 7 | 			  <requestedExecutionLevel level="asInvoker" uiAccess="false" />
 8 | 		  </requestedPrivileges>
 9 | 		  <applicationRequestMinimum>
10 | 			  <defaultAssemblyRequest permissionSetReference="Custom" />
11 | 			  <PermissionSet ID="Custom" SameSite="site" Unrestricted="true" />
12 | 		  </applicationRequestMinimum>
13 | 	  </security>
14 |   </trustInfo>
15 | 
16 |   <application xmlns="urn:schemas-microsoft-com:asm.v3">
17 |     <windowsSettings>
18 | 	    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
19 | 	    <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
20 |     </windowsSettings>
21 |   </application>
22 |   
23 | 
24 | 
25 | </assembly>
26 | 


--------------------------------------------------------------------------------
/ClickShow/app.manifest.elevate:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
 3 |   <assemblyIdentity version="1.3.0.0" name="ClickShow"/>
 4 |   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
 5 | 	  <security>
 6 | 		  <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
 7 | 			  <requestedExecutionLevel level="asInvoker" uiAccess="true" />
 8 | 		  </requestedPrivileges>
 9 | 		  <applicationRequestMinimum>
10 | 			  <defaultAssemblyRequest permissionSetReference="Custom" />
11 | 			  <PermissionSet ID="Custom" SameSite="site" Unrestricted="true" />
12 | 		  </applicationRequestMinimum>
13 | 	  </security>
14 |   </trustInfo>
15 | 
16 |   <application xmlns="urn:schemas-microsoft-com:asm.v3">
17 |     <windowsSettings>
18 | 	    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
19 | 	    <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
20 |     </windowsSettings>
21 |   </application>
22 |   
23 | 
24 | 
25 | </assembly>
26 | 


--------------------------------------------------------------------------------
/ClickShow/app.manifest.normal:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
 3 |   <assemblyIdentity version="1.3.0.0" name="ClickShow"/>
 4 |   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
 5 | 	  <security>
 6 | 		  <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
 7 | 			  <requestedExecutionLevel level="asInvoker" uiAccess="false" />
 8 | 		  </requestedPrivileges>
 9 | 		  <applicationRequestMinimum>
10 | 			  <defaultAssemblyRequest permissionSetReference="Custom" />
11 | 			  <PermissionSet ID="Custom" SameSite="site" Unrestricted="true" />
12 | 		  </applicationRequestMinimum>
13 | 	  </security>
14 |   </trustInfo>
15 | 
16 |   <application xmlns="urn:schemas-microsoft-com:asm.v3">
17 |     <windowsSettings>
18 | 	    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
19 | 	    <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
20 |     </windowsSettings>
21 |   </application>
22 |   
23 | 
24 | 
25 | </assembly>
26 | 


--------------------------------------------------------------------------------
/ClickShow/clickshow.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuiliang/ClickShow/f20c4a153616d0cb87ef7420d722c3ce497e37b6/ClickShow/clickshow.ico


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2021 CuiLiang
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # ClickShow
 2 | 用于提示鼠标点击、鼠标位置。
 3 | 
 4 | **特色功能**
 5 | - 鼠标点击时显示波纹特效,每个按键对应不同的颜色;
 6 | - 支持跟随鼠标的位置指示圆标;
 7 | - 支持多屏DPI感知;
 8 | - 支持开机自启动;
 9 | 
10 | 
11 | 下载地址:https://github.com/cuiliang/ClickShow/releases
12 | 
13 | 图标来源:https://www.iconfont.cn/collections/detail?spm=a313x.7781069.1998910419.dc64b3430&cid=13315
14 | 
15 | 
16 | ![test](https://user-images.githubusercontent.com/1972649/122925974-f17ead00-d399-11eb-9c57-9b2f14dd5973.gif)
17 | 
18 | 
19 | 
20 | # 使用
21 | - 系统需求:Windows7 sp1+, .Net 4.7.2 版本(win10自带)
22 | - 如需在任务管理器、开始菜单、以管理员身份启动的窗口上生效,请将程序(1.3.1+版本)放到 `C:\Windows` 或 `C:\Program Files` 目录下使用。这时候程序会自动提升权限。
23 | - 程序启动后自动缩小到系统托盘。
24 | - 点击X最小化到系统托盘。
25 | - 点击托盘图标打开主窗口,右键点击托盘图标打开菜单。
26 | 
27 | 
28 | ![image](https://user-images.githubusercontent.com/1972649/129450207-45174d8b-89ad-489c-876b-a2bc657e5417.png)
29 | 
30 | 
31 | 
32 | 
33 | ## 更新历史
34 | 
35 | ### 1.4.1
36 | - 修复鼠标穿透问题。
37 | - 启动后检查版本更新。
38 | 
39 | ### 1.4.0
40 | - 增加参数设置与自动保存。感谢 @BigDevil82 贡献代码。
41 | 
42 | ### 1.3.3
43 | - 按下时的波纹效果避开中心一点。
44 | 
45 | ### 1.3.2
46 | - 长按鼠标抬起时,或者鼠标移动了较远距离抬起时,显示小波纹提示抬起事件。
47 | 
48 | ### 1.3.1
49 | - 避免某些情况下显示到别的窗口下面的问题。
50 | 
51 | ### 1.3
52 | - 解决Win7下不生效的问题
53 | - 支持多屏Dpi感知
54 | - 支持随Windows自动启动
55 | - 换了一个蓝色的图标(导致程序变大了,现在210k)
56 | 
57 | ## 可能会遇到的问题
58 | - 特效丢失:鼠标挂钩丢失了,这时候需要重启一下程序。
59 | - 自启动不生效:被各类管家或启动软件拦截,请在这些软件里设置。
60 | 
61 |    
62 | 
63 | # 广告位😎
64 | - 欢迎使用本人开发的其它软件:[Quicker - PC上的快捷指令](https://getquicker.net/)。
65 | 
66 | 
67 | 谢谢~
68 | 
69 | 
70 | 


--------------------------------------------------------------------------------
/version.txt:
--------------------------------------------------------------------------------
1 | 1.4.1.0
2 | 


--------------------------------------------------------------------------------