Skip to content

Commit 585022e

Browse files
committed
v1.1
1 parent a97bba0 commit 585022e

File tree

3 files changed

+58
-25
lines changed

3 files changed

+58
-25
lines changed

KeyCodeInfo/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Runtime.CompilerServices;
33

44
[assembly: AssemblyCopyright("© 2024 - NS Tech Bytes 🇵🇰")]
5-
[assembly: AssemblyVersion("1.0")]
5+
[assembly: AssemblyVersion("1.1.0.0")]
66

77
// Do not change the entries below!
88
#if X64

KeyCodeInfo/KeyCodeInfo.cs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace KeyCodeInfoPlugin
1111
internal class Measure
1212
{
1313
private API _api;
14-
14+
1515
private static IntPtr _hookID = IntPtr.Zero;
1616
private static LowLevelKeyboardProc _proc = HookCallback;
1717
private static Measure instance;
@@ -26,6 +26,12 @@ internal class Measure
2626
private const int WM_SYSKEYDOWN = 0x0104;
2727
private const int WM_KEYUP = 0x0101;
2828
private const int WM_SYSKEYUP = 0x0105;
29+
private static string lastCombo = "";
30+
31+
// New field for the OnReleaseKeyAction parameter.
32+
private string onReleaseKeyAction = "";
33+
// Flag to ensure the release action is triggered only once per key press cycle.
34+
private bool releaseActionTriggered = false;
2935

3036
// Parameters:
3137
// showCodeMode:
@@ -35,30 +41,29 @@ internal class Measure
3541
// 4 = return key combination (e.g., "Ctrl + Alt + A") in order of press.
3642
private int showCodeMode;
3743
// hideForce: for modes 0, 1, and 3, if true the stored key is cleared immediately.
38-
// For mode 4 (combination), keys remain until they are released.
44+
// For mode 4 (combination), keys remain until released.
3945
private bool hideForce;
4046

4147
/// <summary>
4248
/// Reload is called when Rainmeter reloads the skin.
43-
/// It reads ShowCode and HideForce options and resets stored key data.
49+
/// It reads ShowCode, HideForce, and OnReleaseKeyAction options and resets stored key data.
4450
/// (Note: the hook and update timer are not started automatically.)
4551
/// </summary>
4652
internal void Reload(API api, ref double maxValue)
4753
{
4854
_api = api;
49-
// Store the instance reference for use in the static hook callback.
5055
instance = this;
5156

52-
// Read ShowCode parameter; default is 1 (numeric).
53-
// Other supported values: 3 for hex, 0 for friendly names, 4 for combination.
5457
showCodeMode = api.ReadInt("ShowCode", 1);
55-
// Read HideForce parameter; default is 1 (clear immediately).
5658
hideForce = api.ReadInt("HideForce", 1) == 1;
59+
// Read the new OnReleaseKeyAction parameter (default to empty string).
60+
onReleaseKeyAction = api.ReadString("OnReleaseKeyAction", "");
5761

58-
// Reset stored key data.
5962
lastKeyCode = 0;
6063
pressedKeyEvents.Clear();
6164
pressedKeyOrder.Clear();
65+
// Reset the release flag
66+
releaseActionTriggered = false;
6267

6368
_api.Log(API.LogType.Debug, "KeyCodeInfo.dll: Plugin reloaded in stopped state.");
6469
}
@@ -85,9 +90,14 @@ internal string GetString()
8590
{
8691
if (showCodeMode == 4)
8792
{
88-
// Build combination string using press order.
93+
// If no keys are currently pressed, and HideForce is off,
94+
// return the last stored combination.
8995
if (pressedKeyOrder.Count == 0)
96+
{
97+
if (!hideForce && !string.IsNullOrEmpty(lastCombo))
98+
return lastCombo;
9099
return "";
100+
}
91101
List<string> comboNames = new List<string>();
92102
foreach (int key in pressedKeyOrder)
93103
{
@@ -101,7 +111,8 @@ internal string GetString()
101111
comboNames.Add(keyName);
102112
}
103113
}
104-
return string.Join(" + ", comboNames);
114+
lastCombo = string.Join(" + ", comboNames);
115+
return lastCombo;
105116
}
106117
else
107118
{
@@ -170,13 +181,12 @@ internal void ExecuteCommand(string command)
170181
// Start the update timer if not already running.
171182
if (updateTimer == null)
172183
{
173-
updateTimer = new Timer(50); // Timer interval in milliseconds.
184+
updateTimer = new Timer(100); // Timer interval in milliseconds.
174185
updateTimer.Elapsed += (sender, e) =>
175186
{
176187
_api.Execute($"!UpdateMeasure \"{measureName}\"");
177188
_api.Execute($"!UpdateMeter *");
178189
_api.Execute($"!Redraw");
179-
// _api.Execute($"!Log \"Updating : {measureName}\"");
180190
};
181191
updateTimer.AutoReset = true;
182192
updateTimer.Start();
@@ -230,6 +240,7 @@ internal void Unload()
230240
updateTimer = null;
231241
_api.Log(API.LogType.Debug, "KeyCodeInfo.dll: Update timer stopped on Unload.");
232242
}
243+
lastCombo = "";
233244
}
234245

235246
// Sets up the low-level keyboard hook.
@@ -255,19 +266,20 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
255266
int key = (int)kbStruct.vkCode;
256267
lastKeyCode = key;
257268
lastKeyEvent = kbStruct;
258-
// If the active instance is in combination mode, update tracking.
269+
// Reset the release flag for every key press
270+
if (instance != null)
271+
instance.releaseActionTriggered = false;
272+
// For combination mode, update tracking.
259273
if (instance != null && instance.showCodeMode == 4)
260274
{
261275
if (pressedKeyEvents.ContainsKey(key))
262276
{
263-
// Remove the key from the order list so it can be re-added at the end.
264277
pressedKeyOrder.Remove(key);
265278
}
266279
pressedKeyEvents[key] = kbStruct;
267280
pressedKeyOrder.Add(key);
268281
}
269282
}
270-
// Handle key-up events.
271283
else if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
272284
{
273285
KBDLLHOOKSTRUCT kbStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
@@ -279,6 +291,22 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
279291
pressedKeyEvents.Remove(key);
280292
}
281293
pressedKeyOrder.Remove(key);
294+
// In combination mode, trigger the action only when all keys are released.
295+
if (pressedKeyEvents.Count == 0 && !instance.releaseActionTriggered && !string.IsNullOrEmpty(instance.onReleaseKeyAction))
296+
{
297+
instance._api.Execute(instance.onReleaseKeyAction);
298+
instance.releaseActionTriggered = true;
299+
}
300+
}
301+
else if (instance != null)
302+
{
303+
// For non-combination modes, trigger the action on every key-up,
304+
// but only once per key press cycle.
305+
if (!instance.releaseActionTriggered && !string.IsNullOrEmpty(instance.onReleaseKeyAction))
306+
{
307+
instance._api.Execute(instance.onReleaseKeyAction);
308+
instance.releaseActionTriggered = true;
309+
}
282310
}
283311
}
284312
}

README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
21
# KeyCodeInfo Plugin
32

43
**KeyCodeInfo** is a Rainmeter plugin written in C# that captures keyboard events and displays key information in various formats. It supports multiple output modes such as:
4+
55
- **Decimal Mode (ShowCode=1):** Displays the key code as a decimal number.
66
- **Hexadecimal Mode (ShowCode=3):** Displays the key code in hexadecimal format (e.g., "0x4A").
77
- **Friendly Name Mode (ShowCode=0):** Displays a friendly key name (e.g., "Space", "CapsLock", "Shift").
@@ -51,9 +51,10 @@ AccurateText=1
5151

5252
[Metadata]
5353
Name=KeyCodeInfo - Key Combination Skin
54-
Author=Your Name
54+
Author=NS Tech Bytes
5555
Information=This skin demonstrates the KeyCodeInfo plugin in combination mode with a background.
56-
Version=1.0
56+
Version=1.1
57+
LICENSE=MIT LICENSE
5758

5859
;-------------------------------------------------
5960
; Background
@@ -74,6 +75,7 @@ Plugin=KeyCodeInfo
7475
ShowCode=4
7576
; Set HideForce=0 to retain the combination until keys are released
7677
HideForce=0
78+
OnReleaseKeyAction=[!Log "Key Release"]
7779

7880
;-------------------------------------------------
7981
; Display the key combination
@@ -121,34 +123,37 @@ DynamicVariables=1
121123
### Bang Commands
122124

123125
- **Start the Plugin:**
126+
124127
```
125128
!CommandMeasure MeasureKeyCode "Start"
126129
```
127-
This command starts the keyboard hook, retrieves the measure name, and starts an update timer that forces the measure, all meters, and a redraw.
128130

131+
This command starts the keyboard hook, retrieves the measure name, and starts an update timer that forces the measure, all meters, and a redraw.
129132
- **Stop the Plugin:**
133+
130134
```
131135
!CommandMeasure MeasureKeyCode "Stop"
132136
```
137+
133138
This command stops the keyboard hook and the update timer.
134139

135140
### Parameter Options
136141

137-
- **ShowCode Parameter:**
142+
- **ShowCode Parameter:**
143+
138144
- `0` - Friendly key names.
139145
- `1` - Decimal key code.
140146
- `3` - Hexadecimal key code.
141147
- `4` - Key combination (displays keys in the order pressed).
148+
- **HideForce Parameter:**
142149

143-
- **HideForce Parameter:**
144150
- `1` (default) - Clears key data immediately after reading (for modes 0, 1, and 3).
145151
- `0` - Retains the last key until a new key press occurs (useful for combination mode).
146152

147153
## Troubleshooting
148154

149-
- **Key Not Displaying:**
150-
Ensure that the DLL is placed in the correct plugins folder and that Rainmeter has been refreshed.
151-
- **Build Issues:**
155+
- **Key Not Displaying:**Ensure that the DLL is placed in the correct plugins folder and that Rainmeter has been refreshed.
156+
- **Build Issues:**
152157
Verify that you have installed the necessary DllExporter tool and that your project settings match your target platform (x86 or x64).
153158

154159
## Contributing

0 commit comments

Comments
 (0)