📄 netconnect.cpp
字号:
if( nItemSelected != LB_ERR )
{
pDPHostEnumSelected = (DPHostEnumInfo*) SendMessage( hWndListBox, LB_GETITEMDATA,
nItemSelected, 0 );
if( pDPHostEnumSelected != NULL && pDPHostEnumSelected->bValid )
{
guidSelectedInstance = pDPHostEnumSelected->pAppDesc->guidInstance;
bFindSelectedGUID = TRUE;
}
}
// Tell listbox not to redraw itself since the contents are going to change
SendMessage( hWndListBox, WM_SETREDRAW, FALSE, 0 );
// Test to see if any sessions exist in the linked list
DPHostEnumInfo* pDPHostEnum = m_DPHostEnumHead.pNext;
while ( pDPHostEnum != &m_DPHostEnumHead )
{
if( pDPHostEnum->bValid )
break;
pDPHostEnum = pDPHostEnum->pNext;
}
// If there are any sessions in list,
// then add them to the listbox
if( pDPHostEnum != &m_DPHostEnumHead )
{
// Clear the contents from the list box and enable the join button
SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
// Enable the join button only if not already connecting to a game
if( !m_bConnecting )
EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), TRUE );
pDPHostEnum = m_DPHostEnumHead.pNext;
while ( pDPHostEnum != &m_DPHostEnumHead )
{
// Add host to list box if it is valid
if( pDPHostEnum->bValid )
{
int nIndex = (int)SendMessage( hWndListBox, LB_ADDSTRING, 0,
(LPARAM)pDPHostEnum->szSession );
SendMessage( hWndListBox, LB_SETITEMDATA, nIndex, (LPARAM)pDPHostEnum );
if( bFindSelectedGUID )
{
// Look for the session the was selected before
if( pDPHostEnum->pAppDesc->guidInstance == guidSelectedInstance )
{
SendMessage( hWndListBox, LB_SETCURSEL, nIndex, 0 );
bFoundSelectedGUID = TRUE;
}
}
}
pDPHostEnum = pDPHostEnum->pNext;
}
if( !bFindSelectedGUID || !bFoundSelectedGUID )
SendMessage( hWndListBox, LB_SETCURSEL, 0, 0 );
}
else
{
// There are no active session, so just reset the listbox
SessionsDlgInitListbox( hDlg );
}
// Tell listbox to redraw itself now since the contents have changed
SendMessage( hWndListBox, WM_SETREDRAW, TRUE, 0 );
InvalidateRect( hWndListBox, NULL, FALSE );
LeaveCriticalSection( &m_csHostEnum );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: SessionsDlgJoinGame()
// Desc: Joins the selected DirectPlay session
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::SessionsDlgJoinGame( HWND hDlg )
{
HRESULT hr;
HWND hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
DPHostEnumInfo* pDPHostEnumSelected = NULL;
int nItemSelected;
DWORD dwPort = 0;
m_bHostPlayer = FALSE;
// Add status text in list box
nItemSelected = (int)SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
EnterCriticalSection( &m_csHostEnum );
pDPHostEnumSelected = (DPHostEnumInfo*) SendMessage( hWndListBox, LB_GETITEMDATA,
nItemSelected, 0 );
if( NULL == pDPHostEnumSelected )
{
LeaveCriticalSection( &m_csHostEnum );
MessageBox( hDlg, TEXT("There are no games to join."),
TEXT("DirectPlay Sample"), MB_OK );
return S_OK;
}
m_bConnecting = TRUE;
// Set the peer info
WCHAR wszPeerName[MAX_PATH];
DXUtil_ConvertGenericStringToWide( wszPeerName, m_strLocalPlayerName );
DPN_PLAYER_INFO dpPlayerInfo;
ZeroMemory( &dpPlayerInfo, sizeof(DPN_PLAYER_INFO) );
dpPlayerInfo.dwSize = sizeof(DPN_PLAYER_INFO);
dpPlayerInfo.dwInfoFlags = DPNINFO_NAME;
dpPlayerInfo.pwszName = wszPeerName;
// Set the peer info, and use the DPNOP_SYNC since by default this
// is an async call. If it is not DPNOP_SYNC, then the peer info may not
// be set by the time we call Connect() below.
if( FAILED( hr = m_pDP->SetPeerInfo( &dpPlayerInfo, NULL, NULL, DPNOP_SYNC ) ) )
return DXTRACE_ERR( TEXT("SetPeerInfo"), hr );
ResetEvent( m_hConnectCompleteEvent );
// Connect to an existing session. DPNCONNECT_OKTOQUERYFORADDRESSING allows
// DirectPlay to prompt the user using a dialog box for any device address
// or host address information that is missing
// We also pass in copies of the app desc and host addr, since pDPHostEnumSelected
// might be deleted from another thread that calls SessionsDlgExpireOldHostEnums().
// This process could also be done using reference counting instead.
hr = m_pDP->Connect( pDPHostEnumSelected->pAppDesc, // the application desc
pDPHostEnumSelected->pHostAddr, // address of the host of the session
pDPHostEnumSelected->pDeviceAddr, // address of the local device the enum responses were received on
NULL, NULL, // DPN_SECURITY_DESC, DPN_SECURITY_CREDENTIALS
NULL, 0, // user data, user data size
NULL, // player context,
NULL, &m_hConnectAsyncOp, // async context, async handle,
DPNCONNECT_OKTOQUERYFORADDRESSING ); // flags
if( hr != E_PENDING && FAILED(hr) )
return DXTRACE_ERR( TEXT("Connect"), hr );
LeaveCriticalSection( &m_csHostEnum );
// Set a timer to wait for m_hConnectCompleteEvent to be signaled.
// This will tell us when DPN_MSGID_CONNECT_COMPLETE has been processed
// which lets us know if the connect was successful or not.
SetTimer( hDlg, TIMERID_CONNECT_COMPLETE, 100, NULL );
// Disable the create/join buttons until connect succeeds or fails
EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), FALSE );
EnableWindow( GetDlgItem( hDlg, IDC_CREATE ), FALSE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: SessionsDlgCreateGame()
// Desc: Asks the user the session name, and creates a new DirectPlay session
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::SessionsDlgCreateGame( HWND hDlg )
{
HRESULT hr;
int nResult;
// Display a modal multiplayer connect dialog box.
EnableWindow( hDlg, FALSE );
nResult = (int)DialogBox( m_hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CREATE),
hDlg, (DLGPROC) StaticCreateSessionDlgProc );
EnableWindow( hDlg, TRUE );
if( nResult == IDCANCEL )
return S_OK;
// Stop the search if we are about to connect
if( m_bSearchingForSessions )
{
CheckDlgButton( m_hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
SendMessage( m_hDlg, WM_COMMAND, IDC_SEARCH_CHECK, 0 );
}
m_bHostPlayer = TRUE;
// Set peer info name
WCHAR wszPeerName[MAX_PATH];
DXUtil_ConvertGenericStringToWide( wszPeerName, m_strLocalPlayerName );
DPN_PLAYER_INFO dpPlayerInfo;
ZeroMemory( &dpPlayerInfo, sizeof(DPN_PLAYER_INFO) );
dpPlayerInfo.dwSize = sizeof(DPN_PLAYER_INFO);
dpPlayerInfo.dwInfoFlags = DPNINFO_NAME;
dpPlayerInfo.pwszName = wszPeerName;
// Set the peer info, and use the DPNOP_SYNC since by default this
// is an async call. If it is not DPNOP_SYNC, then the peer info may not
// be set by the time we call Host() below.
if( FAILED( hr = m_pDP->SetPeerInfo( &dpPlayerInfo, NULL, NULL, DPNOP_SYNC ) ) )
return DXTRACE_ERR( TEXT("SetPeerInfo"), hr );
WCHAR wszSessionName[MAX_PATH];
DXUtil_ConvertGenericStringToWide( wszSessionName, m_strSessionName );
// Setup the application desc
DPN_APPLICATION_DESC dnAppDesc;
ZeroMemory( &dnAppDesc, sizeof(DPN_APPLICATION_DESC) );
dnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
dnAppDesc.guidApplication = m_guidApp;
dnAppDesc.pwszSessionName = wszSessionName;
dnAppDesc.dwMaxPlayers = m_dwMaxPlayers;
dnAppDesc.dwFlags = 0;
if( m_bMigrateHost )
dnAppDesc.dwFlags |= DPNSESSION_MIGRATE_HOST;
// Host a game on m_pDeviceAddress as described by dnAppDesc
// DPNHOST_OKTOQUERYFORADDRESSING allows DirectPlay to prompt the user
// using a dialog box for any device address information that is missing
if( FAILED( hr = m_pDP->Host( &dnAppDesc, // the application desc
&m_pDeviceAddress, // array of addresses of the local devices used to connect to the host
1, // number in array
NULL, NULL, // DPN_SECURITY_DESC, DPN_SECURITY_CREDENTIALS
NULL, // player context
DPNHOST_OKTOQUERYFORADDRESSING ) ) ) // flags
return DXTRACE_ERR( TEXT("Host"), hr );
// DirectPlay connect successful, so end dialog
m_hrDialog = NCW_S_FORWARD;
EndDialog( hDlg, 0 );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: StaticConnectionsDlgProc()
// Desc: Static msg handler which passes messages
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetConnectWizard::StaticCreateSessionDlgProc( HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
if( g_pNCW )
return g_pNCW->CreateSessionDlgProc( hDlg, uMsg, wParam, lParam );
return FALSE; // Message not handled
}
//-----------------------------------------------------------------------------
// Name: CreateSessionDlgProc()
// Desc: Handles messages fro the multiplayer create game dialog
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetConnectWizard::CreateSessionDlgProc( HWND hDlg, UINT msg,
WPARAM wParam, LPARAM lParam )
{
DWORD dwNameLength;
switch( msg )
{
case WM_INITDIALOG:
SetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME, m_strSessionName );
CheckDlgButton( hDlg, IDC_MIGRATE_HOST, BST_CHECKED );
return TRUE;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDOK:
dwNameLength = GetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME,
m_strSessionName,
MAX_PATH );
if( dwNameLength == 0 )
return TRUE; // Don't accept blank session names
m_bMigrateHost = ( IsDlgButtonChecked( hDlg,
IDC_MIGRATE_HOST ) == BST_CHECKED );
EndDialog( hDlg, IDOK );
return TRUE;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
return TRUE;
}
break;
}
return FALSE; // Didn't handle message
}
//-----------------------------------------------------------------------------
// Name: SessionsDlgEnumListCleanup()
// Desc: Deletes the linked list, g_DPHostEnumInfoHead
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::SessionsDlgEnumListCleanup()
{
DPHostEnumInfo* pDPHostEnum = m_DPHostEnumHead.pNext;
DPHostEnumInfo* pDPHostEnumDelete;
while ( pDPHostEnum != &m_DPHostEnumHead )
{
pDPHostEnumDelete = pDPHostEnum;
pDPHostEnum = pDPHostEnum->pNext;
if( pDPHostEnumDelete->pAppDesc )
{
SAFE_DELETE_ARRAY( pDPHostEnumDelete->pAppDesc->pwszSessionName );
SAFE_DELETE_ARRAY( pDPHostEnumDelete->pAppDesc );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -