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

📄 sessionwnd.cpp

📁 Windows CE .Net 下面 VOIP编程的经典实例。对于初学Windows 平台下VOIP编程技术的程序员颇具借鉴意义!
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*************************************************************************


  Disclaimer:

    This code and information is provided "as is" without warranty of
    any kind, either expressed or implied, including but not limited to
    the implied warranties of merchantability and/or fitness for a
    particular purpose.

Module Name:

	SessionWnd.cpp

Abstract:
	
	Methods for the SessionWindow or UI of current voice / IM sessions.
	
Notes:
	
	This module contains all methods related to the session window, which
	is used to display status messages for voice sessions and for user input
	of instant messages and display of the receipt of these.

	The SessionWindowCallBack function is notified of RTC events through the 
	rtcevent.cpp event handlers.  

**************************************************************************/

#include "stdafx.h"
#include <commctrl.h>
#include "rtcs.h"
#include "voipdemo.h"
#include "sessionwnd.h"
#include "dbase.h"

#define MSGSENDBUTTON 0

/*************************************************************************************************
  Internal global variables
 *************************************************************************************************/

// Handle to the local user's information
extern LOCAL_USER_INFO*	g_pLocalUserInfo;


// information for display of different buttons
SBUTTONDATA			m_sSessionButtons[]=
	{ { 0, 0, 0, 0, { IDB_SMSGBTN, IDB_SMSGBTN, IDB_SMSGDISABLEDBTN } },		// Send message
	  { 10, 10, 50, 50, { IDB_CALLBTN, IDB_HANGUPBTN, IDB_CALLDISABLEDBTN } },	// Should be talking
	  { 62, 10, 50, 50, { IDB_SENDBTN, IDB_STOPSENDBTN, IDB_SENDDISABLEDBTN } },// Should be messaging
	  { 114, 10, 50, 50, { IDB_STATBTN, IDB_STATBTN, IDB_STATBTN } } };			// Should be changing my status


// Static data members must be initialized at file scope, even if private.
HINSTANCE CSessionWndContainer::hInstance;
CSessionWnd* CSessionWndContainer::pSessionWindow;
WNDPROC CSessionWnd::m_pEditProc;

/*************************************************************************************************

  CSessionWndContainer constructor

	Store the program instance in the container

 *************************************************************************************************/

CSessionWndContainer::CSessionWndContainer( HINSTANCE hInst )
{
	pSessionWindow = NULL;
	hInstance = hInst;
}

/*************************************************************************************************

  ~CSessionWndContainer destructor
	
	Destroy any existing sessionwindows (at present date, only 1 supported)s

 *************************************************************************************************/

CSessionWndContainer::~CSessionWndContainer()
{
	if ( pSessionWindow )
		delete pSessionWindow;
}


/*************************************************************************************************

  MyRegisterSessionWnd

	Register the session window class with Win32

 *************************************************************************************************/

ATOM CSessionWndContainer::MyRegisterSessionWnd( HINSTANCE hInstance, LPTSTR szWindowClass )
{
	WNDCLASS	wc;

    wc.style			= CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc		= (WNDPROC) CSessionWnd::SessionWndProc;
    wc.cbClsExtra		= 0;
    wc.cbWndExtra		= 0;
    wc.hInstance		= hInstance;
    wc.hIcon			= LoadIcon( hInstance, MAKEINTRESOURCE( IDI_VOIPDEMO ) );
    wc.hCursor			= 0;
    wc.hbrBackground	= ( HBRUSH ) CreateSolidBrush( RGB( 128, 128, 255 ) );	// blue background
    wc.lpszMenuName		= 0;
    wc.lpszClassName	= szWindowClass;

	return RegisterClass(&wc);
}

/*************************************************************************************************

  SessionWndCallback

	Handle callback messages from other UI methods, events, and recursive calls.

	This callback 

 *************************************************************************************************/

int CSessionWndContainer::SessionWndCallback( SESSIONWNDCALLBACKMSGS eMsgType, void* pMsgBody, HANDLE hSess )
{
	// If the callback has been called with no window present - only valid if initiating from other party or party has left
	if ( !pSessionWindow && eMsgType != SWCBM_IM_INITIATING_INCOMING && eMsgType != SWCBM_CALL_INITIATING_INCOMING &&
							eMsgType != SWCBM_IM_INITIATING_OUTGOING && eMsgType != SWCBM_CALL_INITIATING_OUTGOING &&
							eMsgType != SWCBM_IM_PARTICIPANT_LEFT    && eMsgType != SWCBM_CALL_PARTICIPANT_LEFT && 
							eMsgType != SWCBM_P2P_CALL_INITIATING_OUTGOING)
	{
		return 0;
	}
	
	switch ( eMsgType )
	{
		case SWCBM_IM_MESSAGE_LOCAL:
		case SWCBM_IM_MESSAGE_STATUS:
		case SWCBM_IM_MESSAGE_ARRIVED:
			{
				// If we have no msg window yet, then set up one now
				if ( eMsgType == SWCBM_IM_MESSAGE_ARRIVED && pSessionWindow->ssMessage == SS_INITIATING_INCOMING )
				{
					if ( !SessionWndCallback( SWCBM_IM_INITIATING_INCOMING, pMsgBody, hSess ) )
					{
						// If it has been declined
						if ( pSessionWindow->m_hWndSession )
						{
							// Clean window if we have one
							pSessionWindow->ssMessage = SS_QUITTING;
							pSessionWindow->InvalidateSessionButton( -100 );
							pSessionWindow->SessionWndUpdateTitle();
						}
						
						// Stop messaging session
						SessionStop(pSessionWindow->m_hIMSession);
						pSessionWindow->m_hIMSession = NULL;

						// If we have no window, destroy the object now (otherwise the window destroy will destroy it later)
						if ( !pSessionWindow->m_hWndSession )
						{
							delete pSessionWindow;
							pSessionWindow = NULL;
						}

						return 0;
					}
					else
					{
						// Accepted the session
						pSessionWindow->ssMessage = SS_GOING;
						pSessionWindow->InvalidateSessionButton( -100 );

						pSessionWindow->SessionWndUpdateTitle();
						pSessionWindow->SessionWndRedrawClient();
					}
				}

				if( !pSessionWindow->m_hMsgWindow )
					return 0;

				SWCB_MESSAGE_ARRIVED* pMA = ( SWCB_MESSAGE_ARRIVED* ) pMsgBody;
				TCHAR* szTxt;

				ASSERT( pMA );

				// Print the other party's line (e.g. "xyz says:")
				// Only if there's a party in the parameter
				if ( pMA->sFrom )
				{
					szTxt = ( TCHAR* )malloc( wcslen( pMA->sFrom->get_Name() ) * sizeof( TCHAR ) + 32 );
					if ( !szTxt )
					{
						DEBUGMSG( ZONE_ERROR, ( L"VoIPDemo: could not allocate memory for other party's name\r\n" ) );
						return 0;
					}
					
					wsprintf( szTxt, L"%s says:", pMA->sFrom->get_Name() );

					pSessionWindow->AddMessage( szTxt, LMT_SAYS );

					free( szTxt );
				}
				

				// Now print the message itself line by line
				TCHAR* pTxt = pMA->szMsg;
				TCHAR* pLine = pMA->szMsg;
				DWORD nIndex  = 0;
				TCHAR szLinePref[] = L"    ";

				// Need these for figuring out whether a line can fit on the screen or should be wrapped
				RECT rt;	
				GetClientRect( pSessionWindow->m_hWndSession, &rt );
				HDC dc = GetDC( pSessionWindow->m_hMsgWindow );
				SelectObject( dc, pSessionWindow->m_hFont );
				SIZE s = { 0, 0 };
				GetTextExtentPoint32( dc, szLinePref, wcslen( szLinePref ), &s );
				int nLinePrefWidth = ( eMsgType != SWCBM_IM_MESSAGE_STATUS )?s.cx : 0;

				// Run through the text
				while ( pTxt && *pTxt )
				{
					// Find EOL characters
					if ( *pTxt == '\n' )
					{
						// Case of \n
						*pTxt = '\0';
						szTxt = ( TCHAR* )malloc( wcslen( pLine ) * sizeof( TCHAR ) + 32 );
						if ( !szTxt )
							break;
						wsprintf( szTxt, L"%s%s", ( eMsgType != SWCBM_IM_MESSAGE_STATUS )?szLinePref:L"", pLine );
						pSessionWindow->AddMessage( szTxt, ( eMsgType == SWCBM_IM_MESSAGE_STATUS )? LMT_PARTY_ACCEPTED:LMT_TEXT );
						free( szTxt );
						pLine = pTxt + 1;
					} 
					else
					if ( *pTxt == '\r' && *( pTxt+1 ) == '\n' )
					{
						// Case of \r\n
						*pTxt = '\0';
						*( pTxt+1 ) = '\0';
						szTxt = ( TCHAR* )malloc( wcslen( pLine ) * sizeof( TCHAR ) + 32 );
						if ( !szTxt )
							break;
						wsprintf( szTxt, L"%s%s", ( eMsgType != SWCBM_IM_MESSAGE_STATUS )?szLinePref:L"", pLine );
						pSessionWindow->AddMessage( szTxt, ( eMsgType == SWCBM_IM_MESSAGE_STATUS )? LMT_PARTY_ACCEPTED:LMT_TEXT );
						free( szTxt );
						pTxt++;		// 2 to skip!
						pLine = pTxt + 1;
					} 
					else
					if ( !*( pTxt + 1 ) )
					{
						// Case of end of text
						szTxt = ( TCHAR* )malloc( wcslen( pLine ) * sizeof( TCHAR ) + 32 );
						if ( !szTxt )
							break;
						wsprintf( szTxt, L"%s%s", ( eMsgType != SWCBM_IM_MESSAGE_STATUS )?szLinePref:L"", pLine );
						pSessionWindow->AddMessage( szTxt, ( eMsgType == SWCBM_IM_MESSAGE_STATUS )? LMT_PARTY_ACCEPTED:LMT_TEXT );
						free( szTxt );
					}
					else
					{
						TCHAR ch = *( pTxt + 1 );
						*( pTxt + 1 ) = '\0';
						SIZE s = { 0, 0 };
						GetTextExtentPoint32( dc, pLine, wcslen( pLine ), &s );
						*( pTxt + 1 ) = ch;
						
						if ( nLinePrefWidth + s.cx >  rt.right - 12 -rt.left - 12 - GetSystemMetrics( SM_CXVSCROLL ) - 16 )
						{
							ch = *pTxt;
							*pTxt = '\0';
							
							// Too long line
							szTxt = ( TCHAR* )malloc( wcslen( pLine ) * sizeof( TCHAR ) + 32 );
							if ( !szTxt )
								break;
							wsprintf( szTxt, L"%s%s", ( eMsgType != SWCBM_IM_MESSAGE_STATUS )?szLinePref:L"", pLine );
							pSessionWindow->AddMessage( szTxt, ( eMsgType == SWCBM_IM_MESSAGE_STATUS )? LMT_PARTY_ACCEPTED:LMT_TEXT );
							free( szTxt );
							pLine = pTxt;
							*pTxt = ch;
						}

					} 

					pTxt++;
				}

				ReleaseDC( pSessionWindow->m_hMsgWindow, dc );

				return 1;
			}
			
		case SWCBM_PRESENCECHANGED:
			{

				if (!pSessionWindow || (IRTCBuddy*) pMsgBody != pSessionWindow->cOtherParty.pBuddy) {
					// buddy not in this session, ignore this callback
					return 1;
				}

				// Get the current presence info for the buddy for this session
				ESTATUS esOldStatus = pSessionWindow->cOtherParty.eStat;
				ESTATUS esThisBuddyStatus = GetBuddyStatus(pSessionWindow->cOtherParty.pBuddy, pSessionWindow->cOtherParty.btBuddyType);

				// Check if the status of our other party has changed
				if ( esThisBuddyStatus != ES_NOSTATUS && esThisBuddyStatus != esOldStatus )
				{
					pSessionWindow->cOtherParty.eStat = esThisBuddyStatus;
					pSessionWindow->InvalidateSessionButton( -100 );

					TCHAR szTxt[ MAX_LOADSTRING ];
					LoadString( m_hInstance, esThisBuddyStatus, szTxt, MAX_LOADSTRING );
					pSessionWindow->LocalMessage( LMT_PARTY_STATUS_CHANGE, pSessionWindow->cOtherParty.get_Name(), szTxt );
				}
				
				return 1;
			}

		case SWCBM_IM_INITIATING_INCOMING:
		case SWCBM_IM_INITIATING_OUTGOING:
			{
				// Check if it's incoming with or without message
				if ( eMsgType == SWCBM_IM_INITIATING_INCOMING && ( !pSessionWindow || pSessionWindow->ssMessage == SS_OFF ) )
				{
					// Incoming with no message
					// Make a new session window if we have none
					if ( !pSessionWindow ) {
						pSessionWindow = new CSessionWnd();

					}
				
					// Incoming with no msg -> just change status
					pSessionWindow->ssMessage = SS_INITIATING_INCOMING;					
					pSessionWindow->InvalidateSessionButton( -100 );
					pSessionWindow->SessionWndUpdateTitle();
					
					// need to get the session handle here
					pSessionWindow->m_hIMSession = hSess;

					return 1;
				}
				
				SWCB_PARTICIPANT_INFO* pPI;

				// Init other party's structure
				if ( eMsgType == SWCBM_IM_INITIATING_INCOMING ) {
					pPI = (( SWCB_MESSAGE_ARRIVED* ) pMsgBody)->sFrom;
				} else {
					pPI = ( SWCB_PARTICIPANT_INFO* ) pMsgBody;
				}

				// Throw message box for accepting or declining session
				if ( eMsgType == SWCBM_IM_INITIATING_INCOMING )
				{
					TCHAR* szTxt = ( TCHAR* ) malloc( ( wcslen( ( ( SWCB_MESSAGE_ARRIVED* ) pMsgBody )->szMsg ) +
														 wcslen( pPI->get_Name() ) +
														 64 ) * sizeof( TCHAR ) );

					wsprintf( szTxt, L"%s said:\r\n%s\r\nDo you accept this messaging session?", pPI->get_Name(), ( ( SWCB_MESSAGE_ARRIVED* ) pMsgBody )->szMsg );

					TCHAR szTitle[ MAX_LOADSTRING ];
					LoadString( m_hInstance, IDS_MSGSESSION, szTitle, MAX_LOADSTRING );
					
					int iRet = MessageBox( NULL, szTxt, szTitle, MB_YESNO );
					free( szTxt );
					
					if ( iRet == IDNO )
					{
						pSessionWindow->m_hIMSession = NULL;
						// Return with rejected
						return 0;
					}
					else
					if ( iRet == IDABORT || iRet == IDIGNORE )
					{
						pSessionWindow->m_hIMSession = NULL;
						// Return with timed out
						return 2;
					}
				}

				// If there's no window (just receiving an invitation), pull up window now
				if ( !pSessionWindow ) {
					pSessionWindow = new CSessionWnd();
				}

				if ( !pSessionWindow->m_hWndSession )
				{
					pSessionWindow->OpenSessionWnd( pPI, eMsgType );
				}

				pSessionWindow->ssMessage = SS_INITIATING;
				pSessionWindow->InvalidateSessionButton( -100 );

				pSessionWindow->SessionWndUpdateTitle();
				pSessionWindow->SessionWndRedrawClient();
				pSessionWindow->SessionWndScrollMessages();

				if ( eMsgType == SWCBM_IM_INITIATING_OUTGOING ) {
					// create the call
					if (!(pSessionWindow->m_hIMSession = OpenSessionTo( (PARTICIPANT_INFO*) pMsgBody, RTCST_IM, (FARPROC) SessionWndCallback))) {
						// NOTE: need some sort of error message/error handling						
					} 					
				} else if ( eMsgType == SWCBM_IM_INITIATING_INCOMING ) {
					pSessionWindow->m_hIMSession = hSess;	
					DEBUGMSG( ZONE_STATUS, (L"Voipdemo:SessionWnd storing %l as the IM Session handle\r\n", hSess) );
				}

				return 1;
			}

		case SWCBM_IM_PARTICIPANT_JOINED:
			if ( pSessionWindow && pSessionWindow->ssMessage != SS_INITIATING_INCOMING )
			{
				// These are going to happen on the callee side only if accepted
				pSessionWindow->ssMessage = SS_GOING;
				pSessionWindow->InvalidateSessionButton( -100 );

				pSessionWindow->SessionWndUpdateTitle();
				pSessionWindow->SessionWndRedrawClient();
				pSessionWindow->SessionWndScrollMessages();

				// The caller should see an acceptance message
				pSessionWindow->LocalMessage( LMT_PARTY_ACCEPTED, (BSTR) pMsgBody, L"messaging" );
			}

⌨️ 快捷键说明

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