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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
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. |
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition
The Problem still exists in the IDE. In this Morning I waited 3 minutes to gain control back. Thats not always but the RDP-optimiziation sometime is not active.
Hi Sven. Most people I’ve heard from seem to see some good improvements. If you can reliably reproduce the problem would you be able to raise an issue on the Quality Portal so it can be looked at? The link is here: https://quality.embarcadero.com/