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

📄 sessionwnd.cpp

📁 Windows CE .Net 下面 VOIP编程的经典实例。对于初学Windows 平台下VOIP编程技术的程序员颇具借鉴意义!
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		case LMT_PARTY_DECLINED:
			wsprintf( szMsg, L"%s has declined the %s session", szPartyName, szTxt );
			break;
			
		case LMT_PARTY_JOINED:
			wsprintf( szMsg, L"%s has joined the %s session", szPartyName, szTxt );
			break;
			
		case LMT_PARTY_LEFT:
			wsprintf( szMsg, L"%s has left the %s session", szPartyName, szTxt );
			break;
	}

	// display the status message on the screen
	SWCB_MESSAGE_ARRIVED sMA = { NULL, szMsg };
	CSessionWndContainer::SessionWndCallback( SWCBM_IM_MESSAGE_STATUS, &sMA, NULL );
}

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

  AddMessage

	Add a message to the listview for display.  Scroll the view to ensure the latest message is
	visible.

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

int CSessionWnd::AddMessage( TCHAR* szTxt, LOCALMSGTYPE mt )

{
	if( !m_hMsgWindow )
		return 0;

	// Delete messages from the beginning so we have no more than SESSIONWND_MAXMSGNUM lines
	while ( ListView_GetItemCount( m_hMsgWindow ) > SESSIONWND_MAXMSGNUM )
		ListView_DeleteItem( m_hMsgWindow, 0 );

	LV_ITEM lvi;
	// Common settings.
	lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_STATE;
	lvi.state = 0;
	lvi.stateMask = 0;
	lvi.iItem = SESSIONWND_MAXMSGNUM + 1;
	lvi.lParam = mt;

	// Add the item.
	lvi.pszText = szTxt;
	lvi.iSubItem = 0;
	ListView_InsertItem( m_hMsgWindow, &lvi );

	SessionWndScrollMessages();

	return 0;
}


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

  OpenSessionWnd

	Saves instance handle to a global, then creates and displays the session window.

	The session window will be created with an owner-drawn listview to display messages to/from
	IM and status/presence change information.  A MULTILINE edit control is also created for the 
	user to input messages for transmit.  Next the command bar and menu are instantiated and the 
	icon is loaded for the task manager.

	Finally, participant information is stored depending upon the sessiontype. (name, URI, status, etc.)

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

BOOL CSessionWnd::OpenSessionWnd( SWCB_PARTICIPANT_INFO* pPart, SESSIONWNDCALLBACKMSGS eMsg )
{
	TCHAR	szTitle[ MAX_LOADSTRING ];			// The title bar text
	TCHAR	szWindowSession[ MAX_LOADSTRING ];	// The window class name

	cOtherParty.pBuddy = pPart->pBuddy;

	ssVoice = SS_OFF;
	ssMessage = SS_OFF;

	wsprintf( szTitle, L"%s - Session", pPart->get_Name() );

	if ( pPart->get_Addr() )
		wcscpy( szPartyIPAddr, pPart->get_Addr() );

	LoadString( CSessionWndContainer::hInstance, IDC_SESSIONWND, szWindowSession, MAX_LOADSTRING );

	m_hWndSession = CreateWindow( szWindowSession, szTitle, WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_SYSMENU,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, CSessionWndContainer::hInstance, NULL );

	if ( !m_hWndSession )
		return FALSE;

	SetWindowLong( m_hWndSession, GWL_USERDATA, ( DWORD )this );

	// Create the list and edit controls inside the window
	m_hMsgWindow = CreateWindowEx( LVS_EX_FULLROWSELECT, WC_LISTVIEW, TEXT( "Listview" ),
					LVS_OWNERDRAWFIXED|LVS_NOCOLUMNHEADER|LVS_AUTOARRANGE|LVS_REPORT|LVS_SINGLESEL|WS_CHILD|WS_VISIBLE|WS_TABSTOP,
					44, 44, 100, 100,
					m_hWndSession, ( HMENU )IDC_MSGLIST, CSessionWndContainer::hInstance, NULL );

	LV_COLUMN lvc;
	lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
	lvc.fmt = LVCFMT_LEFT;
	lvc.cx = 10;
	lvc.pszText = L"1";
	lvc.iSubItem = 0;
	ListView_InsertColumn( m_hMsgWindow, 0, &lvc );

	// Use the edit window for p2p sessions?
	m_hEditWindow = CreateWindow( TEXT( "EDIT" ), NULL,
			ES_MULTILINE|ES_AUTOVSCROLL|ES_LEFT|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP,
			44, 44, 100, 100,
			m_hWndSession, ( HMENU )IDC_MSGEDIT, CSessionWndContainer::hInstance, NULL );

	SetWindowLong( m_hEditWindow, GWL_USERDATA, ( DWORD )-1 );

	SendMessage( m_hEditWindow, EM_LIMITTEXT, SESSIONWND_MAXEDITLENGTH, 0 );
			
	// Subclass the edit to get the CTRL+ENTERs
	if ( m_hEditWindow ) {
		// Save the original window proc only the first time!
		WNDPROC fp = ( WNDPROC ) SetWindowLong( m_hEditWindow, GWL_WNDPROC, ( LONG ) CSessionWnd::SessionWndProc );
		if ( !m_pEditProc )
			m_pEditProc = fp;
	}

	// Also insert the command bar and menu
	m_hWndSessionCB = CommandBar_Create( CSessionWndContainer::hInstance, m_hWndSession, 1 );
	CommandBar_InsertMenubar( m_hWndSessionCB, CSessionWndContainer::hInstance, IDM_SESSIONMENU, 0 );

	// Load the icon to be shown in task manager
	HICON hSmallIcon = ( HICON )LoadImage( CSessionWndContainer::hInstance, MAKEINTRESOURCE( IDI_VOIPSESSION ), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );
	if ( NULL != hSmallIcon ) {
		SendMessage( m_hWndSession, WM_SETICON, ICON_SMALL, ( LPARAM )hSmallIcon );
	}

	SendMessage( m_hMsgWindow, WM_SETFONT, ( WPARAM )m_hFont, TRUE );
	SendMessage( m_hEditWindow, WM_SETFONT, ( WPARAM )m_hFont, TRUE );

	if ( m_hWndSessionCB )
		CommandBar_Show( m_hWndSessionCB, TRUE );

	ShowWindow( m_hWndSession, SW_SHOW );
	UpdateWindow( m_hWndSession );


	// Save the buddy type for callbacks to format the callee's address
	cOtherParty.btBuddyType = pPart->btBuddyType;
	cOtherParty.put_Name(pPart->get_Name());
	cOtherParty.put_Addr(pPart->get_Addr());

	// Also if incoming, save the caller in the buddy list for the life of the session window
	// This will enable us to see the guy's presence info so to signal if we can call back or IM him/her
	if ( eMsg == SWCBM_IM_INITIATING_INCOMING || eMsg == SWCBM_CALL_INITIATING_INCOMING ) {
		
		// if anyone is calling us, it must be a computer buddy (no phone support currently allowed)
		cOtherParty.btBuddyType = BT_COMPUTER;

		// we don't want to overwrite the existing guy if this is an existing buddy
		cOtherParty.pBuddy = CheckForExistingBuddy(&cOtherParty);

		if (!cOtherParty.pBuddy) {
			// couldn't find the buddy, make a temporary one, but don't add him to the listview
			cOtherParty.pBuddy = AddBuddyRTC(pPart->get_Addr(), pPart->get_Name(), cOtherParty.btBuddyType, VARIANT_FALSE);

			bTemporaryBuddy = TRUE;

			if (!cOtherParty.pBuddy) {
				DEBUGMSG( ZONE_ERROR, (L"Voipdemo: CSessionWnd::OpenSessionWnd() Unable to add temporary buddy during incoming session \r\n") );
				ASSERT(FALSE);
			}
		}
		cOtherParty.eStat = GetBuddyStatus(cOtherParty.pBuddy, cOtherParty.btBuddyType);
	} else if ( eMsg != SWCBM_P2P_CALL_INITIATING_OUTGOING ) {
		// outgoing call, we've already got this buddy stored
		cOtherParty.pBuddy = pPart->pBuddy;
		cOtherParty.btBuddyType = pPart->btBuddyType;
		
		if (pPart->btBuddyType == BT_PHONE) {
			cOtherParty.eStat = ES_ONLINE;
		} else if (cOtherParty.pBuddy) {
			cOtherParty.eStat = GetBuddyStatus(cOtherParty.pBuddy, cOtherParty.btBuddyType);					
		} else {
			// We have no buddy for him, check depending on the call type (incoming calls handled earlier)v
			cOtherParty.eStat = (eMsg == SWCBM_CALL_INITIATING_OUTGOING) ? ES_ONLINE : ES_OFFLINE;
		}
	} else {
		//Phone2Phone call, what to do?  Set p2p type and store number of participants
		cOtherParty.btBuddyType = BT_PHONE;
		cOtherParty.iSelectedBuddies = ((BUDDY_SELECTION*) pPart)->iSelectedBuddies;
		m_bP2PSession = TRUE; // affects messages displayed on Accepted, etc.
	}
	return TRUE;
}

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

  SessionWndProc

	Processes messages for the session window

  	WM_COMMAND	- process the menu and buttons
	WM_PAINT	- Paint the session window
	WM_DESTROY	- close the window
	WM_DRAWITEM - Paint the listview item ( that line of text )

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

LRESULT CALLBACK CSessionWnd::SessionWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	CSessionWnd* pThis = ( CSessionWnd* )GetWindowLong( hWnd, GWL_USERDATA );
	
	// If it's a message for one of the subclassed windows
	if ( ( int )pThis == -1 )
	{
		// If it's the "Send Message" accelerator, send it up on the window tree
		if ( message == WM_COMMAND && LOWORD( wParam ) == ID_EDIT_SENDMESSAGE &&
			 GetParent( hWnd ) )
		{
			SendMessage( GetParent( hWnd ), message, wParam, lParam );
			return 0;
		}
		
		// Call the child's original window proc
		return CallWindowProc( CSessionWnd::m_pEditProc, hWnd, message, wParam, lParam );
	}		

	static BOOL bLastTextValid = FALSE;
	int wmId, wmEvent, nB;

	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_HELP_ABOUT:
					DialogBox( CSessionWndContainer::hInstance, (LPCTSTR)IDD_ABOUTBOX, hWnd, ( DLGPROC )Proc_About );
					break;
				   
				case IDM_FILE_CLOSE:
					
					DestroyWindow( hWnd );
					break;

				case ID_FILE_MYSTATUS:
					if ( DialogBox( CSessionWndContainer::hInstance, (LPCTSTR)IDD_MYSTATUSBOX, hWnd, ( DLGPROC )Proc_MyStatus ) ==	 IDOK )
						InvalidateRect( m_hWndMain, NULL, FALSE );
					break;					
				   
				case ID_VIEW_TOOLBAR:
					pThis->bToolbar = !pThis->bToolbar;
					InvalidateRect( pThis->m_hWndSession, NULL, FALSE );
					break;

				case ID_VIEW_STATUSBAR:
					pThis->bStatusbar = !pThis->bStatusbar;
					InvalidateRect( pThis->m_hWndSession, NULL, TRUE );
					break;

				case ID_VIEW_ALWAYSONTOP:
					pThis->bAlwaysOnTop = !pThis->bAlwaysOnTop;
					SetWindowPos( pThis->m_hWndSession, ( pThis->bAlwaysOnTop )?HWND_TOPMOST:HWND_NOTOPMOST, 0, 0, 0, 0,
						SWP_NOMOVE|SWP_NOSIZE );
					break;

				case ID_EDIT_CHANGEFONT:
					break;

				case ID_TOOLS_SENDINSTANTMESSAGE:
					if (!pThis->cOtherParty.IMCapable()) {
						break;
					}

					if ( pThis->ssMessage == SS_OFF)
					{
						pThis->ssMessage = SS_INITIATING;
						pThis->InvalidateSessionButton( -100 );
						pThis->SessionWndUpdateTitle();
						
						// Start messaging session
						PARTICIPANT_INFO PartInfo(pThis->cOtherParty.get_Name(), pThis->cOtherParty.get_Addr(), 0, pThis->cOtherParty.btBuddyType);
						pThis->m_hIMSession = OpenSessionTo( &PartInfo, RTCST_IM, ( FARPROC )CSessionWndContainer::SessionWndCallback );
                        ASSERT(pThis->m_hIMSession);
						if (!pThis->m_hIMSession) {
							pThis->ssMessage = SS_OFF;
							pThis->InvalidateSessionButton(-100);
							pThis->SessionWndUpdateTitle();

						}
						SetFocus( pThis->m_hEditWindow );
					}
					else if (pThis->ssMessage != SS_QUITTING)
					{
						pThis->ssMessage = SS_QUITTING;
						pThis->InvalidateSessionButton( -100 );
						pThis->SessionWndUpdateTitle();

						SessionStop( pThis->m_hIMSession );
					}

					pThis->SessionWndRedrawClient();
					pThis->SessionWndScrollMessages();
					Sleep( 10 );

					pThis->SessionWndRedrawClient();

					break;
					
				case ID_TOOLS_CALL:
					// Check if we have to initiate a call
					if ( pThis->ssVoice == SS_OFF )
					{
						// Check if the other party can be called
						if (!pThis->cOtherParty.CallCapable() || pThis->m_bP2PSession)
							break;

						pThis->ssVoice = SS_INITIATING;
						pThis->InvalidateSessionButton( -100 );
						pThis->SessionWndUpdateTitle();

						PARTICIPANT_INFO PartInfo(pThis->cOtherParty.get_Name(), pThis->cOtherParty.get_Addr(), 0, pThis->cOtherParty.btBuddyType);
						pThis->m_hCallSession = OpenSessionTo( &PartInfo, (PartInfo.btBuddyType == BT_COMPUTER) ? RTCST_PC_TO_PC : RTCST_PC_TO_PHONE, ( FARPROC )CSessionWndContainer::SessionWndCallback );
						if (!pThis->m_hCallSession) {
							pThis->ssVoice = SS_OFF;
							pThis->InvalidateSessionButton( -100 );
							pThis->SessionWndUpdateTitle();
						}
					}
					// Otherwise hang up if initiating, or online
					else if (pThis->ssVoice != SS_QUITTING)
					{
						// if we are in the quitting state, we don't want to re-hang up
						pThis->ssVoice = SS_QUITTING;
						pThis->InvalidateSessionButton( -100 );
						pThis->SessionWndUpdateTitle();
						// Stop voice session
						SessionStop( pThis->m_hCallSession );
					}

					break;
		
				case ID_EDIT_SENDMESSAGE:
					// Send the message from the edit box (if any)
					if ( GetWindowTextLength( pThis->m_hEditWindow ) )
					{
						TCHAR szTxt[ SESSIONWND_MAXEDITLENGTH + 4 ];
						GetWindowText( pThis->m_hEditWindow, szTxt, sizeof( szTxt ) );

						SWCB_PARTICIPANT_INFO* pPI = (SWCB_PARTICIPANT_INFO*) g_pLocalUserInfo;
						SWCB_MESSAGE_ARRIVED sMA = { pPI, szTxt };
						
						// NOTE: Eventually hold a handle to the IM session, for now use nothing.
						if (!SendIMTo( pThis->m_hIMSession, &sMA ) ) {
							// IM message error
							wsprintf( sMA.szMsg, L"Unspecified error sending message");
							CSessionWndContainer::SessionWndCallback( SWCBM_IM_MESSAGE_LOCAL, &sMA, NULL );

						} else {
							// Also echo the message locally
							CSessionWndContainer::SessionWndCallback( SWCBM_IM_MESSAGE_LOCAL, &sMA, NULL );							
							SetWindowText( pThis->m_hEditWindow, L"" );
							bLastTextValid = FALSE;
							pThis->InvalidateSessionButton( MSGSENDBUTTON );
						}
					}
					break;

				case IDC_MSGEDIT:
					// At every character entry check the text size and enable/disable the send button
					if ( wmEvent == EN_CHANGE )
					{
						BOOL bTextValid = GetWindowTextLength( pThis->m_hEditWindow ) > 0;
						if ( bLastTextValid != bTextValid )
						{
							bLastTextValid = bTextValid;
							pThis->InvalidateSessionButton( MSGSENDBUTTON );
						}
					}
					break;
					
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		case WM_CHAR:
			break;

		case WM_MEASUREITEM:
			if ( ( ( LPMEASUREITEMSTRUCT )lParam )->CtlID == IDC_MSGLIST )
			{
				( ( LPMEASUREITEMSTRUCT )lParam )->itemHeight = pThis->nMsgFontHight + 1;
			}

			break;
			
		case WM_DRAWITEM:
			if ( ( ( LPDRAWITEMSTRUCT )lParam )->CtlID == IDC_MSGLIST )
			{
				LPDRAWITEMSTRUCT lpdis = ( LPDRAWITEMSTRUCT )lParam;
				BOOL fTextHighlight = lpdis->itemState & ODS_SELECTED;
				HDC hdc = lpdis->hDC;
				RECT rc = lpdis->rcItem;

				TCHAR szTxt[1024];

				LV_ITEM lvi;
				lvi.mask = LVIF_PARAM|LVIF_TEXT;
				lvi.iItem = lpdis->itemID; // row index 
				lvi.iSubItem = 0; // column 0 of this row 
				lvi.pszText = szTxt;
				lvi.cchTextMax = sizeof( szTxt );
				ListView_GetItem( pThis->m_hMsgWindow, &lvi );

				SetBkColor( hdc, ListView_GetBkColor( pThis->m_hMsgWindow ) );
				switch( lvi.lParam )
				{
					case LMT_TEXT:
						SetTextColor( hdc, RGB( 0, 0, 0 ) );
						break;
					case LMT_SAYS:
						SetTextColor( hdc, RGB( 0, 255, 64 ) );
						break;
					default:
					{
						SIZE s = { 0, 0 };
						GetTextExtentPoint32( hdc, szTxt, wcslen( szTxt ), &s );
						rc.left += ( ( rc.right - rc.left ) - s.cx ) / 2;
						SetTextColor( hdc, RGB( 255, 128, 0 ) );
						break;
					}
				}
				
				ExtTextOut( hdc, rc.left, rc.top, ETO_OPAQUE, NULL, szTxt, wcslen( szTxt ), NULL);
			}
			

⌨️ 快捷键说明

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