diff --git a/TypeClipboard.sln b/TypeClipboard.sln index 1be7a51..662aaa4 100644 --- a/TypeClipboard.sln +++ b/TypeClipboard.sln @@ -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", "{464D3F7B-8EB2-464E-A036-03FE6366C2A3}" +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 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM.ActiveCfg = Debug|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM.Build.0 = Debug|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM.Deploy.0 = Debug|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM64.Build.0 = Debug|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x64.ActiveCfg = Debug|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x64.Build.0 = Debug|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x64.Deploy.0 = Debug|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x86.ActiveCfg = Debug|x86 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x86.Build.0 = Debug|x86 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Debug|x86.Deploy.0 = Debug|x86 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|Any CPU.Build.0 = Release|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|Any CPU.Deploy.0 = Release|Any CPU + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM.ActiveCfg = Release|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM.Build.0 = Release|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM.Deploy.0 = Release|ARM + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM64.ActiveCfg = Release|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM64.Build.0 = Release|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|ARM64.Deploy.0 = Release|ARM64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x64.ActiveCfg = Release|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x64.Build.0 = Release|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x64.Deploy.0 = Release|x64 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x86.ActiveCfg = Release|x86 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x86.Build.0 = Release|x86 + {464D3F7B-8EB2-464E-A036-03FE6366C2A3}.Release|x86.Deploy.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TypeClipboard/App.config b/TypeClipboard/App.config index bae5d6d..3992291 100644 --- a/TypeClipboard/App.config +++ b/TypeClipboard/App.config @@ -1,6 +1,18 @@ + + +
+ + - + + + + + True + + + diff --git a/TypeClipboard/ClipboardNotification.cs b/TypeClipboard/ClipboardNotification.cs new file mode 100644 index 0000000..4a1f929 --- /dev/null +++ b/TypeClipboard/ClipboardNotification.cs @@ -0,0 +1,79 @@ +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 + // + + /// + /// Provides notifications when the contents of the clipboard is updated. + /// + public sealed class ClipboardNotification + { + /// + /// Occurs when the contents of the clipboard is updated. + /// + public static event EventHandler ClipboardUpdate; + + private static NotificationForm _form = new NotificationForm(); + + /// + /// Raises the event. + /// + /// Event arguments for the event. + private static void OnClipboardUpdate(EventArgs e) + { + var handler = ClipboardUpdate; + if (handler != null) + { + handler(null, e); + } + } + + /// + /// Hidden form to recieve the WM_CLIPBOARDUPDATE message. + /// + 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); + } + } + } + + internal static 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); + } +} diff --git a/TypeClipboard/Form1.Designer.cs b/TypeClipboard/Form1.Designer.cs index 982080c..f0ebc79 100644 --- a/TypeClipboard/Form1.Designer.cs +++ b/TypeClipboard/Form1.Designer.cs @@ -30,30 +30,44 @@ { this.textBox1 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); + this.chkHotkey = new System.Windows.Forms.CheckBox(); 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(12, 41); + this.chkHotkey.Name = "chkHotkey"; + this.chkHotkey.Size = new System.Drawing.Size(109, 17); + this.chkHotkey.TabIndex = 2; + this.chkHotkey.Text = "Enable F8 hotkey"; + this.chkHotkey.UseVisualStyleBackColor = true; + this.chkHotkey.CheckedChanged += new System.EventHandler(this.chkHotkey_CheckedChanged); + // // Form1 // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.ClientSize = new System.Drawing.Size(317, 44); + this.ClientSize = new System.Drawing.Size(334, 66); + this.Controls.Add(this.chkHotkey); this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; @@ -65,6 +79,8 @@ 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 +92,7 @@ private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Button button1; + private System.Windows.Forms.CheckBox chkHotkey; } } diff --git a/TypeClipboard/Form1.cs b/TypeClipboard/Form1.cs index 966c3e3..0c6328a 100644 --- a/TypeClipboard/Form1.cs +++ b/TypeClipboard/Form1.cs @@ -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,40 @@ namespace TypeClipboard { UpdateTextbox(); } + + private void Form1_Load(object sender, EventArgs e) + { + _listener = new LowLevelKeyboardListener(); + // Changing the Checked property also hooks the listener + chkHotkey.Checked = Properties.Settings.Default.enableHotkey; + + _tc = new Typer(); + + 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(); + } } } diff --git a/TypeClipboard/LowLevelKeyboardListener.cs b/TypeClipboard/LowLevelKeyboardListener.cs new file mode 100644 index 0000000..2ce19dc --- /dev/null +++ b/TypeClipboard/LowLevelKeyboardListener.cs @@ -0,0 +1,118 @@ +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 OnKeyPressed; + + private LowLevelKeyboardProc _proc; + private IntPtr _hookID = IntPtr.Zero; + private Typer _tc = new Typer(); + + public LowLevelKeyboardListener() + { + _proc = HookCallback; + } + + 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; + } + } +} \ No newline at end of file diff --git a/TypeClipboard/Properties/AssemblyInfo.cs b/TypeClipboard/Properties/AssemblyInfo.cs index 262195e..78f52b3 100644 --- a/TypeClipboard/Properties/AssemblyInfo.cs +++ b/TypeClipboard/Properties/AssemblyInfo.cs @@ -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, 2020")] [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.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/TypeClipboard/Properties/Resources.Designer.cs b/TypeClipboard/Properties/Resources.Designer.cs index fdbc03a..d77065e 100644 --- a/TypeClipboard/Properties/Resources.Designer.cs +++ b/TypeClipboard/Properties/Resources.Designer.cs @@ -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 { diff --git a/TypeClipboard/Properties/Settings.Designer.cs b/TypeClipboard/Properties/Settings.Designer.cs index 96328ff..a2feb68 100644 --- a/TypeClipboard/Properties/Settings.Designer.cs +++ b/TypeClipboard/Properties/Settings.Designer.cs @@ -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", "16.5.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,17 @@ namespace TypeClipboard.Properties { return defaultInstance; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool enableHotkey { + get { + return ((bool)(this["enableHotkey"])); + } + set { + this["enableHotkey"] = value; + } + } } } diff --git a/TypeClipboard/Properties/Settings.settings b/TypeClipboard/Properties/Settings.settings index 3964565..cf5bb55 100644 --- a/TypeClipboard/Properties/Settings.settings +++ b/TypeClipboard/Properties/Settings.settings @@ -1,7 +1,9 @@  - - - - - - + + + + + True + + + \ No newline at end of file diff --git a/TypeClipboard/TypeClipboard.csproj b/TypeClipboard/TypeClipboard.csproj index d0d758e..6348097 100644 --- a/TypeClipboard/TypeClipboard.csproj +++ b/TypeClipboard/TypeClipboard.csproj @@ -8,11 +8,26 @@ WinExe TypeClipboard TypeClipboard - v4.6.1 + v4.7.2 512 true true + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.1.0.%2a + false + true AnyCPU @@ -35,6 +50,9 @@ 4 false + + icon.ico + @@ -47,16 +65,20 @@ + + Form Form1.cs + + Form1.cs @@ -83,5 +105,20 @@ + + + + + + False + Microsoft .NET Framework 4.6.1 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + \ No newline at end of file diff --git a/TypeClipboard/Typer.cs b/TypeClipboard/Typer.cs new file mode 100644 index 0000000..43038a8 --- /dev/null +++ b/TypeClipboard/Typer.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace TypeClipboard +{ + class Typer + { + private const int INTERKEY_DELAY = 20; + + public void TypeClipboard(int delay = 2000) + { + if (Clipboard.ContainsText(TextDataFormat.UnicodeText)) + { + String clipboard = Clipboard.GetText(TextDataFormat.UnicodeText); + Thread.Sleep(delay); + 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(INTERKEY_DELAY); + } + } + } + } +} diff --git a/TypeClipboardAppx/Package.appxmanifest b/TypeClipboardAppx/Package.appxmanifest new file mode 100644 index 0000000..8401a2d --- /dev/null +++ b/TypeClipboardAppx/Package.appxmanifest @@ -0,0 +1,48 @@ + + + + + + + + TypeClipboard + Jed Laundry + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TypeClipboardAppx/TypeClipboardAppx.wapproj b/TypeClipboardAppx/TypeClipboardAppx.wapproj new file mode 100644 index 0000000..17bbade --- /dev/null +++ b/TypeClipboardAppx/TypeClipboardAppx.wapproj @@ -0,0 +1,80 @@ + + + + 15.0 + + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + AnyCPU + + + Release + AnyCPU + + + + $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ + + + + 464d3f7b-8eb2-464e-a036-03fe6366c2a3 + 10.0.18362.0 + 10.0.17134.0 + en-US + True + ..\TypeClipboard\TypeClipboard.csproj + 1FE726909EEA4590EFD12ABAF82B374BA7F31A8A + + + + Designer + + + + + + + + + + + + + + + + + \ No newline at end of file