├── JxqyWpf.sln
├── JxqyWpf
├── App.config
├── App.xaml
├── App.xaml.cs
├── ConfigFile.cs
├── Docusments
│ ├── JX3Assist功能设计计划表.xlsx
│ ├── Jx3Assist软件设计说明书.docx
│ └── Jx3Assist需求分析说明书.docx
├── Interception
│ ├── Input.cs
│ ├── InterceptionDriver.cs
│ ├── Interceptor.csproj
│ ├── KeyPressedEventArgs.cs
│ ├── Keys.cs
│ ├── MousePressedEventArgs.cs
│ └── ScrollDirection.cs
├── Jx3AssistConfig.cfg
├── JxqyWpf.csproj
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MyApp.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Resources
│ └── AppIcon.ico
├── Update.cs
├── UpdateWindow.xaml
├── UpdateWindow.xaml.cs
└── misc
│ ├── AppConfig.ini
│ ├── ReadMe.docx
│ ├── Release.zip
│ ├── ServerUpdate.ini
│ ├── Sword Online 3 Assist WPF.exe
│ ├── Update.ini
│ ├── install-interception.exe
│ └── interception.dll
├── README.md
└── _config.yml
/JxqyWpf.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26206.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JxqyWpf", "JxqyWpf\JxqyWpf.csproj", "{3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Release|Any CPU = Release|Any CPU
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Debug|x64.ActiveCfg = Debug|x64
19 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Debug|x64.Build.0 = Debug|x64
20 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Release|x64.ActiveCfg = Release|x64
23 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/JxqyWpf/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/JxqyWpf/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/JxqyWpf/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace JxqyWpf
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/JxqyWpf/ConfigFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Runtime.InteropServices;
7 | using System.IO;
8 |
9 | namespace JxqyWpf
10 | {
11 | public class ConfigFile
12 | {
13 | [DllImport("kernel32")]
14 | private static extern long GetPrivateProfileString(string section, string key, string defValue, StringBuilder retValue, int size, string filePath);
15 |
16 |
17 | [DllImport("kernel32")]
18 | private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
19 |
20 |
21 |
22 | public ConfigFile(string inFileName)
23 | {
24 | this.fileName = inFileName;
25 | }
26 |
27 | public void WriteValue(string section, string key, string value)
28 | {
29 | if(File.Exists(fileName))
30 | {
31 | WritePrivateProfileString(section, key, value, fileName);
32 | }
33 | else
34 | {
35 | ///Do something.
36 | }
37 | }
38 |
39 | public string ReadValue(string section, string key)
40 | {
41 | if(File.Exists(fileName))
42 | {
43 | StringBuilder ret = new StringBuilder(255);
44 | long i = GetPrivateProfileString(section, key, string.Empty, ret, 255, fileName);
45 | return ret.ToString();
46 | }
47 | else
48 | {
49 | ///Wrong.
50 | return string.Empty;
51 | }
52 | }
53 |
54 | public bool SetFileName(string inFIleName)
55 | {
56 | this.fileName = inFIleName;
57 | return true;
58 | }
59 |
60 | public string GetFileName()
61 | {
62 | return fileName;
63 | }
64 |
65 | protected string fileName;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/JxqyWpf/Docusments/JX3Assist功能设计计划表.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/Docusments/JX3Assist功能设计计划表.xlsx
--------------------------------------------------------------------------------
/JxqyWpf/Docusments/Jx3Assist软件设计说明书.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/Docusments/Jx3Assist软件设计说明书.docx
--------------------------------------------------------------------------------
/JxqyWpf/Docusments/Jx3Assist需求分析说明书.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/Docusments/Jx3Assist需求分析说明书.docx
--------------------------------------------------------------------------------
/JxqyWpf/Interception/Input.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Runtime.InteropServices;
8 | using System.Windows;
9 | using System.Windows.Input;
10 |
11 | namespace Interceptor
12 | {
13 | public class Input
14 | {
15 |
16 | [DllImport("user32.dll")]
17 | static extern bool SetCursorPos(int x, int y);
18 |
19 | private IntPtr context;
20 | private Thread callbackThread;
21 |
22 | ///
23 | /// Determines whether the driver traps no keyboard events, all events, or a range of events in-between (down only, up only...etc). Set this before loading otherwise the driver will not filter any events and no keypresses can be sent.
24 | ///
25 | public KeyboardFilterMode KeyboardFilterMode { get; set; }
26 |
27 | ///
28 | /// Determines whether the driver traps no events, all events, or a range of events in-between. Set this before loading otherwise the driver will not filter any events and no mouse clicks can be sent.
29 | ///
30 | public MouseFilterMode MouseFilterMode { get; set; }
31 |
32 | public bool IsLoaded { get; set; }
33 |
34 | ///
35 | /// Gets or sets the delay in milliseconds after each key stroke down and up. Pressing a key requires both a key stroke down and up. A delay of 0 (inadvisable) may result in no keys being apparently pressed. A delay of 20 - 40 milliseconds makes the key presses visible.
36 | ///
37 | public int KeyPressDelay { get; set; }
38 |
39 | ///
40 | /// Gets or sets the delay in milliseconds after each mouse event down and up. 'Clicking' the cursor (whether left or right) requires both a mouse event down and up. A delay of 0 (inadvisable) may result in no apparent click. A delay of 20 - 40 milliseconds makes the clicks apparent.
41 | ///
42 | public int ClickDelay { get; set; }
43 |
44 | public int ScrollDelay { get; set; }
45 |
46 | public event EventHandler OnKeyPressed;
47 | public event EventHandler OnMousePressed;
48 |
49 | private int deviceId; /* Very important; which device the driver sends events to */
50 |
51 | public Input()
52 | {
53 | context = IntPtr.Zero;
54 |
55 | KeyboardFilterMode = KeyboardFilterMode.None;
56 | MouseFilterMode = MouseFilterMode.None;
57 |
58 | KeyPressDelay = 1;
59 | ClickDelay = 1;
60 | ScrollDelay = 15;
61 | }
62 |
63 | /*
64 | * Attempts to load the driver. You may get an error if the C++ library 'interception.dll' is not in the same folder as the executable and other DLLs. MouseFilterMode and KeyboardFilterMode must be set before Load() is called. Calling Load() twice has no effect if already loaded.
65 | */
66 | public bool Load()
67 | {
68 | if (IsLoaded) return false;
69 |
70 | context = InterceptionDriver.CreateContext();
71 |
72 | if (context != IntPtr.Zero)
73 | {
74 | callbackThread = new Thread(new ThreadStart(DriverCallback));
75 | callbackThread.Priority = ThreadPriority.Highest;
76 | callbackThread.IsBackground = true;
77 | callbackThread.Start();
78 |
79 | IsLoaded = true;
80 |
81 | return true;
82 | }
83 | else
84 | {
85 | IsLoaded = false;
86 |
87 | return false;
88 | }
89 | }
90 |
91 | /*
92 | * Safely unloads the driver. Calling Unload() twice has no effect.
93 | */
94 | public void Unload()
95 | {
96 | if (!IsLoaded) return;
97 |
98 | if (context != IntPtr.Zero)
99 | {
100 | callbackThread.Abort();
101 | InterceptionDriver.DestroyContext(context);
102 | IsLoaded = false;
103 | }
104 | }
105 |
106 | private void DriverCallback()
107 | {
108 | InterceptionDriver.SetFilter(context, InterceptionDriver.IsKeyboard, (Int32) KeyboardFilterMode);
109 | InterceptionDriver.SetFilter(context, InterceptionDriver.IsMouse, (Int32) MouseFilterMode);
110 |
111 | Stroke stroke = new Stroke();
112 |
113 | while (InterceptionDriver.Receive(context, deviceId = InterceptionDriver.Wait(context), ref stroke, 1) > 0)
114 | {
115 | if (InterceptionDriver.IsMouse(deviceId) > 0)
116 | {
117 | if (OnMousePressed != null)
118 | {
119 | var args = new MousePressedEventArgs() { X = stroke.Mouse.X, Y = stroke.Mouse.Y, State = stroke.Mouse.State, Rolling = stroke.Mouse.Rolling };
120 | OnMousePressed(this, args);
121 |
122 | if (args.Handled)
123 | {
124 | continue;
125 | }
126 | stroke.Mouse.X = args.X;
127 | stroke.Mouse.Y = args.Y;
128 | stroke.Mouse.State = args.State;
129 | stroke.Mouse.Rolling = args.Rolling;
130 | }
131 | }
132 |
133 | if (InterceptionDriver.IsKeyboard(deviceId) > 0)
134 | {
135 | if (OnKeyPressed != null)
136 | {
137 | var args = new KeyPressedEventArgs() { Key = stroke.Key.Code, State = stroke.Key.State};
138 | OnKeyPressed(this, args);
139 |
140 | if (args.Handled)
141 | {
142 | continue;
143 | }
144 | stroke.Key.Code = args.Key;
145 | stroke.Key.State = args.State;
146 | }
147 | }
148 |
149 | InterceptionDriver.Send(context, deviceId, ref stroke, 1);
150 | }
151 |
152 | Unload();
153 | throw new Exception("Interception.Receive() failed for an unknown reason. The driver has been unloaded.");
154 | }
155 |
156 | public void SendKey(Keys key, KeyState state)
157 | {
158 | Stroke stroke = new Stroke();
159 | KeyStroke keyStroke = new KeyStroke();
160 |
161 | keyStroke.Code = key;
162 | keyStroke.State = state;
163 |
164 | stroke.Key = keyStroke;
165 |
166 | InterceptionDriver.Send(context, deviceId, ref stroke, 1);
167 |
168 | if (KeyPressDelay > 0)
169 | Thread.Sleep(KeyPressDelay);
170 | }
171 |
172 | ///
173 | /// Warning: Do not use this overload of SendKey() for non-letter, non-number, or non-ENTER keys. It may require a special KeyState of not KeyState.Down or KeyState.Up, but instead KeyState.E0 and KeyState.E1.
174 | ///
175 | public void SendKey(Keys key)
176 | {
177 | SendKey(key, KeyState.Down);
178 |
179 | if (KeyPressDelay > 0)
180 | Thread.Sleep(KeyPressDelay);
181 |
182 | SendKey(key, KeyState.Up);
183 | }
184 |
185 | public void SendKeys(params Keys[] keys)
186 | {
187 | foreach (Keys key in keys)
188 | {
189 | SendKey(key);
190 | }
191 | }
192 |
193 | ///
194 | /// Warning: Only use this overload for sending letters, numbers, and symbols (those to the right of the letters on a U.S. keyboard and those obtained by pressing shift-#). Do not send special keys like Tab or Control or Enter.
195 | ///
196 | ///
197 | public void SendText(string text)
198 | {
199 | foreach (char letter in text)
200 | {
201 | var tuple = CharacterToKeysEnum(letter);
202 |
203 | if (tuple.Item2 == true) // We need to press shift to get the next character
204 | SendKey(Keys.LeftShift, KeyState.Down);
205 |
206 | SendKey(tuple.Item1);
207 |
208 | if (tuple.Item2 == true)
209 | SendKey(Keys.LeftShift, KeyState.Up);
210 | }
211 | }
212 |
213 | ///
214 | /// Converts a character to a Keys enum and a 'do we need to press shift'.
215 | ///
216 | private Tuple CharacterToKeysEnum(char c)
217 | {
218 | switch (Char.ToLower(c))
219 | {
220 | case 'a':
221 | return new Tuple(Keys.A, false);
222 | case 'b':
223 | return new Tuple(Keys.B, false);
224 | case 'c':
225 | return new Tuple(Keys.C, false);
226 | case 'd':
227 | return new Tuple(Keys.D, false);
228 | case 'e':
229 | return new Tuple(Keys.E, false);
230 | case 'f':
231 | return new Tuple(Keys.F, false);
232 | case 'g':
233 | return new Tuple(Keys.G, false);
234 | case 'h':
235 | return new Tuple(Keys.H, false);
236 | case 'i':
237 | return new Tuple(Keys.I, false);
238 | case 'j':
239 | return new Tuple(Keys.J, false);
240 | case 'k':
241 | return new Tuple(Keys.K, false);
242 | case 'l':
243 | return new Tuple(Keys.L, false);
244 | case 'm':
245 | return new Tuple(Keys.M, false);
246 | case 'n':
247 | return new Tuple(Keys.N, false);
248 | case 'o':
249 | return new Tuple(Keys.O, false);
250 | case 'p':
251 | return new Tuple(Keys.P, false);
252 | case 'q':
253 | return new Tuple(Keys.Q, false);
254 | case 'r':
255 | return new Tuple(Keys.R, false);
256 | case 's':
257 | return new Tuple(Keys.S, false);
258 | case 't':
259 | return new Tuple(Keys.T, false);
260 | case 'u':
261 | return new Tuple(Keys.U, false);
262 | case 'v':
263 | return new Tuple(Keys.V, false);
264 | case 'w':
265 | return new Tuple(Keys.W, false);
266 | case 'x':
267 | return new Tuple(Keys.X, false);
268 | case 'y':
269 | return new Tuple(Keys.Y, false);
270 | case 'z':
271 | return new Tuple(Keys.Z, false);
272 | case '1':
273 | return new Tuple(Keys.One, false);
274 | case '2':
275 | return new Tuple(Keys.Two, false);
276 | case '3':
277 | return new Tuple(Keys.Three, false);
278 | case '4':
279 | return new Tuple(Keys.Four, false);
280 | case '5':
281 | return new Tuple(Keys.Five, false);
282 | case '6':
283 | return new Tuple(Keys.Six, false);
284 | case '7':
285 | return new Tuple(Keys.Seven, false);
286 | case '8':
287 | return new Tuple(Keys.Eight, false);
288 | case '9':
289 | return new Tuple(Keys.Nine, false);
290 | case '0':
291 | return new Tuple(Keys.Zero, false);
292 | case '-':
293 | return new Tuple(Keys.DashUnderscore, false);
294 | case '+':
295 | return new Tuple(Keys.PlusEquals, false);
296 | case '[':
297 | return new Tuple(Keys.OpenBracketBrace, false);
298 | case ']':
299 | return new Tuple(Keys.CloseBracketBrace, false);
300 | case ';':
301 | return new Tuple(Keys.SemicolonColon, false);
302 | case '\'':
303 | return new Tuple(Keys.SingleDoubleQuote, false);
304 | case ',':
305 | return new Tuple(Keys.CommaLeftArrow, false);
306 | case '.':
307 | return new Tuple(Keys.PeriodRightArrow, false);
308 | case '/':
309 | return new Tuple(Keys.ForwardSlashQuestionMark, false);
310 | case '{':
311 | return new Tuple(Keys.OpenBracketBrace, true);
312 | case '}':
313 | return new Tuple(Keys.CloseBracketBrace, true);
314 | case ':':
315 | return new Tuple(Keys.SemicolonColon, true);
316 | case '\"':
317 | return new Tuple(Keys.SingleDoubleQuote, true);
318 | case '<':
319 | return new Tuple(Keys.CommaLeftArrow, true);
320 | case '>':
321 | return new Tuple(Keys.PeriodRightArrow, true);
322 | case '?':
323 | return new Tuple(Keys.ForwardSlashQuestionMark, true);
324 | case '\\':
325 | return new Tuple(Keys.BackslashPipe, false);
326 | case '|':
327 | return new Tuple(Keys.BackslashPipe, true);
328 | case '`':
329 | return new Tuple(Keys.Tilde, false);
330 | case '~':
331 | return new Tuple(Keys.Tilde, true);
332 | case '!':
333 | return new Tuple(Keys.One, true);
334 | case '@':
335 | return new Tuple(Keys.Two, true);
336 | case '#':
337 | return new Tuple(Keys.Three, true);
338 | case '$':
339 | return new Tuple(Keys.Four, true);
340 | case '%':
341 | return new Tuple(Keys.Five, true);
342 | case '^':
343 | return new Tuple(Keys.Six, true);
344 | case '&':
345 | return new Tuple(Keys.Seven, true);
346 | case '*':
347 | return new Tuple(Keys.Eight, true);
348 | case '(':
349 | return new Tuple(Keys.Nine, true);
350 | case ')':
351 | return new Tuple(Keys.Zero, true);
352 | case ' ':
353 | return new Tuple(Keys.Space, true);
354 | default:
355 | return new Tuple(Keys.ForwardSlashQuestionMark, true);
356 | }
357 | }
358 |
359 | public void SendMouseEvent(MouseState state)
360 | {
361 | Stroke stroke = new Stroke();
362 | MouseStroke mouseStroke = new MouseStroke();
363 |
364 | mouseStroke.State = state;
365 |
366 | if (state == MouseState.ScrollUp)
367 | {
368 | mouseStroke.Rolling = 120;
369 | }
370 | else if (state == MouseState.ScrollDown)
371 | {
372 | mouseStroke.Rolling = -120;
373 | }
374 |
375 | stroke.Mouse = mouseStroke;
376 |
377 | InterceptionDriver.Send(context, 12, ref stroke, 1);
378 | }
379 |
380 | public void SendLeftClick()
381 | {
382 | SendMouseEvent(MouseState.LeftDown);
383 | Thread.Sleep(ClickDelay);
384 | SendMouseEvent(MouseState.LeftUp);
385 | }
386 |
387 | public void SendRightClick()
388 | {
389 | SendMouseEvent(MouseState.RightDown);
390 | Thread.Sleep(ClickDelay);
391 | SendMouseEvent(MouseState.RightUp);
392 | }
393 |
394 | public void ScrollMouse(ScrollDirection direction)
395 | {
396 | switch (direction)
397 | {
398 | case ScrollDirection.Down:
399 | SendMouseEvent(MouseState.ScrollDown);
400 | break;
401 | case ScrollDirection.Up:
402 | SendMouseEvent(MouseState.ScrollUp);
403 | break;
404 | }
405 | }
406 |
407 | ///
408 | /// Warning: This function, if using the driver, does not function reliably and often moves the mouse in unpredictable vectors. An alternate version uses the standard Win32 API to get the current cursor's position, calculates the desired destination's offset, and uses the Win32 API to set the cursor to the new position.
409 | ///
410 | public void MoveMouseBy(int deltaX, int deltaY, bool useDriver = false)
411 | {
412 | if (useDriver)
413 | {
414 | Stroke stroke = new Stroke();
415 | MouseStroke mouseStroke = new MouseStroke();
416 |
417 | mouseStroke.X = deltaX;
418 | mouseStroke.Y = deltaY;
419 |
420 | stroke.Mouse = mouseStroke;
421 | stroke.Mouse.Flags = MouseFlags.MoveRelative;
422 |
423 | InterceptionDriver.Send(context, 12, ref stroke, 1);
424 | }
425 | else
426 | {
427 | var currentPos = Mouse.GetPosition(null);
428 | //var currentPos = Cursor.Position;
429 |
430 | SetCursorPos((int)currentPos.X + deltaX, (int)currentPos.Y - deltaY);
431 | //Cursor.Position = new Point(currentPos.X + deltaX, currentPos.Y - deltaY); // Coordinate system for y: 0 begins at top, and bottom of screen has the largest number
432 | }
433 | }
434 |
435 | ///
436 | /// Warning: This function, if using the driver, does not function reliably and often moves the mouse in unpredictable vectors. An alternate version uses the standard Win32 API to set the cursor's position and does not use the driver.
437 | ///
438 | public void MoveMouseTo(int x, int y, bool useDriver = false)
439 | {
440 | if (useDriver)
441 | {
442 | Stroke stroke = new Stroke();
443 | MouseStroke mouseStroke = new MouseStroke();
444 |
445 | mouseStroke.X = x;
446 | mouseStroke.Y = y;
447 |
448 | stroke.Mouse = mouseStroke;
449 | stroke.Mouse.Flags = MouseFlags.MoveAbsolute;
450 |
451 | InterceptionDriver.Send(context, 12, ref stroke, 1);
452 | }
453 | {
454 | SetCursorPos(x, y);
455 | //Cursor.Position = new Point(x, y);
456 | }
457 | }
458 | }
459 | }
460 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/InterceptionDriver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 |
7 | namespace Interceptor
8 | {
9 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
10 | public delegate int Predicate(int device);
11 |
12 | [Flags]
13 | public enum KeyState : ushort
14 | {
15 | Down = 0x00,
16 | Up = 0x01,
17 | E0 = 0x02,
18 | E1 = 0x04,
19 | TermsrvSetLED = 0x08,
20 | TermsrvShadow = 0x10,
21 | TermsrvVKPacket = 0x20
22 | }
23 |
24 | [Flags]
25 | public enum KeyboardFilterMode : ushort
26 | {
27 | None = 0x0000,
28 | All = 0xFFFF,
29 | KeyDown = KeyState.Up,
30 | KeyUp = KeyState.Up << 1,
31 | KeyE0 = KeyState.E0 << 1,
32 | KeyE1 = KeyState.E1 << 1,
33 | KeyTermsrvSetLED = KeyState.TermsrvSetLED << 1,
34 | KeyTermsrvShadow = KeyState.TermsrvShadow << 1,
35 | KeyTermsrvVKPacket = KeyState.TermsrvVKPacket << 1
36 | }
37 |
38 | [Flags]
39 | public enum MouseState : ushort
40 | {
41 | LeftDown = 0x01,
42 | LeftUp = 0x02,
43 | RightDown = 0x04,
44 | RightUp = 0x08,
45 | MiddleDown = 0x10,
46 | MiddleUp = 0x20,
47 | LeftExtraDown = 0x40,
48 | LeftExtraUp = 0x80,
49 | RightExtraDown = 0x100,
50 | RightExtraUp = 0x200,
51 | ScrollVertical = 0x400,
52 | ScrollUp = 0x400,
53 | ScrollDown = 0x400,
54 | ScrollHorizontal = 0x800,
55 | ScrollLeft = 0x800,
56 | ScrollRight = 0x800,
57 | }
58 |
59 | [Flags]
60 | public enum MouseFilterMode : ushort
61 | {
62 | None = 0x0000,
63 | All = 0xFFFF,
64 | LeftDown = 0x01,
65 | LeftUp = 0x02,
66 | RightDown = 0x04,
67 | RightUp = 0x08,
68 | MiddleDown = 0x10,
69 | MiddleUp = 0x20,
70 | LeftExtraDown = 0x40,
71 | LeftExtraUp = 0x80,
72 | RightExtraDown = 0x100,
73 | RightExtraUp = 0x200,
74 | MouseWheelVertical = 0x400,
75 | MouseWheelHorizontal = 0x800,
76 | MouseMove = 0x1000,
77 | }
78 |
79 | [Flags]
80 | public enum MouseFlags : ushort
81 | {
82 | MoveRelative = 0x000,
83 | MoveAbsolute = 0x001,
84 | VirtualDesktop = 0x002,
85 | AttributesChanged = 0x004,
86 | MoveWithoutCoalescing = 0x008,
87 | TerminalServicesSourceShadow = 0x100
88 | }
89 |
90 | [StructLayout(LayoutKind.Sequential)]
91 | public struct MouseStroke
92 | {
93 | public MouseState State;
94 | public MouseFlags Flags;
95 | public Int16 Rolling;
96 | public Int32 X;
97 | public Int32 Y;
98 | public UInt16 Information;
99 | }
100 |
101 | [StructLayout(LayoutKind.Sequential)]
102 | public struct KeyStroke
103 | {
104 | public Keys Code;
105 | public KeyState State;
106 | public UInt32 Information;
107 | }
108 |
109 | [StructLayout(LayoutKind.Explicit)]
110 | public struct Stroke
111 | {
112 | [FieldOffset(0)] public MouseStroke Mouse;
113 |
114 | [FieldOffset(0)] public KeyStroke Key;
115 | }
116 |
117 | ///
118 | /// The .NET wrapper class around the C++ library interception.dll.
119 | ///
120 | public static class InterceptionDriver
121 | {
122 | [DllImport("interception.dll", EntryPoint = "interception_create_context", CallingConvention = CallingConvention.Cdecl)]
123 | public static extern IntPtr CreateContext();
124 |
125 | [DllImport("interception.dll", EntryPoint = "interception_destroy_context", CallingConvention = CallingConvention.Cdecl)]
126 | public static extern void DestroyContext(IntPtr context);
127 |
128 | [DllImport("interception.dll", EntryPoint = "interception_get_precedence", CallingConvention = CallingConvention.Cdecl)]
129 | public static extern void GetPrecedence(IntPtr context, Int32 device);
130 |
131 | [DllImport("interception.dll", EntryPoint = "interception_set_precedence", CallingConvention = CallingConvention.Cdecl)]
132 | public static extern void SetPrecedence(IntPtr context, Int32 device, Int32 Precedence);
133 |
134 | [DllImport("interception.dll", EntryPoint = "interception_get_filter", CallingConvention = CallingConvention.Cdecl)]
135 | public static extern void GetFilter(IntPtr context, Int32 device);
136 |
137 | [DllImport("interception.dll", EntryPoint = "interception_set_filter", CallingConvention = CallingConvention.Cdecl)]
138 | public static extern void SetFilter(IntPtr context, Predicate predicate, Int32 keyboardFilterMode);
139 |
140 | [DllImport("interception.dll", EntryPoint = "interception_wait", CallingConvention = CallingConvention.Cdecl)]
141 | public static extern Int32 Wait(IntPtr context);
142 |
143 | [DllImport("interception.dll", EntryPoint = "interception_wait_with_timeout", CallingConvention = CallingConvention.Cdecl)]
144 | public static extern Int32 WaitWithTimeout(IntPtr context, UInt64 milliseconds);
145 |
146 | [DllImport("interception.dll", EntryPoint = "interception_send", CallingConvention = CallingConvention.Cdecl)]
147 | public static extern Int32 Send(IntPtr context, Int32 device, ref Stroke stroke, UInt32 numStrokes);
148 |
149 | [DllImport("interception.dll", EntryPoint = "interception_receive", CallingConvention = CallingConvention.Cdecl)]
150 | public static extern Int32 Receive(IntPtr context, Int32 device, ref Stroke stroke, UInt32 numStrokes);
151 |
152 | [DllImport("interception.dll", EntryPoint = "interception_get_hardware_id", CallingConvention = CallingConvention.Cdecl)]
153 | public static extern Int32 GetHardwareId(IntPtr context, Int32 device, String hardwareIdentifier, UInt32 sizeOfString);
154 |
155 | [DllImport("interception.dll", EntryPoint = "interception_is_invalid", CallingConvention = CallingConvention.Cdecl)]
156 | public static extern Int32 IsInvalid(Int32 device);
157 |
158 | [DllImport("interception.dll", EntryPoint = "interception_is_keyboard", CallingConvention = CallingConvention.Cdecl)]
159 | public static extern Int32 IsKeyboard(Int32 device);
160 |
161 | [DllImport("interception.dll", EntryPoint = "interception_is_mouse", CallingConvention = CallingConvention.Cdecl)]
162 | public static extern Int32 IsMouse(Int32 device);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/Interceptor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {C451A00E-77F1-4F3F-B7EE-27DC712EA316}
9 | Library
10 | Properties
11 | Interceptor
12 | Interceptor
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | x64
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 | true
36 | bin\x64\Debug\
37 | DEBUG;TRACE
38 | full
39 | x64
40 | prompt
41 | MinimumRecommendedRules.ruleset
42 |
43 |
44 | bin\x64\Release\
45 | TRACE
46 | true
47 | pdbonly
48 | x64
49 | prompt
50 | MinimumRecommendedRules.ruleset
51 |
52 |
53 | true
54 | bin\x86\Debug\
55 | DEBUG;TRACE
56 | full
57 | x86
58 | prompt
59 | MinimumRecommendedRules.ruleset
60 |
61 |
62 | bin\x86\Release\
63 | TRACE
64 | true
65 | pdbonly
66 | x86
67 | prompt
68 | MinimumRecommendedRules.ruleset
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
98 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/KeyPressedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Interceptor
7 | {
8 | public class KeyPressedEventArgs : EventArgs
9 | {
10 | public Keys Key { get; set; }
11 | public KeyState State { get; set; }
12 | public bool Handled { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/Keys.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Interceptor
7 | {
8 | ///
9 | /// A list of scancodes.
10 | ///
11 | /// Scancodes change according to keyboard layout...so this may be inaccurate.
12 | public enum Keys : ushort
13 | {
14 | Escape = 1,
15 | One = 2,
16 | Two = 3,
17 | Three = 4,
18 | Four = 5,
19 | Five = 6,
20 | Six = 7,
21 | Seven = 8,
22 | Eight = 9,
23 | Nine = 10,
24 | Zero = 11,
25 | DashUnderscore = 12,
26 | PlusEquals = 13,
27 | Backspace = 14,
28 | Tab = 15,
29 | Q = 16,
30 | W = 17,
31 | E = 18,
32 | R = 19,
33 | T = 20,
34 | Y = 21,
35 | U = 22,
36 | I = 23,
37 | O = 24,
38 | P = 25,
39 | OpenBracketBrace = 26,
40 | CloseBracketBrace = 27,
41 | Enter = 28,
42 | Control = 29,
43 | A = 30,
44 | S = 31,
45 | D = 32,
46 | F = 33,
47 | G = 34,
48 | H = 35,
49 | J = 36,
50 | K = 37,
51 | L = 38,
52 | SemicolonColon = 39,
53 | SingleDoubleQuote = 40,
54 | Tilde = 41,
55 | LeftShift = 42,
56 | BackslashPipe = 43,
57 | Z = 44,
58 | X = 45,
59 | C = 46,
60 | V = 47,
61 | B = 48,
62 | N = 49,
63 | M = 50,
64 | CommaLeftArrow = 51,
65 | PeriodRightArrow = 52,
66 | ForwardSlashQuestionMark = 53,
67 | RightShift = 54,
68 | RightAlt = 56,
69 | Space = 57,
70 | CapsLock = 58,
71 | F1 = 59,
72 | F2 = 60,
73 | F3 = 61,
74 | F4 = 62,
75 | F5 = 63,
76 | F6 = 64,
77 | F7 = 65,
78 | F8 = 66,
79 | F9 = 67,
80 | F10 = 68,
81 | F11 = 87,
82 | F12 = 88,
83 | Up = 72,
84 | Down = 80,
85 | Right = 77,
86 | Left = 75,
87 | Home = 71,
88 | End = 79,
89 | Delete = 83,
90 | PageUp = 73,
91 | PageDown = 81,
92 | Insert = 82,
93 | PrintScreen = 55, // And break key is 42
94 | NumLock = 69,
95 | ScrollLock = 70,
96 | Menu = 93,
97 | WindowsKey = 91,
98 | NumpadDivide = 53,
99 | NumpadAsterisk = 55,
100 | Numpad7 = 71,
101 | Numpad8 = 72,
102 | Numpad9 = 73,
103 | Numpad4 = 75,
104 | Numpad5 = 76,
105 | Numpad6 = 77,
106 | Numpad1 = 79,
107 | Numpad2 = 80,
108 | Numpad3 = 81,
109 | Numpad0 = 82,
110 | NumpadDelete = 83,
111 | NumpadEnter = 28,
112 | NumpadPlus = 78,
113 | NumpadMinus = 74,
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/MousePressedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Interceptor
7 | {
8 | public class MousePressedEventArgs : EventArgs
9 | {
10 | public MouseState State { get; set; }
11 | public bool Handled { get; set; }
12 | public int X { get; set; }
13 | public int Y { get; set; }
14 | public short Rolling { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/JxqyWpf/Interception/ScrollDirection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Interceptor
7 | {
8 | public enum ScrollDirection
9 | {
10 | Down,
11 | Up
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/JxqyWpf/Jx3AssistConfig.cfg:
--------------------------------------------------------------------------------
1 | HotKey = 41
2 | MacroKey = 44
--------------------------------------------------------------------------------
/JxqyWpf/JxqyWpf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3B662F2F-0DA0-4F57-A728-A07F33DE6ABA}
8 | WinExe
9 | JxqyWpf
10 | Sword Online 3 Assist WPF
11 | v4.5.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 | true
38 | bin\x64\Debug\
39 | DEBUG;TRACE
40 | full
41 | x64
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | true
45 |
46 |
47 | bin\x64\Release\
48 | TRACE
49 | true
50 | pdbonly
51 | x64
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | true
55 |
56 |
57 |
58 | Resources\AppIcon.ico
59 |
60 |
61 | true
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 4.0
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | MSBuild:Compile
86 | Designer
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | UpdateWindow.xaml
99 |
100 |
101 | MSBuild:Compile
102 | Designer
103 |
104 |
105 | App.xaml
106 | Code
107 |
108 |
109 | MainWindow.xaml
110 | Code
111 |
112 |
113 | Designer
114 | MSBuild:Compile
115 |
116 |
117 |
118 |
119 | Code
120 |
121 |
122 | True
123 | True
124 | Resources.resx
125 |
126 |
127 | True
128 | Settings.settings
129 | True
130 |
131 |
132 | ResXFileCodeGenerator
133 | Resources.Designer.cs
134 |
135 |
136 | SettingsSingleFileGenerator
137 | Settings.Designer.cs
138 |
139 |
140 |
141 |
142 | Designer
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/JxqyWpf/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/JxqyWpf/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using System.Runtime.InteropServices;
16 | using System.Windows.Interop;
17 | using System.Media;
18 | using System.Threading;
19 | using System.Windows.Forms;
20 | using System.Drawing;
21 | using System.ComponentModel;
22 |
23 | namespace JxqyWpf
24 | {
25 | ///
26 | /// Interaction logic for MainWindow.xaml
27 | ///
28 | public partial class MainWindow : Window
29 | {
30 | public MyApp app = new MyApp();
31 | public Update upd = new Update();
32 |
33 | NotifyIcon appNotifyIcon = new NotifyIcon();
34 |
35 | public MainWindow()
36 | {
37 | InitializeComponent();
38 | this.Title = app.windowTitle;
39 | appNotifyIcon.BalloonTipText = "JX3 Assist";
40 | appNotifyIcon.ShowBalloonTip(2000);
41 | appNotifyIcon.Text = "JX3 Assist";
42 | appNotifyIcon.Visible = true;
43 | appNotifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Windows.Forms.Application.ExecutablePath);
44 | appNotifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler((obj, e) =>
45 | {
46 | if (e.Button == MouseButtons.Left)
47 | {
48 | Show(obj, e);
49 | }
50 |
51 | });
52 |
53 | StateChanged += MainWindow_StateChanged;
54 |
55 | }
56 |
57 | private void MainWindow_StateChanged(object obj, EventArgs e)
58 | {
59 | if (this.WindowState == WindowState.Minimized)
60 | {
61 | Hide(obj, e);
62 | }
63 | }
64 |
65 | protected override void OnClosing(CancelEventArgs e)
66 | {
67 | base.OnClosing(e);
68 | if(appNotifyIcon != null)
69 | {
70 | appNotifyIcon.Dispose();
71 | }
72 | }
73 |
74 | private void Show(object obj, EventArgs e)
75 | {
76 | Visibility = Visibility.Visible;
77 | ShowInTaskbar = true;
78 | Activate();
79 | }
80 |
81 | private void Hide(object obj, EventArgs e)
82 | {
83 | ShowInTaskbar = false;
84 | Visibility = Visibility.Hidden;
85 | }
86 |
87 | private void btnStart_Click(object sender, RoutedEventArgs e)
88 | {
89 | app.Start();
90 | }
91 |
92 | private void btnStop_Click(object sender, RoutedEventArgs e)
93 | {
94 | app.Stop();
95 | }
96 |
97 | private void btnSetTick_Click(object sender, RoutedEventArgs e)
98 | {
99 | int time = 50;
100 | if(int.TryParse(txtInTime.Text, out time))
101 | {
102 | if(time < 20 || time > 9999)
103 | {
104 | System.Windows.MessageBox.Show("TickTime Should Between 20 and 9999");
105 | }
106 | else
107 | {
108 | app.SetTickTime(time);
109 | System.Windows.MessageBox.Show("Successful");
110 | }
111 | }
112 | else
113 | {
114 | System.Windows.MessageBox.Show("TickTime Should Between 20 and 9999");
115 | }
116 | txtInTime.Text = time.ToString();
117 | }
118 |
119 | protected override void OnClosed(EventArgs e)
120 | {
121 | System.Environment.Exit(0);
122 | base.OnClosed(e);
123 | }
124 |
125 | private void btnCheckUpdate_Click(object sender, RoutedEventArgs e)
126 | {
127 | upd.CheckUpdate();
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/JxqyWpf/MyApp.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Interceptor;
7 | using System.Windows;
8 | using System.Threading;
9 | using System.Runtime.InteropServices;
10 | using System.Media;
11 | using System.IO;
12 |
13 | namespace JxqyWpf
14 | {
15 | public class AppConfig
16 | {
17 | public AppConfig(string inFileName)
18 | {
19 | configFileName = inFileName;
20 | }
21 |
22 | public string ReadPowerKey()
23 | {
24 | ConfigFile cfg = new ConfigFile(configFileName);
25 | return cfg.ReadValue("Key", "PowerKey");
26 | }
27 |
28 | public void SetPowerKey(string key)
29 | {
30 | ConfigFile cfg = new ConfigFile(configFileName);
31 | cfg.WriteValue("Key", "PowerKey", key);
32 | }
33 |
34 | public string ReadMacroKey()
35 | {
36 | ConfigFile cfg = new ConfigFile(configFileName);
37 | return cfg.ReadValue("Key", "MacroKey");
38 | }
39 |
40 | public void SetMacroKey(string key)
41 | {
42 | ConfigFile cfg = new ConfigFile(configFileName);
43 | cfg.WriteValue("Key", "MacroKey", key);
44 | }
45 |
46 | public string ReadWindowTitle()
47 | {
48 | ConfigFile cfg = new ConfigFile(configFileName);
49 | return cfg.ReadValue("Key", "WindowTitle");
50 | }
51 |
52 | private string configFileName;
53 | }
54 |
55 | public class MyApp
56 | {
57 | private Input inputObj = new Input();
58 | private int tickTime = 50;
59 | private bool bShouldTick = false;
60 | private Object thisLock = new Object();
61 | private int powerKey = 41;
62 | private int macroKey = 66;
63 | private Thread fun;
64 | public string windowTitle = "Jx3Assist";
65 |
66 |
67 | [DllImport("Kernel32")]
68 | public static extern void AllocConsole();
69 | [DllImport("Kernel32")]
70 | public static extern void FreeConsole();
71 |
72 | public MyApp()
73 | {
74 | #if DEBUG
75 |
76 | AllocConsole();
77 | #endif
78 | inputObj.KeyboardFilterMode = KeyboardFilterMode.All;
79 | inputObj.Load();
80 | ConfigApp();
81 |
82 | fun = new Thread(new ThreadStart(WaitForCmd));
83 | fun.Start();
84 |
85 | Tick();
86 | }
87 |
88 | private void ConfigApp()
89 | {
90 | AppConfig config = new AppConfig(Directory.GetCurrentDirectory() + "/AppConfig.ini");
91 |
92 | ///读取开始、停止按钮
93 | string pStr = config.ReadPowerKey();
94 | int pKey = 0;
95 | if (int.TryParse(pStr, out pKey))
96 | {
97 | SetPowerKey(pKey);
98 | #if DEBUG
99 | Console.WriteLine("SetPowerKey" + pKey);
100 | #endif
101 |
102 | }
103 |
104 | ///读取宏按钮
105 | string mStr = config.ReadMacroKey();
106 | int mKey = 0;
107 | if (int.TryParse(mStr, out mKey))
108 | {
109 | SetMacroKey(mKey);
110 | #if DEBUG
111 | Console.WriteLine("SetMacroKey" + mKey);
112 | #endif
113 |
114 | }
115 |
116 | ///读取窗口标题
117 | windowTitle = config.ReadWindowTitle();
118 | }
119 |
120 | public async void Tick()
121 | {
122 | while(true)
123 | {
124 | if(bShouldTick)
125 | {
126 | inputObj.SendKey((Keys)macroKey, KeyState.Down);
127 | await Task.Delay(5);
128 | inputObj.SendKey((Keys)macroKey, KeyState.Up);
129 | await Task.Delay(tickTime - 5);
130 | }
131 | else
132 | {
133 | await Task.Delay(250);
134 | }
135 | }
136 | }
137 |
138 | public bool IsRunning()
139 | {
140 | return bShouldTick == true;
141 | }
142 |
143 | public int SetTickTime(int inTIme)
144 | {
145 | tickTime = inTIme;
146 | return tickTime;
147 | }
148 |
149 | public int SetPowerKey(int inKey)
150 | {
151 | powerKey = inKey;
152 | return inKey;
153 | }
154 |
155 | public int SetMacroKey(int inKey)
156 | {
157 | macroKey = inKey;
158 | return inKey;
159 | }
160 |
161 | public void Start()
162 | {
163 | lock(thisLock)
164 | {
165 | bShouldTick = true;
166 | }
167 | SystemSounds.Hand.Play();
168 | }
169 |
170 | public void Stop()
171 | {
172 | lock (thisLock)
173 | {
174 | bShouldTick = false;
175 | }
176 | SystemSounds.Asterisk.Play();
177 | }
178 |
179 | public void WaitForCmd()
180 | {
181 | IntPtr ctx = InterceptionDriver.CreateContext();
182 | int device = 0;
183 | Stroke strk = new Stroke();
184 | InterceptionDriver.SetFilter(ctx, InterceptionDriver.IsKeyboard, (int)KeyboardFilterMode.KeyDown | (int)KeyboardFilterMode.KeyUp);
185 |
186 | int i = 0;
187 | while (InterceptionDriver.Receive(ctx, device = InterceptionDriver.Wait(ctx), ref strk, 1) > 0)
188 | {
189 | #if DEBUG
190 | Console.WriteLine((int)strk.Key.Code);
191 | #endif
192 | if (strk.Key.Code == (Keys)powerKey)
193 | {
194 | ++i;
195 | if(i < 2)
196 | {
197 | continue;
198 | }
199 | lock (thisLock)
200 | {
201 | if(IsRunning())
202 | {
203 | Stop();
204 |
205 | #if DEBUG
206 | Console.WriteLine("Stop");
207 | #endif
208 | }
209 | else
210 | {
211 | Start();
212 |
213 | #if DEBUG
214 | Console.WriteLine("Start");
215 | #endif
216 | }
217 | }
218 | i = 0;
219 | }
220 | InterceptionDriver.Send(ctx, device, ref strk, 1);
221 | }
222 | }
223 |
224 | public void ReadConfig(string fileName)
225 | {
226 | FileStream file = new FileStream(fileName, FileMode.Open);
227 |
228 | file.Seek(0, SeekOrigin.Begin);
229 |
230 |
231 | }
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/JxqyWpf/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("Sword Online 3 Assist WPF")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("Shuangyuehuanye")]
14 | [assembly: AssemblyProduct("Sword Online 3 Assist WPF")]
15 | [assembly: AssemblyCopyright("Copyright © 2017")]
16 | [assembly: AssemblyTrademark("剑侠情缘")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/JxqyWpf/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 JxqyWpf.Properties
12 | {
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", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JxqyWpf.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/JxqyWpf/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 |
--------------------------------------------------------------------------------
/JxqyWpf/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 JxqyWpf.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/JxqyWpf/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/JxqyWpf/Resources/AppIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/Resources/AppIcon.ico
--------------------------------------------------------------------------------
/JxqyWpf/Update.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Net;
7 | using System.IO;
8 | using System.ComponentModel;
9 | using System.Windows;
10 | using System.Windows.Automation;
11 | using System.Diagnostics;
12 |
13 | namespace JxqyWpf
14 | {
15 | public class Update
16 | {
17 | protected string updateConfigName = "Update.ini";
18 | protected string workPath = System.Environment.CurrentDirectory;
19 | protected string localVersion;
20 | protected string serverVersion;
21 | protected string tmpFileName = "tmp";
22 | protected string serverConfigFileUrl;
23 | protected string patchFileName = "Patch.tmp";
24 | protected bool isChecking = false;
25 |
26 | protected UpdateWindow updWin = new UpdateWindow();
27 |
28 | public Update()
29 | {
30 | ConfigFile updateCfg = new ConfigFile(workPath + "/" + updateConfigName);
31 | serverConfigFileUrl = updateCfg.ReadValue("ServerInfo", "ConfigFileUrl");
32 |
33 | if (File.Exists("old_"))
34 | {
35 | File.Delete("old_");
36 | }
37 | }
38 |
39 | public void CheckUpdate()
40 | {
41 | if(isChecking == true)
42 | {
43 | return;
44 | }
45 |
46 | isChecking = true;
47 |
48 |
49 | ConfigFile updateCfg = new ConfigFile(workPath + "/" + updateConfigName);
50 | localVersion = updateCfg.ReadValue("AppInfo", "AppVersion");
51 | WebClient dlClient = new WebClient();
52 |
53 | dlClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnCheckUpdateEnd);
54 |
55 | try
56 | {
57 | dlClient.DownloadFileAsync(new Uri(serverConfigFileUrl), tmpFileName);
58 | }
59 | catch(Exception ex)
60 | {
61 | MessageBox.Show(ex.Message);
62 | }
63 |
64 | return;
65 | }
66 |
67 | public void OnCheckUpdateEnd(object sender, AsyncCompletedEventArgs e)
68 | {
69 | ConfigFile serverCfg = new ConfigFile(workPath + "/" + tmpFileName);
70 | serverVersion = serverCfg.ReadValue("AppInfo", "AppVersion");
71 | if (localVersion == serverVersion)
72 | {
73 | isChecking = false;
74 | if (File.Exists(tmpFileName))
75 | {
76 | File.Delete(tmpFileName);
77 | }
78 | MessageBox.Show("Your App is the latest version");
79 | return;
80 | }
81 |
82 | WebClient dlClient = new WebClient();
83 |
84 | string patchUrl = serverCfg.ReadValue("PatchName", "Url");
85 | dlClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadEnd);
86 | dlClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadChanged);
87 |
88 | if (File.Exists(patchFileName))
89 | {
90 | File.Delete(patchFileName);
91 | }
92 |
93 | try
94 | {
95 | dlClient.DownloadFileAsync(new Uri(patchUrl), patchFileName);
96 | }
97 | catch (Exception ex)
98 | {
99 | MessageBox.Show(ex.Message);
100 | }
101 |
102 | if (File.Exists(tmpFileName))
103 | {
104 | File.Delete(tmpFileName);
105 | }
106 |
107 | updWin.Show();
108 | }
109 |
110 | public void OnDownloadChanged(object sender, DownloadProgressChangedEventArgs e)
111 | {
112 | updWin.ChangePrograss(e.ProgressPercentage);
113 | }
114 |
115 | public void OnDownloadEnd(object sender, AsyncCompletedEventArgs e)
116 | {
117 | updWin.Close();
118 | UpdateSelf(patchFileName);
119 |
120 | }
121 |
122 | public void UpdateSelf(string newFileName)
123 | {
124 | string selfName = Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
125 |
126 | if (File.Exists("old_"))
127 | {
128 | File.Delete("old_");
129 | }
130 |
131 | File.Move(selfName, "old_");
132 | File.Copy(patchFileName, selfName);
133 |
134 | ConfigFile updateCfg = new ConfigFile(workPath + "/" + updateConfigName);
135 | updateCfg.WriteValue("AppInfo", "AppVersion", serverVersion);
136 | MessageBox.Show("Updating sucessful.App is restarting.");
137 |
138 | if (File.Exists(patchFileName))
139 | {
140 | File.Delete(patchFileName);
141 | }
142 |
143 | Process.Start(selfName);
144 | System.Environment.Exit(0);
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/JxqyWpf/UpdateWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/JxqyWpf/UpdateWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace JxqyWpf
16 | {
17 | ///
18 | /// UpdateWindow.xaml 的交互逻辑
19 | ///
20 | public partial class UpdateWindow : Window
21 | {
22 | public UpdateWindow()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | public void ChangePrograss(float value)
28 | {
29 | pbUpdate.Value = value;
30 | lbValue.Content = value.ToString() + "%";
31 | }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/JxqyWpf/misc/AppConfig.ini:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/AppConfig.ini
--------------------------------------------------------------------------------
/JxqyWpf/misc/ReadMe.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/ReadMe.docx
--------------------------------------------------------------------------------
/JxqyWpf/misc/Release.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/Release.zip
--------------------------------------------------------------------------------
/JxqyWpf/misc/ServerUpdate.ini:
--------------------------------------------------------------------------------
1 | #Config file on server
2 | [AppInfo]
3 | AppName=JX3Assist
4 | AppVersion = 1.1.5(Beta)
5 |
6 | [PatchName]
7 | Url = https://raw.githubusercontent.com/RPG3D/JX3Assist/master/JxqyWpf/misc/Sword Online 3 Assist WPF.exe
8 |
--------------------------------------------------------------------------------
/JxqyWpf/misc/Sword Online 3 Assist WPF.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/Sword Online 3 Assist WPF.exe
--------------------------------------------------------------------------------
/JxqyWpf/misc/Update.ini:
--------------------------------------------------------------------------------
1 |
2 | #Config file on
3 | [ServerInfo]
4 | ConfigFileUrl = https://raw.githubusercontent.com/RPG3D/JX3Assist/master/JxqyWpf/misc/ServerUpdate.ini
5 |
6 | [AppInfo]
7 | AppName=JX3Assist
8 | AppVersion =1.1.5
9 |
--------------------------------------------------------------------------------
/JxqyWpf/misc/install-interception.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/install-interception.exe
--------------------------------------------------------------------------------
/JxqyWpf/misc/interception.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RPG3D/JX3Assist/4310107c59d9d0c1f828f28ab6cbc70a2c21e335/JxqyWpf/misc/interception.dll
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LearnCSharp
2 | download the release app from here:
3 | https://raw.githubusercontent.com/RPG3D/JX3Assist/master/JxqyWpf/misc/Release.zip
4 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-architect
--------------------------------------------------------------------------------