Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does an application have to do in order "support" Remote Desktop Services?

I have a Delphi program that needs to be run via Remote Desktop Services. What should I look out for that would stop it running properly ?

like image 756
mmmm Avatar asked Jan 31 '11 18:01

mmmm


People also ask

What services are required for remote desktop?

To work with Remote Desktop Services, the PCs must be running a Windows operating system, have the RDP display protocol installed, and have a live network connection using TCP/IP and a valid IP address.

What does Remote Desktop Services do?

Remote Desktop Services (RDS) is an umbrella term for features of Microsoft Windows Server that allow users to remotely access graphical desktops and Windows applications.


2 Answers

Andreas is correct in pin-pointing double-buffering. This is the most important aspect to consider that I am aware of.

As a mild counter point, I don't like double-buffering in general because it's very hard to get it right. Many components don't succeed. I'm thinking of VCL drop down list boxes which don't draw right under Windows Basic. There are others!

But some controls really do need double-buffering to avoid flicker, so what do you do? You want the benefit of double buffering when the user is locally connected, but you don't want to tax them with the network bandwidth when they are remote.

So, here's what I do:

procedure WMWTSSessionChange(var Message: TMessage); message WM_WTSSESSION_CHANGE;

procedure TBaseForm.WMWTSSessionChange(var Message: TMessage);
begin
  case Message.WParam of
  WTS_CONSOLE_DISCONNECT,WTS_REMOTE_DISCONNECT,
  WTS_SESSION_LOCK,WTS_SESSION_LOGOFF:
    SessionDisconnected;
  WTS_CONSOLE_CONNECT,WTS_REMOTE_CONNECT,
  WTS_SESSION_UNLOCK,WTS_SESSION_LOGON:
    SessionConnected;
  end;
  inherited;
end;

function WTSRegisterSessionNotification(hWnd: HWND; dwFlags: DWORD): BOOL; stdcall; external 'Wtsapi32.dll';
function WTSUnRegisterSessionNotification(hWnd: HWND): BOOL; stdcall; external 'Wtsapi32.dll';

const
  NOTIFY_FOR_THIS_SESSION = 0;
  NOTIFY_FOR_ALL_SESSIONS = 1;

procedure TBaseForm.CreateWnd;
begin
  inherited;
  WTSRegisterSessionNotification(WindowHandle, NOTIFY_FOR_THIS_SESSION);
end;

procedure TBaseForm.DestroyWnd;
begin
  WTSUnRegisterSessionNotification(WindowHandle);
  inherited;
end;

All forms in my app descend from TBaseForm and so inherit this behaviour. The SessionConnected and SessionDisconnected methods are virtual so individual forms can take specific actions.

In particular, all my forms call UpdateDoubleBuffered:

function InRemoteSession: Boolean;
begin
  Result := Windows.GetSystemMetrics(SM_REMOTESESSION)<>0;
end;

class procedure TBaseForm.UpdateDoubleBuffered(Control: TWinControl);
var
  DoubleBuffered: Boolean;
begin
  if InRemoteSession then begin
    //see The Old New Thing, Taxes: Remote Desktop Connection and painting
    DoubleBuffered := False;
  end else begin
    DoubleBuffered := (Control is TCustomListView) 
                   or (Control is TCustomStatusBar);
    //TCustomListView flickers when updating without double buffering
    //TCustomStatusBar has drawing infidelities without double buffering in my app
  end;
  Control.DoubleBuffered := DoubleBuffered;
end;

procedure TBaseForm.UpdateDoubleBuffered;
var
  Control: TControl;
begin
  for Control in ControlEnumerator(TWinControl) do begin
    UpdateDoubleBuffered(TWinControl(Control));
  end;
end;

ControlEnumerator is an enumerator that walks the children of a component.

The Old New Thing reference is to an article entitled Taxes: Remote Desktop Connection and painting which was my inspiration for much of this code.

I'm sure that there are other issues relating to remote desktop, but double-buffering is certainly one of the more important ones.

like image 83
David Heffernan Avatar answered Oct 16 '22 17:10

David Heffernan


Double buffering is one such thing.

Generally double-buffering is a great thing, and I use it all the time. See for instance my components (1), (2), and (3). They are all double-buffered, and therefore completely free from flickering (and easy to implement), but if you run this remotely, you have to send bitmaps and not GDI commands, so it might be rather slow (and uneconomical).

like image 43
Andreas Rejbrand Avatar answered Oct 16 '22 19:10

Andreas Rejbrand