📄 netclient.cpp
字号:
//-----------------------------------------------------------------------------
// File: NetClient.cpp
//
// Desc: This is a class that given a IDirectPlay8Client upon DoConnectWizard()
// will enumerate hosts, and allows the user to join 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 "NetClient.h"
#include "NetClientRes.h"
#include "DXUtil.h"
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
CNetClientWizard* g_pNCW = NULL; // Pointer to the net connect wizard
//-----------------------------------------------------------------------------
// Name: CNetClientWizard
// Desc: Init the class
//-----------------------------------------------------------------------------
CNetClientWizard::CNetClientWizard( HINSTANCE hInst, TCHAR* strAppName,
GUID* pGuidApp )
{
g_pNCW = this;
m_hInst = hInst;
m_guidApp = *pGuidApp;
_tcscpy( m_strAppName, strAppName );
m_dwEnumHostExpireInterval = 0;
m_hConnectCompleteEvent = NULL;
m_hrConnectComplete = 0;
m_bConnecting = FALSE;
m_bEnumListChanged = FALSE;
m_bSearchingForSessions = FALSE;
m_hEnumAsyncOp = NULL;
m_hConnectAsyncOp = NULL;
m_pDPClient = NULL;
m_pLobbiedApp = NULL;
m_bHaveConnectionSettingsFromLobby = FALSE;
m_hLobbyClient = NULL;
m_hDlg = NULL;
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: ~CNetClientWizard
// Desc: Cleanup the class
//-----------------------------------------------------------------------------
CNetClientWizard::~CNetClientWizard()
{
DeleteCriticalSection( &m_csHostEnum );
CloseHandle( m_hConnectCompleteEvent );
CloseHandle( m_hLobbyConnectionEvent );
}
//-----------------------------------------------------------------------------
// Name: Init
// Desc:
//-----------------------------------------------------------------------------
VOID CNetClientWizard::Init( IDirectPlay8Client* pDPClient,
IDirectPlay8LobbiedApplication* pLobbiedApp )
{
m_pDPClient = pDPClient;
m_pLobbiedApp = pLobbiedApp;
m_bHaveConnectionSettingsFromLobby = FALSE;
m_hLobbyClient = NULL;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CNetClientWizard::DoConnectWizard()
{
m_hrDialog = S_OK;
// Display the multiplayer games dialog box.
DialogBox( m_hInst, MAKEINTRESOURCE(IDD_CLIENT_CONNECT), NULL,
(DLGPROC) StaticSessionsDlgProc );
return m_hrDialog;
}
//-----------------------------------------------------------------------------
// Name: StaticSessionsDlgProc()
// Desc: Static msg handler which passes messages
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetClientWizard::StaticSessionsDlgProc( HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
if( g_pNCW )
return g_pNCW->SessionsDlgProc( hDlg, uMsg, wParam, lParam );
return FALSE; // Message not handled
}
//-----------------------------------------------------------------------------
// Name: SessionsDlgProc()
// Desc: Handles messages for the multiplayer games dialog
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetClientWizard::SessionsDlgProc( HWND hDlg, UINT msg,
WPARAM wParam, LPARAM lParam )
{
HRESULT hr;
switch( msg )
{
case WM_INITDIALOG:
{
// 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
SetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, m_strLocalPlayerName );
// Set the window title
TCHAR strWindowTitle[256];
wsprintf( strWindowTitle, TEXT("%s - Multiplayer Games"), m_strAppName );
SetWindowText( hDlg, strWindowTitle );
// Init the search portion of the dialog
m_bSearchingForSessions = FALSE;
SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Start Search") );
SessionsDlgInitListbox( hDlg );
}
break;
case WM_TIMER:
// Upon this timer message, then refresh the list of hosts
// by expiring old hosts, and displaying the list in the
// dialog box
if( wParam == TIMERID_DISPLAY_HOSTS )
{
// Don't refresh if we are not enumerating hosts
if( !m_bSearchingForSessions )
break;
// Expire all of the hosts that haven't
// refreshed in a certain period of time
SessionsDlgExpireOldHostEnums();
// Display the list of hosts in the dialog
if( FAILED( hr = SessionsDlgDisplayEnumList( hDlg ) ) )
{
DXTRACE_ERR( TEXT("SessionsDlgEnumHosts"), hr );
MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
m_strAppName, MB_OK | MB_ICONERROR );
m_bSearchingForSessions = FALSE;
KillTimer( hDlg, TIMERID_DISPLAY_HOSTS );
CheckDlgButton( hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Start Search") );
SessionsDlgInitListbox( hDlg );
}
}
else if( wParam == TIMERID_CONNECT_COMPLETE )
{
// Check to see if the MessageHandler has set an event to tell us the
// DPN_MSGID_CONNECT_COMPLETE has been processed. Now m_hrConnectComplete
// is valid.
if( WAIT_OBJECT_0 == WaitForSingleObject( m_hConnectCompleteEvent, 0 ) )
{
m_bConnecting = FALSE;
if( FAILED( m_hrConnectComplete ) )
{
DXTRACE_ERR( TEXT("DPN_MSGID_CONNECT_COMPLETE"), m_hrConnectComplete );
MessageBox( hDlg, TEXT("Unable to join game."),
m_strAppName, MB_OK | MB_ICONERROR );
}
else
{
// DirectPlay connect successful, so end dialog
m_hrDialog = NCW_S_FORWARD;
EndDialog( hDlg, 0 );
}
}
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_SEARCH_CHECK:
m_bSearchingForSessions = !m_bSearchingForSessions;
if( m_bSearchingForSessions )
{
SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Searching...") );
// Start the timer to display the host list every so often
SetTimer( hDlg, TIMERID_DISPLAY_HOSTS, DISPLAY_REFRESH_RATE, NULL );
// Start the async enumeration
if( FAILED( hr = SessionsDlgEnumHosts( hDlg ) ) )
{
if( hr == DPNERR_ADDRESSING )
{
// This will be returned if the ip address is invalid
// for example something like "asdf"
MessageBox( hDlg, TEXT("IP address not valid. Stopping search"),
m_strAppName, MB_OK );
}
else
{
DXTRACE_ERR( TEXT("SessionsDlgEnumHosts"), hr );
MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
m_strAppName, MB_OK | MB_ICONERROR );
}
m_bSearchingForSessions = FALSE;
KillTimer( hDlg, TIMERID_DISPLAY_HOSTS );
CheckDlgButton( hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Start Search") );
SessionsDlgInitListbox( hDlg );
}
}
else
{
SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Start Search") );
// Stop the timer, and stop the async enumeration
KillTimer( hDlg, TIMERID_DISPLAY_HOSTS );
// Until the CancelAsyncOperation returns, it is possible
// to still receive host enumerations
if( m_hEnumAsyncOp )
m_pDPClient->CancelAsyncOperation( m_hEnumAsyncOp, 0 );
// Reset the search portion of the dialog
SessionsDlgInitListbox( hDlg );
}
break;
case IDC_GAMES_LIST:
if( HIWORD(wParam) != LBN_DBLCLK )
break;
// Fall through
case IDC_JOIN:
if( FAILED( hr = SessionsDlgJoinGame( hDlg ) ) )
{
DXTRACE_ERR( TEXT("SessionsDlgJoinGame"), hr );
MessageBox( hDlg, TEXT("Unable to join game."),
TEXT("DirectPlay Sample"),
MB_OK | MB_ICONERROR );
}
break;
case IDCANCEL: // The close button was press
m_hrDialog = NCW_S_QUIT;
EndDialog( hDlg, 0 );
break;
default:
return FALSE; // Message not handled
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -