📄 ch20.htm
字号:
</TD> <TD ALIGN="LEFT">Disabled </TD> <TD ALIGN="LEFT">Checked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Edit Box </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_EMSG </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Disabled </TD> <TD ALIGN="LEFT">Checked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Command Button </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_BSEND </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Caption </TD> <TD ALIGN="LEFT">S&end </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Disabled </TD> <TD ALIGN="LEFT">Checked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Static Text </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_STATIC </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Caption </TD> <TD ALIGN="LEFT">Sent: </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">List Box </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_LSENT </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Tab Stop </TD> <TD ALIGN="LEFT">Unchecked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Sort </TD> <TD ALIGN="LEFT">Unchecked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Selection </TD> <TD ALIGN="LEFT">None </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Static Text </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_STATIC </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Caption </TD> <TD ALIGN="LEFT">Received: </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">List Box </TD> <TD ALIGN="LEFT">ID </TD> <TD ALIGN="LEFT">IDC_LRECVD </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Tab Stop </TD> <TD ALIGN="LEFT">Unchecked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Sort </TD> <TD ALIGN="LEFT">Unchecked </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"> <P> </TD> <TD ALIGN="LEFT">Selection </TD> <TD ALIGN="LEFT">None </TD> </TR></TABLE></P><P>Once you have the dialog designed, open the Class Wizard to attach variables tothe controls on the dialog, as specified in Table 20.3.</P><P><H4>TABLE 20.3. CONTROL VARIABLES.</H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT"><I>Object</I></TD> <TD ALIGN="LEFT"><I>Name</I></TD> <TD ALIGN="LEFT"><I>Category</I></TD> <TD ALIGN="LEFT"><I>Type</I></TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_BCONNECT </TD> <TD ALIGN="LEFT">m_ctlConnect </TD> <TD ALIGN="LEFT">Control </TD> <TD ALIGN="LEFT">CButton </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_EMSG </TD> <TD ALIGN="LEFT">m_strMessage </TD> <TD ALIGN="LEFT">Value </TD> <TD ALIGN="LEFT">CString </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_ESERVNAME </TD> <TD ALIGN="LEFT">m_strName </TD> <TD ALIGN="LEFT">Value </TD> <TD ALIGN="LEFT">CString </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_ESERVPORT </TD> <TD ALIGN="LEFT">m_iPort </TD> <TD ALIGN="LEFT">Value </TD> <TD ALIGN="LEFT">int </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_LRECVD </TD> <TD ALIGN="LEFT">m_ctlRecvd </TD> <TD ALIGN="LEFT">Control </TD> <TD ALIGN="LEFT">CListBox </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_LSENT </TD> <TD ALIGN="LEFT">m_ctlSent </TD> <TD ALIGN="LEFT">Control </TD> <TD ALIGN="LEFT">CListBox </TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">IDC_RCLIENT </TD> <TD ALIGN="LEFT">m_iType </TD> <TD ALIGN="LEFT">Value </TD> <TD ALIGN="LEFT">int </TD> </TR></TABLE></P><P>So that you can reuse the Connect button to place the server application intolisten mode, you'll add a function to the clicked event message for both radio buttons,changing the text on the command button depending on which of the two is currentlyselected. To add this functionality to your application, add a function to the BN_CLICKEDevent message for the IDC_RCLIENT control ID, naming the function OnRType. Add thesame function to the BN_CLICKED event message for the IDC_RSERVER control ID. Editthis function, adding the code in Listing 20.1.</P><P><H4>LISTING 20.1. THE CSockDlg OnRType FUNCTION.</H4><PRE> 1: void CSockDlg::OnRType() 2: { 3: // TODO: Add your control notification handler code here 4: // Sync the controls with the variables 5: UpdateData(TRUE); 6: // Which mode are we in? 7: if (m_iType == 0) // Set the appropriate text on the button 8: m_ctlConnect.SetWindowText("C&onnect"); 9: else10: m_ctlConnect.SetWindowText("&Listen");11: }</PRE><P>Now, if you compile and run your application, you should be able to select oneand then the other of these two radio buttons, and the text on the command buttonshould change to reflect the part the application will play, as in Figure 20.5.</P><P><A HREF="javascript:popUp('20fig05.gif')"><B>FIGURE 20.5.</B></A><B> </B><I>Changingthe button text.</I></P><P><I></I><H3><A NAME="Heading11"></A>Inheriting from the CAsyncSocket Class</H3><P>So that you will be able to capture and respond to the socket events, you'll createyour own descendent class from CAsyncSocket. This class will need its own versionsof the event functions, as well as a means of passing this event to the dialog thatthe object will be a member of. So that you can pass each of these events to thedialog-class level, you'll add a pointer to the parent dialog class as a member variableof your socket class. You'll use this pointer to call event functions for each ofthe socket events that are member functions of the dialog, after checking to makesure that no errors have occurred (of course).</P><P>To create this class in your application, select Insert | New Class from the menu.In the New Class dialog, leave the class type with the default value of MFC Class.Enter a name for your class, such as CMySocket, and select CAsyncSocket from thelist of available base classes. This is all that you can specify on the New Classdialog, so click the OK button to add this new class to your application.</P><P>Once you have created the socket class, add a member variable to the class toserve as a pointer to the parent dialog window. Specify the variable type as CDialog*,the variable name as m_pWnd, and the access as private. You also need to add a methodto the class to set the pointer, so add a member function to your new socket class.Specify the function type as void, the declaration as SetParent(CDialog* pWnd), andthe access as public. Edit this new function, setting the pointer passed as a parameterto the member variable pointer, as in Listing 20.2.</P><P><H4>LISTING 20.2. THE CMySocket SetParent FUNCTION.</H4><PRE> 1: void CMySocket::SetParent(CDialog *pWnd) 2: { 3: // Set the member pointer 4: m_pWnd = pWnd; 5: }</PRE><P>The only other thing that you need to do to your socket class is add the eventfunctions, which you'll use to call similarly named functions on the dialog class.To add a function for the OnAccept event function, add a member function to yoursocket class. Specify the function type as void, the function declaration as OnAccept(intnErrorCode), and the access as protected and check the virtual check box. Edit thisfunction, adding the code in Listing 20.3.</P><P><H4>LISTING 20.3. The CMySocket OnAccept FUNCTION.</H4><PRE> 1: void CMySocket::OnAccept(int nErrorCode) 2: { 3: // Were there any errors? 4: if (nErrorCode == 0) 5: // No, call the dialog's OnAccept function 6: ((CSockDlg*)m_pWnd)->OnAccept(); 7: }</PRE><P>Add similar functions to your socket class for the OnConnect, OnClose, OnReceive,and OnSend functions, calling same-named functions in the dialog class, which you'lladd later. After you've added all these functions, you'll need to include the headerfile for your application dialog in your socket class, as in line 7 of Listing 20.4.</P><P><H4>LISTING 20.4. THE CMySocket INCLUDES.</H4><PRE>1: // MySocket.cpp: implementation file2: //3:4: #include "stdafx.h"5: #include "Sock.h"6: #include "MySocket.h"7: #include "SockDlg.h"</PRE><P>Once you've added all the necessary event functions to your socket class, you'lladd a variable of your socket class to the dialog class. For the server functionality,you'll need two variables in the dialog class, one to listen for connection requestsand the other to be connected to the other application. Because you will need twosocket objects, add two member variables to the dialog class (CSockDlg). Specifythe type of both variables as your socket class (CMySocket) and the access for bothas private. Name one variable m_sListenSocket, to be used for listening for connectionrequests, and the other m_sConnectSocket, to be used for sending messages back andforth.</P><P>Once you've added the socket variables, you'll add the initialization code forall the variables. As a default, set the application type to client, the server nameas loopback, and the port to 4000. Along with these variables, you'll set the parentdialog pointers in your two socket objects so that they point to the dialog class.You can do this by adding the code in Listing 20.5 to the OnInitDialog function inthe dialog class.</P><BLOCKQUOTE> <P><HR><STRONG>NOTE:</STRONG> The computer name loopback is a special name used in the TCP/IP network protocol to indicate the computer you are working on. It's an internal computer name that is resolved to the network address 127.0.0.1. This is a computer name and address that is commonly used by applications that need to connect to other applications running on the same computer.<HR></BLOCKQUOTE><H4>LISTING 20.5. THE CSockDlg OnInitDialog FUNCTION.</H4><PRE> 1: BOOL CSockDlg::OnInitDialog() 2: { 3: CDialog::OnInitDialog(); 4: 5: // Add "About..." menu item to system menu. 6:...26: SetIcon(m_hIcon, FALSE); // Set small icon27:28: // TODO: Add extra initialization here29: // Initialize the control variables30: m_iType = 0;31: m_strName = "loopback";32: m_iPort = 4000;33: // Update the controls34: UpdateData(FALSE);35: // Set the socket dialog pointers36: m_sConnectSocket.SetParent(this);37: m_sListenSocket.SetParent(this);38:39: return TRUE; // return TRUE unless you set the focus to a Âcontrol40: }</PRE><H3><A NAME="Heading12"></A>Connecting the Application</H3><P>When the user clicks the Connect button, you'll disable all the top controls onthe dialog. At this point, you don't want the user to think that she is able to changethe settings of the computer that she's connecting to or change how the applicationis listening. You'll call the Create function on the appropriate socket variable,depending on whether the application is running as the client or server. Finally,you'll call either the Connect or Listen function to initiate the application's sideof the connection. To add this functionality to your application, open the ClassWizard and add a function to the BN_CLICKED event message for the Connect button(ID IDC_BCONNECT). Edit this function, adding the code in Listing 20.6.</P><P><H4>LISTING 20.6. The CSockDlg OnBconnect FUNCTION.</H4><PRE> 1: void CSockDlg::OnBconnect() 2: { 3: // TODO: Add your control notification handler code here 4: // Sync the variables with the controls 5: UpdateData(TRUE); 6: // Disable the connection and type controls 7: GetDlgItem(IDC_BCONNECT)->EnableWindow(FALSE); 8: GetDlgItem(IDC_ESERVNAME)->EnableWindow(FALSE); 9: GetDlgItem(IDC_ESERVPORT)->EnableWindow(FALSE);10: GetDlgItem(IDC_STATICNAME)->EnableWindow(FALSE);11: GetDlgItem(IDC_STATICPORT)->EnableWindow(FALSE);12: GetDlgItem(IDC_RCLIENT)->EnableWindow(FALSE);13: GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);14: GetDlgItem(IDC_STATICTYPE)->EnableWindow(FALSE);15: // Are we running as client or server?16: if (m_iType == 0)17: {18: // Client, create a default socket19: m_sConnectSocket.Create();20: // Open the connection to the server21: m_sConnectSocket.Connect(m_strName, m_iPort);22: }23: else24: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -