📄 sessionwnd.cpp
字号:
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 + -