0
|
1 ???using System; |
|
2 using System.Collections.Generic; |
|
3 using System.ComponentModel; |
|
4 using System.Drawing; |
|
5 using System.Text; |
|
6 using System.Windows.Forms; |
|
7 using System.Threading; |
|
8 using VirtualBox; |
|
9 |
|
10 namespace ConsoleApplication1 { |
|
11 public partial class Display : Form { |
|
12 public Framebuffer Framebuffer { get; private set; } |
|
13 public IConsole VMConsole { get; private set; } |
|
14 private Point MouseLocation = new Point(0, 0); |
|
15 private VBoxEventListener EventListener = new VBoxEventListener(); |
|
16 private VBoxKeyboardHelper Keyboard; |
|
17 private Size RequestedClientSize = new Size(0, 0); |
|
18 private IProgress WaitingForProgress = null; |
|
19 private Boolean InitialPaused = true; |
|
20 |
|
21 public Display(IConsole console, Framebuffer fb) { |
|
22 VMConsole = console; |
|
23 Framebuffer = fb; |
|
24 Keyboard = new VBoxKeyboardHelper(VMConsole.Keyboard); |
|
25 InitializeComponent(); |
|
26 Framebuffer.BufferChanged += Framebuffer_BufferChanged; |
|
27 Framebuffer.Update += Framebuffer_Update; |
|
28 DisplayBox.Image = Framebuffer.Bitmap; |
|
29 EventListener.HandleEvent += EventListener_HandleEvent; |
|
30 EventListener.RegisterSource(VMConsole.EventSource, VBoxEventType.VBoxEventType_Any); |
|
31 this.MouseWheel += Display_MouseEvent; |
|
32 } |
|
33 |
|
34 private void Display_Load(object sender, EventArgs e) { |
|
35 ClientSize = RequestedClientSize = new Size(800, 600); |
|
36 if (ProgramRun.VBoxXPCOM != null) COMEventTimer.Enabled = true; |
|
37 Framebuffer.WinId = Handle.ToInt64(); |
|
38 } |
|
39 |
|
40 private void EventListener_HandleEvent(Object sender, VBoxEventArgs ea) { |
|
41 IEvent aEvent = ea.Event; |
|
42 switch (aEvent.Type) { |
|
43 case VBoxEventType.VBoxEventType_OnCanShowWindow: { |
|
44 ICanShowWindowEvent e = (ICanShowWindowEvent)aEvent; |
|
45 } break; |
|
46 case VBoxEventType.VBoxEventType_OnEventSourceChanged: |
|
47 break; |
|
48 case VBoxEventType.VBoxEventType_OnStateChanged: { |
|
49 IStateChangedEvent e = (IStateChangedEvent)aEvent; |
|
50 Console.WriteLine("New state: {0}", e.State); |
|
51 switch (e.State) { |
|
52 case MachineState.MachineState_Paused: |
|
53 if (InitialPaused) { |
|
54 InitialPaused = false; |
|
55 ThreadPool.QueueUserWorkItem(delegate(Object state) { |
|
56 VMConsole.Resume(); |
|
57 }); |
|
58 } |
|
59 break; |
|
60 case MachineState.MachineState_Running: |
|
61 ThreadPool.QueueUserWorkItem(delegate(Object state) { |
|
62 try { |
|
63 if (VMConsole.Mouse.AbsoluteSupported == 0 && VMConsole.Mouse.RelativeSupported != 0) { |
|
64 Console.WriteLine("Reset mouse position to {0}", MouseLocation); |
|
65 //MouseLocation = new Point(0, 0); |
|
66 VMConsole.Mouse.PutMouseEvent(-(int)Framebuffer.Width, -(int)Framebuffer.Height, 0, 0, 0); |
|
67 VMConsole.Mouse.PutMouseEvent(MouseLocation.X, MouseLocation.Y, 0, 0, 0); |
|
68 } |
|
69 } catch (Exception ex) { |
|
70 Console.WriteLine(ex.ToString()); |
|
71 } |
|
72 try { |
|
73 VMConsole.Display.InvalidateAndUpdate(); |
|
74 } catch (Exception ex) { |
|
75 Console.WriteLine(ex.ToString()); |
|
76 } |
|
77 }); |
|
78 break; |
|
79 case MachineState.MachineState_Aborted: |
|
80 case MachineState.MachineState_PoweredOff: |
|
81 case MachineState.MachineState_Saved: |
|
82 if (IsHandleCreated) Invoke((MethodInvoker)delegate() { Close(); }); |
|
83 break; |
|
84 } |
|
85 } break; |
|
86 case VBoxEventType.VBoxEventType_OnShowWindow: { |
|
87 IShowWindowEvent e = (IShowWindowEvent)aEvent; |
|
88 e.WinId = Handle.ToInt64(); |
|
89 } break; |
|
90 case VBoxEventType.VBoxEventType_OnKeyboardLedsChanged: { |
|
91 IKeyboardLedsChangedEvent e = (IKeyboardLedsChangedEvent)aEvent; |
|
92 Console.WriteLine("Keyboard leds: Numlock={0} Capslock={1} Scrolllock={2}", e.NumLock, e.CapsLock, e.ScrollLock); |
|
93 } break; |
|
94 case VBoxEventType.VBoxEventType_OnMouseCapabilityChanged: { |
|
95 IMouseCapabilityChangedEvent e = (IMouseCapabilityChangedEvent)aEvent; |
|
96 Console.WriteLine("MouseCapabilityChanged NeedsHostCursor={0} SupportsAbsolute={1} SupportsRelative={2}", e.NeedsHostCursor, e.SupportsAbsolute, e.SupportsRelative); |
|
97 } break; |
|
98 case VBoxEventType.VBoxEventType_OnMousePointerShapeChanged: { |
|
99 IMousePointerShapeChangedEvent e = (IMousePointerShapeChangedEvent)aEvent; |
|
100 } break; |
|
101 case VBoxEventType.VBoxEventType_OnAdditionsStateChanged: { |
|
102 IAdditionsStateChangedEvent e = (IAdditionsStateChangedEvent)aEvent; |
|
103 } break; |
|
104 } |
|
105 } |
|
106 |
|
107 private void COMEventTimer_Tick(object sender, EventArgs e) { |
|
108 ProgramRun.VBoxXPCOM.EventQueue.ProcessPendingEvents(); |
|
109 } |
|
110 |
|
111 private void Display_Resize(object sender, EventArgs e) { |
|
112 if (RequestedClientSize.Equals(ClientSize)) return; |
|
113 if (VMConsole.State != MachineState.MachineState_Running) return; |
|
114 VMConsole.Display.SetVideoModeHint((uint)DisplayBox.Width, (uint)DisplayBox.Height, 0, 0); |
|
115 } |
|
116 |
|
117 private void Framebuffer_BufferChanged(Object sender, EventArgs e) { |
|
118 DisplayBox.Invoke((MethodInvoker)delegate() { |
|
119 Framebuffer fb = (Framebuffer)sender; |
|
120 DisplayBox.Image = fb.Bitmap; |
|
121 if (fb.Width > Screen.FromControl(this).WorkingArea.Width || fb.Height > Screen.FromControl(this).WorkingArea.Height) return; |
|
122 ClientSize = RequestedClientSize = new Size((int)fb.Width + ClientSize.Width - DisplayBox.Width, (int)fb.Height + ClientSize.Height - DisplayBox.Height); |
|
123 }); |
|
124 } |
|
125 |
|
126 private void Framebuffer_Update(Object sender, FramebufferUpdateEventArgs e) { |
|
127 DisplayBox.Invoke((MethodInvoker)delegate() { |
|
128 DisplayBox.Invalidate(e.Rectangle); |
|
129 }); |
|
130 } |
|
131 |
|
132 private void Display_MouseEvent(object sender, MouseEventArgs e) { |
|
133 IMouse mouse = VMConsole.Mouse; |
|
134 MouseButtonState mbs = (MouseButtonState)0; |
|
135 if ((e.Button & MouseButtons.Left) == MouseButtons.Left) mbs |= MouseButtonState.MouseButtonState_LeftButton; |
|
136 if ((e.Button & MouseButtons.Right) == MouseButtons.Right) mbs |= MouseButtonState.MouseButtonState_RightButton; |
|
137 if ((e.Button & MouseButtons.Middle) == MouseButtons.Middle) mbs |= MouseButtonState.MouseButtonState_MiddleButton; |
|
138 if ((e.Button & MouseButtons.XButton1) == MouseButtons.XButton1) mbs |= MouseButtonState.MouseButtonState_XButton1; |
|
139 if ((e.Button & MouseButtons.XButton2) == MouseButtons.XButton2) mbs |= MouseButtonState.MouseButtonState_XButton2; |
|
140 try { |
|
141 //Console.WriteLine("Mouse {0} Scroll {1} Buttons {2}", e.Location, e.Delta, mbs); |
|
142 if (mouse.AbsoluteSupported != 0) { |
|
143 mouse.PutMouseEventAbsolute(e.X + 1, e.Y + 1, -e.Delta / 120, 0, (int)mbs); |
|
144 } else if (mouse.RelativeSupported != 0) { |
|
145 mouse.PutMouseEvent(e.X - MouseLocation.X, e.Y - MouseLocation.Y, -e.Delta / 120, 0, (int)mbs); |
|
146 } |
|
147 MouseLocation = e.Location; |
|
148 } catch (Exception ex) { |
|
149 Console.WriteLine("MouseEventHandler Exception: {0}", ex.ToString()); |
|
150 } |
|
151 } |
|
152 |
|
153 private void Display_KeyDown(object sender, KeyEventArgs e) { |
|
154 Keyboard.SendKeyCode(e.KeyCode, true); |
|
155 } |
|
156 |
|
157 private void Display_KeyUp(object sender, KeyEventArgs e) { |
|
158 Keyboard.SendKeyCode(e.KeyCode, false); |
|
159 } |
|
160 |
|
161 private void pauseToolStripMenuItem_Click(object sender, EventArgs e) { |
|
162 try { |
|
163 VMConsole.Pause(); |
|
164 statusLabel.Text = "Paused"; |
|
165 statusLabel.Visible = true; |
|
166 } catch (Exception ex) { |
|
167 MessageBox.Show(ex.ToString()); |
|
168 } |
|
169 } |
|
170 |
|
171 private void resumeToolStripMenuItem_Click(object sender, EventArgs e) { |
|
172 try { |
|
173 VMConsole.Resume(); |
|
174 if (statusLabel.Text == "Paused") statusLabel.Visible = false; |
|
175 } catch (Exception ex) { |
|
176 MessageBox.Show(ex.ToString()); |
|
177 } |
|
178 } |
|
179 |
|
180 private void savestateToolStripMenuItem_Click(object sender, EventArgs e) { |
|
181 try { |
|
182 MonitorUntilCompleted(VMConsole.SaveState()); |
|
183 } catch (Exception ex) { |
|
184 MessageBox.Show(ex.ToString()); |
|
185 } |
|
186 } |
|
187 |
|
188 private void aCPIPowerButtonToolStripMenuItem_Click(object sender, EventArgs e) { |
|
189 try { |
|
190 VMConsole.PowerButton(); |
|
191 } catch (Exception ex) { |
|
192 MessageBox.Show(ex.ToString()); |
|
193 } |
|
194 } |
|
195 |
|
196 private void powerdownToolStripMenuItem_Click(object sender, EventArgs e) { |
|
197 try { |
|
198 MonitorUntilCompleted(VMConsole.PowerDown()); |
|
199 } catch (Exception ex) { |
|
200 MessageBox.Show(ex.ToString()); |
|
201 } |
|
202 } |
|
203 |
|
204 private void resetToolStripMenuItem_Click(object sender, EventArgs e) { |
|
205 try { |
|
206 VMConsole.Reset(); |
|
207 } catch (Exception ex) { |
|
208 MessageBox.Show(ex.ToString()); |
|
209 } |
|
210 } |
|
211 |
|
212 public void MonitorUntilCompleted(IProgress p) { |
|
213 WaitingForProgress = p; |
|
214 statusLabel.Visible = true; |
|
215 statusLabel.Text = "Busy..."; |
|
216 ProgressWatcher.Enabled = true; |
|
217 } |
|
218 |
|
219 private void ProgressWatcher_Tick(object sender, EventArgs e) { |
|
220 IProgress p = WaitingForProgress; |
|
221 if (p == null) { |
|
222 ProgressWatcher.Enabled = false; |
|
223 statusLabel.Visible = false; |
|
224 } else { |
|
225 if (p.Canceled == 0 && p.Completed == 0) { |
|
226 statusLabel.Text = "Busy " + p.Percent + "%..."; |
|
227 } else if (p.Canceled != 0) { |
|
228 WaitingForProgress = null; |
|
229 statusLabel.Text = "Operation aborted"; |
|
230 } else if (p.Completed != 0) { |
|
231 WaitingForProgress = null; |
|
232 if (p.ErrorInfo == null || p.ErrorInfo.ResultCode == 0) { |
|
233 statusLabel.Text = "Operation completed"; |
|
234 } else { |
|
235 statusLabel.Text = "Operation failed"; |
|
236 MessageBox.Show(p.ErrorInfo.Text, "Operation failed"); |
|
237 if (p.Cancelable != 0) p.Cancel(); |
|
238 } |
|
239 } |
|
240 } |
|
241 } |
|
242 } |
|
243 } |