Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
DelphiNews

How to Speed Up Remote Desktop Applications

remote desktop faster

One feature update to RAD Studio 10.4.2, driven by analysis showing an increase in the number of developers using remote desktop to development during Covid, has been a speed up to the IDE rendering over Remote Desktop.

The main issues focused on were the IDE freezing in some situations (such as when connecting or disconnecting remote desktop), flickering, and a few AV’s.

The QP items looked at for 10.4.2 include:

  • Reconnect an Existing RDP session using the same screen settings (same machine) RS-99048
  • Reconnect an Existing RDP session using different screen settings (e.g from a different machine) RS-103339
  • Reconnect an Existing RDP session with the FMX designer opened causes AV.

Additionally, there were a number of internal reports.

While I’ve not got a sample project that can be shared, I have got permission to share a few notes the R&D team at Embarcadero provided based on their experiences, and I hope this will be useful to other developers too.

The root cause for all those issues is that any RDP session change (lock, unlock, connect, disconnect) sent a system-wide setting change (WM_SETTINGCHANGE) causing a message cascade that leads to multiple redraws in the IDE. This was the cause of some of the AV’s as between the cascade messages sent by the OS it included the WM_THEMECHANGED message that was triggering the handle recreation for some controls. This was affecting the VCL/FMX designers when they were left open and a session was reconnected via RDP.

The WTS API provides a way to receive the RDP session change notifications (WM_WTSSESSION_CHANGE). Managing this enables the IDE to become notified when the session is locked, unlocked, connected, disconnected, and from here we can choose how the WM_SETTINGCHANGE is handled and avoid the flickering/repainting issues.

One note from the R&D team was using VCL styles on terminal services is more likely to cause an application to see flicker under normal circumstances.

This skeleton sample of code (untested) should hopefully provide pointers in the right direction for anyone looking to add similar support into their applications.

type
  TFormMain = class(TForm)
    TimerEnableMetricSettings : TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TimerEnableMetricSettingsOnTimer(Sender: TObject);
  private
    FMethodWnd: HWND;
    procedure WTS_SessionWndProc(var Message: TMessage);
    procedure DoHandleRDPLock;
    procedure DoHandleRDPUnLock;
  end;

var
  FormMain: TFormMain;

implementation
{$R *.dfm}

procedure TFormMain.DoHandleRDPLock;
begin
  // Prevent the VCL App reacting to WM_SETTINGCHANGE when a rdp session is locked/disconnected.
  // Stop the timer if it's already running
  if TimerEnableMetricSettings.Enabled then
    TimerEnableMetricSettings.Enabled := False;
  Application.UpdateMetricSettings := False;
end;

procedure TFormMain.DoHandleRDPUnLock;
begin
  // Stop the timer if it's already running
  if TimerEnableMetricSettings.Enabled then
    TimerEnableMetricSettings.Enabled := False;
  // Re-start the timer.
  TimerEnableMetricSettings.Enabled := True;
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  TimerEnableMetricSettings.Interval := 30000;
  TimerEnableMetricSettings.Enabled := False;
  // This hooks to the method WTS_SessionWndProc below to control the Lock
  FMethodWnd := AllocateHWnd(WTS_SessionWndProc); 
  WTSRegisterSessionNotification(FMethodWnd, NOTIFY_FOR_THIS_SESSION);
end;
   
procedure TFormMain.FormDestroy(Sender: TObject);
begin
  if FMethodWnd <> 0 then
  begin
    WTSUnRegisterSessionNotification(FMethodWnd);
    DeallocateHWnd(FMethodWnd);
  end;
end;

procedure TFormMain.WTS_SessionWndProc(var Message: TMessage);
begin
  if Message.Msg = WM_WTSSESSION_CHANGE then
  begin
    case Message.wParam of
      WTS_SESSION_LOCK,
      WTS_REMOTE_DISCONNECT:  DoHandleRDPLock;
      WTS_REMOTE_CONNECT,
      WTS_SESSION_UNLOCK:  DoHandleRDPUnLock;
    end;
  end;
  Message.Result := DefWindowProc(FMethodWnd, Message.Msg, Message.WParam, Message.LParam);
end;

procedure TFormMain.TimerEnableMetricSettingsOnTimer(Sender : TObject);
begin
  // stop the timer
  TimerEnableMetricSettings.Enabled := False;
  // it is recommended to wait a few seconds before this is run
  // hence setting the timer interval to 30000 in FormCreate 
  Application.UpdateMetricSettings := True;  
end;

end.
RAD Studio 13.1 Florence Now Available See What's New in RAD Studio 13.1 Delphi is 31 - Webinar Replay

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

About author

Pre-sales Director at Embarcadero

2 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES