Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 May : Re: Indy Error ?

www.cryer.info
Managed Newsgroup Archive

Re: Indy Error ?

Subject:Re: Indy Error ?
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Mon, 8 May 2006 12:49:31

"Mike C" <MikeCooperInWG@ic24.net> wrote in message
news:445c63fa$1@newsgroups.borland.com...

> I am migrating an application from 'Delphi 5' to 'Delphi 2006
>  VCL for Win32'. The D5 code uses a TServerSocket, so I
> am having to use a TIdTCPServer in D2006, which might be
> causing a problem.

Any particular reason why you don't continue to use TServerSocket?  It is
still available in BDS, although you have to install the dclsocket100
package manually now.

> However, with the line 'ShowWindow()' active, the MainForm
>  is initially in the Tray. When telnet is used and the MainForm
> shown again, the listbox has disappeared. Also when the
>  apllication shuts down it generates a 'System Error Code 1400 -
> Invalid window handle'.

TIdTCPServer is a multi-threaded component, and your event handler code for
the server is not thread-safe.  You need to use the TThread.Synchronize()
method, either directly or via the TIdSync class, in order to access the GUI
safely.

Try this code instead:

    unit IndyErrorMain;

    interface

    uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics,
        Controls, Forms, Dialogs, StdCtrls, IdBaseComponent, IdComponent,
        IdCustomTCPServer, IdTCPServer, IdContext, Menus, ShellAPI;

    type
        TfrmIEMain = class(TForm)
            IdTCPServer: TIdTCPServer;
            lbxLog: TListBox;
            puTray: TPopupMenu;
            puitRestore: TMenuItem;
            btnToTray: TButton;
            puTerminate: TMenuItem;
            procedure FormClose(Sender: TObject; var Action: TCloseAction);
            procedure puTerminateClick(Sender: TObject);
            procedure btnToTrayClick(Sender: TObject);
            procedure puitRestoreClick(Sender: TObject);
            procedure IdTCPServerExecute(AContext: TIdContext);
            procedure IdTCPServerDisconnect(AContext: TIdContext);
            procedure IdTCPServerConnect(AContext: TIdContext);
        protected
            procedure CreateWnd; override;
            procedure DestroyWnd; override;
            procedure WndProc(var Msg : TMessage); override;
        private
            procedure MakeOrderlyExit;
        public
            { Public declarations }
        end;

    var
        frmIEMain: TfrmIEMain;

    implementation

    uses
        IdSync;

    {$R *.dfm}

    { TLogSync }

    type
        TLogSync = class(TIdSync)
        protected
            FStr: String;
            procedure DoSynchronize; override;
        public
            constructor Create(const AStr: String); reintroduce;
            class procedure Add(const AStr: String);
        end;

    constructor TLogSync.Create(const AStr: String);
    begin
        inherited Create;
        FStr := AStr;
    end;

    procedure TLogSync.DoSynchronize;
    begin
        frmIEMain.lbxLog.Items.Add(FStr);
    end;

    class procedure TLogSync.Add(const AStr: String);
    begin
        with Create(AStr) do try
            Synchronize;
        finally
            Free;
        end;
    end;

    { TfrmIEMain }

    procedure TfrmIEMain.WndProc(var Msg : TMessage);
    var
        p : TPoint;
    begin
        if Msg.Msg = WM_USER+1 then
        begin
            if Msg.lParam = WM_RBUTTONDOWN then
            begin
                GetCursorPos(p);
                puTray.PopUp(p.x, p.y);
            end;
        end else
            inherited;
    end;

    procedure TfrmIEMain.btnToTrayClick(Sender: TObject);
    begin
        Close;
    end;

    procedure TfrmIEMain.FormClose(Sender: TObject; var Action:
TCloseAction);
    begin
        if not Application.Terminated then
            Action := caHide;
    end;

    procedure TfrmIEMain.CreateWnd;
    var
        IconData : TNotifyIconData;
    begin
        inherited;
        if HandleAllocated then
        begin
            FillChar(@IconData, sizeof(TNotifyIconData), 0);
            with IconData do
            begin
                cbSize := sizeof(IconData);
                Wnd := Handle;
                uID := 100;
                uFlags := NIF_MESSAGE  or NIF_ICON or NIF_TIP;
                uCallbackMessage := WM_USER+1;
                hIcon := Application.Icon.Handle;
                StrPCopy(szTip, Application.Title);
            end;
            Shell_NotifyIcon(NIM_ADD, @IconData);
        end;
    end;

    procedure TfrmIEMain.DestroyWnd;
    var
        IconData : TNotifyIconData;
    begin
        if HandleAllocated then
        begin
            FillChar(@IconData, sizeof(TNotifyIconData), 0);
            with IconData do
            begin
                cbSize := sizeof(IconData);
                Wnd := Handle;
                uID := 100;
            end;
            Shell_NotifyIcon(NIM_DELETE, @IconData);
        end;
        inherited;
    end;

    procedure TfrmIEMain.IdTCPServerConnect(AContext: TIdContext);
    begin
        TLogSync.Add('Connected');
        try
            AContext.Connection.IOHandler.WriteLn(Application.Title + '
ready');
        except
            on E: Exception do
            begin
                TLogSync.Add('Error: ' + E.Message);
                raise;
            end;
        end;
    end;

    procedure TfrmIEMain.IdTCPServerDisconnect(AContext: TIdContext);
    begin
        TLogSync.Add('Disconnected');
    end;

    procedure TfrmIEMain.IdTCPServerExecute(AContext: TIdContext);
    var
        s : string;
    begin
        try
            s := AContext.Connection.IOHandler.ReadLn;
            TLogSync.Add(s);
        except
            on E: Exception do
            begin
                TLogSync.Add('Error: ' + E.Message);
                raise;
            end;
        end;
    end;

    procedure TfrmIEMain.MakeOrderlyExit;
    begin
        IdTCPServer.Active := False;
        Application.Terminate;
    end;

    procedure TfrmIEMain.puitRestoreClick(Sender: TObject);
    begin
        frmIEMain.Show;
    end;

    procedure TfrmIEMain.puTerminateClick(Sender: TObject);
    const
        strMsg = 'Do you really want to close down %s ?'#13#13'If you do
then -'#13'       PIMS will not be able'#13'       to print any more labels
!';
        strCaption = 'Exiting %s application';
    begin
        if Application.MessageBox(PChar(Format(strMsg,
[Application.Title])), PChar(Format(strCaption, [Application.Title])),
MB_YESNO or MB_ICONQUESTION) = IDYES then
            MakeOrderlyExit;
    end;

    end.


Gambit

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive