Compare commits
19 Commits
v1.0
...
fix-keyboa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0875422116 | ||
|
|
a63b268fb8 | ||
|
|
c5e9ab752a | ||
|
|
0722af4b74 | ||
|
|
34fed5e5ba | ||
|
|
f3cc28e379 | ||
|
|
2a714f8bef | ||
|
|
66029e7b3a | ||
|
|
741821c2a3 | ||
|
|
154a7fd63e | ||
|
|
264ba03421 | ||
|
|
60e7804aba | ||
|
|
6877f6642a | ||
|
|
3b4f802a4e | ||
|
|
731fc744d7 | ||
|
|
04705ecbb8 | ||
|
|
aa57a2aaf9 | ||
|
|
48cd49cfd5 | ||
|
|
aa1d0376b4 |
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Jed Laundry
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
12
PRIVACY.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Privacy Policy
|
||||
|
||||
TypeClipboard does one thing, and one thing only: type (through a virtual keyboard) the contents of the clipboard.
|
||||
|
||||
It does not:
|
||||
- store clipboard information
|
||||
- process clipboard information
|
||||
- send your data over the internet, especially not to dodgy hackers
|
||||
|
||||
That's it.
|
||||
|
||||
Sorry this isn't 333 pages long...
|
||||
14
README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# TypeClipboard
|
||||
|
||||
For IT professionals everywhere who are sick of typing long complex passwords into remote consoles. Just copy the password into your clipboard, select the password box, and press F8 or click Type!
|
||||
|
||||

|
||||
|
||||
(Doesn't have to be a password either, also useful for URLs, Base64-encoded things, etc.)
|
||||
|
||||
Also, if you don't want to compile yourself, this is also available in the Windows Store:
|
||||
|
||||
https://www.microsoft.com/en-us/p/type-clipboard/9p5r4jk7r8h5
|
||||
|
||||
Tested with a wide variety of consoles, including vSphere, Horizon (HTML5), and Citrix. There is a known issue where VMWare Horizon's client seems to be using a very low-level keyboard driver, so it doesn't work with it. Sorry.
|
||||
|
||||
@@ -1,20 +1,76 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28306.52
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30011.22
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TypeClipboard", "TypeClipboard\TypeClipboard.csproj", "{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}"
|
||||
EndProject
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "TypeClipboardAppx", "TypeClipboardAppx\TypeClipboardAppx.wapproj", "{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AFF27396-3E91-471E-B46B-2D2DA30FE6DB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x64.Build.0 = Debug|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x86.Build.0 = Debug|x86
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM.Build.0 = Release|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x64.ActiveCfg = Release|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x64.Build.0 = Release|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x64.Deploy.0 = Release|x64
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x86.ActiveCfg = Release|x86
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x86.Build.0 = Release|x86
|
||||
{D041BCC6-3C9D-4BDC-8443-2BEC9B290D1A}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="TypeClipboard.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
</startup>
|
||||
<userSettings>
|
||||
<TypeClipboard.Properties.Settings>
|
||||
<setting name="enableHotkey" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="enableEnter" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
</TypeClipboard.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
62
TypeClipboard/ClipboardNotification.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TypeClipboard
|
||||
{
|
||||
//
|
||||
// https://gist.github.com/glombard/7986317
|
||||
// from: http://stackoverflow.com/questions/2226920/how-to-monitor-clipboard-content-changes-in-c
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Provides notifications when the contents of the clipboard is updated.
|
||||
/// </summary>
|
||||
public sealed class ClipboardNotification
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the contents of the clipboard is updated.
|
||||
/// </summary>
|
||||
public static event EventHandler ClipboardUpdate;
|
||||
|
||||
private static NotificationForm _form = new NotificationForm();
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="ClipboardUpdate"/> event.
|
||||
/// </summary>
|
||||
/// <param name="e">Event arguments for the event.</param>
|
||||
private static void OnClipboardUpdate(EventArgs e)
|
||||
{
|
||||
var handler = ClipboardUpdate;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hidden form to recieve the WM_CLIPBOARDUPDATE message.
|
||||
/// </summary>
|
||||
private class NotificationForm : Form
|
||||
{
|
||||
public NotificationForm()
|
||||
{
|
||||
NativeMethods.SetParent(Handle, NativeMethods.HWND_MESSAGE);
|
||||
NativeMethods.AddClipboardFormatListener(Handle);
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == NativeMethods.WM_CLIPBOARDUPDATE)
|
||||
{
|
||||
OnClipboardUpdate(null);
|
||||
}
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
90
TypeClipboard/Form1.Designer.cs
generated
@@ -28,43 +28,115 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.chkHotkey = new System.Windows.Forms.CheckBox();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.button3 = new System.Windows.Forms.Button();
|
||||
this.chkEnter = new System.Windows.Forms.CheckBox();
|
||||
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.textBox1.Location = new System.Drawing.Point(12, 12);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.ReadOnly = true;
|
||||
this.textBox1.Size = new System.Drawing.Size(184, 20);
|
||||
this.textBox1.Size = new System.Drawing.Size(201, 22);
|
||||
this.textBox1.TabIndex = 0;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(202, 10);
|
||||
this.button1.Location = new System.Drawing.Point(219, 12);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(103, 23);
|
||||
this.button1.Size = new System.Drawing.Size(103, 22);
|
||||
this.button1.TabIndex = 1;
|
||||
this.button1.Text = "Type (2s delay)";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// chkHotkey
|
||||
//
|
||||
this.chkHotkey.AutoSize = true;
|
||||
this.chkHotkey.Location = new System.Drawing.Point(172, 42);
|
||||
this.chkHotkey.Name = "chkHotkey";
|
||||
this.chkHotkey.Size = new System.Drawing.Size(73, 17);
|
||||
this.chkHotkey.TabIndex = 2;
|
||||
this.chkHotkey.Text = "F8 hotkey";
|
||||
this.toolTip1.SetToolTip(this.chkHotkey, "Enables the F8 hotkey");
|
||||
this.chkHotkey.UseVisualStyleBackColor = true;
|
||||
this.chkHotkey.CheckedChanged += new System.EventHandler(this.chkHotkey_CheckedChanged);
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Location = new System.Drawing.Point(219, 65);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(103, 22);
|
||||
this.button2.TabIndex = 4;
|
||||
this.button2.Text = "Type (2s delay)";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
this.button2.Click += new System.EventHandler(this.button2_Click);
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.textBox2.Location = new System.Drawing.Point(12, 65);
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.ReadOnly = true;
|
||||
this.textBox2.Size = new System.Drawing.Size(201, 22);
|
||||
this.textBox2.TabIndex = 5;
|
||||
//
|
||||
// button3
|
||||
//
|
||||
this.button3.Location = new System.Drawing.Point(12, 39);
|
||||
this.button3.Name = "button3";
|
||||
this.button3.Size = new System.Drawing.Size(154, 22);
|
||||
this.button3.TabIndex = 6;
|
||||
this.button3.Text = "Copy clipboard to buffer";
|
||||
this.button3.UseVisualStyleBackColor = true;
|
||||
this.button3.Click += new System.EventHandler(this.button3_Click);
|
||||
//
|
||||
// chkEnter
|
||||
//
|
||||
this.chkEnter.AutoSize = true;
|
||||
this.chkEnter.Location = new System.Drawing.Point(244, 42);
|
||||
this.chkEnter.Name = "chkEnter";
|
||||
this.chkEnter.Size = new System.Drawing.Size(78, 17);
|
||||
this.chkEnter.TabIndex = 7;
|
||||
this.chkEnter.Text = "Type Enter";
|
||||
this.toolTip1.SetToolTip(this.chkEnter, "If set, Type will type newline (\\n) as Enter, which is useful for large blobs of " +
|
||||
"text.\r\n\r\nIf unset, Type will stop before the first newline, which is useful for " +
|
||||
"passwords.");
|
||||
this.chkEnter.UseVisualStyleBackColor = true;
|
||||
this.chkEnter.CheckedChanged += new System.EventHandler(this.chkEnter_CheckedChanged);
|
||||
//
|
||||
// toolTip1
|
||||
//
|
||||
this.toolTip1.ShowAlways = true;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.ClientSize = new System.Drawing.Size(317, 44);
|
||||
this.ClientSize = new System.Drawing.Size(334, 99);
|
||||
this.Controls.Add(this.chkEnter);
|
||||
this.Controls.Add(this.button3);
|
||||
this.Controls.Add(this.textBox2);
|
||||
this.Controls.Add(this.button2);
|
||||
this.Controls.Add(this.chkHotkey);
|
||||
this.Controls.Add(this.button1);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Form1";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.Text = "Type Clipboard";
|
||||
this.TopMost = true;
|
||||
this.Activated += new System.EventHandler(this.Form1_Activated);
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.Enter += new System.EventHandler(this.Form1_Enter);
|
||||
this.MouseEnter += new System.EventHandler(this.Form1_MouseEnter);
|
||||
this.ResumeLayout(false);
|
||||
@@ -76,6 +148,12 @@
|
||||
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.CheckBox chkHotkey;
|
||||
private System.Windows.Forms.Button button2;
|
||||
private System.Windows.Forms.TextBox textBox2;
|
||||
private System.Windows.Forms.Button button3;
|
||||
private System.Windows.Forms.CheckBox chkEnter;
|
||||
private System.Windows.Forms.ToolTip toolTip1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace TypeClipboard
|
||||
{
|
||||
const int WS_EX_NOACTIVATE = 0x08000000;
|
||||
|
||||
private LowLevelKeyboardListener _listener;
|
||||
private Typer _tc;
|
||||
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -29,70 +32,38 @@ namespace TypeClipboard
|
||||
}
|
||||
}
|
||||
|
||||
public void TypeClipboard()
|
||||
{
|
||||
if (Clipboard.ContainsText(TextDataFormat.UnicodeText))
|
||||
{
|
||||
String clipboard = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||
Thread.Sleep(2000);
|
||||
foreach (Char c in clipboard.ToCharArray())
|
||||
{
|
||||
// Some characters have special meaning
|
||||
// https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/sendkeys-statement
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
return;
|
||||
case '\r':
|
||||
return;
|
||||
case '{':
|
||||
SendKeys.Send("{{}");
|
||||
break;
|
||||
case '}':
|
||||
SendKeys.Send("{}}");
|
||||
break;
|
||||
case '+':
|
||||
SendKeys.Send("{+}");
|
||||
break;
|
||||
case '^':
|
||||
SendKeys.Send("{^}");
|
||||
break;
|
||||
case '%':
|
||||
SendKeys.Send("{%}");
|
||||
break;
|
||||
case '~':
|
||||
SendKeys.Send("{~}");
|
||||
break;
|
||||
case '(':
|
||||
SendKeys.Send("{(}");
|
||||
break;
|
||||
case ')':
|
||||
SendKeys.Send("{)}");
|
||||
break;
|
||||
default:
|
||||
SendKeys.Send(c.ToString());
|
||||
break;
|
||||
}
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
TypeClipboard();
|
||||
_tc.TypeClipboard(2000);
|
||||
}
|
||||
|
||||
public void UpdateTextbox()
|
||||
public void UpdateTextbox(EventArgs e = null)
|
||||
{
|
||||
if (Clipboard.ContainsText(TextDataFormat.UnicodeText))
|
||||
{
|
||||
String clipboard = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(clipboard.Substring(0, Math.Min(3, clipboard.Length)));
|
||||
sb.Append(" ... ");
|
||||
sb.Append(clipboard.Substring(clipboard.Length - Math.Min(clipboard.Length, 3)));
|
||||
sb.Append(" (" + clipboard.Length.ToString() + " characters)");
|
||||
|
||||
if (clipboard.Length <= 4)
|
||||
{
|
||||
sb.Append(" (" + clipboard.Length.ToString() + " characters)");
|
||||
}
|
||||
else if (clipboard.Length <= 9)
|
||||
{
|
||||
sb.Append(clipboard.Substring(0, 1));
|
||||
sb.Append("...");
|
||||
sb.Append(clipboard.Substring(clipboard.Length - 1));
|
||||
sb.Append(" (" + clipboard.Length.ToString() + " characters)");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(clipboard.Substring(0, 3));
|
||||
sb.Append("...");
|
||||
sb.Append(clipboard.Substring(clipboard.Length - 3));
|
||||
sb.Append(" (" + clipboard.Length.ToString() + " characters)");
|
||||
}
|
||||
|
||||
|
||||
textBox1.Text = sb.ToString();
|
||||
}
|
||||
else
|
||||
@@ -115,5 +86,60 @@ namespace TypeClipboard
|
||||
{
|
||||
UpdateTextbox();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
_tc = new Typer();
|
||||
_listener = new LowLevelKeyboardListener(_tc);
|
||||
// Changing the chkHotkey.Checked property also hooks the listener
|
||||
chkHotkey.Checked = Properties.Settings.Default.enableHotkey;
|
||||
|
||||
// Changing the chkEnter.Checked property also changes _tc.TypeEnter property
|
||||
chkEnter.Checked = Properties.Settings.Default.enableEnter;
|
||||
|
||||
ClipboardNotification.ClipboardUpdate += delegate (object cb_sender, EventArgs cb_e) {
|
||||
UpdateTextbox();
|
||||
};
|
||||
UpdateTextbox();
|
||||
}
|
||||
|
||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
_listener.UnHookKeyboard();
|
||||
}
|
||||
|
||||
private void chkHotkey_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Properties.Settings.Default.enableHotkey = chkHotkey.Checked;
|
||||
|
||||
if (Properties.Settings.Default.enableHotkey)
|
||||
{
|
||||
_listener.HookKeyboard();
|
||||
}
|
||||
else
|
||||
{
|
||||
_listener.UnHookKeyboard();
|
||||
}
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void button2_Click(object sender, EventArgs e)
|
||||
{
|
||||
_tc.Type(textBox2.Text);
|
||||
}
|
||||
|
||||
private void button3_Click(object sender, EventArgs e)
|
||||
{
|
||||
String clipboard = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||
textBox2.Text = clipboard;
|
||||
}
|
||||
|
||||
private void chkEnter_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Properties.Settings.Default.enableEnter = chkEnter.Checked;
|
||||
_tc.TypeEnter = chkEnter.Checked;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +117,13 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
119
TypeClipboard/LowLevelKeyboardListener.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
|
||||
/*
|
||||
Portions Copyright (c) 2019 dylansweb.com, http://www.dylansweb.com/2014/10/low-level-global-keyboard-hook-sink-in-c-net/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace TypeClipboard
|
||||
{
|
||||
public class LowLevelKeyboardListener
|
||||
{
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
private const int WM_KEYDOWN = 0x0100;
|
||||
private const int WM_SYSKEYDOWN = 0x0104;
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
||||
|
||||
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
public event EventHandler<KeyPressedArgs> OnKeyPressed;
|
||||
|
||||
private LowLevelKeyboardProc _proc;
|
||||
private IntPtr _hookID = IntPtr.Zero;
|
||||
public Typer _tc;
|
||||
|
||||
public LowLevelKeyboardListener(Typer tc)
|
||||
{
|
||||
_proc = HookCallback;
|
||||
_tc = tc;
|
||||
}
|
||||
|
||||
public void HookKeyboard()
|
||||
{
|
||||
_hookID = SetHook(_proc);
|
||||
}
|
||||
|
||||
public void UnHookKeyboard()
|
||||
{
|
||||
if(_hookID != IntPtr.Zero)
|
||||
{
|
||||
UnhookWindowsHookEx(_hookID);
|
||||
_hookID = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr SetHook(LowLevelKeyboardProc proc)
|
||||
{
|
||||
using (Process curProcess = Process.GetCurrentProcess())
|
||||
using (ProcessModule curModule = curProcess.MainModule)
|
||||
{
|
||||
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
|
||||
{
|
||||
int vkCode = Marshal.ReadInt32(lParam);
|
||||
Key keyPressed = KeyInterop.KeyFromVirtualKey(vkCode);
|
||||
|
||||
// Explicitly putting this here because we need to return before CallNextHookEx
|
||||
if (keyPressed == Key.F8)
|
||||
{
|
||||
// Call Type Clipboard
|
||||
_tc.TypeClipboard(100);
|
||||
|
||||
// Prevent key bring pressed further into the app
|
||||
return new IntPtr(1);
|
||||
}
|
||||
|
||||
if (OnKeyPressed != null) { OnKeyPressed(this, new KeyPressedArgs(keyPressed)); }
|
||||
}
|
||||
|
||||
return CallNextHookEx(_hookID, nCode, wParam, lParam);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyPressedArgs : EventArgs
|
||||
{
|
||||
public Key KeyPressed { get; private set; }
|
||||
|
||||
public KeyPressedArgs(Key key)
|
||||
{
|
||||
KeyPressed = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Jed Laundry")]
|
||||
[assembly: AssemblyProduct("Type Clipboard")]
|
||||
[assembly: AssemblyCopyright("Copyright © Jed Laundry, 2019")]
|
||||
[assembly: AssemblyCopyright("Copyright © Jed Laundry, 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("1.5.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.5.0.0")]
|
||||
|
||||
2
TypeClipboard/Properties/Resources.Designer.cs
generated
@@ -19,7 +19,7 @@ namespace TypeClipboard.Properties {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
26
TypeClipboard/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace TypeClipboard.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -22,5 +22,29 @@ namespace TypeClipboard.Properties {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool enableHotkey {
|
||||
get {
|
||||
return ((bool)(this["enableHotkey"]));
|
||||
}
|
||||
set {
|
||||
this["enableHotkey"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool enableEnter {
|
||||
get {
|
||||
return ((bool)(this["enableEnter"]));
|
||||
}
|
||||
set {
|
||||
this["enableEnter"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TypeClipboard.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="enableHotkey" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="enableEnter" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -8,11 +8,26 @@
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>TypeClipboard</RootNamespace>
|
||||
<AssemblyName>TypeClipboard</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.5.0.</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -30,11 +45,15 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>typeclipboard.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -47,16 +66,20 @@
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ClipboardNotification.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LowLevelKeyboardListener.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Typer.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -83,5 +106,20 @@
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="typeclipboard.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
516
TypeClipboard/Typer.cs
Normal file
@@ -0,0 +1,516 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TypeClipboard
|
||||
{
|
||||
public class Typer
|
||||
{
|
||||
private const int INTERKEY_DELAY = 50;
|
||||
|
||||
private bool _typeEnter = false;
|
||||
public bool TypeEnter { get => _typeEnter; set => _typeEnter = value; }
|
||||
|
||||
public void Type(String str, int delay = 2000)
|
||||
{
|
||||
Thread.Sleep(delay);
|
||||
NativeMethods.BlockInput(true);
|
||||
//KeyboardTyper.Reset();
|
||||
|
||||
KeyboardTyper.Type(str, _typeEnter, INTERKEY_DELAY);
|
||||
//KeyboardTyper.Press(Key.LeftShift);
|
||||
//KeyboardTyper.Type("hello, capitalized world");
|
||||
//KeyboardTyper.Release(Key.LeftShift);
|
||||
|
||||
NativeMethods.BlockInput(false);
|
||||
|
||||
}
|
||||
|
||||
public void TypeClipboard(int delay = 2000)
|
||||
{
|
||||
if (Clipboard.ContainsText(TextDataFormat.UnicodeText))
|
||||
{
|
||||
String clipboard = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||
this.Type(clipboard, delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://gist.github.com/obviliontsk/90403a0fea8c24258570f3a577704864
|
||||
|
||||
/// <summary>
|
||||
/// Native methods
|
||||
/// </summary>
|
||||
public static partial class NativeMethods
|
||||
{
|
||||
// See http://msdn.microsoft.com/en-us/library/ms649021%28v=vs.85%29.aspx
|
||||
public const int WM_CLIPBOARDUPDATE = 0x031D;
|
||||
public static IntPtr HWND_MESSAGE = new IntPtr(-3);
|
||||
|
||||
// See http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AddClipboardFormatListener(IntPtr hwnd);
|
||||
|
||||
// See http://msdn.microsoft.com/en-us/library/ms633541%28v=vs.85%29.aspx
|
||||
// See http://msdn.microsoft.com/en-us/library/ms649033%28VS.85%29.aspx
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
|
||||
|
||||
//User32 wrappers cover API's used for Mouse input
|
||||
#region User32
|
||||
// Two special bitMasks we define to be able to grab
|
||||
// shift and character information out of a VKey.
|
||||
internal const int VKeyShiftMask = 0x0100;
|
||||
internal const int VKeyCharMask = 0x00FF;
|
||||
|
||||
// Various Win32 constants
|
||||
internal const int KeyeventfExtendedkey = 0x0001;
|
||||
internal const int KeyeventfKeyup = 0x0002;
|
||||
internal const int KeyeventfUnicode = 0x0004;
|
||||
internal const int KeyeventfScancode = 0x0008;
|
||||
|
||||
|
||||
internal const int MouseeventfVirtualdesk = 0x4000;
|
||||
|
||||
internal const int SMXvirtualscreen = 76;
|
||||
internal const int SMYvirtualscreen = 77;
|
||||
internal const int SMCxvirtualscreen = 78;
|
||||
internal const int SMCyvirtualscreen = 79;
|
||||
|
||||
internal const int XButton1 = 0x0001;
|
||||
internal const int XButton2 = 0x0002;
|
||||
internal const int WheelDelta = 120;
|
||||
|
||||
internal const int InputMouse = 0;
|
||||
internal const int InputKeyboard = 1;
|
||||
|
||||
// Various Win32 data structures
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct INPUT
|
||||
{
|
||||
internal int type;
|
||||
internal INPUTUNION union;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct INPUTUNION
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal MOUSEINPUT mouseInput;
|
||||
[FieldOffset(0)]
|
||||
internal KEYBDINPUT keyboardInput;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct MOUSEINPUT
|
||||
{
|
||||
internal int dx;
|
||||
internal int dy;
|
||||
internal int mouseData;
|
||||
internal int dwFlags;
|
||||
internal int time;
|
||||
internal IntPtr dwExtraInfo;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct KEYBDINPUT
|
||||
{
|
||||
internal short wVk;
|
||||
internal short wScan;
|
||||
internal int dwFlags;
|
||||
internal int time;
|
||||
internal IntPtr dwExtraInfo;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct POINT
|
||||
{
|
||||
public readonly int X;
|
||||
public readonly int Y;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum SendMouseInputFlags
|
||||
{
|
||||
Move = 0x0001,
|
||||
LeftDown = 0x0002,
|
||||
LeftUp = 0x0004,
|
||||
RightDown = 0x0008,
|
||||
RightUp = 0x0010,
|
||||
MiddleDown = 0x0020,
|
||||
MiddleUp = 0x0040,
|
||||
XDown = 0x0080,
|
||||
XUp = 0x0100,
|
||||
Wheel = 0x0800,
|
||||
Absolute = 0x8000,
|
||||
};
|
||||
|
||||
// Importing various Win32 APIs that we need for input
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetSystemMetrics(int nIndex);
|
||||
|
||||
// DllImport CharSet = CharSet.Auto -> Unicode / Utf.16 for windows, so 'W'
|
||||
[DllImport("user32.dll", EntryPoint = "MapVirtualKeyW")]
|
||||
public static extern int MapVirtualKey(int nVirtKey, int nMapType);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern int SendInput(int nInputs, ref INPUT mi, int cbSize);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "BlockInput")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool BlockInput([MarshalAs(UnmanagedType.Bool)] bool fBlockIt);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool GetCursorPos(out POINT lpPoint);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exposes a simple interface to common keyboard operations, allowing the user to simulate keyboard input.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// The following code types "Hello world" with the specified casing,
|
||||
/// and then types "hello, capitalized world" which will be in all caps because
|
||||
/// the left shift key is being held down.
|
||||
/// To send input with hotkeys use BlockInput method (app will need admin rights) to block all users inputs
|
||||
/// and reset inputs state, so they won't interfere
|
||||
/// <code>
|
||||
/**
|
||||
NativeMethods.BlockInput(true);
|
||||
Keyboard.Reset();
|
||||
|
||||
Keyboard.Type("Hello world");
|
||||
Keyboard.Press(Key.LeftShift);
|
||||
Keyboard.Type("hello, capitalized world");
|
||||
Keyboard.Release(Key.LeftShift);
|
||||
|
||||
NativeMethods.BlockInput(false);
|
||||
*/
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static class KeyboardTyper
|
||||
{
|
||||
#region Public Members
|
||||
|
||||
/// <summary>
|
||||
/// Presses down a key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to press.</param>
|
||||
public static void Press(Key key)
|
||||
{
|
||||
SendKeyboardInput(key, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to release.</param>
|
||||
public static void Release(Key key)
|
||||
{
|
||||
SendKeyboardInput(key, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Presses down a key.
|
||||
/// </summary>
|
||||
/// <param name="input">The key to press.</param>
|
||||
public static void Press(char input)
|
||||
{
|
||||
SendKeyboardInput(input, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a key.
|
||||
/// </summary>
|
||||
/// <param name="input">The key to release.</param>
|
||||
public static void Release(char input)
|
||||
{
|
||||
SendKeyboardInput(input, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the system keyboard to a clean state.
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
return;
|
||||
foreach (Key key in Enum.GetValues(typeof(Key)))
|
||||
{
|
||||
// TODO System.Windows.Input.Keyboard exists from WPF, this is WinForms...
|
||||
//if (key != Key.None && (System.Windows.Input.Keyboard.GetKeyStates(key) & KeyStates.Down) > 0)
|
||||
//{
|
||||
// Release(key);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a press-and-release operation for the specified key, which is effectively equivalent to typing.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to press.</param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">releaseDelayMs less than 0</exception>
|
||||
public static void Type(Key key, int releaseDelayMs = 0)
|
||||
{
|
||||
if (releaseDelayMs < 0) throw new ArgumentOutOfRangeException(nameof(releaseDelayMs), releaseDelayMs, "Less than zero");
|
||||
Press(key);
|
||||
if (releaseDelayMs > 0)
|
||||
Thread.Sleep(releaseDelayMs);
|
||||
Release(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a press-and-release operation for the specified key specific amount of times.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to press.</param>
|
||||
/// <param name="amountToType"></param>
|
||||
/// <param name="inputDelayMs">Delay after releasing key</param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">releaseDelayMs less than 0 or amountToType less than 1 or inputDelayMs less than 0</exception>
|
||||
public static void TypeKeyNTimes(Key key, int amountToType = 1, int inputDelayMs = 0, int releaseDelayMs = 0)
|
||||
{
|
||||
if (amountToType < 1) throw new ArgumentOutOfRangeException(nameof(amountToType), amountToType, "Less than one");
|
||||
if (inputDelayMs < 0) throw new ArgumentOutOfRangeException(nameof(inputDelayMs), releaseDelayMs, "Less than zero");
|
||||
for (int i = 0; i < amountToType; i++)
|
||||
{
|
||||
Type(key, releaseDelayMs);
|
||||
if (inputDelayMs > 0)
|
||||
Thread.Sleep(releaseDelayMs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types the specified text.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to type.</param>
|
||||
/// <param name="inputDelayMs">Delay between typing each key</param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">releaseDelayMs less than 0 or inputDelayMs less than 0</exception>
|
||||
public static void Type(string text, bool typeEnter = false, int inputDelayMs = 0, int releaseDelayMs = 0)
|
||||
{
|
||||
int delay = 0;
|
||||
|
||||
if (text.Length > 1)
|
||||
delay = inputDelayMs;
|
||||
foreach (char c in text)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
if (typeEnter)
|
||||
{
|
||||
Press(Key.Return);
|
||||
if (releaseDelayMs > 0) Thread.Sleep(releaseDelayMs);
|
||||
Release(Key.Return);
|
||||
break;
|
||||
}
|
||||
else
|
||||
// Stop at the first line break
|
||||
return;
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
Type(c, releaseDelayMs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (delay > 0) Thread.Sleep(delay);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types the specified char.
|
||||
/// </summary>
|
||||
/// <param name="input">The char to type.</param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">releaseDelayMs less than 0 or inputDelayMs less than 0</exception>
|
||||
public static void Type(char input, int releaseDelayMs = 0)
|
||||
{
|
||||
if (releaseDelayMs < 0) throw new ArgumentOutOfRangeException(nameof(releaseDelayMs), releaseDelayMs, "Less than zero");
|
||||
Press(input);
|
||||
if (releaseDelayMs > 0) Thread.Sleep(releaseDelayMs);
|
||||
Release(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types a key while a set of modifier keys are being pressed. Modifer keys
|
||||
/// are pressed in the order specified and released in reverse order.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to type.</param>
|
||||
/// <param name="modifierKeys">Set of keys to hold down with key is typed.</param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
public static void Type(Key key, Key[] modifierKeys, int releaseDelayMs = 0)
|
||||
{
|
||||
foreach (Key modifierKey in modifierKeys)
|
||||
{
|
||||
if (modifierKey == Key.None)
|
||||
continue;
|
||||
Press(modifierKey);
|
||||
}
|
||||
|
||||
Type(key, releaseDelayMs);
|
||||
|
||||
foreach (Key modifierKey in modifierKeys.Reverse())
|
||||
{
|
||||
if (modifierKey == Key.None)
|
||||
continue;
|
||||
Release(modifierKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types a key while a set of modifier keys are being pressed. Modifer keys
|
||||
/// are pressed in the order Ctrl->Shift->Alt->Win.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to type.</param>
|
||||
/// <param name="modifierKeys">Set of ModifierKeys enum flags to hold down with key is typed. </param>
|
||||
/// <param name="releaseDelayMs">Delay before key release</param>
|
||||
public static void Type(Key key, ModifierKeys modifierKeys, int releaseDelayMs = 0)
|
||||
{
|
||||
var modifierKeysArray = ModifierKeysToArrayConverter(modifierKeys);
|
||||
Type(key, modifierKeysArray, releaseDelayMs);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to convert ModifierKeys enum flags to Key array
|
||||
/// </summary>
|
||||
/// <param name="modifierKeys">ModifierKeys enum flags</param>
|
||||
private static Key[] ModifierKeysToArrayConverter(ModifierKeys modifierKeys)
|
||||
{
|
||||
Key[] keys = new Key[4];
|
||||
if (modifierKeys.HasFlag(ModifierKeys.Control))
|
||||
keys.SetValue(Key.LeftCtrl, 0);
|
||||
if (modifierKeys.HasFlag(ModifierKeys.Shift))
|
||||
keys.SetValue(Key.LeftShift, 1);
|
||||
if (modifierKeys.HasFlag(ModifierKeys.Alt))
|
||||
keys.SetValue(Key.LeftAlt, 2);
|
||||
if (modifierKeys.HasFlag(ModifierKeys.Windows))
|
||||
keys.SetValue(Key.LWin, 3);
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Injects keyboard input into the system.
|
||||
/// </summary>
|
||||
/// <param name="key">Indicates the key pressed or released. Can be one of the constants defined in the Key enum.</param>
|
||||
/// <param name="press">True to inject a key press, false to inject a key release.</param>
|
||||
private static void SendKeyboardInput(Key key, bool press)
|
||||
{
|
||||
NativeMethods.INPUT ki = new NativeMethods.INPUT
|
||||
{
|
||||
type = NativeMethods.InputKeyboard
|
||||
};
|
||||
ki.union.keyboardInput.wVk = (short)KeyInterop.VirtualKeyFromKey(key);
|
||||
ki.union.keyboardInput.wScan = (short)NativeMethods.MapVirtualKey(ki.union.keyboardInput.wVk, 0);
|
||||
|
||||
int dwFlags = 0;
|
||||
|
||||
if (ki.union.keyboardInput.wScan > 0)
|
||||
{
|
||||
dwFlags |= NativeMethods.KeyeventfScancode;
|
||||
}
|
||||
|
||||
if (!press)
|
||||
{
|
||||
dwFlags |= NativeMethods.KeyeventfKeyup;
|
||||
}
|
||||
|
||||
ki.union.keyboardInput.dwFlags = dwFlags;
|
||||
|
||||
if (ExtendedKeys.Contains(key))
|
||||
{
|
||||
ki.union.keyboardInput.dwFlags |= NativeMethods.KeyeventfExtendedkey;
|
||||
}
|
||||
|
||||
ki.union.keyboardInput.time = 0;
|
||||
ki.union.keyboardInput.dwExtraInfo = new IntPtr(0);
|
||||
|
||||
if (NativeMethods.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Injects keyboard input into the system.
|
||||
/// </summary>
|
||||
/// <param name="input">Indicates the character pressed or released..</param>
|
||||
/// <param name="press">True to inject a key press, false to inject a key release.</param>
|
||||
private static void SendKeyboardInput(char input, bool press)
|
||||
{
|
||||
NativeMethods.INPUT ki = new NativeMethods.INPUT
|
||||
{
|
||||
type = NativeMethods.InputKeyboard
|
||||
};
|
||||
ki.union.keyboardInput.wVk = 0;
|
||||
ki.union.keyboardInput.wScan = (short)input;
|
||||
|
||||
int dwFlags = 0;
|
||||
dwFlags |= NativeMethods.KeyeventfUnicode;
|
||||
|
||||
if (!press)
|
||||
{
|
||||
dwFlags |= NativeMethods.KeyeventfKeyup;
|
||||
}
|
||||
|
||||
ki.union.keyboardInput.dwFlags = dwFlags;
|
||||
ki.union.keyboardInput.time = 0;
|
||||
ki.union.keyboardInput.dwExtraInfo = new IntPtr(0);
|
||||
|
||||
if (NativeMethods.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
|
||||
// From the SDK:
|
||||
// The extended-key flag indicates whether the keystroke message originated from one of
|
||||
// the additional keys on the enhanced keyboard. The extended keys consist of the ALT and
|
||||
// CTRL keys on the right-hand side of the keyboard; the INS, DEL, HOME, END, PAGE UP,
|
||||
// PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; the NUM LOCK
|
||||
// key; the BREAK (CTRL+PAUSE) key; the PRINT SCRN key; and the divide (/) and ENTER keys in
|
||||
// the numeric keypad. The extended-key flag is set if the key is an extended key.
|
||||
//
|
||||
// - docs appear to be incorrect. Use of Spy++ indicates that break is not an extended key.
|
||||
// Also, menu key and windows keys also appear to be extended.
|
||||
private static readonly Key[] ExtendedKeys = {
|
||||
Key.RightAlt,
|
||||
Key.RightCtrl,
|
||||
Key.NumLock,
|
||||
Key.Insert,
|
||||
Key.Delete,
|
||||
Key.Home,
|
||||
Key.End,
|
||||
Key.Prior,
|
||||
Key.Next,
|
||||
Key.Up,
|
||||
Key.Down,
|
||||
Key.Left,
|
||||
Key.Right,
|
||||
Key.Apps,
|
||||
Key.RWin,
|
||||
Key.LWin
|
||||
};
|
||||
// Note that there are no distinct values for the following keys:
|
||||
// numpad divide
|
||||
// numpad enter
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
BIN
TypeClipboard/typeclipboard.ico
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
TypeClipboard/typeclipboard.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
99
TypeClipboard/typeclipboard.svg
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="512"
|
||||
height="512"
|
||||
version="1.1"
|
||||
id="svg3739"
|
||||
sodipodi:docname="typeclipboard.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
inkscape:export-filename="C:\Users\jlaundry\Downloads\typeclipboard.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<metadata
|
||||
id="metadata3745">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs3743" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview3741"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
inkscape:zoom="1.65625"
|
||||
inkscape:cx="157.88679"
|
||||
inkscape:cy="297.0566"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3739" />
|
||||
<rect
|
||||
style="fill:none;stroke:#ffffff;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="36"
|
||||
y="37"
|
||||
width="439.99997"
|
||||
height="440"
|
||||
id="svg_1"
|
||||
rx="50.671612"
|
||||
ry="50.671612" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:4.99999952;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="168.5"
|
||||
y="14.5"
|
||||
width="175"
|
||||
height="75"
|
||||
id="svg_3"
|
||||
rx="4.2934704"
|
||||
ry="4.2934704" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:5"
|
||||
x="268.5"
|
||||
y="130.5"
|
||||
width="145"
|
||||
height="145"
|
||||
id="svg_7"
|
||||
rx="10"
|
||||
ry="10" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:5"
|
||||
x="178.5"
|
||||
y="300.5"
|
||||
width="145"
|
||||
height="145"
|
||||
id="svg_8"
|
||||
rx="10"
|
||||
ry="10.000001" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:5"
|
||||
x="98.5"
|
||||
y="130.5"
|
||||
width="145"
|
||||
height="145"
|
||||
id="svg_9"
|
||||
rx="10"
|
||||
ry="10" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
BIN
TypeClipboardAppx/Images/LockScreenLogo.scale-200.png
Normal file
|
After Width: | Height: | Size: 780 B |
BIN
TypeClipboardAppx/Images/SplashScreen.scale-200.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
TypeClipboardAppx/Images/Square150x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
TypeClipboardAppx/Images/Square44x44Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 479 B |
BIN
TypeClipboardAppx/Images/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 838 B |
BIN
TypeClipboardAppx/Images/Wide310x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
53
TypeClipboardAppx/Package.appxmanifest
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity
|
||||
Name="3373JedLaundry.TypeClipboard"
|
||||
Publisher="CN=CE320BA0-58BC-4F47-AF5B-94DB661147CC"
|
||||
Version="1.5.0.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>TypeClipboard</DisplayName>
|
||||
<PublisherDisplayName>Jed Laundry</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="TypeClipboard"
|
||||
Description="TypeClipboard"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" ShortName="TypeClipboard">
|
||||
<uap:ShowNameOnTiles>
|
||||
<uap:ShowOn Tile="square150x150Logo"/>
|
||||
<uap:ShowOn Tile="wide310x150Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile >
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
118
TypeClipboardAppx/TypeClipboardAppx.wapproj
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0'">
|
||||
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x86">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|AnyCPU">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|AnyCPU">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>d041bcc6-3c9d-4bdc-8443-2bec9b290d1a</ProjectGuid>
|
||||
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<EntryPointProjectUniqueName>..\TypeClipboard\TypeClipboard.csproj</EntryPointProjectUniqueName>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<GenerateTestArtifacts>False</GenerateTestArtifacts>
|
||||
<AppxBundlePlatforms>neutral</AppxBundlePlatforms>
|
||||
<AppInstallerUri>C:\temp</AppInstallerUri>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
<PackageCertificateThumbprint>0AF17626AE23A8AA61789F56A539111877550E76</PackageCertificateThumbprint>
|
||||
<PackageCertificateKeyFile>TypeClipboardAppx_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Images\SplashScreen.scale-200.png" />
|
||||
<Content Include="Images\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Images\Square150x150Logo.scale-200.png" />
|
||||
<Content Include="Images\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Content Include="Images\StoreLogo.png" />
|
||||
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
||||
<None Include="Package.StoreAssociation.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TypeClipboard\TypeClipboard.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
|
||||
</Project>
|
||||
BIN
screenshot.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
8
teststrings.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
~!@#$%^&*()_+
|
||||
`1234567890-=
|
||||
qwertyuiop[]\
|
||||
QWERTYUIOP{}|
|
||||
asdfghjkl;'
|
||||
ASDFGHJKL:"
|
||||
zxcvbnm,./
|
||||
ZXCVBNM<>?
|
||||