├── .gitignore
├── LICENSE
├── MouseTester
├── MouseTester.sln
└── MouseTester
│ ├── Form1.Designer.cs
│ ├── Form1.cs
│ ├── Form1.resx
│ ├── GraphicsRenderContext.cs
│ ├── MouseEvent.cs
│ ├── MouseLog.cs
│ ├── MousePlot.Designer.cs
│ ├── MousePlot.cs
│ ├── MousePlot.resx
│ ├── MouseTester.csproj
│ ├── OxyPlot.WindowsForms.dll
│ ├── OxyPlot.dll
│ ├── Program.cs
│ ├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ ├── Settings.settings
│ └── app.manifest
│ ├── RawMouse.cs
│ └── app.config
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 microe1
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30717.126
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseTester", "MouseTester\MouseTester.csproj", "{B0953B29-AF9B-4C37-A2EC-947E98F683B3}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|x64.ActiveCfg = Debug|x64
21 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|x64.Build.0 = Debug|x64
22 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|x86.ActiveCfg = Debug|x86
23 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Debug|x86.Build.0 = Debug|x86
24 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|x64.ActiveCfg = Release|x64
27 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|x64.Build.0 = Release|x64
28 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|x86.ActiveCfg = Release|x86
29 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {FEE93D0A-FE0A-4153-BD9B-A612BE91F7FC}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MouseTester
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.groupBox1 = new System.Windows.Forms.GroupBox();
32 | this.textBoxDesc = new System.Windows.Forms.TextBox();
33 | this.textBoxCPI = new System.Windows.Forms.TextBox();
34 | this.groupBox2 = new System.Windows.Forms.GroupBox();
35 | this.label1 = new System.Windows.Forms.Label();
36 | this.buttonMeasure = new System.Windows.Forms.Button();
37 | this.groupBox3 = new System.Windows.Forms.GroupBox();
38 | this.buttonSave = new System.Windows.Forms.Button();
39 | this.buttonLoad = new System.Windows.Forms.Button();
40 | this.buttonPlot = new System.Windows.Forms.Button();
41 | this.groupBox4 = new System.Windows.Forms.GroupBox();
42 | this.buttonLog = new System.Windows.Forms.Button();
43 | this.buttonCollect = new System.Windows.Forms.Button();
44 | this.textBox1 = new System.Windows.Forms.TextBox();
45 | this.statusStrip1 = new System.Windows.Forms.StatusStrip();
46 | this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
47 | this.groupBox1.SuspendLayout();
48 | this.groupBox2.SuspendLayout();
49 | this.groupBox3.SuspendLayout();
50 | this.groupBox4.SuspendLayout();
51 | this.statusStrip1.SuspendLayout();
52 | this.SuspendLayout();
53 | //
54 | // groupBox1
55 | //
56 | this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
57 | | System.Windows.Forms.AnchorStyles.Right)));
58 | this.groupBox1.Controls.Add(this.textBoxDesc);
59 | this.groupBox1.Location = new System.Drawing.Point(13, 13);
60 | this.groupBox1.Name = "groupBox1";
61 | this.groupBox1.Size = new System.Drawing.Size(267, 50);
62 | this.groupBox1.TabIndex = 0;
63 | this.groupBox1.TabStop = false;
64 | this.groupBox1.Text = "Description";
65 | //
66 | // textBoxDesc
67 | //
68 | this.textBoxDesc.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
69 | | System.Windows.Forms.AnchorStyles.Left)
70 | | System.Windows.Forms.AnchorStyles.Right)));
71 | this.textBoxDesc.Location = new System.Drawing.Point(6, 19);
72 | this.textBoxDesc.Name = "textBoxDesc";
73 | this.textBoxDesc.Size = new System.Drawing.Size(250, 20);
74 | this.textBoxDesc.TabIndex = 0;
75 | //
76 | // textBoxCPI
77 | //
78 | this.textBoxCPI.Location = new System.Drawing.Point(88, 21);
79 | this.textBoxCPI.Name = "textBoxCPI";
80 | this.textBoxCPI.Size = new System.Drawing.Size(100, 20);
81 | this.textBoxCPI.TabIndex = 0;
82 | this.textBoxCPI.Validated += new System.EventHandler(this.textBoxCPI_Validated);
83 | //
84 | // groupBox2
85 | //
86 | this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
87 | | System.Windows.Forms.AnchorStyles.Right)));
88 | this.groupBox2.Controls.Add(this.label1);
89 | this.groupBox2.Controls.Add(this.buttonMeasure);
90 | this.groupBox2.Controls.Add(this.textBoxCPI);
91 | this.groupBox2.Location = new System.Drawing.Point(13, 69);
92 | this.groupBox2.Name = "groupBox2";
93 | this.groupBox2.Size = new System.Drawing.Size(267, 50);
94 | this.groupBox2.TabIndex = 1;
95 | this.groupBox2.TabStop = false;
96 | this.groupBox2.Text = "Resolution";
97 | //
98 | // label1
99 | //
100 | this.label1.AutoSize = true;
101 | this.label1.Location = new System.Drawing.Point(194, 24);
102 | this.label1.Name = "label1";
103 | this.label1.Size = new System.Drawing.Size(21, 13);
104 | this.label1.TabIndex = 2;
105 | this.label1.Text = "cpi";
106 | //
107 | // buttonMeasure
108 | //
109 | this.buttonMeasure.Location = new System.Drawing.Point(6, 19);
110 | this.buttonMeasure.Name = "buttonMeasure";
111 | this.buttonMeasure.Size = new System.Drawing.Size(75, 23);
112 | this.buttonMeasure.TabIndex = 1;
113 | this.buttonMeasure.Text = "Measure";
114 | this.buttonMeasure.UseVisualStyleBackColor = true;
115 | this.buttonMeasure.Click += new System.EventHandler(this.buttonMeasure_Click);
116 | //
117 | // groupBox3
118 | //
119 | this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
120 | | System.Windows.Forms.AnchorStyles.Right)));
121 | this.groupBox3.Controls.Add(this.buttonSave);
122 | this.groupBox3.Controls.Add(this.buttonLoad);
123 | this.groupBox3.Location = new System.Drawing.Point(13, 182);
124 | this.groupBox3.Name = "groupBox3";
125 | this.groupBox3.Size = new System.Drawing.Size(267, 50);
126 | this.groupBox3.TabIndex = 2;
127 | this.groupBox3.TabStop = false;
128 | this.groupBox3.Text = "LogFile";
129 | //
130 | // buttonSave
131 | //
132 | this.buttonSave.Location = new System.Drawing.Point(88, 20);
133 | this.buttonSave.Name = "buttonSave";
134 | this.buttonSave.Size = new System.Drawing.Size(75, 23);
135 | this.buttonSave.TabIndex = 1;
136 | this.buttonSave.Text = "Save";
137 | this.buttonSave.UseVisualStyleBackColor = true;
138 | this.buttonSave.Click += new System.EventHandler(this.buttonSave_Click);
139 | //
140 | // buttonLoad
141 | //
142 | this.buttonLoad.Location = new System.Drawing.Point(7, 20);
143 | this.buttonLoad.Name = "buttonLoad";
144 | this.buttonLoad.Size = new System.Drawing.Size(75, 23);
145 | this.buttonLoad.TabIndex = 0;
146 | this.buttonLoad.Text = "Load";
147 | this.buttonLoad.UseVisualStyleBackColor = true;
148 | this.buttonLoad.Click += new System.EventHandler(this.buttonLoad_Click);
149 | //
150 | // buttonPlot
151 | //
152 | this.buttonPlot.Location = new System.Drawing.Point(168, 19);
153 | this.buttonPlot.Name = "buttonPlot";
154 | this.buttonPlot.Size = new System.Drawing.Size(75, 23);
155 | this.buttonPlot.TabIndex = 2;
156 | this.buttonPlot.Text = "Plot (F3)";
157 | this.buttonPlot.UseVisualStyleBackColor = true;
158 | this.buttonPlot.Click += new System.EventHandler(this.buttonPlot_Click);
159 | //
160 | // groupBox4
161 | //
162 | this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
163 | | System.Windows.Forms.AnchorStyles.Right)));
164 | this.groupBox4.Controls.Add(this.buttonLog);
165 | this.groupBox4.Controls.Add(this.buttonCollect);
166 | this.groupBox4.Controls.Add(this.buttonPlot);
167 | this.groupBox4.Location = new System.Drawing.Point(13, 126);
168 | this.groupBox4.Name = "groupBox4";
169 | this.groupBox4.Size = new System.Drawing.Size(267, 50);
170 | this.groupBox4.TabIndex = 3;
171 | this.groupBox4.TabStop = false;
172 | this.groupBox4.Text = "MouseData";
173 | //
174 | // buttonLog
175 | //
176 | this.buttonLog.Location = new System.Drawing.Point(87, 19);
177 | this.buttonLog.Name = "buttonLog";
178 | this.buttonLog.Size = new System.Drawing.Size(75, 23);
179 | this.buttonLog.TabIndex = 4;
180 | this.buttonLog.Text = "Start (F1)";
181 | this.buttonLog.UseVisualStyleBackColor = true;
182 | this.buttonLog.Click += new System.EventHandler(this.buttonLog_Click);
183 | //
184 | // buttonCollect
185 | //
186 | this.buttonCollect.Location = new System.Drawing.Point(6, 19);
187 | this.buttonCollect.Name = "buttonCollect";
188 | this.buttonCollect.Size = new System.Drawing.Size(75, 23);
189 | this.buttonCollect.TabIndex = 3;
190 | this.buttonCollect.Text = "Collect";
191 | this.buttonCollect.UseVisualStyleBackColor = true;
192 | this.buttonCollect.Click += new System.EventHandler(this.buttonCollect_Click);
193 | //
194 | // textBox1
195 | //
196 | this.textBox1.Location = new System.Drawing.Point(13, 239);
197 | this.textBox1.Multiline = true;
198 | this.textBox1.Name = "textBox1";
199 | this.textBox1.ReadOnly = true;
200 | this.textBox1.Size = new System.Drawing.Size(267, 100);
201 | this.textBox1.TabIndex = 4;
202 | //
203 | // statusStrip1
204 | //
205 | this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
206 | this.toolStripStatusLabel1});
207 | this.statusStrip1.Location = new System.Drawing.Point(0, 339);
208 | this.statusStrip1.Name = "statusStrip1";
209 | this.statusStrip1.Size = new System.Drawing.Size(284, 22);
210 | this.statusStrip1.TabIndex = 5;
211 | this.statusStrip1.Text = "statusStrip1";
212 | //
213 | // toolStripStatusLabel1
214 | //
215 | this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
216 | this.toolStripStatusLabel1.Size = new System.Drawing.Size(118, 17);
217 | this.toolStripStatusLabel1.Text = "toolStripStatusLabel1";
218 | //
219 | // Form1
220 | //
221 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
222 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
223 | this.ClientSize = new System.Drawing.Size(284, 361);
224 | this.Controls.Add(this.statusStrip1);
225 | this.Controls.Add(this.textBox1);
226 | this.Controls.Add(this.groupBox4);
227 | this.Controls.Add(this.groupBox3);
228 | this.Controls.Add(this.groupBox2);
229 | this.Controls.Add(this.groupBox1);
230 | this.MaximumSize = new System.Drawing.Size(300, 400);
231 | this.MinimumSize = new System.Drawing.Size(300, 400);
232 | this.Name = "Form1";
233 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
234 | this.Text = "MouseTester v1.3";
235 | this.groupBox1.ResumeLayout(false);
236 | this.groupBox1.PerformLayout();
237 | this.groupBox2.ResumeLayout(false);
238 | this.groupBox2.PerformLayout();
239 | this.groupBox3.ResumeLayout(false);
240 | this.groupBox4.ResumeLayout(false);
241 | this.statusStrip1.ResumeLayout(false);
242 | this.statusStrip1.PerformLayout();
243 | this.ResumeLayout(false);
244 | this.PerformLayout();
245 |
246 | }
247 |
248 | #endregion
249 |
250 | private System.Windows.Forms.GroupBox groupBox1;
251 | private System.Windows.Forms.TextBox textBoxDesc;
252 | private System.Windows.Forms.TextBox textBoxCPI;
253 | private System.Windows.Forms.GroupBox groupBox2;
254 | private System.Windows.Forms.Button buttonMeasure;
255 | private System.Windows.Forms.GroupBox groupBox3;
256 | private System.Windows.Forms.Button buttonPlot;
257 | private System.Windows.Forms.Button buttonSave;
258 | private System.Windows.Forms.Button buttonLoad;
259 | private System.Windows.Forms.GroupBox groupBox4;
260 | private System.Windows.Forms.Button buttonCollect;
261 | private System.Windows.Forms.Label label1;
262 | private System.Windows.Forms.TextBox textBox1;
263 | private System.Windows.Forms.StatusStrip statusStrip1;
264 | private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
265 | private System.Windows.Forms.Button buttonLog;
266 |
267 |
268 | }
269 | }
270 |
271 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Runtime.InteropServices;
9 | using System.Text;
10 | using System.Threading;
11 | using System.Windows.Forms;
12 |
13 | using OxyPlot;
14 |
15 | namespace MouseTester
16 | {
17 | using OxyPlot.Series;
18 |
19 | public partial class Form1 : Form
20 | {
21 | private MouseLog mlog = new MouseLog();
22 | enum state { idle, measure_wait, measure, collect_wait, collect, log };
23 | private state test_state = state.idle;
24 | private long pFreq;
25 |
26 | public Form1()
27 | {
28 | InitializeComponent();
29 | try {
30 | // Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2); // Use only the second core
31 | // Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; // Set highest process priority
32 | // Thread.CurrentThread.Priority = ThreadPriority.Highest; // Set highest thread priority
33 | } catch (Exception ex) {
34 | Debug.WriteLine(ex.ToString());
35 | }
36 |
37 | this.RegisterRawInputMouse(Handle);
38 | this.textBoxDesc.Text = this.mlog.Desc.ToString();
39 | this.textBoxCPI.Text = this.mlog.Cpi.ToString();
40 | this.textBox1.Text = "Enter the correct CPI" +
41 | "\r\n or\r\n" +
42 | "Press the Measure button" +
43 | "\r\n or\r\n" +
44 | "Press the Load button";
45 | this.toolStripStatusLabel1.Text = "";
46 | this.KeyPreview = true;
47 | this.KeyDown += new KeyEventHandler(Form1_KeyDown);
48 |
49 | QueryPerformanceFrequency(out pFreq);
50 | // Debug.WriteLine("PerformanceCounterFrequency: " + pFreq.ToString() + " Hz\n");
51 | }
52 |
53 | private void Form1_KeyDown(object sender, KeyEventArgs e)
54 | {
55 | // TODO: Replace with Global Hotkey
56 | // https://social.msdn.microsoft.com/Forums/vstudio/en-US/c061954b-19bf-463b-a57d-b09c98a3fe7d/assign-global-hotkey-to-a-system-tray-application-in-c?forum=csharpgeneral
57 |
58 | if (e.KeyCode == Keys.F1)
59 | {
60 | buttonLog.PerformClick();
61 | e.Handled = true;
62 | }
63 | if (e.KeyCode == Keys.F2)
64 | {
65 | buttonLog.PerformClick();
66 | e.Handled = true;
67 | }
68 | else if (e.KeyCode == Keys.F3)
69 | {
70 | buttonPlot.PerformClick();
71 | e.Handled = false;
72 | }
73 | }
74 |
75 | protected override void WndProc(ref Message m)
76 | {
77 | if (m.Msg == WM_INPUT)
78 | {
79 | #if true
80 | RAWINPUT raw = new RAWINPUT();
81 | uint size = (uint)Marshal.SizeOf(typeof(RAWINPUT));
82 | int outsize = GetRawInputData(m.LParam, RID_INPUT, out raw, ref size, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)));
83 | if (outsize != -1)
84 | {
85 | if (raw.header.dwType == RIM_TYPEMOUSE)
86 | {
87 | QueryPerformanceCounter(out long pCounter);
88 | logMouseEvent(new MouseEvent(raw.data.mouse.buttonsStr.usButtonFlags, raw.data.mouse.lLastX, -(raw.data.mouse.lLastY), pCounter));
89 | }
90 | }
91 | #else
92 | uint dwSize = 0;
93 |
94 | GetRawInputData(m.LParam, RID_INPUT, IntPtr.Zero, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)));
95 |
96 | IntPtr buffer = Marshal.AllocHGlobal((int)dwSize);
97 | try
98 | {
99 | if ((buffer != IntPtr.Zero) &&
100 | (GetRawInputData(m.LParam, RID_INPUT, buffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) == dwSize))
101 | {
102 | RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT));
103 |
104 | if (raw.header.dwType == RIM_TYPEMOUSE)
105 | {
106 | logMouseEvent(new MouseEvent(raw.data.mouse.buttonsStr.usButtonFlags, raw.data.mouse.lLastX, -(raw.data.mouse.lLastY), pCounter));
107 | }
108 | }
109 | }
110 | finally
111 | {
112 | Marshal.FreeHGlobal(buffer);
113 | }
114 | #endif
115 | }
116 | base.WndProc(ref m);
117 | }
118 |
119 | private void logMouseEvent(MouseEvent mevent)
120 | {
121 | // Debug.WriteLine(mevent.pcounter + ", " + mevent.lastx + ", " + mevent.lasty + ", " + mevent.buttonflags);
122 | if (this.test_state == state.idle)
123 | {
124 |
125 | }
126 | else if (this.test_state == state.measure_wait)
127 | {
128 | if (mevent.buttonflags == 0x0001)
129 | {
130 | this.mlog.Add(mevent);
131 | this.toolStripStatusLabel1.Text = "Measuring";
132 | this.test_state = state.measure;
133 | }
134 | }
135 | else if (this.test_state == state.measure)
136 | {
137 | this.mlog.Add(mevent);
138 | if (mevent.buttonflags == 0x0002)
139 | {
140 | double x = 0.0;
141 | double y = 0.0;
142 | foreach (MouseEvent e in this.mlog.Events)
143 | {
144 | x += (double)e.lastx;
145 | y += (double)e.lasty;
146 | }
147 | tsCalc();
148 | this.mlog.Cpi = Math.Round(Math.Sqrt((x * x) + (y * y)) / (10 / 2.54));
149 | this.textBoxCPI.Text = this.mlog.Cpi.ToString();
150 | this.textBox1.Text = "Press the Collect or Log Start button\r\n";
151 | this.toolStripStatusLabel1.Text = "";
152 | this.test_state = state.idle;
153 | }
154 | }
155 | else if (this.test_state == state.collect_wait)
156 | {
157 | if (mevent.buttonflags == 0x0001)
158 | {
159 | this.mlog.Add(mevent);
160 | this.toolStripStatusLabel1.Text = "Collecting";
161 | this.test_state = state.collect;
162 | }
163 | }
164 | else if (this.test_state == state.collect)
165 | {
166 | this.mlog.Add(mevent);
167 | if (mevent.buttonflags == 0x0002)
168 | {
169 | tsCalc();
170 | this.textBox1.Text = "Press the plot button to view data\r\n" +
171 | " or\r\n" +
172 | "Press the save button to save log file\r\n" +
173 | "Events: " + this.mlog.Events.Count.ToString() + "\r\n" +
174 | "Sum X: " + this.mlog.deltaX().ToString() + " counts " + Math.Abs(this.mlog.deltaX() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
175 | "Sum Y: " + this.mlog.deltaY().ToString() + " counts " + Math.Abs(this.mlog.deltaY() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
176 | "Path: " + this.mlog.path().ToString("0") + " counts " + (this.mlog.path() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm";
177 | this.toolStripStatusLabel1.Text = "";
178 | this.test_state = state.idle;
179 | }
180 | }
181 | else if (this.test_state == state.log)
182 | {
183 | this.mlog.Add(mevent);
184 | }
185 | }
186 |
187 | private void buttonMeasure_Click(object sender, EventArgs e)
188 | {
189 | if (this.test_state == state.idle) {
190 | this.textBox1.Text = "1. Press and hold the left mouse button\r\n" +
191 | "2. Move the mouse 10 cm in a straight line\r\n" +
192 | "3. Release the left mouse button\r\n";
193 | this.toolStripStatusLabel1.Text = "Press the left mouse button";
194 | this.mlog.Clear();
195 | this.test_state = state.measure_wait;
196 | }
197 | }
198 |
199 | private void buttonCollect_Click(object sender, EventArgs e)
200 | {
201 | if (this.test_state == state.idle)
202 | {
203 | this.textBox1.Text = "1. Press and hold the left mouse button\r\n" +
204 | "2. Move the mouse\r\n" +
205 | "3. Release the left mouse button\r\n";
206 | this.toolStripStatusLabel1.Text = "Press the left mouse button";
207 | this.mlog.Clear();
208 | this.test_state = state.collect_wait;
209 | }
210 | }
211 |
212 | private void buttonLog_Click(object sender, EventArgs e)
213 | {
214 | if (this.test_state == state.idle)
215 | {
216 | this.textBox1.Text = "1. Press the Log Stop button\r\n";
217 | this.toolStripStatusLabel1.Text = "Logging...";
218 | this.mlog.Clear();
219 | this.test_state = state.log;
220 | buttonLog.Text = "Stop (F2)";
221 | }
222 | else if (this.test_state == state.log)
223 | {
224 | tsCalc();
225 | this.textBox1.Text = "Press the plot button to view data\r\n" +
226 | " or\r\n" +
227 | "Press the save button to save log file\r\n" +
228 | "Events: " + this.mlog.Events.Count.ToString() + "\r\n" +
229 | "Sum X: " + this.mlog.deltaX().ToString() + " counts " + Math.Abs(this.mlog.deltaX() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
230 | "Sum Y: " + this.mlog.deltaY().ToString() + " counts " + Math.Abs(this.mlog.deltaY() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
231 | "Path: " + this.mlog.path().ToString("0") + " counts " + (this.mlog.path() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm";
232 | this.toolStripStatusLabel1.Text = "";
233 | this.test_state = state.idle;
234 | buttonLog.Text = "Start (F1)";
235 | }
236 | }
237 |
238 | private void buttonPlot_Click(object sender, EventArgs e)
239 | {
240 | if (this.mlog.Events.Count > 0)
241 | {
242 | this.mlog.Desc = textBoxDesc.Text;
243 | MousePlot mousePlot = new MousePlot(this.mlog);
244 | mousePlot.Show();
245 | }
246 | }
247 |
248 | private void buttonLoad_Click(object sender, EventArgs e)
249 | {
250 | OpenFileDialog openFileDialog1 = new OpenFileDialog();
251 | openFileDialog1.Filter = "CSV Files (*.csv)|*.csv|All Files(*.*)|*.*";
252 | openFileDialog1.FilterIndex = 1;
253 | openFileDialog1.Multiselect = false;
254 | if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
255 | {
256 | this.mlog.Load(openFileDialog1.FileName);
257 | }
258 | this.textBox1.Text = "Events: " + this.mlog.Events.Count.ToString() + "\r\n" +
259 | "Sum X: " + this.mlog.deltaX().ToString() + " counts " + Math.Abs(this.mlog.deltaX() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
260 | "Sum Y: " + this.mlog.deltaY().ToString() + " counts " + Math.Abs(this.mlog.deltaY() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm\r\n" +
261 | "Path: " + this.mlog.path().ToString("0") + " counts " + (this.mlog.path() / this.mlog.Cpi * 2.54).ToString("0.0") + " cm";
262 | this.textBoxDesc.Text = this.mlog.Desc.ToString();
263 | this.textBoxCPI.Text = this.mlog.Cpi.ToString();
264 | if (this.mlog.Events.Count > 0)
265 | {
266 | MousePlot mousePlot = new MousePlot(this.mlog);
267 | mousePlot.Show();
268 | }
269 | }
270 |
271 | private void buttonSave_Click(object sender, EventArgs e)
272 | {
273 | SaveFileDialog saveFileDialog1 = new SaveFileDialog();
274 | saveFileDialog1.Filter = "CSV Files (*.csv)|*.csv|All Files(*.*)|*.*";
275 | saveFileDialog1.FilterIndex = 1;
276 | if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
277 | {
278 | this.mlog.Desc = textBoxDesc.Text;
279 | this.mlog.Save(saveFileDialog1.FileName);
280 | }
281 | }
282 |
283 | private void textBoxCPI_Validated(object sender, EventArgs e)
284 | {
285 | try
286 | {
287 | this.mlog.Cpi = double.Parse(this.textBoxCPI.Text);
288 | }
289 | catch //(Exception ex)
290 | {
291 | MessageBox.Show("Invalid CPI, resetting to previous value");
292 | this.textBoxCPI.Text = this.mlog.Cpi.ToString();
293 | }
294 | this.textBox1.Text = "Press the Collect or Log Start button\r\n";
295 | }
296 |
297 | private void tsCalc()
298 | {
299 | long pcounter_min = this.mlog.Events[0].pcounter;
300 | foreach (MouseEvent me in this.mlog.Events)
301 | {
302 | me.ts = (me.pcounter - pcounter_min) * 1000.0 / pFreq;
303 | }
304 | }
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/GraphicsRenderContext.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // The MIT License (MIT)
4 | //
5 | // Copyright (c) 2012 Oystein Bjorke
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a
8 | // copy of this software and associated documentation files (the
9 | // "Software"), to deal in the Software without restriction, including
10 | // without limitation the rights to use, copy, modify, merge, publish,
11 | // distribute, sublicense, and/or sell copies of the Software, and to
12 | // permit persons to whom the Software is furnished to do so, subject to
13 | // the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included
16 | // in all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | //
26 | //
27 | // The graphics render context.
28 | //
29 | // --------------------------------------------------------------------------------------------------------------------
30 | namespace OxyPlot.WindowsForms
31 | {
32 | using System;
33 | using System.Collections.Generic;
34 | using System.Drawing;
35 | using System.Drawing.Drawing2D;
36 | using System.Drawing.Imaging;
37 | using System.IO;
38 | using System.Linq;
39 |
40 | using OxyPlot;
41 |
42 | ///
43 | /// The graphics render context.
44 | ///
45 | internal class GraphicsRenderContext : RenderContextBase
46 | {
47 | ///
48 | /// The font size factor.
49 | ///
50 | private const float FontsizeFactor = 0.8f;
51 |
52 | ///
53 | /// The GDI+ drawing surface.
54 | ///
55 | private Graphics g;
56 |
57 | ///
58 | /// Initializes a new instance of the class.
59 | ///
60 | public GraphicsRenderContext()
61 | {
62 | }
63 |
64 | ///
65 | /// Sets the graphics target.
66 | ///
67 | /// The graphics surface.
68 | public void SetGraphicsTarget(Graphics graphics)
69 | {
70 | this.g = graphics;
71 | this.g.CompositingMode = CompositingMode.SourceOver;
72 | this.g.CompositingQuality = CompositingQuality.HighQuality;
73 | this.g.InterpolationMode = InterpolationMode.HighQualityBicubic;
74 | this.g.PixelOffsetMode = PixelOffsetMode.HighQuality;
75 | this.g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
76 | this.g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
77 | }
78 |
79 | ///
80 | /// Draws the ellipse.
81 | ///
82 | /// The rect.
83 | /// The fill.
84 | /// The stroke.
85 | /// The thickness.
86 | public override void DrawEllipse(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
87 | {
88 | if (fill != null)
89 | {
90 | this.g.FillEllipse(
91 | this.ToBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
92 | }
93 |
94 | if (stroke == null || thickness <= 0)
95 | {
96 | return;
97 | }
98 |
99 | using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
100 | {
101 | this.g.SmoothingMode = SmoothingMode.HighQuality;
102 | this.g.DrawEllipse(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
103 | }
104 | }
105 |
106 | ///
107 | /// Draws the line.
108 | ///
109 | /// The points.
110 | /// The stroke.
111 | /// The thickness.
112 | /// The dash array.
113 | /// The line join.
114 | /// if set to true [aliased].
115 | public override void DrawLine(
116 | IList points,
117 | OxyColor stroke,
118 | double thickness,
119 | double[] dashArray,
120 | OxyPenLineJoin lineJoin,
121 | bool aliased)
122 | {
123 | if (stroke == null || thickness <= 0 || points.Count < 2)
124 | {
125 | return;
126 | }
127 |
128 | this.g.SmoothingMode = aliased ? SmoothingMode.None : SmoothingMode.HighQuality;
129 | using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
130 | {
131 |
132 | if (dashArray != null)
133 | {
134 | pen.DashPattern = this.ToFloatArray(dashArray);
135 | }
136 |
137 | switch (lineJoin)
138 | {
139 | case OxyPenLineJoin.Round:
140 | pen.LineJoin = LineJoin.Round;
141 | break;
142 | case OxyPenLineJoin.Bevel:
143 | pen.LineJoin = LineJoin.Bevel;
144 | break;
145 |
146 | // The default LineJoin is Miter
147 | }
148 |
149 | this.g.DrawLines(pen, this.ToPoints(points));
150 | }
151 | }
152 |
153 | ///
154 | /// Draws the polygon.
155 | ///
156 | /// The points.
157 | /// The fill.
158 | /// The stroke.
159 | /// The thickness.
160 | /// The dash array.
161 | /// The line join.
162 | /// if set to true [aliased].
163 | public override void DrawPolygon(
164 | IList points,
165 | OxyColor fill,
166 | OxyColor stroke,
167 | double thickness,
168 | double[] dashArray,
169 | OxyPenLineJoin lineJoin,
170 | bool aliased)
171 | {
172 | if (points.Count < 2)
173 | {
174 | return;
175 | }
176 |
177 | this.g.SmoothingMode = aliased ? SmoothingMode.None : SmoothingMode.HighQuality;
178 |
179 | PointF[] pts = this.ToPoints(points);
180 | if (fill != null)
181 | {
182 | this.g.FillPolygon(this.ToBrush(fill), pts);
183 | }
184 |
185 | if (stroke != null && thickness > 0)
186 | {
187 | using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
188 | {
189 |
190 | if (dashArray != null)
191 | {
192 | pen.DashPattern = this.ToFloatArray(dashArray);
193 | }
194 |
195 | switch (lineJoin)
196 | {
197 | case OxyPenLineJoin.Round:
198 | pen.LineJoin = LineJoin.Round;
199 | break;
200 | case OxyPenLineJoin.Bevel:
201 | pen.LineJoin = LineJoin.Bevel;
202 | break;
203 |
204 | // The default LineJoin is Miter
205 | }
206 |
207 | this.g.DrawPolygon(pen, pts);
208 | }
209 | }
210 | }
211 |
212 | ///
213 | /// The draw rectangle.
214 | ///
215 | ///
216 | /// The rect.
217 | ///
218 | ///
219 | /// The fill.
220 | ///
221 | ///
222 | /// The stroke.
223 | ///
224 | ///
225 | /// The thickness.
226 | ///
227 | public override void DrawRectangle(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
228 | {
229 | if (fill != null)
230 | {
231 | this.g.FillRectangle(
232 | this.ToBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
233 | }
234 |
235 | if (stroke == null || thickness <= 0)
236 | {
237 | return;
238 | }
239 |
240 | using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
241 | {
242 | this.g.DrawRectangle(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
243 | }
244 | }
245 |
246 | ///
247 | /// The draw text.
248 | ///
249 | ///
250 | /// The p.
251 | ///
252 | ///
253 | /// The text.
254 | ///
255 | ///
256 | /// The fill.
257 | ///
258 | ///
259 | /// The font family.
260 | ///
261 | ///
262 | /// The font size.
263 | ///
264 | ///
265 | /// The font weight.
266 | ///
267 | ///
268 | /// The rotate.
269 | ///
270 | ///
271 | /// The halign.
272 | ///
273 | ///
274 | /// The valign.
275 | ///
276 | ///
277 | /// The maximum size of the text.
278 | ///
279 | public override void DrawText(
280 | ScreenPoint p,
281 | string text,
282 | OxyColor fill,
283 | string fontFamily,
284 | double fontSize,
285 | double fontWeight,
286 | double rotate,
287 | HorizontalAlignment halign,
288 | VerticalAlignment valign,
289 | OxySize? maxSize)
290 | {
291 | var fs = FontStyle.Regular;
292 | if (fontWeight >= 700)
293 | {
294 | fs = FontStyle.Bold;
295 | }
296 |
297 | using (var font = new Font(fontFamily, (float)fontSize * FontsizeFactor, fs))
298 | {
299 | using (var sf = new StringFormat { Alignment = StringAlignment.Near })
300 | {
301 | var size = this.g.MeasureString(text, font);
302 | if (maxSize != null)
303 | {
304 | if (size.Width > maxSize.Value.Width)
305 | {
306 | size.Width = (float)maxSize.Value.Width;
307 | }
308 |
309 | if (size.Height > maxSize.Value.Height)
310 | {
311 | size.Height = (float)maxSize.Value.Height;
312 | }
313 | }
314 |
315 | float dx = 0;
316 | if (halign == HorizontalAlignment.Center)
317 | {
318 | dx = -size.Width / 2;
319 | }
320 |
321 | if (halign == HorizontalAlignment.Right)
322 | {
323 | dx = -size.Width;
324 | }
325 |
326 | float dy = 0;
327 | sf.LineAlignment = StringAlignment.Near;
328 | if (valign == VerticalAlignment.Middle)
329 | {
330 | dy = -size.Height / 2;
331 | }
332 |
333 | if (valign == VerticalAlignment.Bottom)
334 | {
335 | dy = -size.Height;
336 | }
337 |
338 | this.g.TranslateTransform((float)p.X, (float)p.Y);
339 | if (Math.Abs(rotate) > double.Epsilon)
340 | {
341 | this.g.RotateTransform((float)rotate);
342 | }
343 |
344 | this.g.TranslateTransform(dx, dy);
345 |
346 | var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
347 | this.g.DrawString(text, font, this.ToBrush(fill), layoutRectangle, sf);
348 |
349 | this.g.ResetTransform();
350 | }
351 | }
352 | }
353 |
354 | ///
355 | /// The measure text.
356 | ///
357 | /// The text.
358 | /// The font family.
359 | /// The font size.
360 | /// The font weight.
361 | /// The size of the text.
362 | public override OxySize MeasureText(string text, string fontFamily, double fontSize, double fontWeight)
363 | {
364 | if (text == null)
365 | {
366 | return OxySize.Empty;
367 | }
368 |
369 | var fs = FontStyle.Regular;
370 | if (fontWeight >= 700)
371 | {
372 | fs = FontStyle.Bold;
373 | }
374 |
375 | using (var font = new Font(fontFamily, (float)fontSize * FontsizeFactor, fs))
376 | {
377 | var size = this.g.MeasureString(text, font);
378 | return new OxySize(size.Width, size.Height);
379 | }
380 | }
381 |
382 | ///
383 | /// Converts a fill color to a System.Drawing.Brush.
384 | ///
385 | ///
386 | /// The fill color.
387 | ///
388 | ///
389 | /// The brush.
390 | ///
391 | private Brush ToBrush(OxyColor fill)
392 | {
393 | if (fill != null)
394 | {
395 | return new SolidBrush(this.ToColor(fill));
396 | }
397 |
398 | return null;
399 | }
400 |
401 | ///
402 | /// Converts a color to a System.Drawing.Color.
403 | ///
404 | ///
405 | /// The color.
406 | ///
407 | ///
408 | /// The System.Drawing.Color.
409 | ///
410 | private Color ToColor(OxyColor c)
411 | {
412 | return Color.FromArgb(c.A, c.R, c.G, c.B);
413 | }
414 |
415 | ///
416 | /// Converts a double array to a float array.
417 | ///
418 | ///
419 | /// The a.
420 | ///
421 | ///
422 | /// The float array.
423 | ///
424 | private float[] ToFloatArray(double[] a)
425 | {
426 | if (a == null)
427 | {
428 | return null;
429 | }
430 |
431 | var r = new float[a.Length];
432 | for (int i = 0; i < a.Length; i++)
433 | {
434 | r[i] = (float)a[i];
435 | }
436 |
437 | return r;
438 | }
439 |
440 | ///
441 | /// Converts a list of point to an array of PointF.
442 | ///
443 | ///
444 | /// The points.
445 | ///
446 | ///
447 | /// An array of points.
448 | ///
449 | private PointF[] ToPoints(IList points)
450 | {
451 | if (points == null)
452 | {
453 | return null;
454 | }
455 |
456 | var r = new PointF[points.Count()];
457 | int i = 0;
458 | foreach (ScreenPoint p in points)
459 | {
460 | r[i++] = new PointF((float)p.X, (float)p.Y);
461 | }
462 |
463 | return r;
464 | }
465 |
466 | public override void CleanUp()
467 | {
468 | var imagesToRelease = imageCache.Keys.Where(i => !imagesInUse.Contains(i));
469 | foreach (var i in imagesToRelease)
470 | {
471 | var image = this.GetImage(i);
472 | image.Dispose();
473 | imageCache.Remove(i);
474 | }
475 |
476 | imagesInUse.Clear();
477 | }
478 |
479 | public override OxyImageInfo GetImageInfo(OxyImage source)
480 | {
481 | var image = this.GetImage(source);
482 | return image == null ? null : new OxyImageInfo { Width = (uint)image.Width, Height = (uint)image.Height, DpiX = image.HorizontalResolution, DpiY = image.VerticalResolution };
483 | }
484 |
485 | public override void DrawImage(OxyImage source, uint srcX, uint srcY, uint srcWidth, uint srcHeight, double x, double y, double w, double h, double opacity, bool interpolate)
486 | {
487 | var image = this.GetImage(source);
488 | if (image != null)
489 | {
490 | ImageAttributes ia = null;
491 | if (opacity < 1)
492 | {
493 | var cm = new ColorMatrix
494 | {
495 | Matrix00 = 1f,
496 | Matrix11 = 1f,
497 | Matrix22 = 1f,
498 | Matrix33 = 1f,
499 | Matrix44 = (float)opacity
500 | };
501 |
502 | ia = new ImageAttributes();
503 | ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
504 | }
505 |
506 | g.InterpolationMode = interpolate ? InterpolationMode.HighQualityBicubic : InterpolationMode.NearestNeighbor;
507 | int sx = (int)Math.Round(x);
508 | int sy = (int)Math.Round(y);
509 | int sw = (int)Math.Round(x + w) - sx;
510 | int sh = (int)Math.Round(y + h) - sy;
511 | g.DrawImage(image, new Rectangle(sx, sy, sw, sh), srcX, srcY, srcWidth, srcHeight, GraphicsUnit.Pixel, ia);
512 | }
513 | }
514 |
515 | private HashSet imagesInUse = new HashSet();
516 |
517 | private Dictionary imageCache = new Dictionary();
518 |
519 |
520 | private Image GetImage(OxyImage source)
521 | {
522 | if (source == null)
523 | {
524 | return null;
525 | }
526 |
527 | if (!this.imagesInUse.Contains(source))
528 | {
529 | this.imagesInUse.Add(source);
530 | }
531 |
532 | Image src;
533 | if (this.imageCache.TryGetValue(source, out src))
534 | {
535 | return src;
536 | }
537 |
538 | if (source != null)
539 | {
540 | Image btm;
541 | using (var ms = new MemoryStream(source.GetData()))
542 | {
543 | btm = Image.FromStream(ms);
544 | }
545 |
546 | this.imageCache.Add(source, btm);
547 | return btm;
548 | }
549 |
550 | return null;
551 | }
552 |
553 | public override bool SetClip(OxyRect rect)
554 | {
555 | this.g.SetClip(rect.ToRect(false));
556 | return true;
557 | }
558 |
559 | public override void ResetClip()
560 | {
561 | this.g.ResetClip();
562 | }
563 | }
564 | }
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MouseEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace MouseTester
7 | {
8 | public class MouseEvent
9 | {
10 | public ushort buttonflags;
11 | public int lastx;
12 | public int lasty;
13 | public long pcounter;
14 | public double ts;
15 |
16 | public MouseEvent(ushort buttonflags, int lastx, int lasty, long pcounter)
17 | {
18 | this.buttonflags = buttonflags;
19 | this.lastx = lastx;
20 | this.lasty = lasty;
21 | this.pcounter = pcounter;
22 | this.ts = 0.0;
23 | }
24 | public MouseEvent(ushort buttonflags, int lastx, int lasty, double ts)
25 | {
26 | this.buttonflags = buttonflags;
27 | this.lastx = lastx;
28 | this.lasty = lasty;
29 | this.pcounter = 0;
30 | this.ts = ts;
31 | }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MouseLog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Globalization;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 |
9 | namespace MouseTester
10 | {
11 | public class MouseLog
12 | {
13 | private string desc = "MouseTester";
14 | private double cpi = 400.0;
15 | private List events = new List();
16 |
17 | public double Cpi
18 | {
19 | get
20 | {
21 | return this.cpi;
22 | }
23 | set
24 | {
25 | cpi = value;
26 | }
27 | }
28 |
29 | public string Desc
30 | {
31 | get
32 | {
33 | return this.desc;
34 | }
35 | set
36 | {
37 | this.desc = value;
38 | }
39 | }
40 |
41 | public List Events
42 | {
43 | get
44 | {
45 | return this.events;
46 | }
47 | }
48 |
49 | public void Add(MouseEvent e)
50 | {
51 | this.events.Add(e);
52 | }
53 |
54 | public void Clear()
55 | {
56 | this.events.Clear();
57 | }
58 |
59 | public void Load(string fname)
60 | {
61 | this.Clear();
62 |
63 | try
64 | {
65 | using (StreamReader sr = File.OpenText(fname))
66 | {
67 | this.desc = sr.ReadLine();
68 | this.cpi = double.Parse(sr.ReadLine());
69 | string headerline = sr.ReadLine();
70 | while (sr.Peek() > -1)
71 | {
72 | string line = sr.ReadLine();
73 | string[] values = line.Split(',');
74 | if (values.Length == 4)
75 | {
76 | this.Add(new MouseEvent(ushort.Parse(values[3]), int.Parse(values[0]), int.Parse(values[1]), double.Parse(values[2])));
77 | }
78 | else if (values.Length == 3)
79 | {
80 | this.Add(new MouseEvent(0, int.Parse(values[0]), int.Parse(values[1]), double.Parse(values[2])));
81 | }
82 | }
83 | }
84 | }
85 | catch (Exception ex)
86 | {
87 | Debug.WriteLine(ex.ToString());
88 | }
89 | }
90 |
91 | public void Save(string fname)
92 | {
93 | try
94 | {
95 | using (StreamWriter sw = File.CreateText(fname))
96 | {
97 | sw.WriteLine(this.desc);
98 | sw.WriteLine(this.cpi.ToString());
99 | sw.WriteLine("xCount,yCount,Time (ms),buttonflags");
100 | foreach (MouseEvent e in this.events)
101 | {
102 | sw.WriteLine(e.lastx.ToString() + "," + e.lasty.ToString() + "," + e.ts.ToString(CultureInfo.InvariantCulture) + "," + e.buttonflags.ToString());
103 | }
104 | }
105 | }
106 | catch (Exception ex)
107 | {
108 | Debug.WriteLine(ex.ToString());
109 | }
110 | }
111 |
112 | public int deltaX()
113 | {
114 | return this.events.Sum(e => e.lastx);
115 | }
116 |
117 | public int deltaY()
118 | {
119 | return this.events.Sum(e => e.lasty);
120 | }
121 |
122 | public double path()
123 | {
124 | return this.events.Sum(e => Math.Sqrt((e.lastx * e.lastx) + (e.lasty * e.lasty)));
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MousePlot.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MouseTester
2 | {
3 | partial class MousePlot
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.splitContainer1 = new System.Windows.Forms.SplitContainer();
32 | this.plot1 = new OxyPlot.WindowsForms.Plot();
33 | this.checkBoxStem = new System.Windows.Forms.CheckBox();
34 | this.buttonSavePNG = new System.Windows.Forms.Button();
35 | this.groupBox3 = new System.Windows.Forms.GroupBox();
36 | this.numericUpDownEnd = new System.Windows.Forms.NumericUpDown();
37 | this.groupBox2 = new System.Windows.Forms.GroupBox();
38 | this.numericUpDownStart = new System.Windows.Forms.NumericUpDown();
39 | this.groupBox1 = new System.Windows.Forms.GroupBox();
40 | this.comboBoxPlotType = new System.Windows.Forms.ComboBox();
41 | this.checkBoxLines = new System.Windows.Forms.CheckBox();
42 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
43 | this.splitContainer1.Panel1.SuspendLayout();
44 | this.splitContainer1.Panel2.SuspendLayout();
45 | this.splitContainer1.SuspendLayout();
46 | this.groupBox3.SuspendLayout();
47 | ((System.ComponentModel.ISupportInitialize)(this.numericUpDownEnd)).BeginInit();
48 | this.groupBox2.SuspendLayout();
49 | ((System.ComponentModel.ISupportInitialize)(this.numericUpDownStart)).BeginInit();
50 | this.groupBox1.SuspendLayout();
51 | this.SuspendLayout();
52 | //
53 | // splitContainer1
54 | //
55 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
56 | this.splitContainer1.Location = new System.Drawing.Point(0, 0);
57 | this.splitContainer1.Name = "splitContainer1";
58 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
59 | //
60 | // splitContainer1.Panel1
61 | //
62 | this.splitContainer1.Panel1.Controls.Add(this.plot1);
63 | //
64 | // splitContainer1.Panel2
65 | //
66 | this.splitContainer1.Panel2.Controls.Add(this.checkBoxLines);
67 | this.splitContainer1.Panel2.Controls.Add(this.checkBoxStem);
68 | this.splitContainer1.Panel2.Controls.Add(this.buttonSavePNG);
69 | this.splitContainer1.Panel2.Controls.Add(this.groupBox3);
70 | this.splitContainer1.Panel2.Controls.Add(this.groupBox2);
71 | this.splitContainer1.Panel2.Controls.Add(this.groupBox1);
72 | this.splitContainer1.Size = new System.Drawing.Size(800, 677);
73 | this.splitContainer1.SplitterDistance = 600;
74 | this.splitContainer1.TabIndex = 0;
75 | //
76 | // plot1
77 | //
78 | this.plot1.BackColor = System.Drawing.Color.White;
79 | this.plot1.Dock = System.Windows.Forms.DockStyle.Fill;
80 | this.plot1.KeyboardPanHorizontalStep = 0.1D;
81 | this.plot1.KeyboardPanVerticalStep = 0.1D;
82 | this.plot1.Location = new System.Drawing.Point(0, 0);
83 | this.plot1.Name = "plot1";
84 | this.plot1.PanCursor = System.Windows.Forms.Cursors.Hand;
85 | this.plot1.Size = new System.Drawing.Size(800, 600);
86 | this.plot1.TabIndex = 0;
87 | this.plot1.Text = "plot1";
88 | this.plot1.ZoomHorizontalCursor = System.Windows.Forms.Cursors.SizeWE;
89 | this.plot1.ZoomRectangleCursor = System.Windows.Forms.Cursors.SizeNWSE;
90 | this.plot1.ZoomVerticalCursor = System.Windows.Forms.Cursors.SizeNS;
91 | //
92 | // checkBoxStem
93 | //
94 | this.checkBoxStem.AutoSize = true;
95 | this.checkBoxStem.Location = new System.Drawing.Point(510, 40);
96 | this.checkBoxStem.Name = "checkBoxStem";
97 | this.checkBoxStem.Size = new System.Drawing.Size(50, 17);
98 | this.checkBoxStem.TabIndex = 8;
99 | this.checkBoxStem.Text = "Stem";
100 | this.checkBoxStem.UseVisualStyleBackColor = true;
101 | //
102 | // buttonSavePNG
103 | //
104 | this.buttonSavePNG.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
105 | this.buttonSavePNG.Location = new System.Drawing.Point(713, 24);
106 | this.buttonSavePNG.Name = "buttonSavePNG";
107 | this.buttonSavePNG.Size = new System.Drawing.Size(75, 23);
108 | this.buttonSavePNG.TabIndex = 7;
109 | this.buttonSavePNG.Text = "SavePNG";
110 | this.buttonSavePNG.UseVisualStyleBackColor = true;
111 | this.buttonSavePNG.Click += new System.EventHandler(this.buttonSavePNG_Click);
112 | //
113 | // groupBox3
114 | //
115 | this.groupBox3.Controls.Add(this.numericUpDownEnd);
116 | this.groupBox3.Location = new System.Drawing.Point(369, 7);
117 | this.groupBox3.Name = "groupBox3";
118 | this.groupBox3.Size = new System.Drawing.Size(135, 50);
119 | this.groupBox3.TabIndex = 6;
120 | this.groupBox3.TabStop = false;
121 | this.groupBox3.Text = "Data Point End";
122 | //
123 | // numericUpDownEnd
124 | //
125 | this.numericUpDownEnd.Location = new System.Drawing.Point(6, 20);
126 | this.numericUpDownEnd.Name = "numericUpDownEnd";
127 | this.numericUpDownEnd.Size = new System.Drawing.Size(120, 20);
128 | this.numericUpDownEnd.TabIndex = 2;
129 | //
130 | // groupBox2
131 | //
132 | this.groupBox2.Controls.Add(this.numericUpDownStart);
133 | this.groupBox2.Location = new System.Drawing.Point(228, 7);
134 | this.groupBox2.Name = "groupBox2";
135 | this.groupBox2.Size = new System.Drawing.Size(135, 50);
136 | this.groupBox2.TabIndex = 5;
137 | this.groupBox2.TabStop = false;
138 | this.groupBox2.Text = "Data Point Start";
139 | //
140 | // numericUpDownStart
141 | //
142 | this.numericUpDownStart.Location = new System.Drawing.Point(6, 20);
143 | this.numericUpDownStart.Name = "numericUpDownStart";
144 | this.numericUpDownStart.Size = new System.Drawing.Size(120, 20);
145 | this.numericUpDownStart.TabIndex = 3;
146 | //
147 | // groupBox1
148 | //
149 | this.groupBox1.Controls.Add(this.comboBoxPlotType);
150 | this.groupBox1.Location = new System.Drawing.Point(12, 7);
151 | this.groupBox1.Name = "groupBox1";
152 | this.groupBox1.Size = new System.Drawing.Size(210, 50);
153 | this.groupBox1.TabIndex = 4;
154 | this.groupBox1.TabStop = false;
155 | this.groupBox1.Text = "Plot Type";
156 | //
157 | // comboBoxPlotType
158 | //
159 | this.comboBoxPlotType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
160 | this.comboBoxPlotType.FormattingEnabled = true;
161 | this.comboBoxPlotType.Items.AddRange(new object[] {
162 | "xCount vs. Time",
163 | "yCount vs. Time",
164 | "xyCount vs. Time",
165 | "Interval vs. Time",
166 | "xVelocity vs. Time",
167 | "yVelocity vs. Time",
168 | "xyVelocity vs. Time",
169 | "X vs. Y"});
170 | this.comboBoxPlotType.Location = new System.Drawing.Point(6, 19);
171 | this.comboBoxPlotType.Name = "comboBoxPlotType";
172 | this.comboBoxPlotType.Size = new System.Drawing.Size(200, 21);
173 | this.comboBoxPlotType.TabIndex = 1;
174 | //
175 | // checkBoxLines
176 | //
177 | this.checkBoxLines.AutoSize = true;
178 | this.checkBoxLines.Location = new System.Drawing.Point(510, 17);
179 | this.checkBoxLines.Name = "checkBoxLines";
180 | this.checkBoxLines.Size = new System.Drawing.Size(51, 17);
181 | this.checkBoxLines.TabIndex = 9;
182 | this.checkBoxLines.Text = "Lines";
183 | this.checkBoxLines.UseVisualStyleBackColor = true;
184 | //
185 | // MousePlot
186 | //
187 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
188 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
189 | this.ClientSize = new System.Drawing.Size(800, 677);
190 | this.Controls.Add(this.splitContainer1);
191 | this.MinimumSize = new System.Drawing.Size(808, 627);
192 | this.Name = "MousePlot";
193 | this.Text = "MousePlot";
194 | this.splitContainer1.Panel1.ResumeLayout(false);
195 | this.splitContainer1.Panel2.ResumeLayout(false);
196 | this.splitContainer1.Panel2.PerformLayout();
197 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
198 | this.splitContainer1.ResumeLayout(false);
199 | this.groupBox3.ResumeLayout(false);
200 | ((System.ComponentModel.ISupportInitialize)(this.numericUpDownEnd)).EndInit();
201 | this.groupBox2.ResumeLayout(false);
202 | ((System.ComponentModel.ISupportInitialize)(this.numericUpDownStart)).EndInit();
203 | this.groupBox1.ResumeLayout(false);
204 | this.ResumeLayout(false);
205 |
206 | }
207 |
208 | #endregion
209 |
210 | private System.Windows.Forms.SplitContainer splitContainer1;
211 | private OxyPlot.WindowsForms.Plot plot1;
212 | private System.Windows.Forms.ComboBox comboBoxPlotType;
213 | private System.Windows.Forms.NumericUpDown numericUpDownStart;
214 | private System.Windows.Forms.NumericUpDown numericUpDownEnd;
215 | private System.Windows.Forms.GroupBox groupBox3;
216 | private System.Windows.Forms.GroupBox groupBox2;
217 | private System.Windows.Forms.GroupBox groupBox1;
218 | private System.Windows.Forms.Button buttonSavePNG;
219 | private System.Windows.Forms.CheckBox checkBoxStem;
220 | private System.Windows.Forms.CheckBox checkBoxLines;
221 | }
222 | }
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MousePlot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using OxyPlot;
10 |
11 | namespace MouseTester
12 | {
13 | using System.Drawing;
14 | using System.Drawing.Imaging;
15 | using OxyPlot.WindowsForms;
16 | using OxyPlot.Annotations;
17 | using OxyPlot.Axes;
18 | using OxyPlot.Series;
19 |
20 | public partial class MousePlot : Form
21 | {
22 | private MouseLog mlog;
23 | private int last_start;
24 | private int last_end;
25 | double x_min;
26 | double x_max;
27 | double y_min;
28 | double y_max;
29 | private string xlabel = "";
30 | private string ylabel = "";
31 |
32 | public MousePlot(MouseLog Mlog)
33 | {
34 | InitializeComponent();
35 | this.mlog = new MouseLog();
36 | this.mlog.Desc = Mlog.Desc;
37 | this.mlog.Cpi = Mlog.Cpi;
38 | int i = 1;
39 | int x = Mlog.Events[0].lastx;
40 | int y = Mlog.Events[0].lasty;
41 | ushort buttonflags = Mlog.Events[0].buttonflags;
42 | double ts = Mlog.Events[0].ts;
43 | while (i < Mlog.Events.Count)
44 | {
45 | this.mlog.Add(new MouseEvent(buttonflags, x, y, ts));
46 | x = Mlog.Events[i].lastx;
47 | y = Mlog.Events[i].lasty;
48 | buttonflags = Mlog.Events[i].buttonflags;
49 | ts = Mlog.Events[i].ts;
50 | i++;
51 | }
52 | this.mlog.Add(new MouseEvent(buttonflags, x, y, ts));
53 |
54 | this.last_start = 0;
55 | this.last_end = this.mlog.Events.Count - 1;
56 | initialize_plot();
57 |
58 | this.comboBoxPlotType.SelectedIndex = 0;
59 | this.comboBoxPlotType.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
60 |
61 | this.numericUpDownStart.Minimum = 0;
62 | this.numericUpDownStart.Maximum = this.mlog.Events.Count - 1;
63 | this.numericUpDownStart.Value = last_start;
64 | this.numericUpDownStart.ValueChanged += new System.EventHandler(this.numericUpDownStart_ValueChanged);
65 |
66 | this.numericUpDownEnd.Minimum = 0;
67 | this.numericUpDownEnd.Maximum = this.mlog.Events.Count - 1;
68 | this.numericUpDownEnd.Value = last_end;
69 | this.numericUpDownEnd.ValueChanged += new System.EventHandler(this.numericUpDownEnd_ValueChanged);
70 |
71 | this.checkBoxStem.Checked = false;
72 | this.checkBoxStem.CheckedChanged += new System.EventHandler(this.checkBoxStem_CheckedChanged);
73 |
74 | this.checkBoxLines.Checked = false;
75 | this.checkBoxLines.CheckedChanged += new System.EventHandler(this.checkBoxLines_CheckedChanged);
76 |
77 | refresh_plot();
78 | }
79 |
80 | private void initialize_plot()
81 | {
82 | var pm = new PlotModel(this.mlog.Desc.ToString())
83 | {
84 | PlotType = PlotType.Cartesian,
85 | Background = OxyColors.White,
86 | Subtitle = this.mlog.Cpi.ToString() + " cpi"
87 | };
88 | plot1.Model = pm;
89 | }
90 |
91 | private void refresh_plot()
92 | {
93 | PlotModel pm = plot1.Model;
94 | pm.Series.Clear();
95 | pm.Axes.Clear();
96 | OxyColor singleLineColor = OxyColors.Green;
97 |
98 | var scatterSeries1 = new ScatterSeries
99 | {
100 | BinSize = 8,
101 | MarkerFill = OxyColors.Blue,
102 | MarkerSize = 1.5,
103 | MarkerStroke = OxyColors.Blue,
104 | MarkerStrokeThickness = 1.0,
105 | MarkerType = MarkerType.Circle
106 | };
107 |
108 | var scatterSeries2 = new ScatterSeries
109 | {
110 | BinSize = 8,
111 | MarkerFill = OxyColors.Red,
112 | MarkerSize = 1.5,
113 | MarkerStroke = OxyColors.Red,
114 | MarkerStrokeThickness = 1.0,
115 | MarkerType = MarkerType.Circle
116 | };
117 |
118 | var lineSeries1 = new LineSeries
119 | {
120 | Color = OxyColors.Blue,
121 | LineStyle = LineStyle.Solid,
122 | StrokeThickness = 2.0,
123 | Smooth = true
124 | };
125 |
126 | var lineSeries2 = new LineSeries
127 | {
128 | Color = OxyColors.Red,
129 | LineStyle = LineStyle.Solid,
130 | StrokeThickness = 2.0,
131 | Smooth = true
132 | };
133 |
134 | if (checkBoxLines.Checked)
135 | {
136 | lineSeries1.Smooth = false;
137 | lineSeries2.Smooth = false;
138 | }
139 |
140 | var stemSeries1 = new StemSeries
141 | {
142 | Color = OxyColors.Blue,
143 | StrokeThickness = 1.0,
144 | };
145 |
146 | var stemSeries2 = new StemSeries
147 | {
148 | Color = OxyColors.Red,
149 | StrokeThickness = 1.0
150 | };
151 |
152 | if (comboBoxPlotType.Text.Contains("xyCount"))
153 | {
154 | plot_xycounts_vs_time(scatterSeries1, scatterSeries2, stemSeries1, stemSeries2, lineSeries1, lineSeries2);
155 | pm.Series.Add(scatterSeries1);
156 | pm.Series.Add(scatterSeries2);
157 | if (!checkBoxLines.Checked)
158 | {
159 | plot_fit(scatterSeries1, lineSeries1);
160 | plot_fit(scatterSeries2, lineSeries2);
161 | }
162 | pm.Series.Add(lineSeries1);
163 | pm.Series.Add(lineSeries2);
164 | if (checkBoxStem.Checked)
165 | {
166 | pm.Series.Add(stemSeries1);
167 | pm.Series.Add(stemSeries2);
168 | }
169 | }
170 | else if (comboBoxPlotType.Text.Contains("xCount"))
171 | {
172 | plot_xcounts_vs_time(scatterSeries1, stemSeries1, lineSeries1);
173 | pm.Series.Add(scatterSeries1);
174 | if (!checkBoxLines.Checked)
175 | {
176 | plot_fit(scatterSeries1, lineSeries1);
177 | lineSeries1.Color = singleLineColor;
178 | }
179 | pm.Series.Add(lineSeries1);
180 | if (checkBoxStem.Checked)
181 | {
182 | pm.Series.Add(stemSeries1);
183 | }
184 | }
185 | else if (comboBoxPlotType.Text.Contains("yCount"))
186 | {
187 | plot_ycounts_vs_time(scatterSeries1, stemSeries1, lineSeries1);
188 | pm.Series.Add(scatterSeries1);
189 | if (!checkBoxLines.Checked)
190 | {
191 | plot_fit(scatterSeries1, lineSeries1);
192 | lineSeries1.Color = singleLineColor;
193 | }
194 | pm.Series.Add(lineSeries1);
195 | if (checkBoxStem.Checked)
196 | {
197 | pm.Series.Add(stemSeries1);
198 | }
199 |
200 | }
201 | else if (comboBoxPlotType.Text.Contains("Interval"))
202 | {
203 | plot_interval_vs_time(scatterSeries1, stemSeries1, lineSeries1);
204 | pm.Series.Add(scatterSeries1);
205 | if (!checkBoxLines.Checked)
206 | {
207 | plot_fit(scatterSeries1, lineSeries1);
208 | lineSeries1.Color = singleLineColor;
209 | }
210 | pm.Series.Add(lineSeries1);
211 | if (checkBoxStem.Checked)
212 | {
213 | pm.Series.Add(stemSeries1);
214 | }
215 |
216 | }
217 | else if (comboBoxPlotType.Text.Contains("xyVelocity"))
218 | {
219 | plot_xyvelocity_vs_time(scatterSeries1, scatterSeries2, stemSeries1, stemSeries2, lineSeries1, lineSeries2);
220 | pm.Series.Add(scatterSeries1);
221 | pm.Series.Add(scatterSeries2);
222 | if (!checkBoxLines.Checked)
223 | {
224 | plot_fit(scatterSeries1, lineSeries1);
225 | plot_fit(scatterSeries2, lineSeries2);
226 | }
227 | pm.Series.Add(lineSeries1);
228 | pm.Series.Add(lineSeries2);
229 | if (checkBoxStem.Checked)
230 | {
231 | pm.Series.Add(stemSeries1);
232 | pm.Series.Add(stemSeries2);
233 | }
234 |
235 | }
236 | else if (comboBoxPlotType.Text.Contains("xVelocity"))
237 | {
238 | plot_xvelocity_vs_time(scatterSeries1, stemSeries1, lineSeries1);
239 | pm.Series.Add(scatterSeries1);
240 | if (!checkBoxLines.Checked)
241 | {
242 | plot_fit(scatterSeries1, lineSeries1);
243 | lineSeries1.Color = singleLineColor;
244 | }
245 | pm.Series.Add(lineSeries1);
246 | if (checkBoxStem.Checked)
247 | {
248 | pm.Series.Add(stemSeries1);
249 | }
250 | }
251 | else if (comboBoxPlotType.Text.Contains("yVelocity"))
252 | {
253 | plot_yvelocity_vs_time(scatterSeries1, stemSeries1, lineSeries1);
254 | pm.Series.Add(scatterSeries1);
255 | if (!checkBoxLines.Checked)
256 | {
257 | plot_fit(scatterSeries1, lineSeries1);
258 | lineSeries1.Color = singleLineColor;
259 | }
260 | pm.Series.Add(lineSeries1);
261 | if (checkBoxStem.Checked)
262 | {
263 | pm.Series.Add(stemSeries1);
264 | }
265 | }
266 | else if (comboBoxPlotType.Text.Contains("X vs. Y"))
267 | {
268 | plot_x_vs_y(scatterSeries1, lineSeries1);
269 | pm.Series.Add(scatterSeries1);
270 | if (checkBoxLines.Checked)
271 | {
272 | pm.Series.Add(lineSeries1);
273 | lineSeries1.Color = singleLineColor;
274 | }
275 | }
276 |
277 | var linearAxis1 = new LinearAxis();
278 | linearAxis1.AbsoluteMinimum = x_min - (x_max - x_min) / 20.0;
279 | linearAxis1.AbsoluteMaximum = x_max + (x_max - x_min) / 20.0;
280 | linearAxis1.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
281 | linearAxis1.MajorGridlineStyle = LineStyle.Solid;
282 | linearAxis1.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
283 | linearAxis1.MinorGridlineStyle = LineStyle.Solid;
284 | linearAxis1.Position = AxisPosition.Bottom;
285 | linearAxis1.Title = xlabel;
286 | pm.Axes.Add(linearAxis1);
287 |
288 | var linearAxis2 = new LinearAxis();
289 | linearAxis2.AbsoluteMinimum = y_min - (y_max - y_min) / 20.0;
290 | linearAxis2.AbsoluteMaximum = y_max + (y_max - y_min) / 20.0;
291 | linearAxis2.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
292 | linearAxis2.MajorGridlineStyle = LineStyle.Solid;
293 | linearAxis2.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
294 | linearAxis2.MinorGridlineStyle = LineStyle.Solid;
295 | linearAxis2.Title = ylabel;
296 | pm.Axes.Add(linearAxis2);
297 |
298 | plot1.RefreshPlot(true);
299 | }
300 |
301 | private void reset_minmax()
302 | {
303 | x_min = double.MaxValue;
304 | x_max = double.MinValue;
305 | y_min = double.MaxValue;
306 | y_max = double.MinValue;
307 | }
308 |
309 | private void update_minmax(double x, double y)
310 | {
311 | if (x < x_min)
312 | {
313 | x_min = x;
314 | }
315 | if (x > x_max)
316 | {
317 | x_max = x;
318 | }
319 | if (y < y_min)
320 | {
321 | y_min = y;
322 | }
323 | if (y > y_max)
324 | {
325 | y_max = y;
326 | }
327 | }
328 |
329 | private void plot_xcounts_vs_time(ScatterSeries scatterSeries1, StemSeries stemSeries1, LineSeries lineSeries1)
330 | {
331 | xlabel = "Time (ms)";
332 | ylabel = "xCounts";
333 | reset_minmax();
334 | for (int i = last_start; i <= last_end; i++)
335 | {
336 | double x = this.mlog.Events[i].ts;
337 | double y = this.mlog.Events[i].lastx;
338 | update_minmax(x, y);
339 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
340 | lineSeries1.Points.Add(new DataPoint(x, y));
341 | stemSeries1.Points.Add(new DataPoint(x, y));
342 | }
343 | }
344 |
345 | private void plot_ycounts_vs_time(ScatterSeries scatterSeries1, StemSeries stemSeries1, LineSeries lineSeries1)
346 | {
347 | xlabel = "Time (ms)";
348 | ylabel = "yCounts";
349 | reset_minmax();
350 | for (int i = last_start; i <= last_end; i++)
351 | {
352 | double x = this.mlog.Events[i].ts;
353 | double y = this.mlog.Events[i].lasty;
354 | update_minmax(x, y);
355 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
356 | lineSeries1.Points.Add(new DataPoint(x, y));
357 | stemSeries1.Points.Add(new DataPoint(x, y));
358 | }
359 | }
360 |
361 | private void plot_xycounts_vs_time(ScatterSeries scatterSeries1, ScatterSeries scatterSeries2, StemSeries stemSeries1, StemSeries stemSeries2, LineSeries lineSeries1, LineSeries lineSeries2)
362 | {
363 | xlabel = "Time (ms)";
364 | ylabel = "Counts [x = Blue, y = Red]";
365 | reset_minmax();
366 | for (int i = last_start; i <= last_end; i++)
367 | {
368 | double x = this.mlog.Events[i].ts;
369 | double y = this.mlog.Events[i].lastx;
370 | update_minmax(x, y);
371 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
372 | lineSeries1.Points.Add(new DataPoint(x, y));
373 | stemSeries1.Points.Add(new DataPoint(x, y));
374 | }
375 |
376 | for (int i = last_start; i <= last_end; i++)
377 | {
378 | double x = this.mlog.Events[i].ts;
379 | double y = this.mlog.Events[i].lasty;
380 | update_minmax(x, y);
381 | scatterSeries2.Points.Add(new ScatterPoint(x, y));
382 | lineSeries2.Points.Add(new DataPoint(x, y));
383 | stemSeries2.Points.Add(new DataPoint(x, y));
384 | }
385 | }
386 |
387 | private void plot_interval_vs_time(ScatterSeries scatterSeries1, StemSeries stemSeries1, LineSeries lineSeries1)
388 | {
389 | xlabel = "Time (ms)";
390 | ylabel = "Update Time (ms)";
391 | reset_minmax();
392 | for (int i = last_start; i <= last_end; i++)
393 | {
394 | double x = this.mlog.Events[i].ts;
395 | double y;
396 | if (i == 0)
397 | {
398 | y = 0.0;
399 | }
400 | else
401 | {
402 | y = this.mlog.Events[i].ts - this.mlog.Events[i - 1].ts;
403 | }
404 | update_minmax(x, y);
405 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
406 | lineSeries1.Points.Add(new DataPoint(x, y));
407 | stemSeries1.Points.Add(new DataPoint(x, y));
408 | }
409 | }
410 |
411 | private void plot_xvelocity_vs_time(ScatterSeries scatterSeries1, StemSeries stemSeries1, LineSeries lineSeries1)
412 | {
413 | xlabel = "Time (ms)";
414 | ylabel = "xVelocity (m/s)";
415 | reset_minmax();
416 | if (this.mlog.Cpi > 0)
417 | {
418 | for (int i = last_start; i <= last_end; i++)
419 | {
420 | double x = this.mlog.Events[i].ts;
421 | double y;
422 | if (i == 0)
423 | {
424 | y = 0.0;
425 | }
426 | else
427 | {
428 | y = (this.mlog.Events[i].lastx) / (this.mlog.Events[i].ts - this.mlog.Events[i - 1].ts) / this.mlog.Cpi * 25.4;
429 | }
430 | update_minmax(x, y);
431 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
432 | lineSeries1.Points.Add(new DataPoint(x, y));
433 | stemSeries1.Points.Add(new DataPoint(x, y));
434 | }
435 | }
436 | else
437 | {
438 | MessageBox.Show("CPI value is invalid, please run Measure");
439 | }
440 | }
441 |
442 | private void plot_yvelocity_vs_time(ScatterSeries scatterSeries1, StemSeries stemSeries1, LineSeries lineSeries1)
443 | {
444 | xlabel = "Time (ms)";
445 | ylabel = "yVelocity (m/s)";
446 | reset_minmax();
447 | if (this.mlog.Cpi > 0)
448 | {
449 | for (int i = last_start; i <= last_end; i++)
450 | {
451 | double x = this.mlog.Events[i].ts;
452 | double y;
453 | if (i == 0)
454 | {
455 | y = 0.0;
456 | }
457 | else
458 | {
459 | y = (this.mlog.Events[i].lasty) / (this.mlog.Events[i].ts - this.mlog.Events[i - 1].ts) / this.mlog.Cpi * 25.4;
460 | }
461 | update_minmax(x, y);
462 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
463 | lineSeries1.Points.Add(new DataPoint(x, y));
464 | stemSeries1.Points.Add(new DataPoint(x, y));
465 | }
466 | }
467 | else
468 | {
469 | MessageBox.Show("CPI value is invalid, please run Measure");
470 | }
471 | }
472 |
473 | private void plot_xyvelocity_vs_time(ScatterSeries scatterSeries1, ScatterSeries scatterSeries2, StemSeries stemSeries1, StemSeries stemSeries2, LineSeries lineSeries1, LineSeries lineSeries2)
474 | {
475 | xlabel = "Time (ms)";
476 | ylabel = "Velocity (m/s) [x = Blue, y = Red]";
477 | reset_minmax();
478 | if (this.mlog.Cpi > 0)
479 | {
480 | for (int i = last_start; i <= last_end; i++)
481 | {
482 | double x = this.mlog.Events[i].ts;
483 | double y;
484 | if (i == 0)
485 | {
486 | y = 0.0;
487 | }
488 | else
489 | {
490 | y = (this.mlog.Events[i].lastx) / (this.mlog.Events[i].ts - this.mlog.Events[i - 1].ts) / this.mlog.Cpi * 25.4;
491 | }
492 | update_minmax(x, y);
493 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
494 | lineSeries1.Points.Add(new DataPoint(x, y));
495 | stemSeries1.Points.Add(new DataPoint(x, y));
496 | }
497 |
498 | for (int i = last_start; i <= last_end; i++)
499 | {
500 | double x = this.mlog.Events[i].ts;
501 | double y;
502 | if (i == 0)
503 | {
504 | y = 0.0;
505 | }
506 | else
507 | {
508 | y = (this.mlog.Events[i].lasty) / (this.mlog.Events[i].ts - this.mlog.Events[i - 1].ts) / this.mlog.Cpi * 25.4;
509 | }
510 | update_minmax(x, y);
511 | scatterSeries2.Points.Add(new ScatterPoint(x, y));
512 | lineSeries2.Points.Add(new DataPoint(x, y));
513 | stemSeries2.Points.Add(new DataPoint(x, y));
514 | }
515 | }
516 | else
517 | {
518 | MessageBox.Show("CPI value is invalid, please run Measure");
519 | }
520 | }
521 |
522 | private void plot_x_vs_y(ScatterSeries scatterSeries1, LineSeries lineSeries1)
523 | {
524 | xlabel = "xCounts";
525 | ylabel = "yCounts";
526 | reset_minmax();
527 | double x = 0.0;
528 | double y = 0.0;
529 | for (int i = last_start; i <= last_end; i++)
530 | {
531 | x += this.mlog.Events[i].lastx;
532 | y += this.mlog.Events[i].lasty;
533 | update_minmax(x, x);
534 | update_minmax(y, y);
535 | scatterSeries1.Points.Add(new ScatterPoint(x, y));
536 | lineSeries1.Points.Add(new DataPoint(x, y));
537 | }
538 | }
539 |
540 | #if false
541 | // Window based smoothing
542 | private void plot_fit(ScatterSeries scatterSeries1, LineSeries lineSeries1)
543 | {
544 | double sum = 0.0;
545 |
546 | lineSeries1.Points.Clear();
547 |
548 | for (int i = 0; ((i < 8) && (i < scatterSeries1.Points.Count)); i++)
549 | //for (int i = 0; ((i < 4) && (i < scatterSeries1.Points.Count)); i++)
550 | {
551 | sum = sum + scatterSeries1.Points[i].Y;
552 | }
553 |
554 | for (int i = 3; i < scatterSeries1.Points.Count - 5; i++)
555 | //for (int i = 1; i < scatterSeries1.Points.Count - 3; i++)
556 | {
557 | double x = (scatterSeries1.Points[i].X + scatterSeries1.Points[i + 1].X) / 2.0;
558 | double y = sum;
559 | lineSeries1.Points.Add(new DataPoint(x, y / 8.0));
560 | sum = sum - scatterSeries1.Points[i - 3].Y;
561 | sum = sum + scatterSeries1.Points[i + 5].Y;
562 | //lineSeries1.Points.Add(new DataPoint(x, y / 4.0));
563 | //sum = sum - scatterSeries1.Points[i - 1].Y;
564 | //sum = sum + scatterSeries1.Points[i + 3].Y;
565 |
566 | }
567 | }
568 | #else
569 | // Time based smoothing
570 | private void plot_fit(ScatterSeries scatterSeries1, LineSeries lineSeries1)
571 | {
572 | double hz = 125;
573 | double ms = 1000.0 / hz;
574 | lineSeries1.Points.Clear();
575 |
576 | int ind = 0;
577 | for (double x = ms; x <= scatterSeries1.Points[scatterSeries1.Points.Count - 1].X; x += ms)
578 | {
579 | double sum = 0.0;
580 | int count = 0;
581 | while (scatterSeries1.Points[ind].X <= x)
582 | {
583 | sum += scatterSeries1.Points[ind++].Y;
584 | count++;
585 | }
586 | lineSeries1.Points.Add(new DataPoint(x - (ms / 2.0), sum / count));
587 | }
588 | }
589 | #endif
590 |
591 | private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
592 | {
593 | refresh_plot();
594 | }
595 |
596 | private void numericUpDownStart_ValueChanged(object sender, EventArgs e)
597 | {
598 | if (numericUpDownStart.Value >= numericUpDownEnd.Value)
599 | {
600 | numericUpDownStart.Value = last_start;
601 | }
602 | else
603 | {
604 | last_start = (int)numericUpDownStart.Value;
605 | refresh_plot();
606 | }
607 | }
608 |
609 | private void numericUpDownEnd_ValueChanged(object sender, EventArgs e)
610 | {
611 | if (numericUpDownEnd.Value <= numericUpDownStart.Value)
612 | {
613 | numericUpDownEnd.Value = last_end;
614 | }
615 | else
616 | {
617 | last_end = (int)numericUpDownEnd.Value;
618 | refresh_plot();
619 | }
620 | }
621 |
622 | private void checkBoxStem_CheckedChanged(object sender, EventArgs e)
623 | {
624 | refresh_plot();
625 | }
626 |
627 | private void checkBoxLines_CheckedChanged(object sender, EventArgs e)
628 | {
629 | refresh_plot();
630 | }
631 |
632 | private void buttonSavePNG_Click(object sender, EventArgs e)
633 | {
634 | SaveFileDialog saveFileDialog1 = new SaveFileDialog();
635 | saveFileDialog1.Filter = "PNG Files (*.png)|*.png";
636 | saveFileDialog1.FilterIndex = 1;
637 | if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
638 | {
639 | MousePlot.Export(this.plot1.Model, saveFileDialog1.FileName, 800, 600);
640 | }
641 | }
642 |
643 | public static void Export(PlotModel model, string fileName, int width, int height, Brush background = null)
644 | {
645 | using (var bm = new Bitmap(width, height))
646 | {
647 | using (Graphics g = Graphics.FromImage(bm))
648 | {
649 | if (background != null)
650 | {
651 | g.FillRectangle(background, 0, 0, width, height);
652 | }
653 |
654 | var rc = new GraphicsRenderContext { RendersToScreen = false };
655 | rc.SetGraphicsTarget(g);
656 | model.Update();
657 | model.Render(rc, width, height);
658 | bm.Save(fileName, ImageFormat.Png);
659 | }
660 | }
661 | }
662 | }
663 | }
664 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MousePlot.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/MouseTester.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {B0953B29-AF9B-4C37-A2EC-947E98F683B3}
9 | WinExe
10 | Properties
11 | MouseTester
12 | MouseTester
13 | v4.6
14 |
15 |
16 | 512
17 | false
18 | publish\
19 | true
20 | Disk
21 | false
22 | Foreground
23 | 7
24 | Days
25 | false
26 | false
27 | true
28 | 0
29 | 1.4.0.%2a
30 | false
31 | true
32 |
33 |
34 | x86
35 | true
36 | full
37 | false
38 | bin\Debug\
39 | DEBUG;TRACE
40 | prompt
41 | 4
42 | false
43 |
44 |
45 | x86
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 | false
53 |
54 |
55 | Internet
56 |
57 |
58 | false
59 |
60 |
61 | Properties\app.manifest
62 |
63 |
64 | true
65 | bin\Debug\
66 | DEBUG;TRACE
67 | full
68 | AnyCPU
69 | 7.3
70 | prompt
71 | false
72 |
73 |
74 | bin\Release\
75 | TRACE
76 | true
77 | pdbonly
78 | AnyCPU
79 | 7.3
80 | prompt
81 | false
82 |
83 |
84 | true
85 | bin\x64\Debug\
86 | DEBUG;TRACE
87 | full
88 | x64
89 | 7.3
90 | prompt
91 | false
92 |
93 |
94 | bin\x64\Release\
95 | TRACE
96 | true
97 | pdbonly
98 | x64
99 | 7.3
100 | prompt
101 | false
102 |
103 |
104 |
105 | False
106 | .\OxyPlot.dll
107 |
108 |
109 | False
110 | .\OxyPlot.WindowsForms.dll
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Form
126 |
127 |
128 | Form1.cs
129 |
130 |
131 |
132 |
133 |
134 | Form
135 |
136 |
137 | MousePlot.cs
138 |
139 |
140 |
141 |
142 | Form
143 |
144 |
145 | Form1.cs
146 | Designer
147 |
148 |
149 | MousePlot.cs
150 |
151 |
152 | ResXFileCodeGenerator
153 | Resources.Designer.cs
154 | Designer
155 |
156 |
157 | True
158 | Resources.resx
159 | True
160 |
161 |
162 |
163 |
164 | SettingsSingleFileGenerator
165 | Settings.Designer.cs
166 |
167 |
168 | True
169 | Settings.settings
170 | True
171 |
172 |
173 |
174 |
175 | False
176 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29
177 | true
178 |
179 |
180 | False
181 | .NET Framework 3.5 SP1 Client Profile
182 | false
183 |
184 |
185 | False
186 | .NET Framework 3.5 SP1
187 | false
188 |
189 |
190 | False
191 | Windows Installer 3.1
192 | true
193 |
194 |
195 |
196 |
203 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/OxyPlot.WindowsForms.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microe1/MouseTester/3c747afa502b7543704d5cea4303ecc2741ec8c8/MouseTester/MouseTester/OxyPlot.WindowsForms.dll
--------------------------------------------------------------------------------
/MouseTester/MouseTester/OxyPlot.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microe1/MouseTester/3c747afa502b7543704d5cea4303ecc2741ec8c8/MouseTester/MouseTester/OxyPlot.dll
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace MouseTester
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | Application.Run(new Form1());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MouseTester")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MouseTester")]
13 | [assembly: AssemblyCopyright("Copyright © 2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("057b69bb-f19d-457e-a0a7-a0bc68b8c2c4")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.4.0.0")]
36 | [assembly: AssemblyFileVersion("1.4.0.0")]
37 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
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 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MouseTester.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
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 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MouseTester.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
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 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MouseTester.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 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/Properties/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
47 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/RawMouse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Diagnostics;
5 | using System.Text;
6 | using System.Runtime.InteropServices;
7 | using System.Windows.Forms;
8 |
9 | namespace MouseTester
10 | {
11 | public partial class Form1
12 | {
13 | private const int RIDEV_INPUTSINK = 0x00000100;
14 | private const int RID_INPUT = 0x10000003;
15 | private const int WM_INPUT = 0x00FF;
16 | private const int RIM_TYPEMOUSE = 0;
17 | private const int RI_MOUSE_LEFT_BUTTON_DOWN = 0x0001;
18 | private const ushort RI_MOUSE_LEFT_BUTTON_UP = 0x0002;
19 | private const int RI_MOUSE_RIGHT_BUTTON_DOWN = 0x0004;
20 | private const ushort RI_MOUSE_RIGHT_BUTTON_UP = 0x0008;
21 |
22 | [StructLayout(LayoutKind.Sequential)]
23 | internal struct RAWINPUTDEVICE
24 | {
25 | [MarshalAs(UnmanagedType.U2)]
26 | public ushort usUsagePage;
27 | [MarshalAs(UnmanagedType.U2)]
28 | public ushort usUsage;
29 | [MarshalAs(UnmanagedType.U4)]
30 | public int dwFlags;
31 | public IntPtr hwndTarget;
32 | }
33 |
34 | [StructLayout(LayoutKind.Sequential)]
35 | internal struct RAWINPUTHEADER
36 | {
37 | [MarshalAs(UnmanagedType.U4)]
38 | public int dwType;
39 | [MarshalAs(UnmanagedType.U4)]
40 | public int dwSize;
41 | public IntPtr hDevice;
42 | [MarshalAs(UnmanagedType.U4)]
43 | public int wParam;
44 | }
45 |
46 | [StructLayout(LayoutKind.Sequential)]
47 | internal struct RAWHID
48 | {
49 | [MarshalAs(UnmanagedType.U4)]
50 | public int dwSizHid;
51 | [MarshalAs(UnmanagedType.U4)]
52 | public int dwCount;
53 | }
54 |
55 | [StructLayout(LayoutKind.Sequential)]
56 | internal struct BUTTONSSTR
57 | {
58 | [MarshalAs(UnmanagedType.U2)]
59 | public ushort usButtonFlags;
60 | [MarshalAs(UnmanagedType.U2)]
61 | public ushort usButtonData;
62 | }
63 |
64 | [StructLayout(LayoutKind.Explicit)]
65 | internal struct RAWMOUSE
66 | {
67 | [MarshalAs(UnmanagedType.U2)]
68 | [FieldOffset(0)]
69 | public ushort usFlags;
70 | [MarshalAs(UnmanagedType.U4)]
71 | [FieldOffset(4)]
72 | public uint ulButtons;
73 | [FieldOffset(4)]
74 | public BUTTONSSTR buttonsStr;
75 | [MarshalAs(UnmanagedType.U4)]
76 | [FieldOffset(8)]
77 | public uint ulRawButtons;
78 | [FieldOffset(12)]
79 | public int lLastX;
80 | [FieldOffset(16)]
81 | public int lLastY;
82 | [MarshalAs(UnmanagedType.U4)]
83 | [FieldOffset(20)]
84 | public uint ulExtraInformation;
85 | }
86 |
87 | [StructLayout(LayoutKind.Sequential)]
88 | internal struct RAWKEYBOARD
89 | {
90 | [MarshalAs(UnmanagedType.U2)]
91 | public ushort MakeCode;
92 | [MarshalAs(UnmanagedType.U2)]
93 | public ushort Flags;
94 | [MarshalAs(UnmanagedType.U2)]
95 | public ushort Reserved;
96 | [MarshalAs(UnmanagedType.U2)]
97 | public ushort VKey;
98 | [MarshalAs(UnmanagedType.U4)]
99 | public uint Message;
100 | [MarshalAs(UnmanagedType.U4)]
101 | public uint ExtraInformation;
102 | }
103 |
104 | [StructLayout(LayoutKind.Sequential)]
105 | internal struct RAWINPUT
106 | {
107 | public RAWINPUTHEADER header;
108 | public Union data;
109 | [StructLayout(LayoutKind.Explicit)]
110 | public struct Union
111 | {
112 | [FieldOffset(0)]
113 | public RAWMOUSE mouse;
114 | [FieldOffset(0)]
115 | public RAWKEYBOARD keyboard;
116 | [FieldOffset(0)]
117 | public RAWHID hid;
118 | }
119 | }
120 |
121 | [DllImport("user32.dll")]
122 | extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices,
123 | uint uiNumDevices,
124 | uint cbSize);
125 |
126 | [DllImport("User32.dll")]
127 | extern static int GetRawInputData(IntPtr hRawInput,
128 | uint uiCommand,
129 | out RAWINPUT pData, //IntPtr pData,
130 | ref uint pcbSize,
131 | uint cbSizeHeader);
132 |
133 | public void RegisterRawInputMouse(IntPtr hwnd)
134 | {
135 | RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];
136 | rid[0].usUsagePage = 1;
137 | rid[0].usUsage = 2;
138 | rid[0].dwFlags = RIDEV_INPUTSINK;
139 | rid[0].hwndTarget = hwnd;
140 |
141 | if (!RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
142 | {
143 | Debug.WriteLine("RegisterRawInputDevices() Failed");
144 | }
145 | }
146 |
147 | [DllImport("Kernel32.dll")]
148 | private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
149 |
150 | [DllImport("Kernel32.dll")]
151 | private static extern bool QueryPerformanceFrequency(out long lpFrequency);
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/MouseTester/MouseTester/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MouseTester
2 | ===========
3 |
--------------------------------------------------------------------------------