⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netconnect.cpp

📁 Visual C++ 游戏开发与设计实例 源代码(所有)
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                    }
                    break;

                case IDC_CREATE:
                    if( FAILED( hr = SessionsDlgCreateGame( hDlg ) ) )
                    {
                        DXTRACE_ERR_MSGBOX( TEXT("SessionsDlgCreateGame"), hr );
                        MessageBox( hDlg, TEXT("Unable to create 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;

                case IDC_BACK: // Cancel button was pressed
                    m_hrDialog = NCW_S_BACKUP;
                    EndDialog(hDlg, 0);
                    break;

                default:
                    return FALSE; // Message not handled
            }
            break;
        
            case WM_DESTROY:
                SessionsDlgStopEnumHosts(hDlg);
                break;

        default:
            return FALSE; // Message not handled
    }

    // Message was handled
    return TRUE;
}




//-----------------------------------------------------------------------------
// Name: SessionsDlgInitListbox()
// Desc: Initializes the listbox
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::SessionsDlgInitListbox( HWND hDlg )
{
    HWND hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );

    // Clear the contents from the list box, and
    // display "Looking for games" text in listbox
    SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
    if( m_bSearchingForSessions )
    {
        SendMessage( hWndListBox, LB_ADDSTRING, 0,
                     (LPARAM) TEXT("Looking for games...") );
    }
    else
    {
        SendMessage( hWndListBox, LB_ADDSTRING, 0,
                     (LPARAM) TEXT("Click Start Search to see a list of games."));
        SendMessage( hWndListBox, LB_ADDSTRING, 0,
                     (LPARAM) TEXT("Click Create to start a new game.") );
    }

    SendMessage( hWndListBox, LB_SETITEMDATA,  0, NULL );
    SendMessage( hWndListBox, LB_SETCURSEL,    0, 0 );

    // Disable the join button until sessions are found
    EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), FALSE );
}




//-----------------------------------------------------------------------------
// Name: SessionsDlgEnumHosts()
// Desc: Enumerates the DirectPlay sessions, and displays them in the listbox
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::SessionsDlgEnumHosts( HWND hDlg )
{
    UNREFERENCED_PARAMETER( hDlg );
    HRESULT hr = S_OK;

    m_bEnumListChanged = TRUE;

    IDirectPlay8Address*   pDP8AddressHost  = NULL;
    IDirectPlay8Address*   pDP8AddressLocal = NULL;

    // Create the local device address object
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
                                       CLSCTX_ALL, IID_IDirectPlay8Address,
                                       (LPVOID*) &pDP8AddressLocal ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
        goto LCleanup;
    }

    // Set local service provider
    if( FAILED( hr = pDP8AddressLocal->SetSP( &m_guidSP ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("SetSP"), hr );
        goto LCleanup;
    }

    // Create the remote host address object
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
                                       CLSCTX_ALL, IID_IDirectPlay8Address,
                                       (LPVOID*) &pDP8AddressHost ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
        goto LCleanup;
    }

    // Set remote service provider
    if( FAILED( hr = pDP8AddressHost->SetSP( &m_guidSP ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("SetSP"), hr );
        goto LCleanup;
    }

    // If we're using a TCP/IP (including network simulator) or IPX
    // service provider, the user was given an option for hostname and
    // port before the search started. 
    if( SPRequiresPort( &m_guidSP ) ) 
    {
        // Add the hostname. If this is blank, DirectPlay will attempt
        // to search the local network.
        if( _tcscmp(m_strHostname, TEXT("")) != 0 )
        {
            WCHAR wszHostName[MAX_PATH];
            DXUtil_ConvertGenericStringToWideCch( wszHostName, m_strHostname, MAX_PATH );
            hr = pDP8AddressHost->AddComponent( DPNA_KEY_HOSTNAME, wszHostName, 
                                                (DWORD) (wcslen(wszHostName)+1)*sizeof(WCHAR), 
                                                DPNA_DATATYPE_STRING );
            if( FAILED(hr) )
            {
                DXTRACE_ERR_MSGBOX( TEXT("AddComponent"), hr );
                goto LCleanup;
            }
        }

        // Add the requested port value. The port value is required in order to
        // receive any search hits if DPNSVR isn't running on the remote machine.
        // Games will typically hard code the port so the user need not know it
        if( m_dwPort != 0 )
        {
            hr = pDP8AddressHost->AddComponent( DPNA_KEY_PORT, 
                                                &m_dwPort, sizeof(m_dwPort),
                                                DPNA_DATATYPE_DWORD );
            if( FAILED(hr) )
            {
                DXTRACE_ERR_MSGBOX( TEXT("AddComponent"), hr );
                goto LCleanup;
            }
        }
    }

    // Enumerate hosts
    DPN_APPLICATION_DESC    dnAppDesc;
    ZeroMemory( &dnAppDesc, sizeof(DPN_APPLICATION_DESC) );
    dnAppDesc.dwSize          = sizeof(DPN_APPLICATION_DESC);
    dnAppDesc.guidApplication = m_guidApp;

    DWORD dwFlags;
    dwFlags = 0;

    // For certain service providers the user has not been
    // asked to fill in the components of the remote address,
    // so DirectPlay should ask for required fields.
    if( !SPRequiresPort( &m_guidSP ) )
    {
        dwFlags = DPNENUMHOSTS_OKTOQUERYFORADDRESSING;
    }

    // Enumerate all the active DirectPlay games on the selected connection
    hr = m_pDP->EnumHosts( &dnAppDesc,                            // application description
                           pDP8AddressHost,                       // host address
                           pDP8AddressLocal,                      // device address
                           NULL,                                  // pointer to user data
                           0,                                     // user data size
                           INFINITE,                              // retry count (forever)
                           0,                                     // retry interval (0=default)
                           INFINITE,                              // time out (forever)
                           NULL,                                  // user context
                           &m_hEnumAsyncOp,                       // async handle
                           dwFlags                                // flags
                           );
    if( FAILED(hr) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("EnumHosts"), hr );
        goto LCleanup;
    }

LCleanup:
    SAFE_RELEASE( pDP8AddressHost);
    SAFE_RELEASE( pDP8AddressLocal );

    return hr;
}




//-----------------------------------------------------------------------------
// Name: SessionsDlgStopEnumHosts()
// Desc: Stops the running session enumeration
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::SessionsDlgStopEnumHosts( HWND hDlg )
{
    HRESULT hr;

    // Update the UI 
    EnableWindow( GetDlgItem( hDlg, IDC_SEARCH_CHECK ), FALSE );
    SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Stopping...") );

    // 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. Instruct DirectPlay to
    // stop the current enumeration and handle the rest of the cleanup
    // when receiving the ASYNC_OP_COMPLETE message. If this method
    // fails we should assume there's no active enumeration and call
    // the finalization method directly.
    if( m_hEnumAsyncOp )
    {
        hr = m_pDP->CancelAsyncOperation( m_hEnumAsyncOp, 0 );
        if( FAILED(hr) )
            SessionsDlgFinalizeEnumHosts( hDlg );
    }
    else
    {
        SessionsDlgFinalizeEnumHosts( hDlg );
    }
}




//-----------------------------------------------------------------------------
// Name: SessionsDlgFinalizeEnumHosts()
// Desc: This method should be called when we receive confirmation from 
//       DirectPlay that the enumeration has completed. It reset the search
//       UI and state variables, and enables the search button.
//-----------------------------------------------------------------------------
VOID CNetConnectWizard::SessionsDlgFinalizeEnumHosts( HWND hDlg )
{
    // Clear the data list
    SessionsDlgEnumListCleanup();

    // Reset the search state variables
    m_hEnumAsyncOp = NULL;
    m_bSearchingForSessions = FALSE;
    
    // Reset the search portion of the dialog
    SessionsDlgInitListbox( hDlg ); 
    CheckDlgButton( hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
    SetDlgItemText( hDlg, IDC_SEARCH_CHECK, TEXT("Start &Search") );
    EnableWindow( GetDlgItem( hDlg, IDC_SEARCH_CHECK ), TRUE );
}




//-----------------------------------------------------------------------------
// Name: SessionsDlgNoteEnumResponse()
// Desc: Stores them in the linked list, m_DPHostEnumHead.  This is
//       called from the DirectPlay message handler so it could be
//       called simultaneously from multiple threads.
//-----------------------------------------------------------------------------
HRESULT CNetConnectWizard::SessionsDlgNoteEnumResponse( PDPNMSG_ENUM_HOSTS_RESPONSE pEnumHostsResponseMsg )
{
    HRESULT hr = S_OK;
    BOOL    bFound;

    // This function is called from the DirectPlay message handler so it could be
    // called simultaneously from multiple threads, so enter a critical section
    // to assure that it we don't get race conditions.  Locking the entire
    // function is crude, and could be more optimal but is effective for this
    // simple sample
    EnterCriticalSection( &m_csHostEnum );

    DPHostEnumInfo* pDPHostEnum          = m_DPHostEnumHead.pNext;
    DPHostEnumInfo* pDPHostEnumNext      = NULL;
    const DPN_APPLICATION_DESC* pResponseMsgAppDesc =
                            pEnumHostsResponseMsg->pApplicationDescription;

    // Look for a matching session instance GUID.
    bFound = FALSE;
    while ( pDPHostEnum != &m_DPHostEnumHead )
    {
        if( pResponseMsgAppDesc->guidInstance == pDPHostEnum->pAppDesc->guidInstance )
        {
            bFound = TRUE;
            break;
        }

        pDPHostEnumNext = pDPHostEnum;
        pDPHostEnum = pDPHostEnum->pNext;
    }

    if( !bFound )
    {
        m_bEnumListChanged = TRUE;

        // If there's no match, then look for invalid session and use it
        pDPHostEnum = m_DPHostEnumHead.pNext;
        while ( pDPHostEnum != &m_DPHostEnumHead )
        {
            if( !pDPHostEnum->bValid )
                break;

            pDPHostEnum = pDPHostEnum->pNext;
        }

        // If no invalid sessions are found then make a new one
        if( pDPHostEnum == &m_DPHostEnumHead )
        {
            // Found a new session, so create a new node
            pDPHostEnum = new DPHostEnumInfo;
            if( NULL == pDPHostEnum )
            {
                hr = E_OUTOFMEMORY;
                goto LCleanup;
            }

            ZeroMemory( pDPHostEnum, sizeof(DPHostEnumInfo) );

            // Add pDPHostEnum to the circular linked list, m_DPHostEnumHead
            pDPHostEnum->pNext = m_DPHostEnumHead.pNext;
            m_DPHostEnumHead.pNext = pDPHostEnum;
        }
    }

    // Update the pDPHostEnum with new information
    TCHAR strName[MAX_PATH];
    if( pResponseMsgAppDesc->pwszSessionName )
    {
        DXUtil_ConvertWideStringToGenericCch( strName, pResponseMsgAppDesc->pwszSessionName, MAX_PATH );
    }

    // Cleanup any old enum
    if( pDPHostEnum->pAppDesc )
    {
        SAFE_DELETE_ARRAY( pDPHostEnum->pAppDesc->pwszSessionName );
        SAFE_DELETE( pDPHostEnum->pAppDesc );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -