home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples.exe / Wintalk / VC / WinTalk.cpp < prev   
Encoding:
C/C++ Source or Header  |  2000-06-23  |  21.1 KB  |  672 lines

  1. /*+==========================================================================
  2.   File:      wintalk.cpp
  3.  
  4.   Summary:   This contains the front-end logic to wintalk, and entry point.
  5.              This application demonstrates the use of WFC and System.Net.DLL.
  6.  
  7.              Wintalk starts with a dialog that with to multi-line edit boxes
  8.              and two buttons (one grayed out).  In the background, it spins 
  9.              off a thread (ServerConnectionThread) which begins listening on 
  10.              TCP/IP port 5000.  When an incoming connection arrives, the 
  11.              ServerConnectionThread posts a message to the UI thread to 
  12.              un-gray the "disconnect" button, and gray out the "connect" 
  13.              button, and a client thread is started which receive all data
  14.              and sends the characters to the top edit window.  The user types 
  15.              in the bottom edit window to transmit to the remote end.
  16.  
  17.              WFC's InvokeAsync is used to provide a thread switch from one 
  18.              of the "worker" threads (such as ServerConnectionThread) to 
  19.              the UI thread (which is started from Main, and messages pumped
  20.              in Application.Run).
  21.              
  22.   Classes:   Wintalk
  23.  
  24.   Functions: 
  25.          Overrides:              Dispose
  26.  
  27.          Initialization:         InitForm
  28.  
  29.          Thread procedures:      ClientConnectionThreadProc, 
  30.                                  ServerConnectionThreadProc
  31.  
  32.          Async Invoked Methods:  OnClientActive, OnClientClosed,
  33.                                  OnServerAccept, OnServerReject
  34.  
  35.          Other:                  EnableClientConnection, 
  36.                                  DisableClientConnection
  37.              
  38.          UI Event Handlers:      panel1_resize, button1_click, 
  39.                                  button2_click, WinTalk_activate
  40.  
  41.          Entry point:            Main
  42.  
  43. ----------------------------------------------------------------------------
  44.   This file is part of the Microsoft NGWS Samples.
  45.  
  46.   Copyright (C) 1998-1999 Microsoft Corporation.  All rights reserved.
  47. ==========================================================================+*/
  48.  
  49. #using <mscorlib.dll>
  50. #using <System.WinForms.dll>
  51. #using <System.DLL>
  52. #using <Microsoft.Win32.Interop.dll>
  53. #using <System.Net.DLL>
  54. #using <System.Drawing.DLL>
  55.  
  56. using namespace System;
  57. using namespace System::Threading;
  58. using namespace System::ComponentModel;
  59. using namespace System::WinForms;
  60. using namespace System::Runtime::InteropServices;
  61. using namespace System::Drawing;
  62. using namespace System::Net;
  63. using namespace System::Net::Sockets;
  64.  
  65. // define delegates to be used with AsyncInvoke
  66. __delegate void AsyncInvokeDelegate();
  67. __delegate void AsyncInvokeStringDelegate(String *str);
  68.  
  69.  
  70. #define NULL 0
  71.  
  72. #include "SendEdit.h"
  73. #include "ConnectDialog.h"
  74.  
  75. __gc class WinTalk : public Form
  76. {
  77. protected:
  78.     Socket* ClientConnection;
  79.     Socket* ServerConnection;
  80.  
  81.     Thread* ClientConnectionThread;
  82.     Thread* ServerConnectionThread;
  83.  
  84.     String* m_ListenStr;
  85.     
  86.     bool bIsInDispose;
  87.  
  88.     Container *components;
  89.     SendEdit *edit2;
  90.     DataEdit *edit1;
  91.     Button *button1;
  92.     Button *button2;
  93.     Label *label1;
  94.     Splitter *splitter1;
  95.     Panel *panel1;
  96.     
  97. public:
  98.     int ServerPort;
  99.     
  100. /*****************************************************************************
  101.  Constructor : WinTalk
  102.  
  103.  Abstract:     Constructs an instance of Wintalk on the given port.
  104.             
  105.  Input Parameters: port(int)
  106.  
  107. ******************************************************************************/
  108.     WinTalk(int port) : ClientConnection(NULL), ServerConnection(NULL),
  109.                         ClientConnectionThread(NULL),
  110.                         ServerConnectionThread(NULL),
  111.                         bIsInDispose(false)
  112.     {
  113.         this->ServerPort = port;
  114.  
  115.         components = new Container();
  116.         edit2 = new SendEdit();
  117.         edit1 = new DataEdit();
  118.         button1 = new Button();
  119.         button2 = new Button();
  120.         label1 = new Label();
  121.         splitter1 = new Splitter();
  122.         panel1 = new Panel();
  123.  
  124.         InitForm();        
  125.  
  126.         // start "Listening" thread
  127.         ServerConnectionThread = new Thread(new ThreadStart(this, &WinTalk::ServerConnectionThreadProc));
  128.         ServerConnectionThread->Start();
  129.     }
  130.  
  131. /*****************************************************************************
  132.  Function:     Dispose
  133.  
  134.  Abstract:     Overrides Form.Dispose, cleans up the component list.
  135.             
  136.  Input Parameters: (None)
  137.  
  138.  Returns: void
  139. ******************************************************************************/
  140.     void Dispose()
  141.     {
  142.         bIsInDispose = true;
  143.         Form::Dispose();
  144.         components->Dispose();        
  145.         
  146.         DisableClientConnection();
  147.         
  148.         // Kill server thread
  149.         try {
  150.             if (ServerConnection != NULL)
  151.                 ServerConnection->Close();
  152.         }
  153.         catch (Exception *e) {}
  154.         ServerConnection = NULL;
  155.         
  156.         if (ServerConnectionThread != NULL)
  157.                 ServerConnectionThread->Join();
  158.         ServerConnectionThread = NULL;
  159.  
  160.         if (ClientConnectionThread != NULL)
  161.             ClientConnectionThread->Join();
  162.         ClientConnectionThread = NULL;
  163.     }
  164.  
  165. /*****************************************************************************
  166.  Function:     OnClientActive
  167.  
  168.  Abstract:     Invoked asynchronously when a connection becomes active.
  169.             
  170.  Input Parameters: (None)
  171.  
  172.  Returns: void
  173. ******************************************************************************/
  174.     void OnClientActive()
  175.     {
  176.         button1->Enabled = false;
  177.         button2->Enabled = true;
  178.         edit2->Focus(); // helps to eliminate confusion, sets focus to SendEdit
  179.         
  180.         IPEndPoint *ep = __try_cast<IPEndPoint*>(ClientConnection->RemoteEndpoint);
  181.  
  182.         String *addr = DNS::InetNtoa(ep->Address);
  183.         int port = ep->Port;
  184.         String *host = DNS::GetHostByAddr(addr)->Hostname;
  185.         String *s = String::Concat(S"Talking to ", addr, S":"); 
  186.         s->Concat(Convert::ToString(port), S"(", host, S")");
  187.         Console::WriteLine(s);
  188.         label1->Text = s;
  189.     }
  190.  
  191. /*****************************************************************************
  192.  Function:     OnClientClosed
  193.  
  194.  Abstract:     Invoked asynchronously when the active connection is closed
  195.             
  196.  Input Parameters: (None)
  197.  
  198.  Returns: void
  199. ******************************************************************************/
  200.     void OnClientClosed()
  201.     {
  202.         edit1->Append(S"\r\n****Notice: Connection Closed****\r\n");
  203.         button1->Enabled = true;
  204.         button2->Enabled = false;
  205.         label1->Text = m_ListenStr;
  206.     }
  207.     
  208. /*****************************************************************************
  209.  Function:     OnServerAccept
  210.  
  211.  Abstract:     Invoked asynchronously when an incoming connection is accepted
  212.                by the server thread.
  213.             
  214.  Input Parameters: (None)
  215.  
  216.  Returns: void
  217. ******************************************************************************/
  218.     void OnServerAccept()
  219.     {
  220.         edit1->Append(S"\r\n****CONNECTION ACTIVE****\r\n");
  221.         WindowState = FormWindowState::Normal;
  222.     }
  223.     
  224. /*****************************************************************************
  225.  Function:     OnServerReject
  226.  
  227.  Abstract:     Invoked asynchronously when an incoming connection is rejected
  228.                by the server thread.
  229.             
  230.  Input Parameters: (None)
  231.  
  232.  Returns: void
  233. ******************************************************************************/
  234.     void OnServerReject()
  235.     {
  236.         edit1->Append(S"\r\n****Warning: Incoming being rejected****\r\n");
  237.     }
  238.  
  239. /*****************************************************************************
  240.  Function:     EnableClientConnection
  241.  
  242.  Abstract:     Called when "ClientConnection" becomes valid.  Resets UI to 
  243.                proper state and spins off a ClientConnectionThread thread.
  244.             
  245.  Input Parameters: None
  246.  
  247.  Returns: Void
  248. ******************************************************************************/
  249.     void EnableClientConnection()
  250.     {
  251.         if (ClientConnectionThread != NULL) {
  252.             throw new ApplicationException(String::Concat(S"Client reader thread ",
  253.                                                           S"(ClientConnectionThread) already ",
  254.                                                           S"active!!"));
  255.         }
  256.         ClientConnectionThread = new Thread(new ThreadStart(this, &WinTalk::ClientConnectionThreadProc));
  257.         ClientConnectionThread->Start();
  258.         BeginInvoke(new AsyncInvokeDelegate(this, &WinTalk::OnClientActive));
  259.         edit2->SetClientConnection(ClientConnection);
  260.     }
  261.     
  262. /*****************************************************************************
  263.  Function:     DisableClientConnection
  264.  
  265.  Abstract:     Called when "ClientConnection" becomes invalid, or actually
  266.                closes ClientConnection.  Resets UI to proper state and if not 
  267.                called from ClientConnectionThread, waits for this thread to 
  268.                terminate.
  269.             
  270.  Input Parameters: None
  271.  
  272.  Returns: Void
  273. ******************************************************************************/
  274.     void DisableClientConnection()
  275.     {
  276.         try {
  277.             edit2->SetClientConnection(NULL);
  278.             try {
  279. //                CriticalSection::Enter(this);
  280.                 if (ClientConnection != NULL) {
  281.                     Console::WriteLine(String::Concat(S"DisableClientConnection: ",
  282.                             S"closing connection"));
  283.                     ClientConnection->Close();
  284.                     ClientConnection = NULL;
  285.                 }
  286.             }
  287.             __finally {
  288. //                CriticalSection::Exit(this);
  289.             }
  290.         }
  291.         catch (Exception *e) {
  292.             MessageBox::Show(this,e->Message,S"Close Error");
  293.         }
  294.         if (Thread::CurrentThread == ClientConnectionThread) {
  295.             ClientConnectionThread = NULL;
  296.             if (this->HandleCreated) {
  297.                 BeginInvoke(new AsyncInvokeDelegate(this, &WinTalk::OnClientClosed));
  298.             }
  299.         } else {
  300.             if (ClientConnectionThread != NULL) {
  301.                 ClientConnectionThread->Join();
  302.                 ClientConnectionThread = NULL;
  303.             }
  304.         }
  305.     }
  306.  
  307. /*****************************************************************************
  308.  Function:     ClientConnectionThreadProc
  309.  
  310.  Abstract:     Called when a client connection is made (click the "connect"
  311.                button, or incoming connection is made).  This thread is
  312.                created and started from the "EnableClientConnection" method.
  313.             
  314.  Input Parameters: None
  315.  
  316.  Returns: Void
  317. ******************************************************************************/
  318.     void ClientConnectionThreadProc()
  319.     {
  320.         Console::WriteLine(S"ClientConnectionThreadProc thread is starting");
  321.         try {
  322.             wchar_t c = L'\0';
  323.         
  324.             bool ignore_next_return = false;
  325.             Char b[] = new Char[1];  //not sure if __managed has a new keyword
  326.  
  327.             // read one character at a time from the Socket
  328.             while (ClientConnection != NULL && ClientConnection->Receive(b,b->Length,0) > 0) {
  329.                 c = b[0];
  330.                 if (ignore_next_return && (c == L'\r' || c == L'\n')) {
  331.                     ignore_next_return = false;
  332.                     continue;
  333.                 }
  334.                 ignore_next_return = false;
  335.  
  336.                 if (c == L'\b') {
  337.                     // backspace character causes use to truncate one char
  338.                     // off of the edit control
  339.                     edit1->BeginInvoke(new AsyncInvokeDelegate(edit1, &DataEdit::TruncateOneCharFromEnd));
  340.                     continue;
  341.                 }
  342.  
  343.                 String *str = NULL;
  344.  
  345.                 if (c == L'\r' && (ignore_next_return = true) || c == L'\n') {
  346.                     // if we receive \r\n, then we only pay attention to \r
  347.                     str = S"\r\n";
  348.                 } else {
  349.                     str = Convert::ToString(c);
  350.                 }
  351.             
  352.                 Object *o __gc[] = new Object* __gc[1]; //not sure if __managed has a new keyword
  353.                 o[0] = str;
  354.                 edit1->BeginInvoke(new AsyncInvokeStringDelegate(edit1, &DataEdit::Append), o);
  355.             }
  356.         }
  357.         catch (Exception *e) {
  358.             Console::WriteLine(String::Concat(S"Client Connection thread: ", e->ToString()));
  359.         }
  360.  
  361.         Console::WriteLine(S"Connection Closed");
  362.  
  363.         DisableClientConnection();
  364.         Console::WriteLine(S"ClientConnectionThreadProc thread is ending");
  365.     }
  366.     
  367. /*****************************************************************************
  368.  Function:     ServerConnectionThreadProc
  369.  
  370.  Abstract:     Listens on "ServerPort" and creates Socket's for each incoming 
  371.                request.  If ClientConnection is already active, the new 
  372.                Socket is destroyed.
  373.             
  374.  Input Parameters: None
  375.  
  376.  Returns: Void
  377. ******************************************************************************/
  378.     void ServerConnectionThreadProc()
  379.     {
  380.         Console::WriteLine(S"ServerConnectionThread starting");
  381.         try {
  382.             // create server socket and listen on port
  383.             ServerConnection = new Socket(AddressFamily::AfINet,SocketType::SockStream,ProtocolType::ProtTCP);
  384.             ServerConnection->Blocking = true;
  385.             if (ServerConnection->Bind(new IPEndPoint(IPAddress::InaddrAny,ServerPort)) != 0) {
  386.                 throw new ApplicationException(String::Concat("Unable to bind to port ", Convert::ToString(ServerPort)));
  387.             }
  388.  
  389.             ServerConnection->Listen(-1);
  390.             m_ListenStr = String::Concat(S"WinTalk listening on port ", Convert::ToString(ServerPort));
  391.             Console::WriteLine(m_ListenStr);
  392.             label1->Text = m_ListenStr;
  393.         }
  394.         catch (Exception *e) {
  395.             Console::WriteLine(String::Concat(S"Excpetion: ", e->Message));
  396.             m_ListenStr = S"Not listening on any port";
  397.             Console::WriteLine(m_ListenStr);
  398.             label1->Text = m_ListenStr;
  399.             return;
  400.         }
  401.         
  402.         try {
  403.             while (true) {
  404.                 // accept socket requests to our listening port
  405.                 Socket *s = ServerConnection->Accept();
  406.                 
  407.                 try {
  408. //                    CriticalSection::Enter(this);
  409.                     if (s == NULL) {
  410.                         throw new ApplicationException(S"Server connection closed");
  411.                     }
  412.  
  413.                     // if connection already active, reject
  414.                     if (ClientConnection != NULL) {
  415.                         BeginInvoke(new AsyncInvokeDelegate(this, &WinTalk::OnServerReject));
  416.                         String *str = S"Sorry connection is being rejected....\n";
  417.                         Console::WriteLine(str);
  418.  
  419.                         Char c[] = str->ToCharArray();
  420.                         Char b[] = new Char[c->Length];
  421.  
  422.                         for (int i = 0; i < c->Length; i++) {
  423.                             b[i] = (char)c[i];
  424.                         }
  425.                         s->Send(b, b->Length, 0);
  426.                         s->Close();
  427.                         continue;
  428.                     }
  429.  
  430.                     // no connection active, make the incoming one our current 
  431.                     // connection
  432.                     ClientConnection = s;
  433.  
  434.                     // notify user that connection has been made
  435.                     BeginInvoke(new AsyncInvokeDelegate(this, &WinTalk::OnServerAccept));
  436.  
  437.                     // notify UI thread that connection is active and 
  438.                     // spin off client thread to handle reads from socket
  439.                     EnableClientConnection();
  440.                 }
  441.                 __finally {
  442. //                    CriticalSection::Exit(this);
  443.                 }
  444.             }
  445.         }
  446.         catch (Exception *e) {
  447.             Console::WriteLine(String::Concat(S"Server Connection Thread: ", e->ToString()));
  448.             if (this->HandleCreated) {
  449.                 MessageBox::Show(this,String::Concat(S"Server Connection: ", e->ToString()),
  450.                         S"WinTalk");
  451.             }
  452.             m_ListenStr = S"Not listening on any port";
  453.             label1->Text = m_ListenStr;
  454.             if (!bIsInDispose) {
  455.                 Console::WriteLine(String::Concat(S"Server Connection Thread: ", e->ToString()));
  456.                 MessageBox::Show(String::Concat(S"Server Connection: ", e->ToString()),S"WinTalk");
  457.             }
  458.         }
  459.         try {
  460.             if (ServerConnection != NULL) {
  461.                 ServerConnection->Close();
  462.                 ServerConnection = NULL;
  463.             }
  464.         }
  465.         catch (Exception *e) {
  466.             Console::WriteLine(String::Concat(S"Server Connection Thread(2): ", e->ToString()));
  467.         }
  468.         Console::WriteLine(S"Server Connection Thread exiting");
  469.     }
  470.         
  471.     
  472. /*****************************************************************************
  473.  Function:     panel1_resize
  474.  
  475.  Abstract:     Invoked when the WFC panel containing the two edit fields
  476.                is resized.  Adjusts the edit boxes to be equal size.
  477.             
  478.  Input Parameters: source(Object), e(EventArgs)
  479.  
  480.  Returns: Void
  481. ******************************************************************************/
  482.     void panel1_resize(Object *source, EventArgs *e)
  483.     {
  484.         // Position the splitter in the center of the window
  485.         edit1->Height = (panel1->Height - splitter1->Height) / 2;
  486.     }
  487.  
  488. /*****************************************************************************
  489.  Function:     button1_click
  490.  
  491.  Abstract:     Invoked when the "Connect" button is clicked.  Creates the 
  492.                "ConnectDialog" and enables the client connection.
  493.             
  494.  Input Parameters: source(Object), e(EventArgs)
  495.  
  496.  Returns: Void
  497. ******************************************************************************/
  498.     void button1_click(Object *source, EventArgs *e)
  499.     {
  500.         Console::WriteLine(S"BUTTON1 clicked!!!");
  501.         try {
  502. //            CriticalSection::Enter(this);
  503.             if (ClientConnection != NULL) {
  504.                 Console::WriteLine(S"ERROR Connection already is open!!");
  505.                 return;
  506.             }
  507.             ConnectDialog *dlg = new ConnectDialog();
  508.             System::WinForms::DialogResult ret = dlg->ShowDialog(this);
  509.             if (ret == DialogResult::OK) {
  510.                 try {
  511.                     ClientConnection = new Socket(AddressFamily::AfINet,SocketType::SockStream,ProtocolType::ProtTCP);
  512.                     IPAddress *host_addr = DNS::Resolve(dlg->host);
  513.                     if (host_addr == NULL) {
  514.                         throw new ApplicationException(String::Concat(S"Unable to resolve host ", dlg->host));
  515.                     }
  516.                     IPEndPoint *ep = new IPEndPoint(host_addr, dlg->port);
  517.                     if (ClientConnection->Connect(ep) != 0) {
  518.                         throw new ApplicationException(S"Client connection failed");
  519.                     }
  520.                     EnableClientConnection();
  521.                 }
  522.                 catch (Exception *ev) {
  523.                     DisableClientConnection();
  524.                     MessageBox::Show(this,ev->Message,S"Connect Error");
  525.                 }
  526.             }
  527.         }
  528.         __finally {
  529. //            CriticalSection::Exit(this);
  530.         }
  531.     }
  532.  
  533. /*****************************************************************************
  534.  Function:     button2_click
  535.  
  536.  Abstract:     Invoked when the "Disconnect" button is clicked. Disables the 
  537.                client connection.
  538.             
  539.  Input Parameters: source(Object), e(EventArgs)
  540.  
  541.  Returns: Void
  542. ******************************************************************************/
  543.     void button2_click(Object *source, EventArgs *e)
  544.     {
  545.         Console::WriteLine(S"BUTTON2 clicked!!!");
  546.         DisableClientConnection();        
  547.     }
  548.  
  549. /*****************************************************************************
  550.  Function:     WinTalk_activate
  551.  
  552.  Abstract:     Invoked when the Wintalk application window becomes active.
  553.                Sets focus to the bottom edit control (less confusion to the
  554.                user as to which edit box to type in).
  555.             
  556.  Input Parameters: source(Object), e(EventArgs)
  557.  
  558.  Returns: Void
  559. ******************************************************************************/
  560.     void WinTalk_activate(Object *source, EventArgs *e)
  561.     {
  562.         edit2->Focus();
  563.     }
  564.  
  565.  
  566. /*****************************************************************************
  567.  Function:     InitForm
  568.  
  569.  Abstract:     Creates UI elements (buttons, edit controls, ...) on the 
  570.                Wintalk WFC form.
  571.             
  572.  Input Parameters: None
  573.  
  574.  Returns: Void
  575. ******************************************************************************/
  576.     void InitForm()
  577.     {
  578.         this->Text = S"WinTalk";
  579.         this->AutoScaleBaseSize = *new System::Drawing::Size(*new Point(5, 13)); //This line is really messed
  580.         this->ClientSize = *new System::Drawing::Size(*new Point(406, 344));
  581.         this->AddOnActivate(new EventHandler(this, &WinTalk::WinTalk_activate));
  582.  
  583.         edit2->Dock = DockStyle::Fill;
  584.         edit2->Location = *new Point(0, 158);
  585.         edit2->Size = *new System::Drawing::Size(*new Point(406, 154));
  586.         edit2->TabIndex = 1;
  587.         edit2->Text = S"";
  588.         edit2->Multiline = true;
  589.         edit2->ReadOnly = true;
  590.         edit2->ScrollBars = ScrollBars::Vertical;
  591.         edit2->BackColor = Color::White;
  592.  
  593.         edit1->Dock = DockStyle::Top;
  594.         edit1->Size = *new System::Drawing::Size(*new Point(406, 153));
  595.         edit1->TabIndex = 0;
  596.         edit1->Text = S"";
  597.         edit1->Multiline = true;
  598.         edit1->ReadOnly = true;
  599.         edit1->ScrollBars = ScrollBars::Vertical;
  600.         edit1->BackColor = Color::White;
  601.  
  602.         label1->Anchor = AnchorStyles::BottomLeftRight;
  603.         label1->Location = *new Point(0, 321);
  604.         label1->Size = *new System::Drawing::Size(*new Point(230, 18));
  605.         label1->TabIndex = 2;
  606.         label1->TabStop = false;
  607.         label1->Text = S"";
  608.  
  609.         button1->Anchor = AnchorStyles::BottomRight;
  610.         button1->Location = *new Point(331, 317);
  611.         button1->Size = *new System::Drawing::Size(*new Point(72, 24));
  612.         button1->TabIndex = 0;
  613.         button1->Text = S"Connect";
  614.         button1->AddOnClick(new EventHandler(this, &WinTalk::button1_click));
  615.  
  616.         button2->Anchor = AnchorStyles::BottomRight;
  617.         button2->Enabled = false;
  618.         button2->Location = *new Point(235, 317);
  619.         button2->Size = *new System::Drawing::Size(*new Point(88, 24));
  620.         button2->TabIndex = 1;
  621.         button2->Text = S"Disconnect";
  622.         button2->AddOnClick(new EventHandler(this, &WinTalk::button2_click));
  623.  
  624.         splitter1->Cursor = Cursors::HSplit;
  625.         splitter1->Dock = DockStyle::Top;
  626.         splitter1->Location = *new Point(0, 153);
  627.         splitter1->Size = *new System::Drawing::Size(*new Point(406, 5));
  628.         splitter1->TabIndex = 2;
  629.         splitter1->TabStop = false;
  630.  
  631.         panel1->Anchor = AnchorStyles::All;
  632.         panel1->Size = *new System::Drawing::Size(*new Point(406, 312));
  633.         panel1->TabIndex = 3;
  634.         panel1->Text = S"panel1";
  635.         panel1->AddOnResize(new EventHandler(this, &WinTalk::panel1_resize));
  636.  
  637.         Control *c1[] = new Control*[4];
  638.         c1[0] = panel1;
  639.         c1[1] = button2;
  640.         c1[2] = button1;
  641.         c1[3] = label1;
  642.  
  643.         this->Controls->All = c1;
  644.  
  645.         Control *c2[] = new Control*[3];
  646.  
  647.         c2[0] = splitter1;
  648.         c2[1] = edit2;
  649.         c2[2] = edit1;
  650.  
  651.         panel1->Controls->All = c2;
  652.     }
  653.  
  654.  
  655. };
  656.  
  657. /*****************************************************************************
  658.  Function:     Main
  659.  
  660.  Abstract:     Entry point into application.
  661.             
  662.  Input Parameters: String[]
  663.  
  664.  Returns: void
  665.  
  666. ******************************************************************************/
  667.     void main()
  668.     {
  669.         int port = 5000;
  670.         Application::Run(new WinTalk(port));
  671.     }
  672.