I'm not sure you're doing this right.
First of all (nitpick):
<FONT face="Courier New">Memo1.Lines.Add('Connected.');
IndyClient.Connect;</FONT>
<FONT face="Courier New">Should be</FONT>
<FONT face="Courier New">IndyClient.Connect;
</FONT><FONT face="Courier New">Memo1.Lines.Add('Connected.');</FONT>
<FONT face="Courier New">Otherwise the message is misleading.</FONT>
<FONT face="Courier New">On to more serious stuff: the message you are getting (Connection closed gracefully), is probably because in some instances you are calling Disconnect on an already disconnected socket. Your code goes like this:</FONT>
<FONT face="Courier New">try
while Connected do stuff;
{ Not connected here }
finally
Disconnect;</FONT>
<FONT face="Courier New">You can see the "finally Disconnect" part is superfluous. Better would be to use 'except': close the connection in case of an error, not in case of normal operation.</FONT>
<FONT face="Courier New">And why is your application "laggy"? Because Indy sockets are normally blocking. The code as you're writing it right now is suitable if you need to receive or send a short burst of information, but it looks as if you're trying to write an interactive prompt. The reason this won't work (or if it works at all, won't work well), is because the program will be stuck in Button1's event handler until the connection is closed. Look at the code: it will not return before that. So until the connection is closed, Edit1's event handler (to write to the socket) will never be triggered. Interactive prompt will not work.</FONT>
<FONT face="Courier New">The right (but hard) way to work around this, is to use the blocking socket in a thread, but that gets complicated awful fast, especially if you have no experience with it.</FONT>
<FONT face="Courier New">The slightly less right (but acceptable in most cases) way is to separate the code into multiple event handlers. Let the button connect, but nothing else. Add a timer that checks periodically (every 10ms) for input on the socket, let it read that and add it to the memo. Let another button disconnect. You can leave the Edit1 event handler like it is, but it should check if the socket is connected before writing.</FONT>
<FONT face="Courier New">The lazy (and hackish) way to make it work is to just add a call to Application.ProcessMessages in your inner loop. This will make sure that other event handlers are called (such as Edit1's keypress event, and memo1's paint event) while you're technically still in Button1's event handler. However, be advised that this will only work each time a line is read from the socket (since the socket is blocking, the call to ReadLn will not return before a line is read or the connection is lost)... so this might still freeze your application if no line is received for a long time (which may very well be the case in an interactive prompt-type of application).</FONT>
I'd recommend solution 2 for now, since it is most correct for the amount of effort you'd have to put in. You don't need to switch to asynchronous sockets. You can, but they're much less nice to code against. Good luck.