📄 netconnect.cpp
字号:
//-----------------------------------------------------------------------------
// File: NetConnect.cpp
//
// Desc: This is a class that given a IDirectPlay8Peer, then DoConnectWizard()
// will enumerate service providers, enumerate hosts, and allow the
// user to either join or host a session. The class uses
// dialog boxes and GDI for the interactive UI. Most games will
// want to change the graphics to use Direct3D or another graphics
// layer, but this simplistic sample uses dialog boxes. Feel
// free to use this class as a starting point for adding extra
// functionality.
//
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <basetsd.h>
#include <stdio.h>
#include <mmsystem.h>
#include <dxerr8.h>
#include <dplay8.h>
#include <dpaddr.h>
#include <dplobby8.h>
#include "NetConnect.h"
#include "NetConnectRes.h"
#include "DXUtil.h"
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
CNetConnectWizard* g_pNCW = NULL; // Pointer to the net connect wizard
//-----------------------------------------------------------------------------
// Name: CNetConnectWizard
// Desc: Init the class
//-----------------------------------------------------------------------------
CNetConnectWizard::CNetConnectWizard( HINSTANCE hInst, TCHAR* strAppName,
GUID* pGuidApp )
{
g_pNCW = this;
m_hInst = hInst;
m_pDP = NULL;
m_pLobbiedApp = NULL;
m_bHaveConnectionSettingsFromLobby = FALSE;
m_hLobbyClient = NULL;
m_guidApp = *pGuidApp;
m_hDlg = NULL;
m_bConnecting = FALSE;
m_hConnectAsyncOp = NULL;
m_pDeviceAddress = NULL;
m_pHostAddress = NULL;
m_hEnumAsyncOp = NULL;
m_dwEnumHostExpireInterval = 0;
// Set the max players unlimited by default. This can be changed by the app
// by calling SetMaxPlayers()
m_dwMaxPlayers = 0;
_tcscpy( m_strAppName, strAppName );
_tcscpy( m_strPreferredProvider, TEXT("DirectPlay8 TCP/IP Service Provider") );
InitializeCriticalSection( &m_csHostEnum );
m_hConnectCompleteEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_hLobbyConnectionEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
// Setup the m_DPHostEnumHead circular linked list
ZeroMemory( &m_DPHostEnumHead, sizeof( DPHostEnumInfo ) );
m_DPHostEnumHead.pNext = &m_DPHostEnumHead;
}
//-----------------------------------------------------------------------------
// Name: ~CNetConnectWizard
// Desc: Cleanup the class
//-----------------------------------------------------------------------------
CNetConnectWizard::~CNetConnectWizard()
{
DeleteCriticalSection( &m_csHostEnum );
CloseHandle( m_hConnectCompleteEvent );
CloseHandle( m_hLobbyConnectionEvent );
}
//-----------------------------------------------------------------------------
// Name: Init
// Desc:
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::Init( IDirectPlay8Peer* pDP,
IDirectPlay8LobbiedApplication* pLobbiedApp )
{
m_pDP = pDP;
m_pLobbiedApp = pLobbiedApp;
m_bHaveConnectionSettingsFromLobby = FALSE;
m_hLobbyClient = NULL;
}
//-----------------------------------------------------------------------------
// Name: Shutdown
// Desc: Releases the DirectPlay interfaces
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::Shutdown()
{
SAFE_RELEASE( m_pDeviceAddress );
SAFE_RELEASE( m_pHostAddress );
}
//-----------------------------------------------------------------------------
// Name: DoConnectWizard
// Desc: This is the main external function. This will launch a series of
// dialog boxes that enumerate service providers, enumerate hosts,
// and allow the user to either join or host a session
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::DoConnectWizard( BOOL bBackTrack )
{
if( m_pDP == NULL )
return E_INVALIDARG;
int nStep;
// If the back track flag is true, then the user has already been through
// the connect process once, and has back tracked out of the main game
// so start at the last dialog box
if( bBackTrack )
nStep = 1;
else
nStep = 0;
// Show the dialog boxes to connect
while( TRUE )
{
m_hrDialog = S_OK;
switch( nStep )
{
case 0:
// Display the multiplayer connect dialog box.
DialogBox( m_hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CONNECT),
NULL, (DLGPROC) StaticConnectionsDlgProc );
break;
case 1:
// Display the multiplayer games dialog box.
DialogBox( m_hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_GAMES),
NULL, (DLGPROC) StaticSessionsDlgProc );
break;
}
if( FAILED( m_hrDialog ) ||
m_hrDialog == NCW_S_QUIT ||
m_hrDialog == NCW_S_LOBBYCONNECT )
break;
if( m_hrDialog == NCW_S_BACKUP )
nStep--;
else
nStep++;
// If we go beyond the last step in the wizard, then stop
// and return.
if( nStep == 2 )
break;
}
// Depending upon a successful m_hrDialog the user has
// either successfully join or created a game, depending on m_bHostPlayer
m_pDP = NULL;
return m_hrDialog;
}
//-----------------------------------------------------------------------------
// Name: StaticConnectionsDlgProc()
// Desc: Static msg handler which passes messages
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetConnectWizard::StaticConnectionsDlgProc( HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
if( g_pNCW )
return g_pNCW->ConnectionsDlgProc( hDlg, uMsg, wParam, lParam );
return FALSE; // Message not handled
}
//-----------------------------------------------------------------------------
// Name: ConnectionsDlgProc()
// Desc: Handles messages for the multiplayer connect dialog
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetConnectWizard::ConnectionsDlgProc( HWND hDlg, UINT msg,
WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_INITDIALOG:
{
SetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, m_strLocalPlayerName );
// Load and set the icon
HICON hIcon = LoadIcon( m_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
SendMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon
SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon
// Set the window title
TCHAR strWindowTitle[256];
wsprintf( strWindowTitle, TEXT("%s - Multiplayer Connect"), m_strAppName );
SetWindowText( hDlg, strWindowTitle );
// Fill the list box with the service providers
if( FAILED( m_hrDialog = ConnectionsDlgFillListBox( hDlg ) ) )
{
DXTRACE_ERR( TEXT("ConnectionsDlgFillListBox"), m_hrDialog );
EndDialog( hDlg, 0 );
}
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_CONNECTION_LIST: if( HIWORD(wParam) != LBN_DBLCLK )
break;
// Fall through
case IDOK:
if( FAILED( m_hrDialog = ConnectionsDlgOnOK( hDlg ) ) )
{
DXTRACE_ERR( TEXT("ConnectionsDlgOnOK"), m_hrDialog );
EndDialog( hDlg, 0 );
}
if( m_hrDialog == NCW_S_LOBBYCONNECT )
{
EndDialog( hDlg, 0 );
}
break;
case IDCANCEL:
m_hrDialog = NCW_S_QUIT;
EndDialog( hDlg, 0 );
break;
default:
return FALSE; // Message not handled
}
break;
case WM_DESTROY:
ConnectionsDlgCleanup( hDlg );
break;
default:
return FALSE; // Message not handled
}
// Message was handled
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: ConnectionsDlgFillListBox()
// Desc: Fills the DirectPlay connection listbox with service providers,
// and also adds a "Wait for Lobby" connection option.
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::ConnectionsDlgFillListBox( HWND hDlg )
{
HRESULT hr;
int iLBIndex;
DWORD dwItems = 0;
DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
DWORD dwSize = 0;
HWND hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
TCHAR strName[MAX_PATH];
// Enumerate all DirectPlay service providers, and store them in the listbox
hr = m_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo, &dwSize,
&dwItems, 0 );
if( hr != DPNERR_BUFFERTOOSMALL )
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
if( FAILED( hr = m_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo,
&dwSize, &dwItems, 0 ) ) )
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
for ( DWORD i = 0; i < dwItems; i++ )
{
DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
// Found a service provider, so put it in the listbox
iLBIndex = (int)SendMessage( hWndListBox, LB_ADDSTRING, 0,
(LPARAM)strName );
if( iLBIndex == CB_ERR )
return E_FAIL; // Error, stop enumerating
// Store pointer to GUID in listbox
GUID* pGuid = new GUID;
memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
SendMessage( hWndListBox, LB_SETITEMDATA, iLBIndex,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -