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

📄 netclient.cpp

📁 VC游戏编程基础
💻 CPP
📖 第 1 页 / 共 4 页
字号:




//-----------------------------------------------------------------------------
// Name: MessageHandler
// Desc: Handler for DirectPlay messages.  This function is called by
//       the DirectPlay message handler pool of threads, so be careful of thread
//       synchronization problems with shared memory
//-----------------------------------------------------------------------------
HRESULT WINAPI CNetClientWizard::MessageHandler( PVOID pvUserContext,
                                                  DWORD dwMessageId,
                                                  PVOID pMsgBuffer )
{
    // Try not to stay in this message handler for too long, otherwise
    // there will be a backlog of data.  The best solution is to
    // queue data as it comes in, and then handle it on other threads.

    // This function is called by the DirectPlay message handler pool of
    // threads, so be careful of thread synchronization problems with shared memory

    switch(dwMessageId)
    {
        case DPN_MSGID_ENUM_HOSTS_RESPONSE:
        {
            PDPNMSG_ENUM_HOSTS_RESPONSE pEnumHostsResponseMsg;
            pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE)pMsgBuffer;

            // Take note of the host response
            SessionsDlgNoteEnumResponse( pEnumHostsResponseMsg );
            break;
        }

        case DPN_MSGID_ASYNC_OP_COMPLETE:
        {
            PDPNMSG_ASYNC_OP_COMPLETE pAsyncOpCompleteMsg;
            pAsyncOpCompleteMsg = (PDPNMSG_ASYNC_OP_COMPLETE)pMsgBuffer;

            if( pAsyncOpCompleteMsg->hAsyncOp == m_hEnumAsyncOp )
            {
                SessionsDlgEnumListCleanup();

                // The user canceled the DirectPlay connection dialog,
                // so stop the search
                if( m_bSearchingForSessions )
                {
                    CheckDlgButton( m_hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
                    SendMessage( m_hDlg, WM_COMMAND, IDC_SEARCH_CHECK, 0 );
                }

                m_hEnumAsyncOp = NULL;
                m_bSearchingForSessions = FALSE;
            }
            break;
        }

        case DPN_MSGID_CONNECT_COMPLETE:
        {
            PDPNMSG_CONNECT_COMPLETE pConnectCompleteMsg;
            pConnectCompleteMsg = (PDPNMSG_CONNECT_COMPLETE)pMsgBuffer;

            // Set m_hrConnectComplete, then set an event letting
            // everyone know that the DPN_MSGID_CONNECT_COMPLETE msg
            // has been handled
            m_hrConnectComplete = pConnectCompleteMsg->hResultCode;
            SetEvent( m_hConnectCompleteEvent );
            break;
        }
    }

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: ConnectUsingLobbySettings
// Desc: Call this after the DPL_MSGID_CONNECT has been processed to carry out
//       the connection settings received by the lobby client.  DPL_MSGID_CONNECT
//       will have already been processed if we were lobby launched, or after
//       WaitForConnection returns without timing out.
//-----------------------------------------------------------------------------
HRESULT CNetClientWizard::ConnectUsingLobbySettings()
{
    HRESULT hr;
    DPNHANDLE hAsync;

    if( m_hLobbyClient == NULL )
        return E_INVALIDARG;

    DPL_CONNECTION_SETTINGS* pSettings = NULL;
    DWORD dwSettingsSize = 0;

    // Get the connection settings from the lobby.
    hr = m_pLobbiedApp->GetConnectionSettings( m_hLobbyClient, pSettings, &dwSettingsSize, 0 );
    if( hr != DPNERR_BUFFERTOOSMALL )
    {
        DXTRACE_ERR_MSGBOX( TEXT("GetConnectionSettings"), hr );
        goto LCleanReturn;
    }

    pSettings = (DPL_CONNECTION_SETTINGS*) new BYTE[dwSettingsSize];
    if( NULL == pSettings )
    {
        hr = E_OUTOFMEMORY;
        DXTRACE_ERR_MSGBOX( TEXT("ConnectUsingLobbySettings"), hr );
        goto LCleanReturn;
    }

    if( FAILED( hr = m_pLobbiedApp->GetConnectionSettings( m_hLobbyClient, pSettings, &dwSettingsSize, 0 ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("GetConnectionSettings"), hr );
        goto LCleanReturn;
    }

    // Set the peer info
    WCHAR wszPeerName[MAX_PLAYER_NAME];
    DXUtil_ConvertGenericStringToWideCch( wszPeerName, m_strLocalPlayerName, MAX_PLAYER_NAME );
    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_pDPClient->SetClientInfo( &dpPlayerInfo, NULL, NULL, DPNOP_SYNC ) ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("SetClientInfo"), hr );
        goto LCleanReturn;
    }

    // Connect to an existing session. There should only be on device address in
    // the connection settings structure when connecting to a session, so just
    // pass in the first one.
    // The enumeration is automatically cancelled after Connect is called 
    hr = m_pDPClient->Connect( &pSettings->dpnAppDesc,              // the application desc
                               pSettings->pdp8HostAddress,          // address of the host of the session
                               pSettings->ppdp8DeviceAddresses[0],  // address of the local device used to connect to the host
                               NULL, NULL,                          // DPN_SECURITY_DESC, DPN_SECURITY_CREDENTIALS
                               NULL, 0,                             // user data, user data size
                               NULL, &hAsync,                       // async context, async handle,
                               0 );                                 // flags
    if( hr != E_PENDING && FAILED(hr) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("Connect"), hr );
        goto LCleanReturn;
    }

    hr = S_OK; // Accept E_PENDING.

    // Wait until the MessageHandler sets an event to tell us the
    // DPN_MSGID_CONNECT_COMPLETE has been processed.  Then m_hrConnectComplete
    // will be valid.
    WaitForSingleObject( m_hConnectCompleteEvent, INFINITE );

    if( FAILED( m_hrConnectComplete ) )
    {
        DXTRACE_ERR_MSGBOX( TEXT("DPN_MSGID_CONNECT_COMPLETE"), m_hrConnectComplete );
        MessageBox( m_hDlg, TEXT("Unable to join game."),
                    TEXT("DirectPlay Sample"),
                    MB_OK | MB_ICONERROR );
        hr = m_hrConnectComplete;
    }

    // Cleanup the addresses and memory obtained from GetConnectionSettings
LCleanReturn:
    if( pSettings )
    {
        SAFE_RELEASE( pSettings->pdp8HostAddress );

        for( DWORD dwIndex=0; dwIndex < pSettings->cNumDeviceAddresses; dwIndex++ )
            SAFE_RELEASE( pSettings->ppdp8DeviceAddresses[dwIndex] );
        
        SAFE_DELETE_ARRAY( pSettings );
    }

    return hr;
}




//-----------------------------------------------------------------------------
// Name: LobbyMessageHandler
// Desc: Handler for DirectPlay messages.  This function is called by
//       the DirectPlay lobby message handler pool of threads, so be careful of thread
//       synchronization problems with shared memory
//-----------------------------------------------------------------------------
HRESULT WINAPI CNetClientWizard::LobbyMessageHandler( PVOID pvUserContext,
                                                       DWORD dwMessageId,
                                                       PVOID pMsgBuffer )
{
    HRESULT hr = S_OK;

    switch(dwMessageId)
    {
        case DPL_MSGID_CONNECT:
        {
            // This message will be processed when a lobby connection has been
            // established. If you were lobby launched then
            // IDirectPlay8LobbiedApplication::Initialize()
            // waits until this message has been processed before returning, so
            // take care not to deadlock by making calls that need to be handled by
            // the thread who called Initialize().  The same is true for WaitForConnection()

            PDPL_MESSAGE_CONNECT pConnectMsg;
            pConnectMsg = (PDPL_MESSAGE_CONNECT)pMsgBuffer;
            PDPL_CONNECTION_SETTINGS pSettings = pConnectMsg->pdplConnectionSettings;

            m_hLobbyClient = pConnectMsg->hConnectId;

            if( FAILED( hr = m_pDPClient->RegisterLobby( m_hLobbyClient, m_pLobbiedApp,
                                                   DPNLOBBY_REGISTER ) ) )
                return DXTRACE_ERR_MSGBOX( TEXT("RegisterLobby"), hr );

            if( pSettings == NULL )
            {
                // There aren't connection settings from the lobby
                m_bHaveConnectionSettingsFromLobby = FALSE;
            }
            else
            {
                // Record the player name if found
                if( pSettings->pwszPlayerName != NULL )
                {
                    TCHAR strPlayerName[MAX_PLAYER_NAME];
                    DXUtil_ConvertWideStringToGenericCch( strPlayerName, pSettings->pwszPlayerName, MAX_PLAYER_NAME );
                    _tcsncpy( m_strLocalPlayerName, strPlayerName, MAX_PLAYER_NAME );
                    m_strLocalPlayerName[MAX_PLAYER_NAME-1] = 0;
                }
                else
                {
                    _tcsncpy( m_strLocalPlayerName, TEXT("Unknown"), MAX_PLAYER_NAME );
                    m_strLocalPlayerName[MAX_PLAYER_NAME-1] = 0;
                }

                m_bHaveConnectionSettingsFromLobby = TRUE;
            }

            // Tell everyone we have a lobby connection now
            SetEvent( m_hLobbyConnectionEvent );
            break;
        }
    }

    return S_OK;
}



//-----------------------------------------------------------------------------
// Name: StaticLobbyWaitDlgProc()
// Desc: Static msg handler which passes messages
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetClientWizard::StaticLobbyWaitDlgProc( HWND hDlg, UINT uMsg,
                                                                WPARAM wParam, LPARAM lParam )
{
    if( g_pNCW )
        return g_pNCW->LobbyWaitDlgProc( hDlg, uMsg, wParam, lParam );

    return FALSE; // Message not handled
}




//-----------------------------------------------------------------------------
// Name: LobbyWaitDlgProc()
// Desc: Handles messages for the lobby wait status dialog
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CNetClientWizard::LobbyWaitDlgProc( HWND hDlg, UINT msg,
                                                      WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_INITDIALOG:
#if defined(WIN32_PLATFORM_PSPC) && (_WIN32_WCE >= 300)
			SHINITDLGINFO	shidi;
			memset(&shidi, 0, sizeof(SHINITDLGINFO));
			shidi.dwMask = SHIDIM_FLAGS;
			shidi.dwFlags = SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
			shidi.hDlg = hDlg;

    	    SetForegroundWindow(hDlg);
    	    SHInitDialog(&shidi);
#endif // WIN32_PLATFORM_PSPC

			// 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 );

            SetDlgItemText( hDlg, IDC_WAIT_TEXT, TEXT("Waiting for lobby connection...") );
            return TRUE;

        case WM_COMMAND:
            switch( LOWORD(wParam) )
            {
                case IDCANCEL:
                    EndDialog( hDlg, IDCANCEL );
                    return TRUE;
            }
            break;

        case WM_TIMER:
        {
            if( wParam == TIMERID_CONNECT_COMPLETE )
            {
                // Wait for a lobby connection.  If this call
                // returns WAIT_OBJECT_0 then the DPL_MSGID_CONNECT will
                // have already been processed.
                DWORD dwResult = WaitForSingleObject( m_hLobbyConnectionEvent, 100 );
                if( dwResult != WAIT_TIMEOUT )
                    EndDialog( hDlg, IDOK );
            }
            break;
        }
    }

    return FALSE; // Didn't handle message
}

⌨️ 快捷键说明

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