Microsoft Visual C++ .NET Professional Projects - Premier Press
.pdfIMPLEMENTING NETWORKING |
Chapter 29 |
861 |
|
|
|
|
|
Button *pBtnExit;
CChat* pChat;
//Thread variable declared Thread* pChatThread; bool bThreadStarted; Encoding* pASCII;
public:
CChatForm()
{
pCaption = “Chat Dialog”; nWidth = 500;
nHeight = 255; bThreadStarted = false;
//Prepare the Chat form InitForm();
pChat = new CChat(pLstBoxMessage, pchkdLstBoxUserList);
}
void ~CChatForm()
{
// Form is being destroyed. Do any necessary cleanup here. Form::Dispose();
}
In the preceding code, the class CChatForm is the user-defined class derived from the Form class. The pChatThread is an object of thread class. The variable pASCII variable is used to handle the encoding and decoding of data passing on network.
In the constructor, CChatForm(), the caption of the form is set to Chat Dialog, the width is set to 500, and the height is set to 255.
Now take a look at initializing the controls and placing them on the form in the code, as indicated in the following code:
void InitForm()
{
// Basic WinForm Settings
Text = pCaption;
862 Project 10 NETWORKING AND REMOTING IN VC++.NET
Size = Drawing::Size(nWidth, nHeight); set_MaximizeBox(false);
pTxtMessage = new TextBox(); pTxtMessage->Name=”Edit_message”; pTxtMessage->Size = Drawing::Size(280, 20); pTxtMessage->TabIndex = 0;
pTxtMessage->Location = Drawing::Point(10, 195); pLstBoxMessage = new ListBox(); pLstBoxMessage->Name=”ListBox_message”; pLstBoxMessage->TabIndex = 1; pLstBoxMessage->set_HorizontalScrollbar(true); pLstBoxMessage->Location = Drawing::Point(10, 10); pLstBoxMessage->Size = Drawing::Size(350, 160); pLstBoxMessage->Enabled = false; pchkdLstBoxUserList = new ListBox();
pchkdLstBoxUserList->Name=”CheckedListBox_UserList”; pchkdLstBoxUserList->set_HorizontalScrollbar(true); pchkdLstBoxUserList->TabIndex = 2; pchkdLstBoxUserList->Location = Drawing::Point(380, 30); pchkdLstBoxUserList->Size = Drawing::Size(100, 140); pchkdLstBoxUserList->Enabled = false;
pLblLoggedOnUser = new Label(); pLblLoggedOnUser->Text=”Logged on Users:”; pLblLoggedOnUser->Size = Drawing::Size(100, 20); pLblLoggedOnUser->Location = Drawing::Point(380, 10); pLblMessage = new Label();
pLblMessage->Text=”Type the message here:”; pLblMessage->Size = Drawing::Size(150, 20); pLblMessage->Location = Drawing::Point(10, 175); pBtnSend = new Button();
pBtnSend->Text = “Se&nd”; pBtnSend->Size = Drawing::Size(55, 20); pBtnSend->TabIndex = 3;
pBtnSend->Location = Drawing::Point(300, 195); pBtnSend->Click += (new EventHandler(this,
IMPLEMENTING NETWORKING |
Chapter 29 |
863 |
|
|
|
|
|
&CChatForm::OnSendButtonClick)); pBtnSave = new Button(); pBtnSave->Text = “&Save”;
pBtnSave->Size = Drawing::Size(55, 20); pBtnSave->TabIndex = 4;
pBtnSave->Location = Drawing::Point(362, 195); pBtnSave->Click += (new EventHandler(this,
&CChatForm::OnSaveButtonClick)); pBtnExit = new Button(); pBtnExit->Text = “E&xit”;
pBtnExit->Size = Drawing::Size(55, 20); pBtnExit->TabIndex = 5;
pBtnExit->Location = Drawing::Point(425, 195); pBtnExit->Click += (new EventHandler(this,
&CChatForm::OnExitButtonClick)); Controls->Add(pTxtMessage); Controls->Add(pLblMessage); Controls->Add(pLblLoggedOnUser); Controls->Add(pLstBoxMessage); Controls->Add(pchkdLstBoxUserList); Controls->Add(pBtnSend); Controls->Add(pBtnSave); Controls->Add(pBtnExit);
//Set the pBtnSend as the default Form::set_AcceptButton(pBtnSend);
//Initialize the Chat session pChat->Initialize();
}
The initialization of the form and controls is done in the initForm() method. To set the caption and size of the form, initialize the Text and Size properties.
You also need to initialize the required property of the controls to place them on the form. Table 29-6 lists the different properties of the controls that are set in the code.
864 |
Project 10 NETWORKING AND REMOTING IN VC++.NET |
|||
|
|
|
|
|
|
|
Table 29-6 Properties of the Controls |
||
|
|
|
|
|
|
|
Property |
Description |
|
|
|
|
|
|
|
|
Name |
Sets the name to the control. |
|
|
|
Text |
Sets the constant text to be displayed in the control. |
|
|
|
Size |
Sets the size of the control. It takes the width and height of the |
|
|
|
|
|
control. |
|
|
Tabindex |
Sets the tab stop of the control. |
|
|
|
HorizontalScrollbar |
Enables you to display the horizontal scroll bar. |
|
|
|
Location |
Enables you to specify the location on the form where the control |
|
|
|
|
|
should be displayed. |
|
|
|
|
|
Apart from the properties discussed in Table 29-6, you need to set the click property for buttons. The Click property will enable the button control to handle the Click event.
Once you have set the properties, add the controls by using the Add method of the
Controls class.
Next, you will start coding for the buttons that appear on the form. You can write the code for these methods in any sequence. To begin with, take a look at the code for the Exit button. This code will be executed when the user clicks on the Exit button.
//Handles the Exit button
void OnExitButtonClick (Object *sender, EventArgs *e)
{
if ( bThreadStarted && (pChatThread != NULL) )
{
CChat::m_bDone = true;
//Notify the listener, User is closing the app String* pStrMsg;
pStrMsg = S”:@”;
Byte bytearrayBuffer [] = new Byte[pStrMsg->Length + 1]; int nLen = pASCII->GetBytes( pStrMsg->ToCharArray(), 0,
pStrMsg->Length, bytearrayBuffer, 0);
IMPLEMENTING NETWORKING |
Chapter 29 |
865 |
|
|
|
|
|
int nECode = CChat::m_pClient->Send(bytearrayBuffer, 2, pChat-
>GetRemoteEP());
//Raises a ThreadAbortException in the thread from within which it is invoked, //to begin the process of terminating the thread.
pChatThread->Abort();
//Blocks the calling thread until a thread terminates pChatThread->Join();
//Show the message in the list box
pLstBoxMessage->Items->Add(S”Thank you for using My Chat App !!!”);
pLstBoxMessage->Refresh();
//Terminate the Chat Session pChat->Terminate(); Thread::Sleep(2000);
}
Close();
}
In the preceding code, you delete all the objects, terminate the thread, and close the form.
Next, let me explain the code for the Save button. When the user clicks on the Save button, the items appearing in the list box need to be saved in the file specified by the user in the Save dialog box. Following is the code written in the Click event of the Save button:
void OnSaveButtonClick (Object *sender, EventArgs *e)
{
//Code here for saving the chat content
int nCount = pLstBoxMessage->Items->Count; String *pStrMessage, *pStrTemp;
for (int i=0; i < nCount; i++)
{
pStrTemp = pLstBoxMessage->Items->get_Item(i)->ToString(); pStrMessage = String::Concat(pStrMessage, S”\n”, pStrTemp);
}
866 Project 10 NETWORKING AND REMOTING IN VC++.NET
//Save pStrItem in a file
SaveFileDialog* pFileDlg = new SaveFileDialog(); pFileDlg->DefaultExt = “txt”;
pFileDlg->Filter = “txt files (*.txt)|*.txt|All files (*.*)|*.*”; pFileDlg->FilterIndex = 2;
pFileDlg->RestoreDirectory = true;
if (pFileDlg->ShowDialog() == DialogResult::OK)
{
Stream *pStream;
if((pStream = pFileDlg->OpenFile()) != NULL)
{
Byte bytearrayBuffer [] = new Byte[pStrMessage->Length + 1]; int nLen = pASCII->GetBytes( pStrMessage->ToCharArray(), 0,
pStrMessage->Length, bytearrayBuffer, 0);
pStream->Write(bytearrayBuffer, 0, pStrMessage->Length); pStream->Close();
}
}
}
In the preceding code, the variable nCount stores the count of items in the list box. The get_Item() method is used to get the values from the list box and store them in the temporary String variable pStrTemp. Once you get the values, concatenate these values using the Concat() method of the String class and store the concatenated string in the pStrMessage variable.
The SaveFileDialog object is declared to invoke the Save dialog box.
The DefaultExt property is set to specify the default extension for the file that the user saves.
The Filter property is used to set the list of extensions that will appear in the Save as type list box in the Save dialog box. The FilterIndex property is used to specify the default value that will be displayed in the Save as type list box.
After you have set the properties of the Save dialog box, you need to write the code for storing the contents of the list box in the file using the Stream class object.
To store the contents to the Stream object, you will first create a byte array bytearrayBuffer. Then, you will transfer the contents of the SUtring variable
pStrMUessage to bytearUrayBuffer by using the GetByte() method.
IMPLEMENTING NETWORKING |
Chapter 29 |
867 |
|
|
|
|
|
Once the contents are stored in the byte array, write the contents to the Stream object using the Write() method and close the stream.
The following code adds the functionality to the Send button, which is used to broadcast the messages sent by a user to all the users that are currently logged in:
void OnSendButtonClick (Object *sender, EventArgs *e)
{
//Handles the Send button if (!bThreadStarted)
{
pChatThread = new Thread(new ThreadStart(0, CChat::Listener));
//Start the thread
pChatThread->Start(); pASCII = Encoding::ASCII; bThreadStarted = true;
}
//Get the text from the message window and send it to active user String* pStrTemp = pTxtMessage->Text;
String* pStrMsg = pStrTemp->Trim(); if (pStrMsg->Length == 0)
{
//Nothing to send return;
}
else
{
//Format the user typed message
String* pHostName = pChat->GetChatHostName(); int nItemIndex = pchkdLstBoxUserList-
>FindStringExact(pHostName);
if (nItemIndex == ListBox::NoMatches)
{
pchkdLstBoxUserList->Items->Add(pHostName);
}
pStrMsg = String::Concat(pChat->GetChatHostName(), S”:”,
pStrMsg);
IMPLEMENTING NETWORKING |
Chapter 29 |
869 |
|
|
|
|
|
Summary
This chapter introduced you to network programming. You learned that you can create a network application based on sockets. You were introduced to the Socket class and the related methods of the class (including namespaces). Another important concept that you learned is that of threads. You saw the functionality of the Thread class and its various methods.
Finally, you created an application that illustrates the implementation of sockets and threads.
