using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using VirtualBox; namespace ConsoleApplication1 { public partial class Display : Form { public Framebuffer Framebuffer { get; private set; } public IConsole VMConsole { get; private set; } private Point MouseLocation = new Point(0, 0); private VBoxEventListener EventListener = new VBoxEventListener(); private VBoxKeyboardHelper Keyboard; private Size RequestedClientSize = new Size(0, 0); private IProgress WaitingForProgress = null; private Boolean InitialPaused = true; public Display(IConsole console, Framebuffer fb) { VMConsole = console; Framebuffer = fb; Keyboard = new VBoxKeyboardHelper(VMConsole.Keyboard); InitializeComponent(); Framebuffer.BufferChanged += Framebuffer_BufferChanged; Framebuffer.Update += Framebuffer_Update; DisplayBox.Image = Framebuffer.Bitmap; EventListener.HandleEvent += EventListener_HandleEvent; EventListener.RegisterSource(VMConsole.EventSource, VBoxEventType.VBoxEventType_Any); this.MouseWheel += Display_MouseEvent; } private void Display_Load(object sender, EventArgs e) { ClientSize = RequestedClientSize = new Size(800, 600); if (ProgramRun.VBoxXPCOM != null) COMEventTimer.Enabled = true; Framebuffer.WinId = Handle.ToInt64(); } private void EventListener_HandleEvent(Object sender, VBoxEventArgs ea) { IEvent aEvent = ea.Event; switch (aEvent.Type) { case VBoxEventType.VBoxEventType_OnCanShowWindow: { ICanShowWindowEvent e = (ICanShowWindowEvent)aEvent; } break; case VBoxEventType.VBoxEventType_OnEventSourceChanged: break; case VBoxEventType.VBoxEventType_OnStateChanged: { IStateChangedEvent e = (IStateChangedEvent)aEvent; Console.WriteLine("New state: {0}", e.State); switch (e.State) { case MachineState.MachineState_Paused: if (InitialPaused) { InitialPaused = false; ThreadPool.QueueUserWorkItem(delegate(Object state) { VMConsole.Resume(); }); } break; case MachineState.MachineState_Running: ThreadPool.QueueUserWorkItem(delegate(Object state) { try { if (VMConsole.Mouse.AbsoluteSupported == 0 && VMConsole.Mouse.RelativeSupported != 0) { Console.WriteLine("Reset mouse position to {0}", MouseLocation); //MouseLocation = new Point(0, 0); VMConsole.Mouse.PutMouseEvent(-(int)Framebuffer.Width, -(int)Framebuffer.Height, 0, 0, 0); VMConsole.Mouse.PutMouseEvent(MouseLocation.X, MouseLocation.Y, 0, 0, 0); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } try { VMConsole.Display.InvalidateAndUpdate(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }); break; case MachineState.MachineState_Aborted: case MachineState.MachineState_PoweredOff: case MachineState.MachineState_Saved: if (IsHandleCreated) Invoke((MethodInvoker)delegate() { Close(); }); break; } } break; case VBoxEventType.VBoxEventType_OnShowWindow: { IShowWindowEvent e = (IShowWindowEvent)aEvent; e.WinId = Handle.ToInt64(); } break; case VBoxEventType.VBoxEventType_OnKeyboardLedsChanged: { IKeyboardLedsChangedEvent e = (IKeyboardLedsChangedEvent)aEvent; Console.WriteLine("Keyboard leds: Numlock={0} Capslock={1} Scrolllock={2}", e.NumLock, e.CapsLock, e.ScrollLock); } break; case VBoxEventType.VBoxEventType_OnMouseCapabilityChanged: { IMouseCapabilityChangedEvent e = (IMouseCapabilityChangedEvent)aEvent; Console.WriteLine("MouseCapabilityChanged NeedsHostCursor={0} SupportsAbsolute={1} SupportsRelative={2}", e.NeedsHostCursor, e.SupportsAbsolute, e.SupportsRelative); } break; case VBoxEventType.VBoxEventType_OnMousePointerShapeChanged: { IMousePointerShapeChangedEvent e = (IMousePointerShapeChangedEvent)aEvent; } break; case VBoxEventType.VBoxEventType_OnAdditionsStateChanged: { IAdditionsStateChangedEvent e = (IAdditionsStateChangedEvent)aEvent; } break; } } private void COMEventTimer_Tick(object sender, EventArgs e) { ProgramRun.VBoxXPCOM.EventQueue.ProcessPendingEvents(); } private void Display_Resize(object sender, EventArgs e) { if (RequestedClientSize.Equals(ClientSize)) return; if (VMConsole.State != MachineState.MachineState_Running) return; VMConsole.Display.SetVideoModeHint((uint)DisplayBox.Width, (uint)DisplayBox.Height, 0, 0); } private void Framebuffer_BufferChanged(Object sender, EventArgs e) { DisplayBox.Invoke((MethodInvoker)delegate() { Framebuffer fb = (Framebuffer)sender; DisplayBox.Image = fb.Bitmap; if (fb.Width > Screen.FromControl(this).WorkingArea.Width || fb.Height > Screen.FromControl(this).WorkingArea.Height) return; ClientSize = RequestedClientSize = new Size((int)fb.Width + ClientSize.Width - DisplayBox.Width, (int)fb.Height + ClientSize.Height - DisplayBox.Height); }); } private void Framebuffer_Update(Object sender, FramebufferUpdateEventArgs e) { DisplayBox.Invoke((MethodInvoker)delegate() { DisplayBox.Invalidate(e.Rectangle); }); } private void Display_MouseEvent(object sender, MouseEventArgs e) { IMouse mouse = VMConsole.Mouse; MouseButtonState mbs = (MouseButtonState)0; if ((e.Button & MouseButtons.Left) == MouseButtons.Left) mbs |= MouseButtonState.MouseButtonState_LeftButton; if ((e.Button & MouseButtons.Right) == MouseButtons.Right) mbs |= MouseButtonState.MouseButtonState_RightButton; if ((e.Button & MouseButtons.Middle) == MouseButtons.Middle) mbs |= MouseButtonState.MouseButtonState_MiddleButton; if ((e.Button & MouseButtons.XButton1) == MouseButtons.XButton1) mbs |= MouseButtonState.MouseButtonState_XButton1; if ((e.Button & MouseButtons.XButton2) == MouseButtons.XButton2) mbs |= MouseButtonState.MouseButtonState_XButton2; try { //Console.WriteLine("Mouse {0} Scroll {1} Buttons {2}", e.Location, e.Delta, mbs); if (mouse.AbsoluteSupported != 0) { mouse.PutMouseEventAbsolute(e.X + 1, e.Y + 1, -e.Delta / 120, 0, (int)mbs); } else if (mouse.RelativeSupported != 0) { mouse.PutMouseEvent(e.X - MouseLocation.X, e.Y - MouseLocation.Y, -e.Delta / 120, 0, (int)mbs); } MouseLocation = e.Location; } catch (Exception ex) { Console.WriteLine("MouseEventHandler Exception: {0}", ex.ToString()); } } private void Display_KeyDown(object sender, KeyEventArgs e) { Keyboard.SendKeyCode(e.KeyCode, true); } private void Display_KeyUp(object sender, KeyEventArgs e) { Keyboard.SendKeyCode(e.KeyCode, false); } private void pauseToolStripMenuItem_Click(object sender, EventArgs e) { try { VMConsole.Pause(); statusLabel.Text = "Paused"; statusLabel.Visible = true; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void resumeToolStripMenuItem_Click(object sender, EventArgs e) { try { VMConsole.Resume(); if (statusLabel.Text == "Paused") statusLabel.Visible = false; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void savestateToolStripMenuItem_Click(object sender, EventArgs e) { try { MonitorUntilCompleted(VMConsole.SaveState()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void aCPIPowerButtonToolStripMenuItem_Click(object sender, EventArgs e) { try { VMConsole.PowerButton(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void powerdownToolStripMenuItem_Click(object sender, EventArgs e) { try { MonitorUntilCompleted(VMConsole.PowerDown()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void resetToolStripMenuItem_Click(object sender, EventArgs e) { try { VMConsole.Reset(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public void MonitorUntilCompleted(IProgress p) { WaitingForProgress = p; statusLabel.Visible = true; statusLabel.Text = "Busy..."; ProgressWatcher.Enabled = true; } private void ProgressWatcher_Tick(object sender, EventArgs e) { IProgress p = WaitingForProgress; if (p == null) { ProgressWatcher.Enabled = false; statusLabel.Visible = false; } else { if (p.Canceled == 0 && p.Completed == 0) { statusLabel.Text = "Busy " + p.Percent + "%..."; } else if (p.Canceled != 0) { WaitingForProgress = null; statusLabel.Text = "Operation aborted"; } else if (p.Completed != 0) { WaitingForProgress = null; if (p.ErrorInfo == null || p.ErrorInfo.ResultCode == 0) { statusLabel.Text = "Operation completed"; } else { statusLabel.Text = "Operation failed"; MessageBox.Show(p.ErrorInfo.Text, "Operation failed"); if (p.Cancelable != 0) p.Cancel(); } } } } } }