public MainWindow() { InitializeComponent(); MouseMoveThrottleTimer.Start(); MousePointer.Source = GetMousePointerImage(); RealtimeService = new UdpRealtimeService(Channel); ScreenshotService = new ScreenshotService(); RealtimeService.ClientResolutionChanged += (o, e) => { var ea = e as ClientResolutionChangedEventArgs; if (ea?.ScreenWidth == 0 || ea?.ScreenHeight == 0) return; ScreenshotService.SetBitmapSize(ea.ScreenWidth, ea.ScreenHeight); }; Closing += async (o, e) => { await RealtimeService.EndConnection(Channel); }; Timer imageTimer = new Timer(ImageTimerTick); imageTimer.Elapsed += (s, e) => { try { Application.Current.Dispatcher.Invoke(() => { var images = RealtimeService.CompletedImages.ToList(); if (!images.Any()) return; var source = ScreenshotService.ProcessBitmaps(images); Screenshot.Source = source; }); } catch (Exception ex) { Console.WriteLine(ex.Message); } }; imageTimer.Start(); RealtimeService.Disconnect += (s, reconnect) => { if (reconnect) { Task.Run(async () => { await RealtimeService.StartConnection(Channel, ScreenshotService.ScreenWidth, ScreenshotService.ScreenHeight); }); } }; RealtimeService.MouseMove += (o, e) => { if (MouseMoveThrottleTimer.ElapsedMilliseconds < MouseMoveThrottle) return; MouseMoveThrottleTimer.Restart(); var ea = e as MouseMoveEventArgs; if (ea == null) return; Application.Current.Dispatcher.Invoke(() => { if (!Screenshot.IsInitialized) return; double tx = Screenshot.ActualWidth / ea.ScreenWidth; double ty = Screenshot.ActualHeight / ea.ScreenHeight; double x = ((double)ea.X * tx - (double)Screenshot.ActualWidth / 2) + 5; double y = ((double)ea.Y * ty - (double)Screenshot.ActualHeight / 2) + 9; if (!MousePointer.IsVisible) MousePointer.Visibility = Visibility.Visible; TranslateTransform trans = new TranslateTransform(); MousePointer.RenderTransform = trans; DoubleAnimation anim1 = new DoubleAnimation(LastPoint.Y, y, TimeSpan.FromMilliseconds(100)); DoubleAnimation anim2 = new DoubleAnimation(LastPoint.X, x, TimeSpan.FromMilliseconds(100)); trans.BeginAnimation(TranslateTransform.YProperty, anim1); trans.BeginAnimation(TranslateTransform.XProperty, anim2); LastPoint = new System.Windows.Point(x, y); }); }; RealtimeService.Sharing += (o, isSharing) => { Application.Current.Dispatcher.Invoke(() => { if (!isSharing) { PausedOverlay.Visibility = Visibility.Visible; PausedText.Visibility = Visibility.Visible; } else { PausedOverlay.Visibility = Visibility.Hidden; PausedText.Visibility = Visibility.Hidden; } }); }; MouseMove += async (s, e) => { await MouseEvent(s, e); }; MouseDown += async (s, e) => { await MouseEvent(s, e); }; MouseUp += async (s, e) => { await MouseEvent(s, e); }; MouseWheel += async (s, e) => { await MouseEvent(s, e, e.Delta); }; KeyDown += async (s, e) => { await KeyboardEvent(true, e); }; KeyUp += async (s, e) => { await KeyboardEvent(false, e); }; Task.Run(async () => { await RealtimeService.StartConnection(Channel, ScreenshotService.ScreenWidth, ScreenshotService.ScreenHeight); Application.Current.Dispatcher.Invoke(() => { Title = $"Technician View [Connection Type: {RealtimeService.Transport}]"; }); }); }