Skip to content

Latest commit

 

History

History
129 lines (82 loc) · 6.44 KB

DEVELOP.md

File metadata and controls

129 lines (82 loc) · 6.44 KB

Key'n'Stroke

(previously PxKeystrokesForScreencasts)

This is a little documentation about how the source code is organized and works

How to make a new release

  1. Change Version:
  • Twice in AssemblyInfo.cs
  • In project settings under "Publish"
  1. Build the App in Release mode
  2. Sign the file using the certum certificate
    • cmd.exe: signtool.exe sign /n Open /t http://time.certum.pl/ /fd sha256 /v Key-n-Stroke.exe
  3. Verify the signature:
    • cmd.exe: signtool.exe verify /pa Key-n-Stroke.exe
  4. ./Key-n-Stroke.exe --create-update-manifest
  5. Change manifest: Update description
  6. ./Key-n-Stroke.exe --sign-update-manifest
  7. Copy executable into release folder
  8. Commit and push
  9. Upload manifest scp updateManifest.xml $SSHSERVER:html/key-n-stroke/

How to prepare the development environment

  • Install Visual Studio 2019
  • Download dependencies:
    • Clean the folder packages in the repository root
    • Search a msbuild.exe and run it like this:
    • e.g. "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" KeyNStroke.sln /t:Restore /p:RestorePackagesConfig=true /p:Configuration=Debug
  • Then run the application using Visual Studio

Main (Program.cs)

The main function is found in Program.cs.

It initializes the classes decribed below.

  • new KeyboardHook()
  • new KeystrokeParser()
  • new SettingsStore()
  • new KeystrokeDisplay()

The keypress information is intercepted in KeyboardHook, passed to KeystrokeParser and then passed to KeystrokeDisplay.

How key events are intercepted from the system

In Windows, you can register a callback (also known as hook) for certain process messages like keyboard and mouse events.

Callbacks are registered using the function SetWindowsHookEx(event type, callback function, ...). This function is not part of PxKS but part of the system library user32.dll. In PxKS we only need to define how each of those system functions looks. This is done in the files NativeMethodsKeyboard.cs, NativeMethodsMouse.cs, NativeMethodsGWL.cs and NativeMethodsSWP.cs.

Sometimes special data structures and constants are needed for these system functions (for example KBDLLHOOKSTRUCT).They are also defined in these files.

System calls (KeyboardHook.cs KeyboardRawEvents.cs)

Now back to the key events. The class that encapsulates the calls to the system functions is KeyboardHook in KeyboardHook.cs. It registers the keyboard event system callback on creation and unregisters it on disposing/deconstructing. The related functions are RegisterKeyboardHook() and UnregisterKeyboardHook().

KeyboardHook exposes the C# event KeyEvent that takes methods of delegate type KeyboardRawEventHandler. (via interface IKeyboardRawEventProvider in KeyboardRawEvent.cs).

The idea is, that you just do this nice pure C# thing

	{
		// process hook
	}
	IKeyboardRawEventProvider myKeyboardHook = new KeyboardHook();
	hook.KeyEvent += hook_KeyEvent;

... instead of dealing with the raw system library calls.

The KeyboardHook class does a little bit more. It executes multiple system calls to find out which modifier keys (shift, ...) are currently pressed and appends this information to raw_e.

Key event processing (KeystrokeParser.cs KeystrokeEvent.cs)

Next, the KeyboardRawEventArgs raw_e are converted into Keystrokes. This is happening in a similar interface/event pattern.

The idea is, that the KeystrokeParser gets the RawEvents as input, determines what should be displayed to the user (for example a simple letter or a more complex information like CTRL + A), and forwards the result to the next program part using a C# event.

Input: The KeystrokeParser registers itself on the KeyEvent of the KeyboardHook in the constructor.

Output: The KeystrokeParser exposes the C# event KeystrokeEvent that takes methods of delegate type KeystrokeEventHandler. (via interface IKeystrokeEventProvider in KeystrokeEvent.cs).

During Calculation, the KeystrokeParser uses the static methods in KeyboardLayoutParser and SpecialkeysParser (can be found in the two .cs files) to do some of the conversion.

The KeyboardLayoutParser wraps some other system library functions that convert raw key information to corresponding letters with respect to the chosen keyboard layout by the user (for example us QWERTY vs german QWERTZ).

The SpecialkeysParser is simply a big switch statement that converts special function keys on keyboards like 'volume up' and normal keys like 'ESC' and 'tab' to text or unicode symbols like 🔊, which are then displayed in the UI.

The output of the KeystrokeParser is used by the KeystrokesDisplay.

Displaying Keystrokes (KeystrokesDisplay.cs code (F7))

  • displays new keys as wished by the information in KeystrokeEventArgs (k_KeystrokeEvent())
  • Checks if resizing mode is activated (CheckForSettingsMode())
  • allows resizing and moving of window
  • keeps track of the History of keystrokes (List<TweenLabel> tweenLabels)

TweenLabel (TweenLabel.cs code (F7))

The TweenLabel is a C# System.Windows.Forms.Control that displays a line of keystrokes in the UI and is capable of fading in and out and nicely moving around in the window.

Settings

Are stored in the C# Application.UserAppDataRegistry using the wrapper functions in SettingsStore.cs.

The Settings are changed in the UI window Settings.cs

NativeMethodsSWP.cs

A wrapper for calling the system library function SetWindowPos. The class NativeMethodsSWP provides a method to pin the UI on top of everything.

NativeMethodsGWL.cs

Some wrappers for calling system library functions. They provide methods to make the UI through clickable and clickable again.

UrlOpener.cs

Open a browser.