Skip to content

Commit

Permalink
Merge pull request quasar#303 from MaxXor/pr/301
Browse files Browse the repository at this point in the history
Improved Remote Desktop
  • Loading branch information
MaxXor committed Jul 28, 2015
2 parents 03bcaab + 44a9ff2 commit 889f16a
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 126 deletions.
12 changes: 0 additions & 12 deletions Server/Controls/PictureBoxEx.cs

This file was deleted.

195 changes: 195 additions & 0 deletions Server/Controls/RapidPictureBox.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using xServer.Core.Utilities;

namespace xServer.Controls
{
public interface IRapidPictureBox
{
bool Running { get; set; }
Image GetImageSafe { get; set; }

void Start();
void Stop();
void UpdateImage(Bitmap bmp, bool cloneBitmap = false);
}

/// <summary>
/// Custom PictureBox Control designed for rapidly-changing images.
/// </summary>
public class RapidPictureBox : PictureBox, IRapidPictureBox
{
/// <summary>
/// True if the PictureBox is currently streaming images, else False.
/// </summary>
public bool Running { get; set; }

/// <summary>
/// Returns the width of the original screen.
/// </summary>
public int ScreenWidth { get; private set; }

/// <summary>
/// Returns the height of the original screen.
/// </summary>
public int ScreenHeight { get; private set; }

/// <summary>
/// Provides thread-safe access to the Image of this Picturebox.
/// </summary>
public Image GetImageSafe
{
get
{
return Image;
}
set
{
lock (_imageLock)
{
Image = value;
}
}
}

/// <summary>
/// The lock object for the Picturebox's image.
/// </summary>
private readonly object _imageLock = new object();

/// <summary>
/// The Stopwatch for internal FPS measuring.
/// </summary>
private Stopwatch _sWatch;

/// <summary>
/// The internal class for FPS measuring.
/// </summary>
private FrameCounter _frameCounter;

/// <summary>
/// Subscribes an Eventhandler to the FrameUpdated event.
/// </summary>
/// <param name="e">The Eventhandler to set.</param>
public void SetFrameUpdatedEvent(FrameUpdatedEventHandler e)
{
_frameCounter.FrameUpdated += e;
}

/// <summary>
/// Unsubscribes an Eventhandler from the FrameUpdated event.
/// </summary>
/// <param name="e">The Eventhandler to remove.</param>
public void UnsetFrameUpdatedEvent(FrameUpdatedEventHandler e)
{
_frameCounter.FrameUpdated -= e;
}

/// <summary>
/// Starts the internal FPS measuring.
/// </summary>
public void Start()
{
_frameCounter = new FrameCounter();

_sWatch = Stopwatch.StartNew();

Running = true;
}

/// <summary>
/// Stops the internal FPS measuring.
/// </summary>
public void Stop()
{
if (_sWatch != null)
_sWatch.Stop();

Running = false;
}

/// <summary>
/// Updates the Image of this Picturebox.
/// </summary>
/// <param name="bmp">The new bitmap to use.</param>
/// <param name="cloneBitmap">If True the bitmap will be cloned, else it uses the original bitmap.</param>
public void UpdateImage(Bitmap bmp, bool cloneBitmap = false)
{
try
{
CountFps();

if ((ScreenWidth != bmp.Width) && (ScreenHeight != bmp.Height))
UpdateScreenSize(bmp.Width, bmp.Height);

lock (_imageLock)
{
if (GetImageSafe != null)
{
GetImageSafe.Dispose();
GetImageSafe = null;
}

GetImageSafe = cloneBitmap ? new Bitmap(bmp, Width, Height) /*resize bitmap*/ : bmp;
}
}
catch (InvalidOperationException)
{
}
catch (Exception ex)
{
MessageBox.Show(
string.Format(
"An unexpected error occurred: {0}\n\nPlease report this as fast as possible here:\\https://github.com/MaxXor/xRAT/issues",
ex.Message), "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

/// <summary>
/// Constructor, sets Picturebox double-buffered and initializes the Framecounter.
/// </summary>
public RapidPictureBox()
{
this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);

_frameCounter = new FrameCounter();
}

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}

protected override void OnPaint(PaintEventArgs pe)
{
lock (_imageLock)
{
if (GetImageSafe != null)
{
pe.Graphics.DrawImage(GetImageSafe, Location);
}
}
}

private void UpdateScreenSize(int newWidth, int newHeight)
{
ScreenWidth = newWidth;
ScreenHeight = newHeight;
}

private void CountFps()
{
var deltaTime = (float)_sWatch.Elapsed.TotalSeconds;
_sWatch = Stopwatch.StartNew();

_frameCounter.Update(deltaTime);
}
}
}
35 changes: 29 additions & 6 deletions Server/Core/Utilities/FrameCounter.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;

namespace xServer.Core.Utilities
{
public class FrameUpdatedEventArgs : EventArgs
{
public float CurrentFramesPerSecond { get; private set; }

public FrameUpdatedEventArgs(float _CurrentFramesPerSecond)
{
CurrentFramesPerSecond = _CurrentFramesPerSecond;
}
}

public delegate void FrameUpdatedEventHandler(FrameUpdatedEventArgs e);

public class FrameCounter
{
public long TotalFrames { get; private set; }
public float TotalSeconds { get; private set; }
public float AverageFramesPerSecond { get; private set; }
public float CurrentFramesPerSecond { get; private set; }

public const int MAXIMUM_SAMPLES = 100;

private Queue<float> _sampleBuffer = new Queue<float>();

public event FrameUpdatedEventHandler FrameUpdated;

public void Update(float deltaTime)
{
CurrentFramesPerSecond = 1.0f / deltaTime;
float currentFramesPerSecond = 1.0f / deltaTime;

_sampleBuffer.Enqueue(CurrentFramesPerSecond);
_sampleBuffer.Enqueue(currentFramesPerSecond);

if (_sampleBuffer.Count > MAXIMUM_SAMPLES)
{
Expand All @@ -27,11 +41,20 @@ public void Update(float deltaTime)
}
else
{
AverageFramesPerSecond = CurrentFramesPerSecond;
AverageFramesPerSecond = currentFramesPerSecond;
}

OnFrameUpdated(new FrameUpdatedEventArgs(AverageFramesPerSecond));

TotalFrames++;
TotalSeconds += deltaTime;
}

protected virtual void OnFrameUpdated(FrameUpdatedEventArgs e)
{
FrameUpdatedEventHandler handler = FrameUpdated;
if (handler != null)
handler(e);
}
}
}
}
17 changes: 8 additions & 9 deletions Server/Forms/FrmRemoteDesktop.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 889f16a

Please sign in to comment.