1
0
mirror of https://github.com/Ylianst/MeshCentralRouter synced 2025-12-06 00:13:33 +00:00
Files
MeshCentralRouter/KVMControl.cs
2021-06-25 14:02:37 -07:00

743 lines
32 KiB
C#

/*
Copyright 2009-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
namespace MeshCentralRouter
{
public partial class KVMControl : UserControl
{
private bool remotepause = true;
private Bitmap desktop = null;
private Graphics desktopGraphics = null;
public uint screenWidth = 0;
public uint screenHeight = 0;
private Pen RedPen = new Pen(System.Drawing.Color.Red);
private Font DebugFont = new Font(FontFamily.GenericSansSerif, 14);
private int compressionlevel = 60; // 60% compression
private int scalinglevel = 1024; // 100% scale
private int frameRate = 100; // Medium frame rate
private bool swamMouseButtons = false;
private bool remoteKeyboardMap = false;
private bool autoSendClipboard = false;
private double scalefactor = 1;
public List<ushort> displays = new List<ushort>();
public ushort currentDisp = 0;
public bool MouseButtonLeft = false;
public bool MouseButtonMiddle = false;
public bool MouseButtonRight = false;
public double DpiX = 96;
public double DpiY = 96;
public KVMViewer parent = null;
private readonly KVMControlHook ControlHook;
private readonly KVMControlHook.KVMCallback KeyboardCallback;
private bool isHookWanted;
private bool isHookPriority;
private bool keyboardIsAttached;
private long killNextKeyPress = 0;
private enum KvmCommands
{
Nop = 0,
Key = 1,
Mouse = 2,
Picture = 3,
Copy = 4,
Compression = 5,
Refresh = 6,
Screen = 7,
Pause = 8,
TerminalText = 9,
CtrlAltDel = 10,
GetDisplays = 11,
SetDisplay = 12,
FrameRateTimer = 13,
InitTouch = 14,
Touch = 15,
Message = 16,
Jumbo = 27,
Disconnect = 59,
Alert = 65,
KeyUnicode = 85,
MouseCursor = 88
}
private enum KvmMouseButtonCommands
{
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEUP = 0x0040
}
[Category("Action")]
[Description("Fires when the remote desktop size changes.")]
public event EventHandler DesktopSizeChanged;
[Category("Action")]
[Description("Fires when it receives the display list.")]
public event EventHandler DisplaysReceived;
public enum ConnectState
{
Disconnected,
Connecting,
Connected
}
public int CompressionLevel { get { return compressionlevel; } set { compressionlevel = value; SendCompressionLevel(); } }
public int ScalingLevel { get { return scalinglevel; } set { scalinglevel = value; SendCompressionLevel(); } }
public int FrameRate { get { return frameRate; } set { frameRate = value; SendCompressionLevel(); } }
public bool SwamMouseButtons { get { return swamMouseButtons; } set { swamMouseButtons = value; } }
public bool RemoteKeyboardMap { get { return remoteKeyboardMap; } set { remoteKeyboardMap = value; } }
public bool AutoSendClipboard { get { return autoSendClipboard; } set { autoSendClipboard = value; } }
public double ScaleFactor { get { return scalefactor; } set { scalefactor = value; } }
public void SetCompressionParams(int level, int scaling, int framerate) { compressionlevel = level; scalinglevel = scaling; frameRate = framerate; SendCompressionLevel(); }
public int DesktopWidth { get { return (int)screenWidth; } }
public int DesktopHeight { get { return (int)screenHeight; } }
// Debug
public int bytesent = 0;
public int byterecv = 0;
public int tilecount = 0;
public int tilecopy = 0;
public bool debugmode = false;
public KVMControl()
{
InitializeComponent();
this.SetStyle(ControlStyles.Selectable, false);
this.SetStyle(ControlStyles.UserMouse, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.MouseWheel += new System.Windows.Forms.MouseEventHandler(KVMControl_MouseWheel);
if (Settings.GetRegValue("Exp_KeyboardHook", false))
{
ControlHook = new KVMControlHook();
KeyboardCallback = SendKey;
isHookWanted = true;
}
else
{
isHookWanted = false;
}
isHookPriority = Settings.GetRegValue("Exp_KeyboardHookPriority", false);
}
public void AttachKeyboard()
{
Console.WriteLine(isHookWanted);
if (!keyboardIsAttached && isHookWanted)
{
ControlHook.AttachKeyboardHook(SendKey);
keyboardIsAttached = true;
}
}
public void DetacheKeyboard()
{
if (keyboardIsAttached)
{
ControlHook.DetachKeyboardHook();
keyboardIsAttached = false;
}
}
public int ProcessData(byte[] buffer, int off, int len)
{
//Console.Write("ProcessData " + off + ", " + len + "\r\n");
int jumboHeaderSize = 0;
if (len == 0) return 0;
if (len >= 4)
{
// Decode the command header
KvmCommands btype = (KvmCommands)((buffer[off] << 8) + buffer[off + 1]);
int blen = (buffer[off + 2] << 8) + buffer[off + 3];
if (len < blen) return 0;
// Handle JUMBO command
if ((btype == KvmCommands.Jumbo) && (blen == 8))
{
jumboHeaderSize = 8;
blen = (int)IPAddress.NetworkToHostOrder((int)BitConverter.ToUInt32(buffer, off + 4));
off += 8;
btype = (KvmCommands)((buffer[off] << 8) + buffer[off + 1]);
}
// Process the command
switch (btype)
{
case KvmCommands.Screen:
{
if (blen != 8) return blen;
uint w = (ushort)((buffer[off + 4] << 8) + buffer[off + 5]);
uint h = (ushort)((buffer[off + 6] << 8) + buffer[off + 7]);
if (screenWidth == w && screenHeight == h) break;
screenWidth = w;
screenHeight = h;
desktop = new Bitmap((int)screenWidth, (int)screenHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
desktopGraphics = Graphics.FromImage(desktop);
SendCompressionLevel();
Invoke(new SetSizeHandler(SetSize));
SendPause(false);
//SendMouse(2, KvmMouseButtonCommands.MOUSEEVENTF_LEFTUP);
//SendMouse(2, KvmMouseButtonCommands.MOUSEEVENTF_MIDDLEUP);
//SendMouse(2, KvmMouseButtonCommands.MOUSEEVENTF_RIGHTUP);
return blen + jumboHeaderSize;
}
case KvmCommands.Picture:
{
Image newtile;
ushort tile_x = (ushort)((buffer[off + 4] << 8) + buffer[off + 5]);
ushort tile_y = (ushort)((buffer[off + 6] << 8) + buffer[off + 7]);
try { newtile = Image.FromStream(new System.IO.MemoryStream(buffer, off + 8, blen - 8)); } catch (Exception) { return blen; }
Rectangle r = new Rectangle((int)tile_x, (int)tile_y, newtile.Width, newtile.Height);
Rectangle r3 = new Rectangle((int)((double)tile_x / (double)scalefactor) - 2, (int)((double)tile_y / (double)scalefactor) - 2, (int)((double)newtile.Width / (double)scalefactor) + 4, (int)((double)newtile.Height / (double)scalefactor) + 4);
tilecount++;
// Winform mode
if (desktop != null)
{
lock (desktop)
{
desktopGraphics.DrawImage(newtile, new Rectangle((int)tile_x, (int)tile_y, newtile.Width, newtile.Height), new Rectangle(0, 0, newtile.Width, newtile.Height), GraphicsUnit.Pixel);
if (debugmode)
{
desktopGraphics.DrawRectangle(RedPen, new Rectangle((int)tile_x, (int)tile_y, newtile.Width - 1, newtile.Height - 1));
desktopGraphics.DrawString(string.Format("{0} / {1}kb", tilecount, blen / 2014), DebugFont, RedPen.Brush, new Point((int)tile_x, (int)tile_y));
}
}
if (scalefactor == 1) Invalidate(r, false); else Invalidate(r3, false);
}
return blen + jumboHeaderSize;
}
case KvmCommands.Copy:
{
ushort sourcex = (ushort)((buffer[off + 4] << 8) + buffer[off + 5]);
ushort sourcey = (ushort)((buffer[off + 6] << 8) + buffer[off + 7]);
ushort targetx = (ushort)((buffer[off + 8] << 8) + buffer[off + 9]);
ushort targety = (ushort)((buffer[off + 10] << 8) + buffer[off + 11]);
ushort tilew = (ushort)((buffer[off + 12] << 8) + buffer[off + 13]);
ushort tileh = (ushort)((buffer[off + 14] << 8) + buffer[off + 15]);
Rectangle r1 = new Rectangle((int)sourcex, (int)sourcey, (int)tilew, (int)tileh);
Rectangle r2 = new Rectangle((int)targetx, (int)targety, (int)tilew, (int)tileh);
Rectangle r3 = new Rectangle((int)((double)targetx / (double)scalefactor) - 2, (int)((double)targety / (double)scalefactor) - 2, (int)((double)tilew / (double)scalefactor) + 4, (int)((double)tileh / (double)scalefactor) + 4);
// WinForm mode
if (desktop != null)
{
lock (desktop)
{
Bitmap bmp = new Bitmap(tilew, tileh);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(desktop, 0, 0, r1, GraphicsUnit.Pixel);
g.Dispose();
desktopGraphics.Flush();
desktopGraphics.DrawImage(bmp, r2, 0, 0, tilew, tileh, GraphicsUnit.Pixel);
if (debugmode) { desktopGraphics.DrawString("COPY", DebugFont, RedPen.Brush, new Point((int)targetx, (int)targety + 20)); }
}
tilecopy++;
}
return blen + jumboHeaderSize;
}
case KvmCommands.GetDisplays:
{
int i = 0;
ushort length = (ushort)((buffer[off + 4] << 8) + buffer[off + 5]);
displays.Clear();
if (length > 0) { for (i = 0; i < length; i++) { displays.Add((ushort)((buffer[off + 6 + i * 2] << 8) + buffer[off + 7 + i * 2])); } }
currentDisp = (ushort)((buffer[off + 6 + i * 2] << 8) + buffer[off + 7 + i * 2]);
if (DisplaysReceived != null) DisplaysReceived(this, null);
break;
}
case KvmCommands.SetDisplay:
{
currentDisp = (ushort)((buffer[off + 4] << 8) + buffer[off + 5]);
break;
}
case KvmCommands.MouseCursor:
{
if (blen != 5) return blen;
ChangeMouseCursor(buffer[off + 4]);
break;
}
default:
{
// MessageBox.Show("Should never happen!");
//Disconnect();
return 0;
}
}
return blen + jumboHeaderSize;
}
return 0;
}
private delegate void ChangeMouseCursorHandler(int cursorId);
private void ChangeMouseCursor(int cursorId)
{
if (this.InvokeRequired) { this.Invoke(new ChangeMouseCursorHandler(ChangeMouseCursor), cursorId); return; }
if (cursorId == 0) { this.Cursor = System.Windows.Forms.Cursors.Default; return; } // default
if (cursorId == 1) { this.Cursor = System.Windows.Forms.Cursors.AppStarting; return; } // progress
if (cursorId == 2) { this.Cursor = System.Windows.Forms.Cursors.Cross; return; } // crosshair
if (cursorId == 3) { this.Cursor = System.Windows.Forms.Cursors.Default; return; } // pointer
if (cursorId == 4) { this.Cursor = System.Windows.Forms.Cursors.Help; return; } // help
if (cursorId == 5) { this.Cursor = System.Windows.Forms.Cursors.IBeam; return; } // text
if (cursorId == 6) { this.Cursor = System.Windows.Forms.Cursors.No; return; } // no-drop
if (cursorId == 7) { this.Cursor = System.Windows.Forms.Cursors.Arrow; return; } // move
if (cursorId == 8) { this.Cursor = System.Windows.Forms.Cursors.SizeNESW; return; } // nesw-resize
if (cursorId == 9) { this.Cursor = System.Windows.Forms.Cursors.SizeNS; return; } // ns-resize
if (cursorId == 10) { this.Cursor = System.Windows.Forms.Cursors.SizeNWSE; return; } // nwse-resize
if (cursorId == 11) { this.Cursor = System.Windows.Forms.Cursors.SizeWE; return; } // w-resize
if (cursorId == 12) { this.Cursor = System.Windows.Forms.Cursors.Arrow; return; } // alias
if (cursorId == 13) { this.Cursor = System.Windows.Forms.Cursors.WaitCursor; return; } // wait
if (cursorId == 14) { this.Cursor = System.Windows.Forms.Cursors.Default; return; } // none
if (cursorId == 15) { this.Cursor = System.Windows.Forms.Cursors.No; return; } // not-allowed
if (cursorId == 16) { this.Cursor = System.Windows.Forms.Cursors.VSplit; return; } // col-resize
if (cursorId == 17) { this.Cursor = System.Windows.Forms.Cursors.HSplit; return; } // row-resize
if (cursorId == 18) { this.Cursor = System.Windows.Forms.Cursors.Default; return; } // copy
if (cursorId == 19) { this.Cursor = System.Windows.Forms.Cursors.SizeAll; return; } // zoom-in
if (cursorId == 20) { this.Cursor = System.Windows.Forms.Cursors.SizeAll; return; } // zoom-out
}
public void Repaint(Region region)
{
Invalidate(region);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Do not paint background.
}
private delegate void SetSizeHandler();
private void SetSize()
{
if (DesktopSizeChanged != null) { DesktopSizeChanged(this, null); }
}
private void KVMControl_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
if (desktop == null)
{
g.FillRectangle(new SolidBrush(Color.Black), e.ClipRectangle);
}
else
{
lock (desktop)
{
if (scalefactor == 1)
{
g.DrawImage(desktop, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
}
else
{
//g.DrawImage((Image)desktop, new Rectangle(0, 0, Width, Height), 0, 0, screenWidth, screenHeight, GraphicsUnit.Pixel);
g.DrawImage((Image)desktop, e.ClipRectangle, (int)((double)e.ClipRectangle.Left * (double)scalefactor), (int)((double)e.ClipRectangle.Top * (double)scalefactor), (int)((double)e.ClipRectangle.Width * (double)scalefactor), (int)((double)e.ClipRectangle.Height * (double)scalefactor), GraphicsUnit.Pixel);
}
}
}
}
public void SendKey(byte key, byte action)
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Key));
bw.Write(IPAddress.HostToNetworkOrder((short)6));
bw.Write((byte)action);
bw.Write((byte)key);
Send(bw);
}
public void SendUnicodeKey(ushort key, byte action)
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.KeyUnicode));
bw.Write(IPAddress.HostToNetworkOrder((short)7));
bw.Write((byte)action);
bw.Write((byte)(key >> 8));
bw.Write((byte)(key & 0xFF));
Send(bw);
}
private void SendPress(KeyPressEventArgs e, byte action)
{
//if (state != ConnectState.Connected) return;
if (remoteKeyboardMap == true) return;
if (killNextKeyPress > 0)
{
long t = DateTime.Now.Ticks;
if ((t - killNextKeyPress) < 10) { killNextKeyPress = 0; return; }
}
ushort c = (ushort)e.KeyChar;
if (c < 32)
{
SendKey((byte)c, 0);
}
else
{
SendUnicodeKey(c, 0);
}
}
private void SendKey(KeyEventArgs e, byte action)
{
//if (state != ConnectState.Connected) return;
if (remoteKeyboardMap == true) { SendKey((byte)e.KeyCode, action); return; } // Use old key system that uses the remote keyboard mapping.
string keycode = e.KeyCode.ToString();
if ((action == 0) && (e.Control == false) && (e.Alt == false) && (((e.KeyValue >= 48) && (e.KeyValue <= 57)) || (keycode.Length == 1) || (keycode.StartsWith("Oem") == true))) return;
if ((e.Control == true) || (e.Alt == true)) { killNextKeyPress = DateTime.Now.Ticks; }
SendKey((byte)e.KeyCode, action);
e.Handled = true;
}
private short LastX = 0;
private short LastY = 0;
private void SendMouse(MouseEventArgs e, byte action)
{
//if (state != ConnectState.Connected) return;
byte buttons = 0;
if (action == 1)
{
switch (e.Button)
{
case MouseButtons.Left:
if (swamMouseButtons)
{
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_RIGHTDOWN;
}
else
{
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_LEFTDOWN;
}
break;
case MouseButtons.Right:
if (swamMouseButtons)
{
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_LEFTDOWN;
}
else
{
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_RIGHTDOWN;
}
break;
case MouseButtons.Middle:
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_MIDDLEDOWN;
break;
}
}
else if (action == 2)
{
switch (e.Button)
{
case MouseButtons.Left:
if (swamMouseButtons) { buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_RIGHTUP; } else { buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_LEFTUP; }
break;
case MouseButtons.Right:
if (swamMouseButtons) { buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_LEFTUP; } else { buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_RIGHTUP; }
break;
case MouseButtons.Middle:
buttons |= (byte)KvmMouseButtonCommands.MOUSEEVENTF_MIDDLEUP;
break;
}
}
LastX = (short)((double)e.X * (double)scalefactor);
LastY = (short)((double)e.Y * (double)scalefactor);
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Mouse));
bw.Write(IPAddress.HostToNetworkOrder((short)(e.Delta == 0 ? 10 : 12)));
bw.Write((byte)action);
bw.Write((byte)buttons);
bw.Write(IPAddress.HostToNetworkOrder(LastX));
bw.Write(IPAddress.HostToNetworkOrder(LastY));
if (e.Delta != 0) { bw.Write(IPAddress.HostToNetworkOrder((short)e.Delta)); }
Send(bw);
}
public void SendMouseWheel(MouseEventArgs e, byte action)
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Mouse));
bw.Write(IPAddress.HostToNetworkOrder((short)(e.Delta == 0 ? 10 : 12)));
bw.Write((short)0);
bw.Write(IPAddress.HostToNetworkOrder(LastX));
bw.Write(IPAddress.HostToNetworkOrder(LastY));
if (e.Delta != 0) { bw.Write(IPAddress.HostToNetworkOrder((short)e.Delta)); }
Send(bw);
}
private void SendMouse(byte action, KvmMouseButtonCommands buttons)
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Mouse));
bw.Write(IPAddress.HostToNetworkOrder((short)10));
bw.Write((byte)action);
bw.Write((byte)buttons);
bw.Write((short)0);
bw.Write((short)0);
Send(bw);
}
public void SendCompressionLevel()
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Compression));
bw.Write(IPAddress.HostToNetworkOrder((short)10));
bw.Write((byte)1); // Image Type (Reserved, 1 = JPEG)
bw.Write((byte)compressionlevel); // Compression Level
bw.Write(IPAddress.HostToNetworkOrder((short)scalinglevel)); // Scaling
bw.Write(IPAddress.HostToNetworkOrder((short)frameRate)); // Frame Rate
Send(bw);
}
public void SendRefresh()
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Refresh));
bw.Write(IPAddress.HostToNetworkOrder((short)4));
Send(bw);
}
public void SendPause(bool paused)
{
//if (remotepauseactive == false || paused == remotepause) return;
//if (paused == remotepause) return;
remotepause = paused;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.Pause));
bw.Write(IPAddress.HostToNetworkOrder((short)5));
bw.Write(paused ? (byte)1 : (byte)0);
Send(bw);
}
public void Send(byte[] buffer)
{
//if (state == ConnectState.Disconnected) return;
try
{
parent.bytesOut += buffer.Length;
parent.bytesOutCompressed += parent.wc.SendBinary(buffer, 0, buffer.Length);
bytesent += buffer.Length;
}
catch (Exception) { }
}
public void Send(string str)
{
//if (state == ConnectState.Disconnected) return;
try
{
parent.bytesOut += str.Length;
parent.bytesOutCompressed += parent.wc.SendString(str);
bytesent += str.Length;
}
catch (Exception) { }
}
public void Send(BinaryWriter bw)
{
//if (state == ConnectState.Disconnected) { RecycleBinaryWriter(bw); return; }
if ((parent != null) && (parent.wc != null))
{
try
{
parent.bytesOut += (int)((MemoryStream)bw.BaseStream).Length;
parent.bytesOutCompressed += parent.wc.SendBinary(((MemoryStream)bw.BaseStream).GetBuffer(), 0, (int)((MemoryStream)bw.BaseStream).Length);
bytesent += (int)((MemoryStream)bw.BaseStream).Length;
}
catch (Exception) { }
}
RecycleBinaryWriter(bw);
}
private void KVMControl_MouseDown(object sender, MouseEventArgs e)
{
SendMouse(e, 1);
}
private void KVMControl_MouseUp(object sender, MouseEventArgs e)
{
SendMouse(e, 2);
}
long lastMouseMove = 0;
private void KVMControl_MouseMove(object sender, MouseEventArgs e)
{
long ct = DateTime.Now.Ticks;
if ((lastMouseMove + 30) < ct)
{
lastMouseMove = ct;
SendMouse(e, 0);
}
}
public void KVMControl_MouseWheel(object sender, MouseEventArgs e)
{
SendMouse(e, 0);
}
private void KVMControl_MouseEnter(object sender, EventArgs e)
{
this.Focus();
}
public void SendCtrlAltDel()
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.CtrlAltDel));
bw.Write(IPAddress.HostToNetworkOrder((short)4));
Send(bw);
}
public void GetDisplayNumbers()
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.GetDisplays));
bw.Write(IPAddress.HostToNetworkOrder((short)4));
Send(bw);
}
public void SendDisplay(int dispNo)
{
//if (state != ConnectState.Connected) return;
BinaryWriter bw = GetBinaryWriter();
bw.Write(IPAddress.HostToNetworkOrder((short)KvmCommands.SetDisplay));
bw.Write(IPAddress.HostToNetworkOrder((short)6));
bw.Write(IPAddress.HostToNetworkOrder((short)dispNo));
Send(bw);
}
public void SendCharmsKey()
{
SendKey(0x5B, 4); // Windows key down
SendKey(67, 1); // C down
SendKey(67, 2); // C up
SendKey(0x5B, 3); // Windows key up
}
// BinaryWriter Object Recycling System
private static Stack<BinaryWriter> BinaryWriteRecycleList = new Stack<BinaryWriter>();
public static BinaryWriter GetBinaryWriter() { lock (BinaryWriteRecycleList) { return (BinaryWriteRecycleList.Count == 0) ? new BinaryWriter(new MemoryStream(32000), Encoding.UTF8) : BinaryWriteRecycleList.Pop(); } }
public static void RecycleBinaryWriter(BinaryWriter obj) { lock (BinaryWriteRecycleList) { ((MemoryStream)obj.BaseStream).SetLength(0); BinaryWriteRecycleList.Push(obj); } }
// MemoryStream Object Recycling System
private static Stack<MemoryStream> MemoryStreamRecycleList = new Stack<MemoryStream>();
public static MemoryStream GetMemoryStream() { lock (MemoryStreamRecycleList) { return (MemoryStreamRecycleList.Count == 0) ? new MemoryStream(32000) : MemoryStreamRecycleList.Pop(); } }
public static void RecycleMemoryStream(MemoryStream obj) { lock (MemoryStreamRecycleList) { obj.SetLength(0); MemoryStreamRecycleList.Push(obj); } }
// StringBuilder Object Recycling System
private static Stack<StringBuilder> StringBuilderRecycleList = new Stack<StringBuilder>();
public static StringBuilder GetStringBuilder() { lock (StringBuilderRecycleList) { return (StringBuilderRecycleList.Count == 0) ? new StringBuilder(16000) : StringBuilderRecycleList.Pop(); } }
public static void RecycleStringBuilder(StringBuilder obj) { lock (StringBuilderRecycleList) { obj.Length = 0; StringBuilderRecycleList.Push(obj); } }
// byte[] Object Recycling System
private static Stack<byte[]> ByteArrayRecycleList = new Stack<byte[]>();
private static int ByteArrayRecycleListCount = 0;
public static byte[] GetByteArray() { lock (ByteArrayRecycleList) { if (ByteArrayRecycleList.Count == 0) ByteArrayRecycleListCount++; return (ByteArrayRecycleList.Count == 0) ? new byte[65535] : ByteArrayRecycleList.Pop(); } }
public static void RecycleByteArray(byte[] obj) { lock (ByteArrayRecycleList) { if (obj != null) ByteArrayRecycleList.Push(obj); } }
private void KVMControl_KeyDown(object sender, KeyEventArgs e)
{
if (!isHookPriority)
{
if ((e.KeyCode == Keys.LWin) || (e.KeyCode == Keys.RWin)) return; // Don't process the Windows key
SendKey(e, 0);
e.Handled = true;
}
}
private void KVMControl_KeyPress(object sender, KeyPressEventArgs e)
{
if (!isHookPriority)
{
SendPress(e, 0);
e.Handled = true;
}
}
private void KVMControl_KeyUp(object sender, KeyEventArgs e)
{
if (!isHookPriority)
{
SendKey(e, 1);
e.Handled = true;
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;
// Tab keys
if (msg.Msg == WM_KEYDOWN && msg.WParam.ToInt32() == 9)
{
SendKey((byte)msg.WParam.ToInt32(), 0);
return true;
}
// Handle arrow keys
if (((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) && msg.WParam.ToInt32() >= 37 && msg.WParam.ToInt32() <= 40)
{
SendKey((byte)msg.WParam.ToInt32(), 0);
return true;
}
return false;
}
}
}