using System; using System.Drawing; using System.Windows.Forms; using System.Collections.Generic; using xServer.Core.Helper; using xServer.Core.Networking; using xServer.Core.Utilities; using xServer.Core.MouseKeyHook; using xServer.Enums; namespace xServer.Forms { //TODO: Fix Alt + Tab public partial class FrmRemoteDesktop : Form { public bool IsStarted { get; private set; } private readonly Client _connectClient; private bool _enableMouseInput; private bool _enableKeyboardInput; private IKeyboardMouseEvents _mEvents; private List _keysPressed; public FrmRemoteDesktop(Client c) { _connectClient = c; _connectClient.Value.FrmRdp = this; if (!PlatformHelper.RunningOnMono) SubscribeWindowsHookEvents(Hook.GlobalEvents()); else SubscribeMonoEvents(); InitializeComponent(); } private void FrmRemoteDesktop_Load(object sender, EventArgs e) { this.Text = WindowHelper.GetWindowTitle("Remote Desktop", _connectClient); panelTop.Left = (this.Width / 2) - (panelTop.Width / 2); btnHide.Left = (panelTop.Width / 2) - (btnHide.Width / 2); btnShow.Location = new Point(377, 0); btnShow.Left = (this.Width / 2) - (btnShow.Width / 2); _keysPressed = new List(); if (_connectClient.Value != null) new Core.Packets.ServerPackets.GetMonitors().Execute(_connectClient); } private void SubscribeWindowsHookEvents(IKeyboardMouseEvents events) { _mEvents = events; _mEvents.MouseWheel += MouseWheelEvent; _mEvents.KeyDown += OnKeyDown; _mEvents.KeyUp += OnKeyUp; } private void SubscribeMonoEvents() { this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FrmRemoteDesktop_KeyDown); this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.FrmRemoteDesktop_KeyUp); } private void UnsubscribeWindowsHookEvents() { if (_mEvents == null) return; _mEvents.MouseWheel -= MouseWheelEvent; _mEvents.KeyDown -= OnKeyDown; _mEvents.KeyUp -= OnKeyUp; } private void UnsubscribeMonoEvents() { this.KeyDown -= new System.Windows.Forms.KeyEventHandler(this.FrmRemoteDesktop_KeyDown); this.KeyUp -= new System.Windows.Forms.KeyEventHandler(this.FrmRemoteDesktop_KeyUp); } public void AddMonitors(int monitors) { try { cbMonitors.Invoke((MethodInvoker)delegate { for (int i = 0; i < monitors; i++) cbMonitors.Items.Add(string.Format("Monitor {0}", i + 1)); cbMonitors.SelectedIndex = 0; }); } catch (InvalidOperationException) { } } public void UpdateImage(Bitmap bmp, bool cloneBitmap = false) { picDesktop.UpdateImage(bmp, cloneBitmap); } private void _frameCounter_FrameUpdated(FrameUpdatedEventArgs e) { try { this.Invoke((MethodInvoker)delegate { this.Text = string.Format("{0} - FPS: {1}", WindowHelper.GetWindowTitle("Remote Desktop", _connectClient), e.CurrentFramesPerSecond.ToString("0.00")); }); } catch (InvalidOperationException) { } } private void ToggleControls(bool t) { IsStarted = !t; try { this.Invoke((MethodInvoker)delegate { btnStart.Enabled = t; btnStop.Enabled = !t; barQuality.Enabled = t; }); } catch (InvalidOperationException) { } } private void FrmRemoteDesktop_FormClosing(object sender, FormClosingEventArgs e) { if (!picDesktop.IsDisposed && !picDesktop.Disposing) picDesktop.Dispose(); if (_connectClient.Value != null) _connectClient.Value.FrmRdp = null; if (!PlatformHelper.RunningOnMono) UnsubscribeWindowsHookEvents(); else UnsubscribeMonoEvents(); } private void FrmRemoteDesktop_Resize(object sender, EventArgs e) { panelTop.Left = (this.Width/2) - (panelTop.Width/2); btnShow.Left = (this.Width/2) - (btnShow.Width/2); } private void btnStart_Click(object sender, EventArgs e) { if (cbMonitors.Items.Count == 0) { MessageBox.Show("No monitor detected.\nPlease wait till the client sends a list with available monitors.", "Starting failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ToggleControls(false); picDesktop.Start(); // Subscribe to the new frame counter. picDesktop.SetFrameUpdatedEvent(_frameCounter_FrameUpdated); this.ActiveControl = picDesktop; new Core.Packets.ServerPackets.GetDesktop(barQuality.Value, cbMonitors.SelectedIndex).Execute(_connectClient); } private void btnStop_Click(object sender, EventArgs e) { ToggleControls(true); picDesktop.Stop(); // Unsubscribe from the frame counter. It will be re-created when starting again. picDesktop.UnsetFrameUpdatedEvent(_frameCounter_FrameUpdated); this.ActiveControl = picDesktop; } private void barQuality_Scroll(object sender, EventArgs e) { int value = barQuality.Value; lblQualityShow.Text = value.ToString(); if (value < 25) lblQualityShow.Text += " (low)"; else if (value >= 85) lblQualityShow.Text += " (best)"; else if (value >= 75) lblQualityShow.Text += " (high)"; else if (value >= 25) lblQualityShow.Text += " (mid)"; this.ActiveControl = picDesktop; } private void btnMouse_Click(object sender, EventArgs e) { if (_enableMouseInput) { this.picDesktop.Cursor = Cursors.Default; btnMouse.Image = Properties.Resources.mouse_delete; toolTipButtons.SetToolTip(btnMouse, "Enable mouse input."); _enableMouseInput = false; } else { this.picDesktop.Cursor = Cursors.Hand; btnMouse.Image = Properties.Resources.mouse_add; toolTipButtons.SetToolTip(btnMouse, "Disable mouse input."); _enableMouseInput = true; } this.ActiveControl = picDesktop; } private void btnKeyboard_Click(object sender, EventArgs e) { if (_enableKeyboardInput) { btnKeyboard.Image = Properties.Resources.keyboard_delete; toolTipButtons.SetToolTip(btnMouse, "Enable keyboard input."); _enableKeyboardInput = false; } else { btnKeyboard.Image = Properties.Resources.keyboard_add; toolTipButtons.SetToolTip(btnMouse, "Disable keyboard input."); _enableKeyboardInput = true; } this.ActiveControl = picDesktop; } private int GetRemoteWidth(int localX) { return localX * picDesktop.ScreenWidth / picDesktop.Width; } private int GetRemoteHeight(int localY) { return localY * picDesktop.ScreenHeight / picDesktop.Height; } private void picDesktop_MouseDown(object sender, MouseEventArgs e) { if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) { int local_x = e.X; int local_y = e.Y; int remote_x = GetRemoteWidth(local_x); int remote_y = GetRemoteHeight(local_y); MouseAction action = MouseAction.None; if (e.Button == MouseButtons.Left) action = MouseAction.LeftDown; if (e.Button == MouseButtons.Right) action = MouseAction.RightDown; int selectedMonitorIndex = cbMonitors.SelectedIndex; if (_connectClient != null) new Core.Packets.ServerPackets.DoMouseEvent(action, true, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); } } private void picDesktop_MouseUp(object sender, MouseEventArgs e) { if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) { int local_x = e.X; int local_y = e.Y; int remote_x = GetRemoteWidth(local_x); int remote_y = GetRemoteHeight(local_y); MouseAction action = MouseAction.None; if (e.Button == MouseButtons.Left) action = MouseAction.LeftDown; if (e.Button == MouseButtons.Right) action = MouseAction.RightDown; int selectedMonitorIndex = cbMonitors.SelectedIndex; if (_connectClient != null) new Core.Packets.ServerPackets.DoMouseEvent(action, false, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); } } private void picDesktop_MouseMove(object sender, MouseEventArgs e) { if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) { int local_x = e.X; int local_y = e.Y; int remote_x = GetRemoteWidth(local_x); int remote_y = GetRemoteHeight(local_y); int selectedMonitorIndex = cbMonitors.SelectedIndex; if (_connectClient != null) new Core.Packets.ServerPackets.DoMouseEvent(MouseAction.MoveCursor, false, remote_x, remote_y, selectedMonitorIndex).Execute(_connectClient); } } private void MouseWheelEvent(object sender, MouseEventArgs e) { if (picDesktop.Image != null && _enableMouseInput && IsStarted && this.ContainsFocus) { if (_connectClient != null) new Core.Packets.ServerPackets.DoMouseEvent(e.Delta == 120 ? MouseAction.ScrollUp : MouseAction.ScrollDown, false, 0, 0, cbMonitors.SelectedIndex).Execute(_connectClient); } } private void OnKeyDown(object sender, KeyEventArgs e) { if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) { e.Handled = true; if (_keysPressed.Contains(e.KeyCode)) return; _keysPressed.Add(e.KeyCode); if (_connectClient != null) new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, true).Execute(_connectClient); } } private void OnKeyUp(object sender, KeyEventArgs e) { if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) { e.Handled = true; _keysPressed.Remove(e.KeyCode); if (_connectClient != null) new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, false).Execute(_connectClient); } } private void FrmRemoteDesktop_KeyDown(object sender, KeyEventArgs e) { if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) { e.Handled = true; if (_keysPressed.Contains(e.KeyCode)) return; _keysPressed.Add(e.KeyCode); if (_connectClient != null) new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, true).Execute(_connectClient); } } private void FrmRemoteDesktop_KeyUp(object sender, KeyEventArgs e) { if (picDesktop.Image != null && _enableKeyboardInput && IsStarted && this.ContainsFocus) { e.Handled = true; _keysPressed.Remove(e.KeyCode); if (_connectClient != null) new Core.Packets.ServerPackets.DoKeyboardEvent((byte)e.KeyCode, false).Execute(_connectClient); } } private void btnHide_Click(object sender, EventArgs e) { panelTop.Visible = false; btnShow.Visible = true; btnHide.Visible = false; this.ActiveControl = picDesktop; } private void btnShow_Click(object sender, EventArgs e) { panelTop.Visible = true; btnShow.Visible = false; btnHide.Visible = true; this.ActiveControl = picDesktop; } } }